theory ArchEmptyFail_AI

lemma arch_decode_ARMASIDControlMakePool_empty_fail:
  "invocation_type label = ArchInvocationLabel ARMASIDControlMakePool
    \<Longrightarrow> empty_fail (arch_decode_invocation label b c d e f)" apply (simp add: arch_decode_invocation_def Let_def) apply (intro impI conjI allI) apply (simp add: isPageFlushLabel_def isPDFlushLabel_def split: arch_cap.splits)+ apply (rule impI) apply (simp add: split_def) apply (wp (once), simp) apply (subst bindE_assoc[symmetric]) apply (rule empty_fail_bindE) subgoal by (force simp: empty_fail_def whenE_def throwError_def select_ext_def bindE_def
                            bind_def return_def returnOk_def lift_def liftE_def fail_def gets_def
                            get_def assert_def select_def
                      split: if_split_asm) by (simp add: Let_def split: cap.splits arch_cap.splits option.splits bool.splits | wp | intro conjI impI allI)+

(* Proof state trace *)
proof (prove)
goal (1 subgoal):
 1. invocation_type label = ArchInvocationLabel ARMASIDControlMakePool \<Longrightarrow> empty_fail (arch_decode_invocation label b c d e f) proof (prove)
goal (1 subgoal):
 1. invocation_type label = ArchInvocationLabel ARMASIDControlMakePool \<Longrightarrow> (Suc 0 < length b \<longrightarrow> (isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool) \<longrightarrow> (Suc 0 < length f \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> let index = b ! 0; depth = b ! 1; (untyped, parent_slot) = f ! 0; root = fst (f ! 1) in doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
free_set <- returnOk (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1});
whenE (free_set = {}) $ throwError DeleteFirst;
free <- liftE $ select_ext (\<lambda>_. free_asid_select asid_table) free_set;
base <- returnOk (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits);
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ MakePool frame dest_slot parent_slot base
odE | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> let start = b ! 0; end = b ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case e of PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | PageDirectoryCap pd (Some asid) \<Rightarrow> returnOk (pd, asid) | _ \<Rightarrow> throwError $ InvalidCapability 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 0;
(liftE $ resolve_vaddr pd start) >>=E case_option (returnOk $ InvokePageDirectory PageDirectoryNothing) (\<lambda>(frame_size, frame_base). let base_start = page_base start frame_size; base_end = page_base (end - 1) frame_size; offset = start && mask (pageBitsForSize frame_size); pstart = frame_base + offset in doE whenE (base_start \<noteq> base_end) $ throwError $ RangeError start (base_start + mask (pageBitsForSize frame_size));
returnOk $ InvokePageDirectory $ PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE)
odE)) \<and> (\<not> Suc 0 < length f \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> let start = b ! 0; end = b ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case e of PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | PageDirectoryCap pd (Some asid) \<Rightarrow> returnOk (pd, asid) | _ \<Rightarrow> throwError $ InvalidCapability 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 0;
(liftE $ resolve_vaddr pd start) >>=E case_option (returnOk $ InvokePageDirectory PageDirectoryNothing) (\<lambda>(frame_size, frame_base). let base_start = page_base start frame_size; base_end = page_base (end - 1) frame_size; offset = start && mask (pageBitsForSize frame_size); pstart = frame_base + offset in doE whenE (base_start \<noteq> base_end) $ throwError $ RangeError start (base_start + mask (pageBitsForSize frame_size));
returnOk $ InvokePageDirectory $ PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE)
odE))) \<and> (\<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool) \<longrightarrow> (Suc 0 < length f \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> let index = b ! 0; depth = b ! 1; (untyped, parent_slot) = f ! 0; root = fst (f ! 1) in doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
free_set <- returnOk (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1});
whenE (free_set = {}) $ throwError DeleteFirst;
free <- liftE $ select_ext (\<lambda>_. free_asid_select asid_table) free_set;
base <- returnOk (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits);
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ MakePool frame dest_slot parent_slot base
odE | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)) \<and> (\<not> Suc 0 < length f \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)))) \<and> (\<not> Suc 0 < length b \<longrightarrow> (isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool) \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)) \<and> (\<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool) \<longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation))) proof (prove)
goal (6 subgoals):
 1. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> let index = b ! 0; depth = b ! 1; (untyped, parent_slot) = f ! 0; root = fst (f ! 1) in doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
