(* * Copyright 2014, NICTA * * 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(NICTA_GPL) *) (* * Proofs regarding the State Translation. *) theory StateTranslationProofs_DR imports StateTranslation_D begin context begin interpretation Arch . (*FIXME: arch_split*) declare transform_current_domain_def [simp] lemma asid_high_bits [simp]: "Types_D.asid_high_bits = asid_high_bits" by (simp add:Types_D.asid_high_bits_def asid_high_bits_def) lemma asid_low_bits [simp]: "Types_D.asid_low_bits = asid_low_bits" by (simp add:Types_D.asid_low_bits_def asid_low_bits_def) lemma asid_bits [simp]: "Types_D.asid_bits = asid_bits" by (simp add:Types_D.asid_bits_def asid_bits_def) lemma get_obj_simps [simp]: "get_obj (s\cur_thread := a\) = get_obj s" apply (rule ext) apply (clarsimp simp: get_obj_def) done lemma transform_objects_simps [simp]: "transform_objects (s\cur_thread := a\) = transform_objects s" apply (rule ext) apply (clarsimp simp: transform_objects_def transform_object_def) done lemma transform_cdt_simps [simp]: "transform_cdt (s\cur_thread := a\) = transform_cdt s" apply (rule ext)+ apply (clarsimp simp: transform_cdt_def split_def) done (* Aggressive simp rules, using explictly *) abbreviation "update_machine ms s \ machine_state_update (\_. ms) s" abbreviation "update_kheap kh s \ kheap_update (\_. kh) s" abbreviation "tcb_set_mi tcb msg \ tcb \tcb_context := (tcb_context tcb)(msg_info_register := msg)\" abbreviation "update_tcb_cxt_badge msg tcb\ tcb \tcb_context := (tcb_context tcb)(badge_register := msg)\" abbreviation "update_tcb_state state tcb \ tcb \tcb_state := state\" abbreviation "update_tcb_boundntfn ntfn_opt tcb \ tcb \tcb_bound_notification := ntfn_opt\" abbreviation "dupdate_cdl_object ptr obj s \ cdl_objects_update (\_. cdl_objects s(ptr \ obj)) s" abbreviation "dupdate_tcb_intent intent tcb\ tcb \cdl_tcb_intent := intent\" lemma update_kheap_triv[simp]: "kheap s y = Some obj\ update_kheap ((kheap s)(y \ obj)) s = s" apply (case_tac s,clarsimp) apply (rule ext,clarsimp) done lemma msg_registers_lt_msg_max_length [simp]: "length msg_registers < msg_max_length" by (simp add: msg_registers_def msgRegisters_def upto_enum_def fromEnum_def enum_register msg_max_length_def) lemma get_tcb_mrs_update_state : "get_tcb_mrs ms (tcb_state_update f tcb) = get_tcb_mrs ms tcb" by (clarsimp simp:get_tcb_mrs_def Suc_le_eq get_tcb_message_info_def get_ipc_buffer_words_def) lemma msg_info_badge_register_no_overlap: "badge_register \ msg_info_register" by (clarsimp simp:badge_register_def msg_info_register_def ARM.badgeRegister_def ARM.msgInfoRegister_def) lemma badge_cap_register_overlap: "badge_register = cap_register" by (clarsimp simp:badge_register_def cap_register_def ARM.badgeRegister_def ARM.capRegister_def) lemma cap_msg_info_register_no_overlap: "cap_register \ msg_info_register" by (clarsimp simp:msg_info_register_def cap_register_def ARM.msgInfoRegister_def ARM.capRegister_def) lemmas register_overlap_check = msg_info_badge_register_no_overlap cap_msg_info_register_no_overlap badge_cap_register_overlap lemma transform_full_intent_cong: "\ms = ms'; ptr = ptr'; arch_tcb_context_get (tcb_arch tcb) = arch_tcb_context_get (tcb_arch tcb'); tcb_ipc_buffer tcb = tcb_ipc_buffer tcb'; tcb_ipcframe tcb = tcb_ipcframe tcb'\ \ transform_full_intent ms ptr tcb = transform_full_intent ms' ptr' tcb'" by (simp add: transform_full_intent_def get_tcb_message_info_def get_tcb_mrs_def Suc_le_eq get_ipc_buffer_words_def) lemma caps_of_state_eq_lift: "\cap. cte_wp_at ((=) cap) p s = cte_wp_at ((=) cap) p s' \ caps_of_state s p = caps_of_state s' p" apply (simp add:cte_wp_at_def caps_of_state_def) done lemma caps_of_state_irrelavent_simp: "ref \ epptr \ caps_of_state (update_kheap (kh(epptr \ obj)) s) (ref, cref) = caps_of_state (update_kheap kh s) (ref, cref)" apply (rule caps_of_state_eq_lift) apply (clarsimp simp: cte_wp_at_cases) done (* This doesn't satisfy the obvious transformation into capDL because of pagetables etc. *) fun caps_of_object :: "kernel_object \ (bool list \ cap)" where "caps_of_object (Structures_A.CNode sz c) = (if well_formed_cnode_n sz c then c else Map.empty)" | "caps_of_object (Structures_A.TCB t) = (\n. option_map (\(f, _). f t) (tcb_cap_cases n))" | "caps_of_object _ = Map.empty" lemma caps_of_state_def2: "caps_of_state s = (\ptr. case (option_map caps_of_object (kheap s (fst ptr))) of None \ None | Some f \ f (snd ptr))" unfolding caps_of_state_def get_cap_def tcb_cnode_map_def apply (rule ext) apply (clarsimp simp add: split_def get_object_def bind_def gets_def get_def return_def assert_def fail_def) apply (case_tac y, simp_all add: bind_def assert_def return_def assert_opt_def fail_def tcb_cap_cases_def split: option.splits) done lemma caps_of_state_update_same_caps: assumes kh: "kh ptr = Some ko" and coo: "caps_of_object ko' = caps_of_object ko" shows "caps_of_state (update_kheap (kh(ptr \ ko')) s) = caps_of_state (update_kheap kh s)" using kh coo apply - apply (rule ext) apply (clarsimp simp add: caps_of_state_def2) done lemma caps_of_state_update_tcb: "\ kh thread = Some (TCB tcb); (tcb_ctable tcb) = (tcb_ctable (f tcb)); (tcb_vtable tcb) = (tcb_vtable (f tcb)); (tcb_reply tcb) = (tcb_reply (f tcb)); (tcb_caller tcb) = (tcb_caller (f tcb)); (tcb_ipcframe tcb) = (tcb_ipcframe (f tcb)) \ \ caps_of_state (update_kheap (kh(thread \ (TCB (f tcb)))) s) = caps_of_state (update_kheap kh s)" apply (erule caps_of_state_update_same_caps) apply (rule ext) apply (simp add: tcb_cap_cases_def split: if_split) done lemmas caps_of_state_upds = caps_of_state_update_tcb caps_of_state_update_same_caps lemma transform_cdt_kheap_update [simp]: "transform_cdt (kheap_update f s) = transform_cdt s" by (clarsimp simp: transform_cdt_def) lemma transform_cdt_update_machine [simp]: "transform_cdt (update_machine ms s) = transform_cdt s " by (clarsimp simp: transform_cdt_def) lemma transform_cdt_update_original_cap [simp]: "transform_cdt (b\is_original_cap := x\) = transform_cdt b" by (clarsimp simp: transform_cdt_def) lemma transform_asid_table_kheap_update [simp]: "transform_asid_table (kheap_update f s) = transform_asid_table s" by (clarsimp simp: transform_asid_table_def) lemma transform_asid_table_update_machine [simp]: "transform_asid_table (update_machine ms s) = transform_asid_table s " by (clarsimp simp: transform_asid_table_def) lemma transform_asid_table_update_original_cap [simp]: "transform_asid_table (b\is_original_cap := x\) = transform_asid_table b" by (clarsimp simp: transform_asid_table_def) lemma transform_objects_update_kheap_same_caps: "\ kh ptr = Some ko; caps_of_object ko' = caps_of_object ko; a_type ko' = a_type ko\ \ transform_objects (update_kheap (kh(ptr \ ko')) s) = (if ptr = idle_thread s then transform_objects (update_kheap kh s) else (transform_objects (update_kheap kh s))(ptr \ transform_object (machine_state s) ptr (ekheap s ptr) ko'))" unfolding transform_objects_def apply (rule ext) apply (simp add: map_option_case restrict_map_def map_add_def ) done lemma transform_objects_update_same: "\ kheap s ptr = Some ko; transform_object (machine_state s) ptr (ekheap s ptr) ko = ko'; ptr \ idle_thread s \ \ (transform_objects s)(ptr \ ko') = transform_objects s" unfolding transform_objects_def by (rule ext) (simp) text {* Facts about map_lift_over *} lemma map_lift_over_eq_Some: "(map_lift_over f m x = Some y) = (\x' y'. x = f x' \ y = f y' \ inj_on f (dom m \ ran m) \ m x' = Some y')" proof - have P: "inj_on f (dom m \ ran m) \ inj_on f (dom m)" by (auto elim: subset_inj_on) have Q: "\x y. \ m x = Some y; inj_on f (dom m \ ran m) \ \ inv_into (dom m) f (f x) = x" using P by (blast intro: inv_into_f_f) show ?thesis by (auto simp add: map_lift_over_def Q) qed lemma map_lift_over_eq_None: "(map_lift_over f m x = None) = (inj_on f (dom m \ ran m) \ (\x'. x = f x' \ m x' = None))" proof - have P: "inj_on f (dom m \ ran m) \ inj_on f (dom m)" by (auto elim: subset_inj_on) show ?thesis by (auto simp add: map_lift_over_def P[THEN inv_into_f_f] domI inj_on_eq_iff[where f=f] | rule ccontr[where P="v = None" for v])+ qed lemma map_lift_over_f_eq: "inj_on f ({x} \ dom m \ ran m) \ (map_lift_over f m (f x) = v) = (v = map_option f (m x))" apply (cases v, simp_all add: map_lift_over_eq_None map_lift_over_eq_Some) apply (auto simp: option_map_def split: option.split) done lemma map_lift_over_eq_cases[unfolded map_lift_over_eq_None map_lift_over_eq_Some]: "(map_lift_over f m x = v) = (case v of None \ map_lift_over f m x = None | Some z \ map_lift_over f m x = Some z)" by (simp split: option.split) lemma map_lift_over_upd: assumes inj_f: "inj_on f ({x} \ set_option y \ dom m \ ran m)" shows "(map_lift_over f (m(x := y))) = ((map_lift_over f m) (f x := map_option f y))" proof - have Q: "inj_on f (dom m \ ran m)" "inj_on f (insert x (dom m \ ran (m(x := y))))" "inj_on f (dom m)" "inj_on f (insert x (dom m))" "inj_on f (dom m - {x} \ ran (m(x := None)))" "inj_on f (dom m - {x})" apply (safe intro!: subset_inj_on[OF inj_f]) apply (auto simp: ran_def split: if_split_asm) done show ?thesis apply (simp add: map_lift_over_def Q del: inj_on_insert) apply (safe; rule ext; simp add: Q[THEN inv_into_f_f] domI cong del: imp_cong) apply (auto simp add: Q[THEN inv_into_f_f] domI inj_on_eq_iff[OF inj_f] ranI simp del: inj_on_insert) done qed lemma map_lift_over_if_eq_twice: assumes inj_f: "inj_on f (dom m \ ran m \ {y, y'} \ set_option z \ set_option z')" shows "map_lift_over f (\x. if m x = Some y then z else if m x = Some y' then z' else m x) = (\x. if map_lift_over f m x = Some (f y) then map_option f z else if map_lift_over f m x = Some (f y') then map_option f z' else map_lift_over f m x)" (is "map_lift_over f ?ifeq = ?rhs") proof - from inj_f have 1: "inj_on f (dom m \ ran m)" "inj_on f (dom m)" by (auto simp: inj_on_Un) have "dom ?ifeq \ dom m" by (auto split: if_split_asm) with inj_f have 2: "inj_on f (dom ?ifeq)" by (auto elim!: subset_inj_on) have "dom ?ifeq \ ran ?ifeq \ dom m \ ran m \ set_option z \ set_option z'" by (auto simp: ran_def) with inj_f have "inj_on f (dom ?ifeq \ ran ?ifeq)" by (auto elim!: subset_inj_on) note Q = 1 2 this note if_split[split del] show ?thesis apply (simp add: map_lift_over_def Q) apply (rule ext) apply (case_tac "x \ f ` dom ?ifeq") apply clarsimp apply (subst if_P, fastforce split: if_split_asm)+ apply (simp add: Q[THEN inv_into_f_f] domI ranI inj_on_eq_iff[OF inj_f] split: if_split_asm) apply (subst if_not_P, simp, rule allI, fastforce)+ apply (auto simp: option_map_def Q[THEN inv_into_f_f] domI ranI inj_on_eq_iff[OF inj_f] split: if_split option.split) done qed lemma map_lift_over_if_eq: assumes inj_f: "inj_on f (dom m \ ran m \ {y} \ set_option z)" shows "map_lift_over f (\x. if m x = Some y then z else m x) = (\x. if map_lift_over f m x = Some (f y) then map_option f z else map_lift_over f m x)" using inj_f map_lift_over_if_eq_twice[where f=f and m=m and y=y and z=z and y'=y and z'=z] apply (simp del: inj_on_insert) done end end