(* * Copyright 2014, General Dynamics C4 Systems * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(GD_GPL) *) (* CSpace invariants *) theory ArchCSpaceInvPre_AI imports "../CSpaceInvPre_AI" begin context Arch begin global_naming ARM lemma aobj_ref_acap_rights_update[simp]: "aobj_ref (acap_rights_update f x) = aobj_ref x" by (cases x; simp add: acap_rights_update_def) lemma arch_obj_size_acap_rights_update[simp]: "arch_obj_size (acap_rights_update f x) = arch_obj_size x" by (cases x; simp add: acap_rights_update_def) lemma valid_arch_cap_acap_rights_update[intro]: "valid_arch_cap x s \ valid_arch_cap (acap_rights_update f x) s" by (cases x; simp add: acap_rights_update_def valid_arch_cap_def) definition cap_master_arch_cap where "cap_master_arch_cap acap \ (case acap of arch_cap.PageCap dev ref rghts sz mapdata \ arch_cap.PageCap dev ref UNIV sz None | arch_cap.ASIDPoolCap pool asid \ arch_cap.ASIDPoolCap pool 0 | arch_cap.PageTableCap ptr data \ arch_cap.PageTableCap ptr None | arch_cap.PageDirectoryCap ptr data \ arch_cap.PageDirectoryCap ptr None | _ \ acap)" lemma cap_master_arch_cap_eqDs1: "cap_master_arch_cap cap = (arch_cap.PageCap dev ref rghts sz mapdata) \ rghts = UNIV \ mapdata = None \ (\rghts mapdata. cap = (arch_cap.PageCap dev ref rghts sz mapdata))" "cap_master_arch_cap cap = arch_cap.ASIDControlCap \ cap = arch_cap.ASIDControlCap" "cap_master_arch_cap cap = (arch_cap.ASIDPoolCap pool asid) \ asid = 0 \ (\asid. cap = (arch_cap.ASIDPoolCap pool asid))" "cap_master_arch_cap cap = (arch_cap.PageTableCap ptr data) \ data = None \ (\data. cap = (arch_cap.PageTableCap ptr data))" "cap_master_arch_cap cap = (arch_cap.PageDirectoryCap ptr data2) \ data2 = None \ (\data2. cap = (arch_cap.PageDirectoryCap ptr data2))" by (clarsimp simp: cap_master_arch_cap_def split: arch_cap.split_asm)+ lemma cap_master_arch_inv: "cap_master_arch_cap (cap_master_arch_cap ac) = cap_master_arch_cap ac" by (cases ac; simp add: cap_master_arch_cap_def) definition "is_ap_cap cap \ case cap of (ArchObjectCap (arch_cap.ASIDPoolCap ap asid)) \ True | _ \ False" lemmas is_ap_cap_simps [simp] = is_ap_cap_def [split_simps cap.split arch_cap.split] definition "reachable_pg_cap cap \ \s. is_pg_cap cap \ (\vref. vs_cap_ref cap = Some vref \ (vref \ obj_ref_of cap) s)" definition replaceable_final_arch_cap :: "'z::state_ext state \ cslot_ptr \ cap \ cap \ bool" where "replaceable_final_arch_cap s sl newcap \ \cap. (\vref. vs_cap_ref cap = Some vref \ (vs_cap_ref newcap = Some vref \ obj_refs newcap = obj_refs cap) \ (\oref \ obj_refs cap. \ (vref \ oref) s)) \ no_cap_to_obj_with_diff_ref newcap {sl} s \ ((is_pt_cap newcap \ is_pd_cap newcap) \ cap_asid newcap = None \ (\ r \ obj_refs newcap. obj_at (empty_table (set (second_level_tables (arch_state s)))) r s)) \ ((is_pt_cap newcap \ is_pd_cap newcap) \ ((is_pt_cap newcap \ is_pt_cap cap \ is_pd_cap newcap \ is_pd_cap cap) \ (cap_asid newcap = None \ cap_asid cap = None) \ obj_refs cap \ obj_refs newcap) \ (\sl'. cte_wp_at (\cap'. obj_refs cap' = obj_refs newcap \ (is_pd_cap newcap \ is_pd_cap cap' \ is_pt_cap newcap \ is_pt_cap cap') \ (cap_asid newcap = None \ cap_asid cap' = None)) sl' s \ sl' = sl)) \ \is_ap_cap newcap" definition replaceable_non_final_arch_cap :: "'z::state_ext state \ cslot_ptr \ cap \ cap \ bool" where "replaceable_non_final_arch_cap s sl newcap \ \cap. \ reachable_pg_cap cap s" declare replaceable_final_arch_cap_def[simp] replaceable_non_final_arch_cap_def[simp] lemma unique_table_refsD: "\ unique_table_refs cps; cps p = Some cap; cps p' = Some cap'; obj_refs cap = obj_refs cap'\ \ table_cap_ref cap = table_cap_ref cap'" unfolding unique_table_refs_def by blast lemma table_cap_ref_vs_cap_ref_Some: "table_cap_ref x = Some y \ vs_cap_ref x = Some y" by (clarsimp simp: table_cap_ref_def vs_cap_ref_def split: cap.splits arch_cap.splits) lemma set_cap_valid_vs_lookup: "\\s. valid_vs_lookup s \ (\vref cap'. cte_wp_at ((=) cap') ptr s \ vs_cap_ref cap' = Some vref \ (vs_cap_ref cap = Some vref \ obj_refs cap = obj_refs cap') \ (\ is_final_cap' cap' s \ \ reachable_pg_cap cap' s) \ (\oref. oref \ obj_refs cap' \ \ (vref \ oref) s)) \ unique_table_refs (caps_of_state s)\ set_cap cap ptr \\rv. valid_vs_lookup\" apply (simp add: valid_vs_lookup_def del: split_paired_All split_paired_Ex) apply (rule hoare_pre) apply (wp hoare_vcg_all_lift hoare_convert_imp[OF set_cap.vs_lookup_pages] hoare_vcg_disj_lift) apply (elim conjE allEI, rule impI, drule(1) mp) apply (simp only: simp_thms) apply (elim exE conjE) apply (case_tac "p' = ptr") apply (clarsimp simp: cte_wp_at_caps_of_state) apply (elim disjE impCE) apply fastforce apply clarsimp apply (drule (1) not_final_another_caps) apply (erule obj_ref_is_gen_obj_ref) apply (simp, elim exEI, clarsimp simp: gen_obj_refs_eq) apply (rule conjI, clarsimp) apply (drule(3) unique_table_refsD) apply (clarsimp simp: reachable_pg_cap_def is_pg_cap_def) apply (case_tac cap, simp_all add: vs_cap_ref_simps)[1] apply (rename_tac arch_cap) apply (case_tac arch_cap, simp_all add: vs_cap_ref_simps table_cap_ref_simps)[1] apply (clarsimp dest!: table_cap_ref_vs_cap_ref_Some) apply fastforce apply (clarsimp dest!: table_cap_ref_vs_cap_ref_Some)+ apply (auto simp: cte_wp_at_caps_of_state)[1] done crunch arch[wp]: set_cap "\s. P (arch_state s)" (simp: split_def) lemma set_cap_valid_table_caps: "\\s. valid_table_caps s \ ((is_pt_cap cap \ is_pd_cap cap) \ cap_asid cap = None \ (\r \ obj_refs cap. obj_at (empty_table (set (second_level_tables (arch_state s)))) r s))\ set_cap cap ptr \\rv. valid_table_caps\" apply (simp add: valid_table_caps_def) apply (wp hoare_vcg_all_lift hoare_vcg_disj_lift hoare_convert_imp[OF set_cap_caps_of_state] hoare_use_eq[OF set_cap_arch set_cap_obj_at_impossible]) apply (simp add: empty_table_caps_of) done lemma set_cap_unique_table_caps: "\\s. unique_table_caps (caps_of_state s) \ ((is_pt_cap cap \ is_pd_cap cap) \ (\oldcap. caps_of_state s ptr = Some oldcap \ (is_pt_cap cap \ is_pt_cap oldcap \ is_pd_cap cap \ is_pd_cap oldcap) \ (cap_asid cap = None \ cap_asid oldcap = None) \ obj_refs oldcap \ obj_refs cap) \ (\ptr'. cte_wp_at (\cap'. obj_refs cap' = obj_refs cap \ (is_pd_cap cap \ is_pd_cap cap' \ is_pt_cap cap \ is_pt_cap cap') \ (cap_asid cap = None \ cap_asid cap' = None)) ptr' s \ ptr' = ptr))\ set_cap cap ptr \\rv s. unique_table_caps (caps_of_state s)\" apply wp apply (simp only: unique_table_caps_def) apply (elim conjE) apply (erule impCE) apply clarsimp apply (erule impCE) prefer 2 apply (simp del: imp_disjL) apply (thin_tac "\a b. P a b" for P) apply (auto simp: cte_wp_at_caps_of_state)[1] apply (clarsimp simp del: imp_disjL del: allI) apply (case_tac "cap_asid cap \ None") apply (clarsimp del: allI) apply (elim allEI | rule impI)+ apply (auto simp: is_pt_cap_def is_pd_cap_def)[1] apply (elim allEI) apply (intro conjI impI) apply (elim allEI) apply (auto simp: is_pt_cap_def is_pd_cap_def)[1] apply (elim allEI) apply (auto simp: is_pt_cap_def is_pd_cap_def)[1] done lemma set_cap_unique_table_refs: "\\s. unique_table_refs (caps_of_state s) \ no_cap_to_obj_with_diff_ref cap {ptr} s\ set_cap cap ptr \\rv s. unique_table_refs (caps_of_state s)\" apply wp apply clarsimp apply (simp add: unique_table_refs_def split del: if_split del: split_paired_All) apply (erule allEI, erule allEI) apply (clarsimp split del: if_split) apply (clarsimp simp: no_cap_to_obj_with_diff_ref_def cte_wp_at_caps_of_state split: if_split_asm) done lemma set_cap_valid_arch_caps: "\\s. valid_arch_caps s \ (\vref cap'. cte_wp_at ((=) cap') ptr s \ vs_cap_ref cap' = Some vref \ (vs_cap_ref cap = Some vref \ obj_refs cap = obj_refs cap') \ (\ is_final_cap' cap' s \ \ reachable_pg_cap cap' s) \ (\oref \ obj_refs cap'. \ (vref \ oref) s)) \ no_cap_to_obj_with_diff_ref cap {ptr} s \ ((is_pt_cap cap \ is_pd_cap cap) \ cap_asid cap = None \ (\r \ obj_refs cap. obj_at (empty_table (set (second_level_tables (arch_state s)))) r s)) \ ((is_pt_cap cap \ is_pd_cap cap) \ (\oldcap. caps_of_state s ptr = Some oldcap \ (is_pt_cap cap \ is_pt_cap oldcap \ is_pd_cap cap \ is_pd_cap oldcap) \ (cap_asid cap = None \ cap_asid oldcap = None) \ obj_refs oldcap \ obj_refs cap) \ (\ptr'. cte_wp_at (\cap'. obj_refs cap' = obj_refs cap \ (is_pd_cap cap \ is_pd_cap cap' \ is_pt_cap cap \ is_pt_cap cap') \ (cap_asid cap = None \ cap_asid cap' = None)) ptr' s \ ptr' = ptr))\ set_cap cap ptr \\rv. valid_arch_caps\" apply (simp add: valid_arch_caps_def pred_conj_def) apply (wp set_cap_valid_vs_lookup set_cap_valid_table_caps set_cap_unique_table_caps set_cap_unique_table_refs) by simp_all blast+ lemma valid_table_capsD: "\ cte_wp_at ((=) cap) ptr s; valid_table_caps s; is_pt_cap cap | is_pd_cap cap; cap_asid cap = None \ \ \r \ obj_refs cap. obj_at (empty_table (set (second_level_tables (arch_state s)))) r s" apply (clarsimp simp: cte_wp_at_caps_of_state valid_table_caps_def) apply (cases ptr, fastforce) done lemma unique_table_capsD: "\ unique_table_caps cps; cps ptr = Some cap; cps ptr' = Some cap'; obj_refs cap = obj_refs cap'; cap_asid cap = None \ cap_asid cap' = None; (is_pd_cap cap \ is_pd_cap cap') \ (is_pt_cap cap \ is_pt_cap cap') \ \ ptr = ptr'" unfolding unique_table_caps_def by blast lemma set_cap_cap_refs_in_kernel_window[wp]: "\cap_refs_in_kernel_window and (\s. \ref \ cap_range cap. arm_kernel_vspace (arch_state s) ref = ArmVSpaceKernelWindow)\ set_cap cap p \\rv. cap_refs_in_kernel_window\" apply (simp add: cap_refs_in_kernel_window_def valid_refs_def2 pred_conj_def) apply (rule hoare_lift_Pf2[where f=arch_state]) apply wp apply (fastforce elim!: ranE split: if_split_asm) apply wp done lemma cap_refs_in_kernel_windowD: "\ caps_of_state s ptr = Some cap; cap_refs_in_kernel_window s \ \ \ref \ cap_range cap. arm_kernel_vspace (arch_state s) ref = ArmVSpaceKernelWindow" apply (clarsimp simp: cap_refs_in_kernel_window_def valid_refs_def cte_wp_at_caps_of_state) apply (cases ptr, fastforce) done lemma valid_cap_imp_valid_vm_rights: "valid_cap (cap.ArchObjectCap (PageCap dev mw rs sz m)) s \ rs \ valid_vm_rights" by (simp add: valid_cap_def valid_vm_rights_def) lemma acap_rights_update_idem [simp]: "acap_rights_update R (acap_rights_update R' cap) = acap_rights_update R cap" by (simp add: acap_rights_update_def split: arch_cap.splits) lemma cap_master_arch_cap_rights [simp]: "cap_master_arch_cap (acap_rights_update R cap) = cap_master_arch_cap cap" by (simp add: cap_master_arch_cap_def acap_rights_update_def split: arch_cap.splits) lemma acap_rights_update_id [intro!, simp]: "valid_arch_cap ac s \ acap_rights_update (acap_rights ac) ac = ac" unfolding acap_rights_update_def acap_rights_def valid_arch_cap_def by (cases ac; simp) lemma obj_ref_none_no_asid: "{} = obj_refs new_cap \ None = table_cap_ref new_cap" "obj_refs new_cap = {} \ table_cap_ref new_cap = None" by (simp add: table_cap_ref_def split: cap.split arch_cap.split)+ lemma set_cap_hyp_refs_of [wp]: "\\s. P (state_hyp_refs_of s)\ set_cap cp p \\rv s. P (state_hyp_refs_of s)\" apply (simp add: set_cap_def set_object_def split_def) apply (wp get_object_wp | wpc)+ apply (auto elim!: rsubst[where P=P] simp: ARM.state_hyp_refs_of_def obj_at_def intro!: ext split: if_split_asm) done lemma state_hyp_refs_of_revokable[simp]: "state_hyp_refs_of (s \ is_original_cap := m \) = state_hyp_refs_of s" by (simp add: state_hyp_refs_of_def) end end