free_set <- returnOk (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1});
whenE (free_set = {}) $ throwError DeleteFirst;
free <- liftE $ select_ext (\<lambda>_. free_asid_select asid_table) free_set;
base <- returnOk (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits);
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ MakePool frame dest_slot parent_slot base
odE | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> let start = b ! 0; end = b ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case e of PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | PageDirectoryCap pd (Some asid) \<Rightarrow> returnOk (pd, asid) | _ \<Rightarrow> throwError $ InvalidCapability 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 0;
(liftE $ resolve_vaddr pd start) >>=E case_option (returnOk $ InvokePageDirectory PageDirectoryNothing) (\<lambda>(frame_size, frame_base). let base_start = page_base start frame_size; base_end = page_base (end - 1) frame_size; offset = start && mask (pageBitsForSize frame_size); pstart = frame_base + offset in doE whenE (base_start \<noteq> base_end) $ throwError $ RangeError start (base_start + mask (pageBitsForSize frame_size));
returnOk $ InvokePageDirectory $ PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE)
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> let start = b ! 0; end = b ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case e of PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | PageDirectoryCap pd (Some asid) \<Rightarrow> returnOk (pd, asid) | _ \<Rightarrow> throwError $ InvalidCapability 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 0;
(liftE $ resolve_vaddr pd start) >>=E case_option (returnOk $ InvokePageDirectory PageDirectoryNothing) (\<lambda>(frame_size, frame_base). let base_start = page_base start frame_size; base_end = page_base (end - 1) frame_size; offset = start && mask (pageBitsForSize frame_size); pstart = frame_base + offset in doE whenE (base_start \<noteq> base_end) $ throwError $ RangeError start (base_start + mask (pageBitsForSize frame_size));
returnOk $ InvokePageDirectory $ PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE)
odE)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> let index = b ! 0; depth = b ! 1; (untyped, parent_slot) = f ! 0; root = fst (f ! 1) in doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
free_set <- returnOk (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1});
whenE (free_set = {}) $ throwError DeleteFirst;
free <- liftE $ select_ext (\<lambda>_. free_asid_select asid_table) free_set;
base <- returnOk (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits);
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ MakePool frame dest_slot parent_slot base
odE | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 5. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 6. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (4 subgoals):
 1. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f\<rbrakk> \<Longrightarrow> e = ASIDControlCap \<longrightarrow> empty_fail (case f ! 0 of (untyped, parent_slot) \<Rightarrow> doE asid_table <- liftE (gets (arm_asid_table \<circ> arch_state));
y <- whenE (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
free <- liftE (select_ext (\<lambda>_. free_asid_select asid_table) (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}));
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE y <- ensure_no_children parent_slot;
returnOk p
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot parent_slot (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (4 subgoals):
 1. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (case f ! 0 of (untyped, parent_slot) \<Rightarrow> doE asid_table <- liftE (gets (arm_asid_table \<circ> arch_state));
y <- whenE (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
free <- liftE (select_ext (\<lambda>_. free_asid_select asid_table) (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}));
(p, n) <- case untyped of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE y <- ensure_no_children parent_slot;
returnOk p
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot parent_slot (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (4 subgoals):
 1. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE asid_table <- liftE (gets (arm_asid_table \<circ> arch_state));
y <- whenE (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
free <- liftE (select_ext (\<lambda>_. free_asid_select asid_table) (- dom asid_table \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}));
p <- case fst (f ! 0) of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if snd p = pageBits then doE y <- ensure_no_children (snd (f ! 0));
returnOk (fst p)
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot (snd (f ! 0)) (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (4 subgoals):
 1. \<And>rv. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE y <- whenE (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
free <- liftE (select_ext (\<lambda>_. free_asid_select rv) (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}));
p <- case fst (f ! 0) of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if snd p = pageBits then doE y <- ensure_no_children (snd (f ! 0));
returnOk (fst p)
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot (snd (f ! 0)) (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (4 subgoals):
 1. \<And>rv. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE free <- doE y <- whenE (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
liftE (select_ext (\<lambda>_. free_asid_select rv) (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}))
odE;
p <- case fst (f ! 0) of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if snd p = pageBits then doE y <- ensure_no_children (snd (f ! 0));
returnOk (fst p)
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot (snd (f ! 0)) (UCAST(7 \<rightarrow> 32) free << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (5 subgoals):
 1. \<And>rv. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE y <- whenE (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
liftE (select_ext (\<lambda>_. free_asid_select rv) (- dom rv \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}))
odE)
 2. \<And>rv rva. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE p <- case fst (f ! 0) of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if snd p = pageBits then doE y <- ensure_no_children (snd (f ! 0));
returnOk (fst p)
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot (snd (f ! 0)) (UCAST(7 \<rightarrow> 32) rva << local.asid_low_bits)))
odE)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 5. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation) proof (prove)
goal (1 subgoal):
 1. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE y <- whenE (- dom rv_ \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1} = {}) (throwError DeleteFirst);
liftE (select_ext (\<lambda>_. free_asid_select rv_) (- dom rv_ \<inter> {x. x \<le> 2 ^ local.asid_high_bits - 1}))
odE) proof (prove)
goal (4 subgoals):
 1. \<And>rv rva. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; Suc 0 < length f; e = ASIDControlCap\<rbrakk> \<Longrightarrow> empty_fail (doE p <- case fst (f ! 0) of UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if snd p = pageBits then doE y <- ensure_no_children (snd (f ! 0));
returnOk (fst p)
odE else throwError (InvalidCapability (Suc 0));
dest_slot <- lookup_slot_for_cnode_op False (fst (f ! Suc 0)) (to_bl (b ! 0)) (unat (b ! Suc 0));
y <- ensure_empty dest_slot;
returnOk (InvokeASIDControl (MakePool frame dest_slot (snd (f ! 0)) (UCAST(7 \<rightarrow> 32) rva << local.asid_low_bits)))
odE)
 2. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool); \<not> Suc 0 < length f\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)
 3. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | _ \<Rightarrow> throwError TruncatedMessage)
 4. \<lbrakk>invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; \<not> Suc 0 < length b; \<not> isPDFlushLabel (ArchInvocationLabel ARMASIDControlMakePool)\<rbrakk> \<Longrightarrow> empty_fail (case e of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length f then let (pd_cap, pd_cap_slot) = f ! 0 in case pd_cap of ArchObjectCap (PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of base));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (p \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool p;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + base \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool base) free_set;
