theory Syscall_DR

lemma transform_intent_arch_cap_None:
  "\<lbrakk>transform_intent (invocation_type label) args = None; cap = cap.ArchObjectCap arch_cap\<rbrakk>
         \<Longrightarrow> \<lbrace>(=) s\<rbrace> Decode_A.decode_invocation label args cap_i slot cap excaps \<lbrace>\<lambda>r. \<bottom>\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>" including no_pre supply gen_invocation_type_eq[symmetric, simp] apply (clarsimp simp:Decode_A.decode_invocation_def) apply wp apply (simp add: arch_decode_invocation_def split del: if_split) apply (case_tac arch_cap) apply (case_labels "invocation_type label"; simp split del: if_split, wp?) apply (clarsimp split: if_splits | rule conjI)+ apply (case_tac "excaps ! 0") apply (clarsimp split: cap.splits | rule conjI | wp)+ apply (clarsimp split: arch_cap.splits | rule conjI | wp)+ apply ((clarsimp simp: transform_intent_def | wp) +)[2] apply (case_labels "invocation_type label"
            ; wpsimp simp: arch_decode_invocation_def split_del: if_split) apply (case_tac "excaps ! 0") apply (clarsimp simp: transform_intent_def transform_cnode_index_and_depth_def
                    split: list.split_asm) apply wp+ apply (case_labels "invocation_type label"
           ; wpsimp simp: arch_decode_invocation_def isPageFlushLabel_def split_del: if_split) apply (clarsimp simp: transform_intent_def transform_intent_page_map_def
                         split: list.split_asm ) apply wp+ apply (case_tac "excaps ! 0") apply (clarsimp simp:transform_intent_def split:list.split_asm) apply ((clarsimp simp:transform_intent_def | wp)+) apply (case_labels "invocation_type label"; simp) apply (intro conjI impI | wp)+ apply (clarsimp | rule conjI)+ apply (clarsimp simp: transform_intent_def transform_intent_page_table_map_def
                      split: list.split_asm) apply (intro conjI impI | wp)+ apply ((clarsimp simp: transform_intent_def split: list.split_asm | wp)+)[1] apply (case_labels "invocation_type label"; simp add: isPDFlushLabel_def) apply (wp)+ done

(* Proof state trace *)
proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> Decode_A.decode_invocation label args cap_i slot cap excaps \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> Decode_A.decode_invocation label args cap_i slot cap excaps \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> Decode_A.decode_invocation label args cap_i slot cap excaps \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> liftME InvokeArchObject (arch_decode_invocation label args cap_i slot arch_cap excaps) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> arch_decode_invocation label args cap_i slot arch_cap excaps \<lbrace>(\<lambda>r _. False) \<circ> InvokeArchObject\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (5 subgoals):
 1. \<And>x11 x12. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDPoolCap x11 x12\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (5 subgoals):
 1. \<And>x11 x12 x2. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign; x2 = ARMASIDPoolAssign\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if excaps \<noteq> [] then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap xa None) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of x12));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (x11 \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool x11;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + x12 \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool x12) free_set;
returnOk $ InvokeASIDPool $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + x12) x11 pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap xa (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (6 subgoals):
 1. \<And>x11 x12. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign; excaps \<noteq> []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case excaps ! 0 of (ArchObjectCap (arch_cap.PageDirectoryCap xa None), pd_cap_slot) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of x12));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (x11 \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool x11;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + x12 \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool x12) free_set;
