(* * 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) *) theory CreateIRQCaps_SI imports "../proof/capDL-api/IRQ_DP" ObjectInitialised_SI RootTask_SI SysInit_SI begin (***************** * Helper lemmas * *****************) lemma si_cnode_caps: "si_cnode_cap = si_cspace_cap" by (simp add: si_cnode_cap_def si_cspace_cap_def) lemma hoare_grab_exs2: "(\x. P x \ \P' x\ f \Q\) \ \\s. \x. P x \ P' x s\ f \Q\" by (fastforce simp: valid_def) lemma sep_map_irq_sep_irq_node: "(irq \irq k_irq_table irq \* R) s \ sep_irq_node s irq = Some (k_irq_table irq)" by (fastforce simp: sep_map_irq_def sep_conj_def sep_disj_sep_state_def sep_state_disj_def plus_sep_state_def sep_state_add_def map_disj_def map_add_Some_iff) (********************************************************************************* * A new definition of si_irq_nodes that states that the mapping is injective. * *********************************************************************************) lemma sep_map_o_distinct: "(obj_id \o obj \* obj_id' \o obj') s \ obj_id \ obj_id'" by (fastforce simp: sep_map_o_def sep_map_general_def sep_conj_def object_to_sep_state_def sep_disj_sep_state_def sep_state_disj_def map_disj_def dom_def disjoint_iff_not_equal) lemma sep_any_map_o_false_eq: "(obj_id \o - \* obj_id \o -) = sep_false" by (fastforce simp: sep_any_def sep_map_o_def sep_map_general_def sep_conj_def object_to_sep_state_def sep_disj_sep_state_def sep_state_disj_def map_disj_def dom_def disjoint_iff_not_equal) lemma sep_any_map_o_false: "(obj_id \o - \* obj_id \o -) s \ False" by (simp add: sep_any_map_o_false_eq) lemma sep_map_o_false: "(obj_id \o obj \* obj_id \o obj') s \ False" by (metis sep_map_o_distinct) lemma sep_map_o_any_distinct_list: "((f x) \o - \* \* map (\x. (f x) \o -) xs) s \ x \ set xs" apply clarsimp apply (subst (asm) sep_list_conj_map_remove1, assumption) apply (sep_drule sep_any_map_o_false) apply clarsimp done lemma sep_any_map_o_inj_on: "(\* map (\x. (f x) \o -) xs) s \ inj_on f (set xs)" apply (induct xs arbitrary: s) apply clarsimp apply clarsimp apply (rule conjI) apply (clarsimp simp: sep_conj_def) apply clarsimp apply (frule sep_map_o_any_distinct_list) apply simp done lemma sep_any_map_o_inj_on_set: "\(\* x \ A. (f x) \o -) s; finite A\ \ inj_on f A" apply (drule sep_map_set_conj_sep_list_conj [where P="\x. (f x) \o -"]) apply clarsimp apply (erule sep_any_map_o_inj_on) done lemma sep_map_o_inj_on_set: "\(\* x \ A. (f x) \o obj) s; finite A\ \ inj_on f A" apply (rule sep_any_map_o_inj_on_set [rotated, where s=s], assumption) apply (erule sep_map_set_conj_impl) apply (fastforce simp: sep_any_def) apply simp done lemma sep_conj_existL: "(P \* Q) s \ \s. P s" by (auto simp: sep_conj_def) lemma sep_conj_existR: "(P \* Q) s \ \s. Q s" by (auto simp: sep_conj_def) lemma si_irq_nodes_def2: "si_irq_nodes spec = (\s. \k_irq_table. inj_on k_irq_table (used_irqs spec) \ (\* irq\used_irqs spec. irq \irq k_irq_table irq \* k_irq_table irq \o IRQNode empty_irq_node) s)" apply (rule ext) apply (clarsimp simp: si_irq_nodes_def) apply (rule iffI) apply clarsimp apply (rule_tac x=k_irq_table in exI, simp) apply (subst (asm) sep.prod.distrib) apply (drule sep_conj_existR, clarsimp) apply (erule sep_map_o_inj_on_set) (* Why doesn't sep_rule work? *) apply simp apply blast done (******************************************* * The actual proofs about create_irq_caps * *******************************************) lemma well_formed_default_irq_node_empty: "\well_formed spec; irq \ used_irqs spec\ \ object_at (\obj. object_default_state obj = IRQNode empty_irq_node) (cdl_irq_node spec irq) spec" apply (frule (1) well_formed_used_irqs_have_irq_node, clarsimp) apply (frule (1) well_formed_irq_is_irq_node) apply (frule (1) well_formed_size_irq_node) apply (clarsimp simp: object_at_def empty_irq_node_def object_default_state_def2 is_irq_node_def object_size_bits_def split: cdl_object.splits) done lemma create_irq_cap_sep: "\\(si_cnode_id, unat free_cptr) \c NullCap \* irq \irq kernel_irq_id \* kernel_irq_id \o (IRQNode empty_irq_node) \* si_objects \* R\ and K(well_formed spec \ irq \ used_irqs spec \ t' (cdl_irq_node spec irq) = Some kernel_irq_id \ irq_caps irq = Some free_cptr \ free_cptr < 2 ^ si_cnode_size)\ create_irq_cap spec (irq, free_cptr) \\_. \irq_empty spec t' irq \* si_irq_cap_at irq_caps spec irq \* si_objects \* R\\" apply (rule hoare_gen_asm, clarsimp) apply (frule (1) well_formed_used_irqs_have_irq_node, clarsimp) apply (frule (1) well_formed_default_irq_node_empty, clarsimp simp: object_at_def) apply (clarsimp simp: create_irq_cap_def si_objects_def si_cnode_caps irq_empty_def irq_initialised_general_def si_irq_cap_at_def sep_conj_assoc) apply (wp add: hoare_drop_imp sep_wp: seL4_IRQHandler_IRQControl_Get, simp) apply (rule conjI) apply sep_solve apply (simp add: offset_slot_si_cnode_size' guard_equal_si_cspace_cap word_bits_def) done lemma create_irq_caps_sep_helper: "\\((\* cptr \ set (take (card (used_irqs spec)) free_cptrs). ((si_cnode_id, unat cptr) \c NullCap)) \* si_caps_at t orig_caps spec dev {obj_id. real_object_at obj_id spec} \* si_objects \* si_irq_nodes spec \* R) and K (well_formed spec \ list_all (\n. n < 2 ^ si_cnode_size) free_cptrs \ distinct free_cptrs \ card (used_irqs spec) \ length free_cptrs)\ \ create_irq_caps spec free_cptrs \\rv s. \(t'::32 word \ 32 word option). \(irqs_empty spec t' (used_irqs spec) \* si_irq_caps_at (fst rv) spec (used_irqs spec) \* si_caps_at t orig_caps spec dev {obj_id. real_object_at obj_id spec} \* si_objects \* R) and K ((map_of (zip (used_irq_list spec) free_cptrs), drop (card (used_irqs spec)) free_cptrs) = rv \ inj_on t' (used_irq_nodes spec) \ dom t' = used_irq_nodes spec)\ s\" including no_pre apply clarsimp apply (rule hoare_gen_asm_conj) apply (clarsimp simp: create_irq_caps_def si_irq_nodes_def2 sep_conj_exists) apply wp apply simp apply (rule hoare_grab_exs2) apply (rule_tac x="(\obj_id. Some ((k_irq_table \ inv (cdl_irq_node spec)) obj_id)) |` used_irq_nodes spec" in hoare_exI) apply (rule_tac P1 = "\(irq,free_cptr). (si_cnode_id, unat free_cptr) \c NullCap \* irq \irq k_irq_table irq \* k_irq_table irq \o IRQNode empty_irq_node" and Q1 = "\(irq,free_cptr). irq_empty spec ((\obj_id. Some ((k_irq_table \ inv (cdl_irq_node spec)) obj_id)) |` used_irq_nodes spec) irq \* si_irq_cap_at (map_of (zip (used_irq_list spec) free_cptrs)) spec irq" and I1 = "si_objects" and R1 = "si_caps_at t orig_caps spec dev {obj_id. real_object_at obj_id spec} \* R" in hoare_chain [OF mapM_x_set_sep]) apply (metis distinct_zipI2) apply (clarsimp split:prod.splits) apply (clarsimp simp: sep_conj_assoc) apply (wp sep_wp: create_irq_cap_sep, simp+) apply (rule conjI) apply (clarsimp simp: sep_conj_assoc sep_conj_exists) apply sep_solve apply (frule well_formed_inj_cdl_irq_node) apply (frule set_zip_leftD) apply (frule in_set_zip2) apply (simp add: map_of_zip_tuple_in list_all_iff unat_less_2_si_cnode_size restrict_map_def used_irq_nodes_def) apply (subst sep_list_conj_sep_map_set_conj [symmetric], erule distinct_zipI2) apply (subst (asm) sep_list_conj_sep_map_set_conj [symmetric, where xs = "used_irq_list spec", simplified]) apply (subst split_beta') apply (subst sep_list_conj_map_add) apply (subst zip_take_length [symmetric]) apply (subst split_beta' [symmetric])+ apply (subst map_zip_snd', simp) apply (subst (asm) (3) append_take_drop_id [where n="card (used_irqs spec)" and xs=free_cptrs, symmetric]) apply (subst map_zip_fst', simp) apply (subst sep_list_conj_sep_map_set_conj, fastforce simp: used_irq_list_def) apply (simp add: comp_def) apply sep_solve apply simp apply (subst (asm) sep_list_conj_sep_map_set_conj [symmetric], erule distinct_zipI2) apply (subst (asm) map_zip_fst', simp) apply (subst (asm) sep_list_conj_map_add) apply (subst (asm) sep_list_conj_sep_map_set_conj, metis used_irq_list_def distinct_sorted_list_of_set) apply (subst (asm) sep_list_conj_sep_map_set_conj, metis used_irq_list_def distinct_sorted_list_of_set) apply (clarsimp simp: irqs_empty_def si_irq_caps_at_def) apply (rule conjI) apply sep_solve apply (frule well_formed_inj_cdl_irq_node) apply (fastforce simp: inj_on_def used_irq_nodes_def) done (***************************************************************************** * The above lemma has an injection on just the IRQs. * * We take the above proof, and join it with the result of CreateObjects * * to produce an injection on all objects. * * * * The sum of the two injections "t_irqs" and "t_real" is injective because: * * - Each individual relation is injective * * - The domains are separate * * - The ranges are separate * * * * The first two are easily true. * * The last one is hard and only true because we have * obj_id \o Untyped \* obj_id \ IRQ, and so the obj_ids are distinct. * *****************************************************************************) lemma irq_empty_cong: "t (cdl_irq_node spec irq) = t' (cdl_irq_node spec irq) \ irq_empty spec t irq = irq_empty spec t' irq" by (clarsimp simp: irq_empty_def irq_initialised_general_def) lemma object_empty_cong: "t obj_id = t' obj_id \ object_empty spec t obj_id = object_empty spec t' obj_id" by (clarsimp simp: object_empty_def object_initialised_general_def) lemma si_cap_at_cong: "t obj_id = t' obj_id \ si_cap_at t si_caps spec dev obj_id = si_cap_at t' si_caps spec dev obj_id" by (clarsimp simp: si_cap_at_def) lemma irq_empty_map_add: "\dom t' = cdl_irq_node spec ` irqs\ \ irqs_empty spec t' irqs = irqs_empty spec (t++t') irqs" apply (clarsimp simp: irqs_empty_def) apply (rule sep.prod.cong, simp) apply (subst irq_empty_cong [where t'="t++t'" and t=t'], simp_all) by (metis imageI map_add_eval_right) lemma object_empty_map_add: "\dom t = obj_ids; map_disj t t'\ \ objects_empty spec t obj_ids = objects_empty spec (t++t') obj_ids" apply (clarsimp simp: objects_empty_def) apply (rule sep.prod.cong, simp) apply (subst object_empty_cong [where t'="t++t'" and t=t], simp_all) by (metis map_add_eval_left) lemma si_caps_at_map_add: "\dom t = obj_ids; map_disj t t'\ \ si_caps_at t si_caps spec dev obj_ids = si_caps_at (t++t') si_caps spec dev obj_ids" apply (clarsimp simp: si_caps_at_def) apply (rule sep.prod.cong, simp) apply (subst si_cap_at_cong [where t'="t++t'" and t=t], simp_all) by (metis map_add_eval_left) lemma inj_on_map_add: "\inj_on m (dom m); inj_on m' (dom m'); dom m \ dom m' = {}; ran m \ ran m' = {}; A = dom m \ dom m'\ \ inj_on (m ++ m') A" apply (rule inj_onI) apply clarsimp apply (elim disjE) apply (metis inj_on_eq_iff inter_empty_not_both map_add_eval_left') apply (metis dom_ran map_add_comm map_add_eval_right orthD1) apply (metis dom_ran map_add_comm map_add_eval_right orthD1) apply (metis inj_on_def map_add_eval_right) done lemma inter_emptyI: "\\x. x \ A \ x \ B \ False\ \ A \ B = {}" by auto lemma ran_inter_emptyI: "\\x a b. f a = Some x \ g b = Some x \ False\ \ ran f \ ran g = {}" apply (rule inter_emptyI) apply (auto simp: ran_def) done lemma irq_empty_objects_empty_ran_distinct: "\\irqs_empty spec t_irq (used_irqs spec) \* objects_empty spec t_real {obj_id. real_object_at obj_id spec} \* R\ s; well_formed spec; inj_on t_irq (cdl_irq_node spec ` used_irqs spec); dom t_irq = cdl_irq_node spec ` used_irqs spec; inj_on t_real {obj_id. real_object_at obj_id spec}; dom t_real = {obj_id. real_object_at obj_id spec}\ \ ran t_real \ ran t_irq = {}" apply (frule well_formed_inj_cdl_irq_node) apply (clarsimp simp: irqs_empty_def irq_empty_def irq_initialised_general_def objects_empty_def object_empty_def object_initialised_general_def) apply (rule ran_inter_emptyI) apply clarsimp apply (frule domI [where m=t_real]) apply (frule domI [where m=t_irq]) apply clarsimp apply (rename_tac irq_obj_id obj_id irq) apply (subst (asm) sep.prod.remove, simp, assumption) apply (subst (asm) sep.prod.remove, simp, fast) apply (clarsimp simp: sep_conj_exists sep_conj_assoc) apply (sep_drule sep_map_o_false, simp) done lemma si_objects_extra_caps'_split: "\well_formed spec; distinct free_cptrs'; free_cptrs = drop (card {obj_id. real_object_at obj_id spec}) free_cptrs'\ \ si_objects_extra_caps' {obj_id. real_object_at obj_id spec} free_cptrs' untyped_cptrs = ((\* cptr \ set (take (card (used_irqs spec)) free_cptrs). (si_cnode_id, unat cptr) \c NullCap) \* si_objects_extra_caps' (dom (cdl_objects spec)) free_cptrs' untyped_cptrs)" apply (frule well_formed_objects_card [symmetric]) apply (subst (asm) add.commute) apply (clarsimp simp: si_objects_extra_caps'_def sep_conj_exists sep_conj_assoc) apply (subst take_drop_append [where a="card {obj_id. real_object_at obj_id spec}" and b="card (used_irqs spec)"]) apply clarsimp apply (subst sep.prod.union_disjoint, (simp add: distinct_take_drop_append)+) apply (clarsimp simp: sep_conj_ac) done lemma create_irq_caps_sep: "\\s. \t_real. \(objects_empty spec t_real {obj_id. real_object_at obj_id spec} \* si_caps_at t_real orig_caps spec dev {obj_id. real_object_at obj_id spec} \* si_objects \* si_objects_extra_caps' {obj_id. real_object_at obj_id spec} free_cptrs_orig untyped_cptrs \* si_irq_nodes spec \* R) and K (well_formed spec \ distinct free_cptrs_orig \ list_all (\n. n < 2 ^ si_cnode_size) free_cptrs \ card (used_irqs spec) \ length free_cptrs \ inj_on t_real {obj_id. real_object_at obj_id spec} \ dom t_real = {obj_id. real_object_at obj_id spec} \ dom orig_caps = {obj_id. real_object_at obj_id spec} \ free_cptrs = drop (card {obj_id. real_object_at obj_id spec}) free_cptrs_orig)\ s\ create_irq_caps spec free_cptrs \\rv s. \(t::32 word \ 32 word option). \(objects_empty spec t {obj_id. real_object_at obj_id spec} \* irqs_empty spec t (used_irqs spec) \* si_caps_at t orig_caps spec dev {obj_id. real_object_at obj_id spec} \* si_irq_caps_at (fst rv) spec (used_irqs spec) \* si_objects \* si_objects_extra_caps' (dom (cdl_objects spec)) free_cptrs_orig untyped_cptrs \* R) and K ((map_of (zip (used_irq_list spec) free_cptrs), drop (card (used_irqs spec)) free_cptrs) = rv \ inj_on t (dom (cdl_objects spec)) \ dom t = dom (cdl_objects spec))\ s\" apply (rule hoare_ex_pre) apply (rule hoare_gen_lifted_asm) apply (elim conjE) apply (subst si_objects_extra_caps'_split, assumption+) apply (rule hoare_chain [OF create_irq_caps_sep_helper, where orig_caps1=orig_caps]) apply (rule pred_andI) apply sep_solve apply clarsimp apply clarsimp apply (rule_tac x="t_real ++ t'" in exI) apply clarsimp apply (frule well_formed_objects_real_or_irq) apply (frule well_formed_objects_only_real_or_irq) apply (clarsimp simp: used_irq_nodes_def) apply (subgoal_tac "map_disj t_real t'") apply (rule conjI) apply (subst object_empty_map_add [symmetric], assumption+) apply (subst irq_empty_map_add [symmetric],simp add: used_irq_nodes_def) apply (subst si_caps_at_map_add [symmetric], assumption+) apply (clarsimp simp: si_objects_extra_caps'_def sep_conj_exists sep_conj_assoc) apply (rule_tac x=untyped_caps in exI) apply (rule_tac x=all_available_ids in exI) apply sep_solve apply (rule conjI) apply (rule inj_on_map_add, simp+) apply (rule irq_empty_objects_empty_ran_distinct, sep_solve, simp+) apply (metis sup_commute) apply (clarsimp simp: map_disjI) done end