returnOk $ InvokeASIDPool $ Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> throwError TruncatedMessage | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length b \<and> 0 < length f then let vaddr = b ! 0; rights_mask = b ! 1; attr = b ! 2; pd_cap = fst (f ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case mapped_address of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize pgsz) - 1);
whenE (kernel_base \<le> vtop) $ throwError $ InvalidArgument 0
odE | Some (asid', vaddr') \<Rightarrow> doE whenE (asid' \<noteq> asid) (throwError $ InvalidCapability 1);
whenE (vaddr' \<noteq> vaddr) (throwError $ InvalidArgument 0)
odE;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
vm_rights <- returnOk (mask_vm_rights R (data_to_rights rights_mask));
check_vp_alignment pgsz vaddr;
entries <- create_mapping_entries (addrFromPPtr p) vaddr pgsz vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ InvokePage $ PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) d entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ InvokePage $ PageUnmap e d else if isPageFlushLabel (invocation_type label) then if 1 < length b then let start = b ! 0; end = b ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some x \<Rightarrow> returnOk x;
pd <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (end \<le> start) $ throwError $ InvalidArgument 1;
page_size <- returnOk $ 1 << pageBitsForSize pgsz;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr p + start) pd asid
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageGetAddress then returnOk $ InvokePage $ PageGetAddr p else throwError IllegalOperation | PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length b \<and> 0 < length f then let vaddr = b ! 0; attr = b ! 1; pd_cap = fst (f ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
whenE (kernel_base \<le> vaddr) $ throwError $ InvalidArgument 0;
pd' <- lookup_error_on_failure False $ find_pd_for_asid asid;
whenE (pd' \<noteq> pd) $ throwError $ InvalidCapability 1;
pd_index <- returnOk (vaddr >> 20);
vaddr' <- returnOk (vaddr && ~~ mask 20);
pd_slot <- returnOk (pd + (pd_index << 2));
oldpde <- liftE $ get_master_pde pd_slot;
unlessE (oldpde = InvalidPDE) $ throwError DeleteFirst;
pde <- returnOk (PageTablePDE (addrFromPPtr p) (attribs_from_word attr \<inter> {ParityEnabled}) 0);
returnOk $ InvokePageTable $ PageTableMap (ArchObjectCap $ PageTableCap p (Some (asid, vaddr'))) d pde pd_slot
odE else throwError TruncatedMessage else throwError IllegalOperation | PageDirectoryCap x xa \<Rightarrow> throwError IllegalOperation)