returnOk $ InvokeASIDPool $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + x12) x11 pd_cap_slot
odE | (ArchObjectCap (arch_cap.PageDirectoryCap xa (Some a)), pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 | (ArchObjectCap _, pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 | (_, pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x11 x12. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign\<rbrakk> \<Longrightarrow> excaps = [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (6 subgoals):
 1. \<And>x11 x12 a b c. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign; excaps \<noteq> []; excaps ! 0 = (a, b, c)\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case excaps ! 0 of (ArchObjectCap (arch_cap.PageDirectoryCap xa None), pd_cap_slot) \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of x12));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (x11 \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool x11;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + x12 \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool x12) free_set;
returnOk $ InvokeASIDPool $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + x12) x11 pd_cap_slot
odE | (ArchObjectCap (arch_cap.PageDirectoryCap xa (Some a)), pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 | (ArchObjectCap _, pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 | (_, pd_cap_slot) \<Rightarrow> throwError $ InvalidCapability 1 \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x11 x12. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign\<rbrakk> \<Longrightarrow> excaps = [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (6 subgoals):
 1. \<And>x11 x12 b c x12a. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign; excaps \<noteq> []; excaps ! 0 = (ArchObjectCap x12a, b, c)\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case x12a of arch_cap.PageDirectoryCap x None \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of x12));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (x11 \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool x11;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + x12 \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool x12) free_set;
returnOk $ InvokeASIDPool $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + x12) x11 (b, c)
odE | arch_cap.PageDirectoryCap x (Some a) \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x11 x12. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign\<rbrakk> \<Longrightarrow> excaps = [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (6 subgoals):
 1. \<And>x11 x12 b c x51 x52. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign; excaps \<noteq> []; excaps ! 0 = (ArchObjectCap (arch_cap.PageDirectoryCap x51 x52), b, c)\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case x52 of None \<Rightarrow> doE asid_table <- liftE $ gets (arm_asid_table \<circ> arch_state);
pool_ptr <- returnOk (asid_table (asid_high_bits_of x12));
whenE (pool_ptr = None) $ throwError $ FailedLookup False InvalidRoot;
whenE (x11 \<noteq> the pool_ptr) $ throwError $ InvalidCapability 0;
pool <- liftE $ get_asid_pool x11;
free_set <- returnOk (- dom pool \<inter> {x. UCAST(10 \<rightarrow> 32) x + x12 \<noteq> 0});
whenE (free_set = {}) $ throwError DeleteFirst;
offset <- liftE $ select_ext (\<lambda>_. free_asid_pool_select pool x12) free_set;
returnOk $ InvokeASIDPool $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + x12) x11 (b, c)
odE | Some a \<Rightarrow> throwError $ InvalidCapability 1 \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x11 x12. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDPoolAssign) args = None; cap = ArchObjectCap (ASIDPoolCap x11 x12); arch_cap = ASIDPoolCap x11 x12; invocation_type label = ArchInvocationLabel ARMASIDPoolAssign\<rbrakk> \<Longrightarrow> excaps = [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (4 subgoals):
 1. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = ASIDControlCap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (4 subgoals):
 1. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDControlMakePool) args = None; cap = ArchObjectCap ASIDControlCap; arch_cap = ASIDControlCap; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args \<and> Suc 0 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (4 subgoals):
 1. \<And>a b c. \<lbrakk>transform_intent (ArchInvocationLabel ARMASIDControlMakePool) args = None; cap = ArchObjectCap ASIDControlCap; arch_cap = ASIDControlCap; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; excaps ! 0 = (a, b, c)\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args \<and> Suc 0 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (5 subgoals):
 1. \<And>a b c. \<lbrakk>cap = ArchObjectCap ASIDControlCap; arch_cap = ASIDControlCap; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; excaps ! 0 = (a, b, c); args = []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>a b c x21. \<lbrakk>cap = ArchObjectCap ASIDControlCap; arch_cap = ASIDControlCap; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; excaps ! 0 = (a, b, c); args = [x21]\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (3 subgoals):
 1. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = PageCap x31 x32 x33 x34 x35\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (9 subgoals):
 1. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageMap) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageMap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if 2 < length args \<and> excaps \<noteq> [] then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
case x35 of None \<Rightarrow> doE vtop <- returnOk (vaddr + (1 << pageBitsForSize x34) - 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 x33 (data_to_rights rights_mask));
check_vp_alignment x34 vaddr;
entries <- create_mapping_entries (addrFromPPtr x32) vaddr x34 vm_rights (attribs_from_word attr) pd;
ensure_safe_mapping entries;
returnOk $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap x31 x32 x33 x34 (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnmap) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnmap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (page_invocation.PageUnmap (PageCap x31 x32 x33 x34 x35) slot)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageClean_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageClean_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageCleanInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageCleanInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnify_Instruction) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnify_Instruction\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageGetAddress) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageGetAddress\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (PageGetAddr x32)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 8. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 9. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (11 subgoals):
 1. \<And>x31 x32 x33 x34 x35. \<lbrakk>cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageMap; args = []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35 x21. \<lbrakk>cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageMap; args = [x21]\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35 x21 x21a. \<lbrakk>cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageMap; args = [x21, x21a]\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnmap) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnmap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (page_invocation.PageUnmap (PageCap x31 x32 x33 x34 x35) slot)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageClean_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageClean_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageCleanInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageCleanInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 8. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnify_Instruction) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnify_Instruction\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 9. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageGetAddress) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageGetAddress\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (PageGetAddr x32)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 10. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
A total of 11 subgoals... proof (prove)
goal (8 subgoals):
 1. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnmap) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnmap\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (page_invocation.PageUnmap (PageCap x31 x32 x33 x34 x35) slot)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageClean_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageClean_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageCleanInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageCleanInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnify_Instruction) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnify_Instruction\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageGetAddress) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageGetAddress\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (PageGetAddr x32)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 8. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (8 subgoals):
 1. \<And>x31 x32 x33 x34 x35 a b c. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnmap) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnmap; excaps ! 0 = (a, b, c)\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (page_invocation.PageUnmap (PageCap x31 x32 x33 x34 x35) slot)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageClean_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageClean_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageCleanInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageCleanInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnify_Instruction) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnify_Instruction\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageGetAddress) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageGetAddress\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (PageGetAddr x32)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 8. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (7 subgoals):
 1. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageClean_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageClean_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageCleanInvalidate_Data) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageCleanInvalidate_Data\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageUnify_Instruction) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageUnify_Instruction\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> if Suc 0 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case x35 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 x34;
whenE (page_size \<le> start \<or> page_size < end) $ throwError $ InvalidArgument 0;
returnOk $ arch_invocation.InvokePage $ PageFlush (label_to_flush_type (invocation_type label)) (start + vaddr) (end + vaddr - 1) (addrFromPPtr x32 + start) pd asid
odE else throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x31 x32 x33 x34 x35. \<lbrakk>transform_intent (ArchInvocationLabel ARMPageGetAddress) args = None; cap = ArchObjectCap (PageCap x31 x32 x33 x34 x35); arch_cap = PageCap x31 x32 x33 x34 x35; invocation_type label = ArchInvocationLabel ARMPageGetAddress\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> returnOk (arch_invocation.InvokePage (PageGetAddr x32)) \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x41 x42. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (2 subgoals):
 1. \<And>x41 x42. \<lbrakk>(case invocation_type label of GenInvocationLabel InvalidInvocation \<Rightarrow> None | GenInvocationLabel UntypedRetype \<Rightarrow> map_option UntypedIntent (transform_intent_untyped_retype args) | GenInvocationLabel TCBReadRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_read_registers args) | GenInvocationLabel TCBWriteRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_write_registers args) | GenInvocationLabel TCBCopyRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_copy_registers args) | GenInvocationLabel TCBConfigure \<Rightarrow> map_option TcbIntent (transform_intent_tcb_configure args) | GenInvocationLabel TCBSetPriority \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_priority args) | GenInvocationLabel TCBSetMCPriority \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_mcpriority args) | GenInvocationLabel TCBSetSchedParams \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_sched_params args) | GenInvocationLabel TCBSetIPCBuffer \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_ipc_buffer args) | GenInvocationLabel TCBSetSpace \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_space args) | GenInvocationLabel TCBSuspend \<Rightarrow> Some (TcbIntent TcbSuspendIntent) | GenInvocationLabel TCBResume \<Rightarrow> Some (TcbIntent TcbResumeIntent) | GenInvocationLabel TCBBindNotification \<Rightarrow> Some (TcbIntent TcbBindNTFNIntent) | GenInvocationLabel TCBUnbindNotification \<Rightarrow> Some (TcbIntent TcbUnbindNTFNIntent) | GenInvocationLabel TCBSetTLSBase \<Rightarrow> Some (TcbIntent TcbSetTLSBaseIntent) | GenInvocationLabel CNodeRevoke \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeRevokeIntent args) | GenInvocationLabel CNodeDelete \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeDeleteIntent args) | GenInvocationLabel CNodeCancelBadgedSends \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeCancelBadgedSendsIntent args) | GenInvocationLabel CNodeCopy \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_copy args) | GenInvocationLabel CNodeMint \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_mint args) | GenInvocationLabel CNodeMove \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_move args) | GenInvocationLabel CNodeMutate \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_mutate args) | GenInvocationLabel CNodeRotate \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_rotate args) | GenInvocationLabel CNodeSaveCaller \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeSaveCallerIntent args) | GenInvocationLabel IRQIssueIRQHandler \<Rightarrow> map_option IrqControlIntent (transform_intent_issue_irq_handler args) | GenInvocationLabel IRQAckIRQ \<Rightarrow> Some (IrqHandlerIntent IrqHandlerAckIntent) | GenInvocationLabel IRQSetIRQHandler \<Rightarrow> Some (IrqHandlerIntent IrqHandlerSetEndpointIntent) | GenInvocationLabel IRQClearIRQHandler \<Rightarrow> Some (IrqHandlerIntent IrqHandlerClearIntent) | GenInvocationLabel DomainSetSet \<Rightarrow> map_option DomainIntent (transform_intent_domain args) | ArchInvocationLabel ARMPageTableMap \<Rightarrow> map_option PageTableIntent (transform_intent_page_table_map args) | ArchInvocationLabel ARMPageTableUnmap \<Rightarrow> Some (PageTableIntent PageTableUnmapIntent) | ArchInvocationLabel ARMPageMap \<Rightarrow> map_option PageIntent (transform_intent_page_map args) | ArchInvocationLabel ARMPageUnmap \<Rightarrow> Some (PageIntent PageUnmapIntent) | ArchInvocationLabel ARMPageClean_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageInvalidate_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageCleanInvalidate_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageUnify_Instruction \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageGetAddress \<Rightarrow> Some (PageIntent PageGetAddressIntent) | ArchInvocationLabel ARMASIDControlMakePool \<Rightarrow> map_option AsidControlIntent (transform_cnode_index_and_depth AsidControlMakePoolIntent args) | ArchInvocationLabel ARMASIDPoolAssign \<Rightarrow> Some (AsidPoolIntent AsidPoolAssignIntent) | ArchInvocationLabel ARMIRQIssueIRQHandler \<Rightarrow> map_option IrqControlIntent (arch_transform_intent_issue_irq_handler args) | ArchInvocationLabel _ \<Rightarrow> Some (PageDirectoryIntent PageDirectoryFlushIntent)) = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> (invocation_type label = ArchInvocationLabel ARMPageTableUnmap \<longrightarrow> \<lbrace>(=) s\<rbrace> doE final <- liftE (IpcCancel_A.is_final_cap (ArchObjectCap (arch_cap.PageTableCap x41 x42)));
y <- unlessE final (throwError RevokeFirst);
returnOk (arch_invocation.InvokePageTable (page_table_invocation.PageTableUnmap (ArchObjectCap (arch_cap.PageTableCap x41 x42)) slot))
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (invocation_type label \<noteq> ArchInvocationLabel ARMPageTableUnmap \<longrightarrow> (invocation_type label = ArchInvocationLabel ARMPageTableMap \<longrightarrow> \<lbrace>(=) s\<rbrace> let vaddr = args ! 0 in doE y <- whenE (\<exists>a b. x42 = Some (a, b)) (throwError (InvalidCapability 0));
(pd, asid) <- case fst (excaps ! 0) of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
y <- whenE (kernel_base \<le> vaddr) (throwError (InvalidArgument 0));
pd' <- lookup_error_on_failure False (find_pd_for_asid asid);
y <- whenE (pd' \<noteq> pd) (throwError (InvalidCapability (Suc 0)));
oldpde <- liftE (get_master_pde (pd + (vaddr >> 20 << 2)));
y <- unlessE (oldpde = InvalidPDE) (throwError DeleteFirst);
returnOk (arch_invocation.InvokePageTable (page_table_invocation.PageTableMap (ArchObjectCap (arch_cap.PageTableCap x41 (Some (asid, vaddr && ~~ mask 20)))) slot (PageTablePDE (addrFromPPtr x41) (attribs_from_word (args ! Suc 0) \<inter> {ParityEnabled}) 0) (pd + (vaddr >> 20 << 2))))
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (invocation_type label \<noteq> ArchInvocationLabel ARMPageTableMap \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>))) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> (invocation_type label = ArchInvocationLabel ARMPageTableUnmap \<longrightarrow> \<lbrace>(=) s\<rbrace> doE final <- liftE (IpcCancel_A.is_final_cap (ArchObjectCap (arch_cap.PageTableCap x41 x42)));
y <- unlessE final (throwError RevokeFirst);
returnOk (arch_invocation.InvokePageTable (page_table_invocation.PageTableUnmap (ArchObjectCap (arch_cap.PageTableCap x41 x42)) slot))
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (invocation_type label \<noteq> ArchInvocationLabel ARMPageTableUnmap \<longrightarrow> (invocation_type label = ArchInvocationLabel ARMPageTableMap \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (invocation_type label \<noteq> ArchInvocationLabel ARMPageTableMap \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)))
 2. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (27 subgoals):
 1. \<And>x41 x42 x1. \<lbrakk>cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel InvalidInvocation; x1 = InvalidInvocation\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 2. \<And>x41 x42 x1. \<lbrakk>transform_intent_untyped_retype args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel UntypedRetype; x1 = UntypedRetype\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 3. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_read_registers args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBReadRegisters; x1 = TCBReadRegisters\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 4. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_write_registers args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBWriteRegisters; x1 = TCBWriteRegisters\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 5. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_copy_registers args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBCopyRegisters; x1 = TCBCopyRegisters\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 6. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_configure args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBConfigure; x1 = TCBConfigure\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 7. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_set_priority args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBSetPriority; x1 = TCBSetPriority\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 8. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_set_mcpriority args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBSetMCPriority; x1 = TCBSetMCPriority\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 9. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_set_sched_params args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBSetSchedParams; x1 = TCBSetSchedParams\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 10. \<And>x41 x42 x1. \<lbrakk>transform_intent_tcb_set_ipc_buffer args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = GenInvocationLabel TCBSetIPCBuffer; x1 = TCBSetIPCBuffer\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
A total of 27 subgoals... proof (prove)
goal (6 subgoals):
 1. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_table_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageTableMap; x2 = ARMPageTableMap; Suc 0 < length args \<and> excaps \<noteq> []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> let vaddr = args ! 0 in doE y <- whenE (\<exists>a b. x42 = Some (a, b)) (throwError (InvalidCapability 0));
(pd, asid) <- case fst (excaps ! 0) of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
y <- whenE (kernel_base \<le> vaddr) (throwError (InvalidArgument 0));
pd' <- lookup_error_on_failure False (find_pd_for_asid asid);
y <- whenE (pd' \<noteq> pd) (throwError (InvalidCapability (Suc 0)));
oldpde <- liftE (get_master_pde (pd + (vaddr >> 20 << 2)));
y <- unlessE (oldpde = InvalidPDE) (throwError DeleteFirst);
returnOk (arch_invocation.InvokePageTable (page_table_invocation.PageTableMap (ArchObjectCap (arch_cap.PageTableCap x41 (Some (asid, vaddr && ~~ mask 20)))) slot (PageTablePDE (addrFromPPtr x41) (attribs_from_word (args ! Suc 0) \<inter> {ParityEnabled}) 0) (pd + (vaddr >> 20 << 2))))
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_table_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageTableMap; x2 = ARMPageTableMap; Suc 0 < length args \<longrightarrow> excaps = []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageMap; x2 = ARMPageMap\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 4. \<And>x41 x42 x2. \<lbrakk>transform_cnode_index_and_depth AsidControlMakePoolIntent args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; x2 = ARMASIDControlMakePool\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 5. \<And>x41 x42 x2. \<lbrakk>arch_transform_intent_issue_irq_handler args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMIRQIssueIRQHandler; x2 = ARMIRQIssueIRQHandler\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (6 subgoals):
 1. \<And>x41 x42. \<lbrakk>transform_intent_page_table_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageTableMap; Suc 0 < length args; excaps \<noteq> []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> let vaddr = args ! 0 in doE y <- whenE (\<exists>a b. x42 = Some (a, b)) (throwError (InvalidCapability 0));
(pd, asid) <- case fst (excaps ! 0) of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.PageDirectoryCap pd (Some asid)) \<Rightarrow> returnOk (pd, asid) | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1;
y <- whenE (kernel_base \<le> vaddr) (throwError (InvalidArgument 0));
pd' <- lookup_error_on_failure False (find_pd_for_asid asid);
y <- whenE (pd' \<noteq> pd) (throwError (InvalidCapability (Suc 0)));
oldpde <- liftE (get_master_pde (pd + (vaddr >> 20 << 2)));
y <- unlessE (oldpde = InvalidPDE) (throwError DeleteFirst);
returnOk (arch_invocation.InvokePageTable (page_table_invocation.PageTableMap (ArchObjectCap (arch_cap.PageTableCap x41 (Some (asid, vaddr && ~~ mask 20)))) slot (PageTablePDE (addrFromPPtr x41) (attribs_from_word (args ! Suc 0) \<inter> {ParityEnabled}) 0) (pd + (vaddr >> 20 << 2))))
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_table_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageTableMap; x2 = ARMPageTableMap; Suc 0 < length args \<longrightarrow> excaps = []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageMap; x2 = ARMPageMap\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 4. \<And>x41 x42 x2. \<lbrakk>transform_cnode_index_and_depth AsidControlMakePoolIntent args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; x2 = ARMASIDControlMakePool\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 5. \<And>x41 x42 x2. \<lbrakk>arch_transform_intent_issue_irq_handler args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMIRQIssueIRQHandler; x2 = ARMIRQIssueIRQHandler\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 6. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (5 subgoals):
 1. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_table_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageTableMap; x2 = ARMPageTableMap; Suc 0 < length args \<longrightarrow> excaps = []\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x41 x42 x2. \<lbrakk>transform_intent_page_map args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMPageMap; x2 = ARMPageMap\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 3. \<And>x41 x42 x2. \<lbrakk>transform_cnode_index_and_depth AsidControlMakePoolIntent args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMASIDControlMakePool; x2 = ARMASIDControlMakePool\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 4. \<And>x41 x42 x2. \<lbrakk>arch_transform_intent_issue_irq_handler args = None; cap = ArchObjectCap (arch_cap.PageTableCap x41 x42); arch_cap = arch_cap.PageTableCap x41 x42; invocation_type label = ArchInvocationLabel ARMIRQIssueIRQHandler; x2 = ARMIRQIssueIRQHandler\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<and> excaps \<noteq> [] \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> ((Suc 0 < length args \<longrightarrow> excaps = []) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)
 5. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<And>x51 x52. \<lbrakk>transform_intent (invocation_type label) args = None; cap = ArchObjectCap arch_cap; arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> case arch_cap of ASIDPoolCap p base \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDPoolAssign then if 0 < length excaps then let (pd_cap, pd_cap_slot) = excaps ! 0 in case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap x 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 $ asid_pool_invocation.Assign (UCAST(10 \<rightarrow> 32) offset + base) p pd_cap_slot
odE | ArchObjectCap (arch_cap.PageDirectoryCap x (Some a)) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap _ \<Rightarrow> throwError $ InvalidCapability 1 | _ \<Rightarrow> throwError $ InvalidCapability 1 else throwError TruncatedMessage else throwError IllegalOperation | ASIDControlCap \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMASIDControlMakePool then if 1 < length args \<and> 1 < length excaps then let index = args ! 0; depth = args ! 1; (untyped, parent_slot) = excaps ! 0; root = fst (excaps ! 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 cap.UntypedCap True p n f \<Rightarrow> throwError $ InvalidCapability 1 | cap.UntypedCap False p n f \<Rightarrow> returnOk (p, n) | _ \<Rightarrow> throwError $ InvalidCapability 1;
frame <- if n = pageBits then doE CSpace_A.ensure_no_children parent_slot;
returnOk p
odE else throwError $ InvalidCapability 1;
dest_slot <- lookup_target_slot root (to_bl index) (unat depth);
CSpaceAcc_A.ensure_empty dest_slot;
returnOk $ InvokeASIDControl $ asid_control_invocation.MakePool frame dest_slot parent_slot base
odE else throwError TruncatedMessage else throwError IllegalOperation | PageCap dev p R pgsz mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageMap then if 2 < length args \<and> 0 < length excaps then let vaddr = args ! 0; rights_mask = args ! 1; attr = args ! 2; pd_cap = fst (excaps ! 0) in doE (pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePage $ page_invocation.PageMap asid (ArchObjectCap $ PageCap dev p R pgsz (Some (asid, vaddr))) slot entries
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageUnmap then returnOk $ arch_invocation.InvokePage $ page_invocation.PageUnmap arch_cap slot else if isPageFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE (asid, vaddr) <- case mapped_address of None \<Rightarrow> throwError IllegalOperation | Some a \<Rightarrow> returnOk a;
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 $ arch_invocation.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 $ arch_invocation.InvokePage $ PageGetAddr p else throwError IllegalOperation | arch_cap.PageTableCap p mapped_address \<Rightarrow> if invocation_type label = ArchInvocationLabel ARMPageTableMap then if 1 < length args \<and> 0 < length excaps then let vaddr = args ! 0; attr = args ! 1; pd_cap = fst (excaps ! 0) in doE whenE (mapped_address \<noteq> None) $ throwError $ InvalidCapability 0;
(pd, asid) <- case pd_cap of ArchObjectCap (arch_cap.PageDirectoryCap pd None) \<Rightarrow> throwError $ InvalidCapability 1 | ArchObjectCap (arch_cap.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 $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableMap (ArchObjectCap $ arch_cap.PageTableCap p (Some (asid, vaddr'))) slot pde pd_slot
odE else throwError TruncatedMessage else if invocation_type label = ArchInvocationLabel ARMPageTableUnmap then doE final <- liftE $ IpcCancel_A.is_final_cap (ArchObjectCap arch_cap);
unlessE final $ throwError RevokeFirst;
returnOk $ arch_invocation.InvokePageTable $ page_table_invocation.PageTableUnmap (ArchObjectCap arch_cap) slot
odE else throwError IllegalOperation | arch_cap.PageDirectoryCap x xa \<Rightarrow> if isPDFlushLabel (invocation_type label) then if 1 < length args then let start = args ! 0; end = args ! 1 in doE whenE (end \<le> start) $ throwError $ InvalidArgument 1;
whenE (kernel_base \<le> start \<or> kernel_base < end) $ throwError IllegalOperation;
(pd, asid) <- case arch_cap of arch_cap.PageDirectoryCap pd None \<Rightarrow> throwError $ InvalidCapability 0 | arch_cap.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;
frame_info <- liftE $ resolve_vaddr pd start;
case frame_info of None \<Rightarrow> returnOk $ arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing | Some (frame_size, frame_base) \<Rightarrow> 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 $ arch_invocation.InvokePageDirectory $ page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) pstart pd asid
odE
odE else throwError TruncatedMessage else throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace> proof (prove)
goal (1 subgoal):
 1. \<And>x51 x52. \<lbrakk>(case invocation_type label of GenInvocationLabel InvalidInvocation \<Rightarrow> None | GenInvocationLabel UntypedRetype \<Rightarrow> map_option UntypedIntent (transform_intent_untyped_retype args) | GenInvocationLabel TCBReadRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_read_registers args) | GenInvocationLabel TCBWriteRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_write_registers args) | GenInvocationLabel TCBCopyRegisters \<Rightarrow> map_option TcbIntent (transform_intent_tcb_copy_registers args) | GenInvocationLabel TCBConfigure \<Rightarrow> map_option TcbIntent (transform_intent_tcb_configure args) | GenInvocationLabel TCBSetPriority \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_priority args) | GenInvocationLabel TCBSetMCPriority \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_mcpriority args) | GenInvocationLabel TCBSetSchedParams \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_sched_params args) | GenInvocationLabel TCBSetIPCBuffer \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_ipc_buffer args) | GenInvocationLabel TCBSetSpace \<Rightarrow> map_option TcbIntent (transform_intent_tcb_set_space args) | GenInvocationLabel TCBSuspend \<Rightarrow> Some (TcbIntent TcbSuspendIntent) | GenInvocationLabel TCBResume \<Rightarrow> Some (TcbIntent TcbResumeIntent) | GenInvocationLabel TCBBindNotification \<Rightarrow> Some (TcbIntent TcbBindNTFNIntent) | GenInvocationLabel TCBUnbindNotification \<Rightarrow> Some (TcbIntent TcbUnbindNTFNIntent) | GenInvocationLabel TCBSetTLSBase \<Rightarrow> Some (TcbIntent TcbSetTLSBaseIntent) | GenInvocationLabel CNodeRevoke \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeRevokeIntent args) | GenInvocationLabel CNodeDelete \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeDeleteIntent args) | GenInvocationLabel CNodeCancelBadgedSends \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeCancelBadgedSendsIntent args) | GenInvocationLabel CNodeCopy \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_copy args) | GenInvocationLabel CNodeMint \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_mint args) | GenInvocationLabel CNodeMove \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_move args) | GenInvocationLabel CNodeMutate \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_mutate args) | GenInvocationLabel CNodeRotate \<Rightarrow> map_option CNodeIntent (transform_intent_cnode_rotate args) | GenInvocationLabel CNodeSaveCaller \<Rightarrow> map_option CNodeIntent (transform_cnode_index_and_depth CNodeSaveCallerIntent args) | GenInvocationLabel IRQIssueIRQHandler \<Rightarrow> map_option IrqControlIntent (transform_intent_issue_irq_handler args) | GenInvocationLabel IRQAckIRQ \<Rightarrow> Some (IrqHandlerIntent IrqHandlerAckIntent) | GenInvocationLabel IRQSetIRQHandler \<Rightarrow> Some (IrqHandlerIntent IrqHandlerSetEndpointIntent) | GenInvocationLabel IRQClearIRQHandler \<Rightarrow> Some (IrqHandlerIntent IrqHandlerClearIntent) | GenInvocationLabel DomainSetSet \<Rightarrow> map_option DomainIntent (transform_intent_domain args) | ArchInvocationLabel ARMPageTableMap \<Rightarrow> map_option PageTableIntent (transform_intent_page_table_map args) | ArchInvocationLabel ARMPageTableUnmap \<Rightarrow> Some (PageTableIntent PageTableUnmapIntent) | ArchInvocationLabel ARMPageMap \<Rightarrow> map_option PageIntent (transform_intent_page_map args) | ArchInvocationLabel ARMPageUnmap \<Rightarrow> Some (PageIntent PageUnmapIntent) | ArchInvocationLabel ARMPageClean_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageInvalidate_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageCleanInvalidate_Data \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageUnify_Instruction \<Rightarrow> Some (PageIntent PageFlushCachesIntent) | ArchInvocationLabel ARMPageGetAddress \<Rightarrow> Some (PageIntent PageGetAddressIntent) | ArchInvocationLabel ARMASIDControlMakePool \<Rightarrow> map_option AsidControlIntent (transform_cnode_index_and_depth AsidControlMakePoolIntent args) | ArchInvocationLabel ARMASIDPoolAssign \<Rightarrow> Some (AsidPoolIntent AsidPoolAssignIntent) | ArchInvocationLabel ARMIRQIssueIRQHandler \<Rightarrow> map_option IrqControlIntent (arch_transform_intent_issue_irq_handler args) | ArchInvocationLabel _ \<Rightarrow> Some (PageDirectoryIntent PageDirectoryFlushIntent)) = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52\<rbrakk> \<Longrightarrow> (Suc 0 < length args \<longrightarrow> (isPDFlushLabel (invocation_type label) \<longrightarrow> \<lbrace>(=) s\<rbrace> let start = args ! 0; end = args ! Suc 0 in doE y <- whenE (end \<le> start) (throwError (InvalidArgument (Suc 0)));
y <- whenE (kernel_base \<le> start \<or> kernel_base < end) (throwError IllegalOperation);
(pd, asid) <- case x52 of None \<Rightarrow> throwError (InvalidCapability 0) | Some asid \<Rightarrow> returnOk (x51, asid);
pd' <- lookup_error_on_failure False (find_pd_for_asid asid);
y <- whenE (pd' \<noteq> pd) (throwError (InvalidCapability 0));
liftE (resolve_vaddr pd start) >>=E case_option (returnOk (arch_invocation.InvokePageDirectory page_directory_invocation.PageDirectoryNothing)) (\<lambda>(frame_size, frame_base). let base_start = page_base start frame_size in doE y <- whenE (base_start \<noteq> page_base (end - 1) frame_size) (throwError (RangeError start (base_start + mask (pageBitsForSize frame_size))));
returnOk (arch_invocation.InvokePageDirectory (page_directory_invocation.PageDirectoryFlush (label_to_flush_type (invocation_type label)) start (end - 1) (frame_base + (start && mask (pageBitsForSize frame_size))) pd asid))
odE)
odE \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (\<not> isPDFlushLabel (invocation_type label) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)) \<and> (\<not> Suc 0 < length args \<longrightarrow> (isPDFlushLabel (invocation_type label) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError TruncatedMessage \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>) \<and> (\<not> isPDFlushLabel (invocation_type label) \<longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>)) proof (prove)
goal (26 subgoals):
 1. \<And>x51 x52 x1. \<lbrakk>cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel InvalidInvocation; x1 = InvalidInvocation\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 2. \<And>x51 x52 x1. \<lbrakk>transform_intent_untyped_retype args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel UntypedRetype; x1 = UntypedRetype\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 3. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_read_registers args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBReadRegisters; x1 = TCBReadRegisters\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 4. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_write_registers args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBWriteRegisters; x1 = TCBWriteRegisters\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 5. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_copy_registers args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBCopyRegisters; x1 = TCBCopyRegisters\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 6. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_configure args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBConfigure; x1 = TCBConfigure\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 7. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_set_priority args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBSetPriority; x1 = TCBSetPriority\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 8. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_set_mcpriority args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBSetMCPriority; x1 = TCBSetMCPriority\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 9. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_set_sched_params args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBSetSchedParams; x1 = TCBSetSchedParams\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
 10. \<And>x51 x52 x1. \<lbrakk>transform_intent_tcb_set_ipc_buffer args = None; cap = ArchObjectCap (arch_cap.PageDirectoryCap x51 x52); arch_cap = arch_cap.PageDirectoryCap x51 x52; invocation_type label = GenInvocationLabel TCBSetIPCBuffer; x1 = TCBSetIPCBuffer\<rbrakk> \<Longrightarrow> \<lbrace>(=) s\<rbrace> throwError IllegalOperation \<lbrace>\<lambda>r _. False\<rbrace>, \<lbrace>\<lambda>x. (=) s\<rbrace>
A total of 26 subgoals... proof (prove)
goal:
No subgoals!