(* * 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 CreateObjects_SI imports "../proof/capDL-api/Retype_DP" ObjectInitialised_SI RootTask_SI SysInit_SI begin (********************************************************* * Rewriting the seL4_Untyped_Retype_sep rule to include * * that it doesn't delete anything from the CDT. * *********************************************************) lemma seL4_Untyped_Retype_cdt_inc': "untyped_cptr < 2 ^ si_cnode_size \ \\s. \ si_tcb_id \f Tcb tcb \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat untyped_cptr) \c UntypedCap obj_range free_range \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* sep_true \ s \ cdl_cdt (kernel_state s) child = Some parent \ seL4_Untyped_Retype untyped_cptr type object_size seL4_CapInitThreadCNode node_index 0 free_cptr 1 \\rv s. cdl_cdt (kernel_state s) child = Some parent\" apply (wp seL4_Untyped_Retype_cdt_inc [where root_size=si_cnode_size and root_cnode_cap=si_cnode_cap], (simp|clarsimp simp: guard_equal_si_cnode_cap offset_slot_si_cnode_size')+) done lemma seL4_Untyped_Retype_has_children_wp: "untyped_cptr < 2 ^ si_cnode_size \ \\s. \si_tcb_id \f Tcb tcb \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat untyped_cptr) \c UntypedCap obj_range free_range \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* sep_true \ s \ has_children parent (kernel_state s)\ seL4_Untyped_Retype untyped_cptr type object_size seL4_CapInitThreadCNode node_index 0 free_cptr 1 \\rv s. has_children parent (kernel_state s)\" apply (clarsimp simp: has_children_def is_cdt_parent_def) apply (subst ex_conj_increase)+ apply (rule hoare_ex_wp)+ apply (rule hoare_chain) apply (erule seL4_Untyped_Retype_cdt_inc' [where parent=parent]) apply fast apply fast done lemma seL4_Untyped_Retype_list_all_has_children_index_wp: "untyped_cptr < 2 ^ si_cnode_size \ \\s. \si_tcb_id \f Tcb tcb \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat untyped_cptr) \c UntypedCap obj_range free_range \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* sep_true\ s \ list_all (\index. has_children (cnode_id, untyped_slots!index) (kernel_state s)) indices\ seL4_Untyped_Retype untyped_cptr type object_size seL4_CapInitThreadCNode node_index 0 free_cptr 1 \\rv s. list_all (\index. has_children (cnode_id, untyped_slots!index) (kernel_state s)) indices\" apply (case_tac "indices=[]", simp_all) apply (rule hoare_TrueI) apply (clarsimp simp: Ball_set_list_all[symmetric]) apply (subst Ball_conj_increase, simp) apply (rule hoare_vcg_ball_lift) apply (rule seL4_Untyped_Retype_has_children_wp, simp) done lemma seL4_Untyped_Retype_sep_cdt_inc: "\untyped_cptr < 2 ^ si_cnode_size; ncptr < 2 ^ si_cnode_size\ \ \\s. (nt\ UntypedType \ default_object nt (unat ts) minBound = Some obj \ free_range\ tot_free_range) \ \si_tcb_id \f (Tcb tcb) \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (cap_object si_cnode_cap \f CNode (empty_cnode si_cnode_size)) \* (si_cnode_id, unat untyped_cptr) \c UntypedCap obj_range free_range \* (si_cnode_id, unat ncptr ) \c NullCap \* (\* ptr\tot_free_range. ptr \o Untyped) \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (cap_object si_cnode_cap, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\ has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ obj_range = free_range) \ list_all (\index. has_children (si_cnode_id, untyped_slots!index) (kernel_state s)) indices\ seL4_Untyped_Retype untyped_cptr nt ts seL4_CapInitThreadCNode node_index 0 ncptr 1 \\r s. (\ r \ (\oid free_range'. (\ (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* si_tcb_id \f (Tcb tcb) \* (si_cnode_id, unat ncptr) \c (default_cap nt {oid} (unat ts)) \* oid \o obj \* (cap_object si_cnode_cap \f CNode (empty_cnode si_cnode_size)) \* (\* ptr\tot_free_range - {oid}. ptr \o Untyped) \* (si_cnode_id, unat untyped_cptr) \c UntypedCap obj_range free_range' \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (cap_object si_cnode_cap, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R \ s ) \ free_range' \ free_range - {oid} \ oid \ free_range) \ has_children (si_cnode_id,unat untyped_cptr) (kernel_state s)) \ (r \ (\ (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* si_tcb_id \f (Tcb tcb) \* (cap_object si_cnode_cap \f CNode (empty_cnode si_cnode_size)) \* (si_cnode_id,unat untyped_cptr) \c UntypedCap obj_range free_range \* (si_cnode_id, unat ncptr) \c NullCap \* (\* ptr\tot_free_range. ptr \o Untyped) \* (si_tcb_id, tcb_cspace_slot) \c si_cnode_cap \* (cap_object si_cnode_cap, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R \ s ) \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ obj_range = free_range)) \ list_all (\index. has_children (si_cnode_id, untyped_slots!index) (kernel_state s)) indices \" apply (rule hoare_chain) apply (rule hoare_conj_lift_inv, rule seL4_Untyped_Retype_sep [where root_cnode=si_cnode_id and root_cnode_cap=si_cnode_cap and root_size=si_cnode_size and ucptr_slot="unat untyped_cptr" and ncptr=ncptr and obj_range=obj_range and tot_free_range=tot_free_range and free_range=free_range and obj=obj and P=R], (simp add: offset_slot' guard_equal_si_cnode_cap)+) apply (rule seL4_Untyped_Retype_list_all_has_children_index_wp [where tcb=tcb and cnode_id=si_cnode_id and untyped_slots=untyped_slots and indices=indices and obj_range=obj_range and free_range=free_range], simp) apply clarsimp apply sep_solve apply clarsimp apply clarsimp done (***************************************************** * End of rewriting the seL4_Untyped_Retype_sep rule * *****************************************************) lemma has_children_map_le: "\cdl_cdt s \\<^sub>m cdl_cdt s'; has_children cap_ref s\ \ has_children cap_ref s'" apply (clarsimp simp: has_children_def is_cdt_parent_def) apply (rule_tac x=a in exI) apply (rule_tac x=b in exI) apply (clarsimp simp: map_le_def) by (metis domIff option.distinct(1)) lemma retype_untyped_wp: "\default_object type sz minBound = Some new_object; available_ids \ all_available_ids; free_cptr < 2 ^ si_cnode_size; untyped_cptr < 2 ^ si_cnode_size; sz < 2 ^ word_bits; type \ UntypedType\ \ \\s. \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\ retype_untyped free_cptr untyped_cptr type sz \\rv s. (\rv \ (\new_id available_ids'. new_id \ available_ids \ available_ids' \ available_ids - {new_id} \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids' \* (\* obj_id \ all_available_ids - {new_id}. (obj_id \o Untyped)) \* new_id \o new_object \* (si_cnode_id, unat free_cptr) \c default_cap type {new_id} sz \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R \ s) \ has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices) \ (rv \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices)\" (* I would like to remove this later by rewritting seL4_Untyped_Retype_sep *) apply (subgoal_tac "si_cspace_cap=si_cnode_cap", simp) apply (unfold retype_untyped_def) apply (rule hoare_chain) apply (rule seL4_Untyped_Retype_sep_cdt_inc [where free_range = available_ids and tot_free_range = all_available_ids and untyped_slots=untyped_slots and indices=indices and obj = new_object and obj_range=cover_ids and tcb="obj_tcb root_tcb" and R=R], (assumption|simp add: unat_of_nat32 |rule offset_slot' [symmetric] guard_equal_si_cnode_cap)+) apply clarsimp apply sep_solve apply (case_tac r) apply clarsimp apply sep_solve apply clarsimp apply (rule_tac x=oid in exI, clarsimp) apply (rule_tac x=free_range' in exI, clarsimp) apply (clarsimp simp: unat_of_nat32) apply sep_solve apply (clarsimp simp: si_cspace_cap_def si_cnode_cap_def) done lemma retype_untyped_wp_success: "\default_object type sz minBound = Some new_object; available_ids \ all_available_ids; free_cptr < 2 ^ si_cnode_size; untyped_cptr < 2 ^ si_cnode_size; sz < 2 ^ word_bits; type \ UntypedType\ \ \\s. \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\ retype_untyped free_cptr untyped_cptr type sz \\rv s. \rv \ (\new_id available_ids'. new_id \ available_ids \ available_ids' \ available_ids - {new_id} \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids' \* (\* obj_id \ all_available_ids - {new_id}. (obj_id \o Untyped)) \* new_id \o new_object \* (si_cnode_id, unat free_cptr) \c default_cap type {new_id} sz \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R \ s) \ has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\" apply (rule hoare_strengthen_post) apply (wp retype_untyped_wp [where R=R], simp+) done lemma retype_untyped_wp_fail: "\default_object type sz minBound = Some new_object; available_ids \ all_available_ids; free_cptr < 2 ^ si_cnode_size; untyped_cptr < 2 ^ si_cnode_size; sz < 2 ^ word_bits; type \ UntypedType\ \ \\s. \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\ retype_untyped free_cptr untyped_cptr type sz \\rv s. rv \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R \ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\" apply (rule hoare_strengthen_post) apply (wp retype_untyped_wp [where R=R], simp+) done lemma retype_untyped_bij_success: "\well_formed spec; cdl_objects spec obj_id = Some spec_object; type = object_type spec_object; sz = of_nat (object_size_bits spec_object); unat free_cptr = free_slot; unat untyped_cptr = untyped_slot; used_ids \ available_ids = {}; free_cptr < 2 ^ si_cnode_size; untyped_cptr < 2 ^ si_cnode_size; type \ UntypedType\ \ \\s. bij_betw_map t used_spec_ids used_ids \ dom t = used_spec_ids \ obj_id \ used_spec_ids \ available_ids \ all_available_ids \ \(si_cnode_id, untyped_slot) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, free_slot) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,untyped_slot) (kernel_state s) \ cover_ids = available_ids) \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\ retype_untyped free_cptr untyped_cptr type sz \\rv s. \rv \ (\new_id available_ids'. bij_betw_map (t(obj_id \ new_id)) (insert obj_id used_spec_ids) (insert new_id used_ids) \ dom (t(obj_id \ new_id)) = (insert obj_id used_spec_ids) \ obj_id \ used_spec_ids \ new_id \ available_ids \ available_ids' \ available_ids - {new_id} \ \(si_cnode_id, untyped_slot) \c UntypedCap cover_ids available_ids' \* (\* obj_id \ all_available_ids - {new_id}. (obj_id \o Untyped)) \* object_empty spec (t(obj_id \ new_id)) obj_id \* si_cap_at (t(obj_id \ new_id)) (si_caps(obj_id \ free_cptr)) spec obj_id \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,untyped_slot) (kernel_state s) \ cover_ids = available_ids - {new_id})) \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs) \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) indices\" apply (frule (1) well_formed_object_slots) apply (frule (1) well_formed_object_domain) apply (frule (1) well_formed_object_size_bits_word_bits) apply (subgoal_tac "sz = object_size_bits spec_object") apply (subgoal_tac "\new_object. default_object type (object_size_bits spec_object) minBound = Some new_object") apply (erule exE) apply (rule hoare_assume_pre) apply (rule hoare_strengthen_post) apply (frule offset_slot' [where slot=free_cptr, symmetric]) apply (frule offset_slot' [where slot=untyped_cptr, symmetric]) apply simp apply (wp retype_untyped_wp_success [where available_ids=available_ids and all_available_ids=all_available_ids and cover_ids=cover_ids and R=R], (assumption|simp|clarsimp|blast)+) apply (metis lt_word_bits_lt_pow well_formed_object_size_bits_word_bits) apply assumption apply force apply clarsimp apply (rule_tac x=new_id in exI) apply clarsimp apply (rule conjI) apply (metis IntI bij_betw_map_fun_updI empty_iff non_dom_eval_eq) apply (rule_tac x=available_ids' in exI) apply (clarsimp simp: object_empty_def object_initialised_general_def sep_conj_exists) apply (clarsimp simp: object_default_state_def) apply (clarsimp simp: si_cap_at_def) apply (clarsimp) apply (clarsimp simp: default_object_def split: cdl_object_type.splits) apply clarsimp done lemma si_cap_at_update: "\(si_cap_at t si_caps spec obj_id) s; obj_id \ obj_id'\ \ (si_cap_at t (si_caps(obj_id' \ cap_ptr)) spec obj_id) s" by (clarsimp simp: si_cap_at_def) lemma map_si_cap_at_update_old: "\distinct obj_ids; obj_id_index < length obj_ids; obj_id = obj_ids ! obj_id_index; (\* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids)) s\ \ (\* map (si_cap_at t (si_caps(obj_id \ cap_ptr)) spec) (take obj_id_index obj_ids)) s" apply (erule sep_list_conj_map_impl [rotated]) apply (erule si_cap_at_update) apply clarsimp apply (erule (2) take_nth_distinct) done lemma map_si_cap_at_update': (* Need better tactics. *) "\(\* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* R) s; distinct obj_ids; obj_id_index < length obj_ids; obj_id = obj_ids ! obj_id_index\ \ (\* map (si_cap_at t (si_caps(obj_id \ cap_ptr)) spec) (take obj_id_index obj_ids) \* R) s" by (drule sep_conj_impl, erule map_si_cap_at_update_old, assumption+) lemma inter_union_empty: "\A \ B = {}; A \ C = {}\ \ A \ (B \ C) = {}" by auto lemma distinct_sets_union_subs: "\C \ A; distinct_sets [A,B]\ \ A \ B - C = A - C \ B" by (fastforce simp: distinct_sets_def) lemma cap_objects_remove_free_ids_Union: "n < length untyped_caps \ (\x\set (untyped_caps [n := remove_free_ids (untyped_caps ! n) new_ids]). cap_objects x) = (\x\set untyped_caps. cap_objects x)" apply (erule Union_list_update_id') apply simp done lemma all_available_ids_updates: "\distinct_sets (map cap_free_ids untyped_caps); all_available_ids = (\x\set untyped_caps. cap_free_ids x); new_ids \ cap_free_ids (untyped_caps ! n); n < length untyped_caps\ \ all_available_ids - new_ids = (\x\set (untyped_caps [n := remove_free_ids (untyped_caps ! n) new_ids]). cap_free_ids x)" apply clarsimp apply (subst upd_conv_take_nth_drop, assumption) apply (subst id_take_nth_drop, assumption) apply (clarsimp simp: cap_free_ids_remove_free_ids) apply (rule distinct_sets_union_subs, assumption) apply (subst (asm) id_take_nth_drop, assumption) apply clarsimp apply (rule inter_union_empty) apply (frule distinct_sets_append_Cons_disjoint) apply clarsimp apply (frule distinct_sets_append2) apply clarsimp done lemma untyped_cap_eq: "is_untyped_cap cap \ UntypedCap (cap_objects cap) (cap_free_ids cap) = cap" by (clarsimp simp: cap_type_def cap_free_ids_def split: cdl_cap.splits) lemma retype_untyped_loop_inv_pre: "\untyped_index < length untyped_caps; obj_id_index < length free_slots; length untyped_caps = length untyped_slots; list_all is_untyped_cap untyped_caps\ \ \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id\all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ list_all (\index. has_children (si_cnode_id, untyped_slots ! index) (kernel_state s)) [index\[0.. is_full_untyped_cap (untyped_caps ! index)] \ \(si_cnode_id, untyped_slots ! untyped_index) \c UntypedCap (cap_objects (untyped_caps ! untyped_index)) (cap_free_ids (untyped_caps ! untyped_index)) \* (\* obj_id\all_available_ids. obj_id \o Untyped) \* (si_cnode_id, free_slots ! obj_id_index) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* \* map (\(slot, cap). (si_cnode_id, slot) \c cap) (take untyped_index (zip untyped_slots untyped_caps)) \* \* map (\(slot, cap). (si_cnode_id, slot) \c cap) (drop (Suc untyped_index) (zip untyped_slots untyped_caps)) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* R\ s \ (\ has_children (si_cnode_id, untyped_slots ! untyped_index) (kernel_state s) \ cap_objects (untyped_caps ! untyped_index) = cap_free_ids (untyped_caps ! untyped_index))" apply (subst (asm) id_take_nth_drop [where i=untyped_index and xs="zip untyped_slots untyped_caps"], simp) apply (subst (asm) drop_Suc_nth [where xs="free_slots"], assumption) apply (subst (asm) sep_conj_map_split [symmetric], simp) apply (clarsimp simp: sep_conj_assoc) apply (frule list_all_nth, simp) apply (clarsimp simp: untyped_cap_eq) apply (rule conjI) apply sep_solve apply (clarsimp simp: Ball_set_list_all[symmetric]) apply (erule_tac x=untyped_index in allE) apply (clarsimp simp: is_full_untyped_cap_simps) done declare [[blast_depth_limit = 1000]] lemma retype_untyped_loop_inv_post: "\untyped_index < length untyped_caps; obj_id_index < length obj_ids; obj_id = obj_ids ! obj_id_index; distinct obj_ids; length untyped_caps = length untyped_slots; list_all is_untyped_cap untyped_caps; distinct_sets (map cap_free_ids untyped_caps); new_id \ cap_free_ids (untyped_caps ! untyped_index)\ \ \(si_cnode_id, untyped_slots ! untyped_index) \c remove_free_ids (untyped_caps ! untyped_index) (cap_free_ids (untyped_caps ! untyped_index) - available_ids') \* (\* obj_id\all_available_ids - {new_id}. obj_id \o Untyped) \* object_empty spec t obj_id \* si_cap_at t (si_caps(obj_id \ of_nat (free_slots ! obj_id_index))) spec obj_id \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* \* map (\(slot, y). (si_cnode_id, slot) \c y) (take untyped_index (zip untyped_slots untyped_caps)) \* \* map (\(slot, y). (si_cnode_id, slot) \c y) (drop (Suc untyped_index) (zip untyped_slots untyped_caps)) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* R\ s \ \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots (untyped_caps[untyped_index := remove_free_ids (untyped_caps ! untyped_index) (cap_free_ids (untyped_caps ! untyped_index) - available_ids')])) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take (Suc obj_id_index) obj_ids) \* (\* obj_id\all_available_ids - {new_id}. obj_id \o Untyped) \* \* map (si_cap_at t (si_caps(obj_id \ of_nat (free_slots ! obj_id_index))) spec) (take (Suc obj_id_index) obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s" apply (subst upd_conv_take_nth_drop, simp) apply (subst sep_conj_zip_take_drop [symmetric], simp+) apply (clarsimp simp: sep_conj_assoc) apply (subst sep_map_take_Suc, assumption) apply (subst sep_map_take_Suc, assumption) apply (clarsimp simp: sep_conj_assoc) apply (sep_drule map_si_cap_at_update' [where obj_ids = obj_ids and obj_id = "obj_ids ! obj_id_index" and cap_ptr = "of_nat (free_slots ! obj_id_index)"]) apply (assumption)+ apply (rule refl) apply (clarsimp simp: remove_free_ids_def) apply (fold remove_free_ids_def) apply (drule list_all_nth, simp) apply sep_solve done lemma sep_map_conj_f_update: assumes l: "i < length xs" assumes d: "distinct xs" assumes u: "\x xs i. xs ! i \ x \ f (t(xs ! i \ a')) x = f t x" shows "\* map (f (t(xs ! i \ a')) ) (take i xs) = \* map (f t) (take i xs)" apply (insert l d) apply (rule sym) apply (induct xs arbitrary: i) apply clarsimp apply clarsimp apply (case_tac i) apply fastforce apply clarsimp apply (subst u) apply (clarsimp) apply simp done lemma map_object_empty_update: "\i < length obj_ids; distinct obj_ids\ \ \* map (object_empty spec (t(obj_ids ! i \ obj_id'))) (take i obj_ids) = \* map (object_empty spec t) (take i obj_ids)" apply (erule (1) sep_map_conj_f_update) apply (clarsimp simp: object_empty_def object_initialised_general_def) done lemma map_si_cap_at_update: "\i < length obj_ids; distinct obj_ids\ \ \* map (si_cap_at (t(obj_ids ! i \ obj_id')) si_caps spec) (take i obj_ids) = \* map (si_cap_at t si_caps spec) (take i obj_ids)" apply (erule (1) sep_map_conj_f_update) apply (clarsimp simp: si_cap_at_def) done lemma nth_map': "\map f xs = ys; i < length xs\ \ f (xs ! i) = ys ! i" by (metis nth_map) lemma bij_betw_map_fun_updI2: "\x \ A; y \ B; bij_betw_map f A B\ \ \B'. bij_betw_map (f(x \ y)) (insert x A) B'" apply (drule (2) bij_betw_map_fun_updI) apply fastforce done lemma ran_insert_new: "\a \ dom m; b \ ran m\ \ ran (m(a \ b)) = insert b (ran m)" by auto lemma retype_untyped_loop_inv_success: "\well_formed spec; distinct obj_ids; cdl_objects spec obj_id = Some object; obj_id_index < length obj_ids; untyped_index < length untyped_slots; obj_id_index < length free_slots; map of_nat untyped_slots = untyped_cptrs; map of_nat free_slots = free_cptrs; obj_id = obj_ids ! obj_id_index; free_cptr = free_cptrs ! obj_id_index; untyped_cptr = untyped_cptrs ! untyped_index; type = object_type object; object_size = of_nat (object_at_pointer_size_bits spec obj_id)\ \ \\s. \untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id\all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ list_all (\n. n < 2 ^ si_cnode_size) untyped_slots \ list_all (\n. n < 2 ^ si_cnode_size) free_slots \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take obj_id_index obj_ids)) (ran t) \ dom t = set (take obj_id_index obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)\ retype_untyped free_cptr untyped_cptr type object_size \\rv s. \rv \ (\untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take (Suc obj_id_index) obj_ids) \* (\* obj_id\all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t (si_caps(obj_id \ free_cptr)) spec) (take (Suc obj_id_index) obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take (Suc obj_id_index) obj_ids)) (ran t) \ dom t = set (take (Suc obj_id_index) obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs))\" apply (subst list_all_imp_filter2)+ apply (rule hoare_ex_pre hoare_ex_pre_conj)+ apply (rule hoare_grab_asm2)+ apply (rule hoare_chain) apply (rule_tac used_spec_ids = "set (take obj_id_index obj_ids)" and available_ids = "cap_free_ids (untyped_caps ! untyped_index)" and all_available_ids = all_available_ids and used_ids = "ran t" and cover_ids = "cap_objects (untyped_caps ! untyped_index)" and obj_id = "obj_ids ! obj_id_index" and free_slot = "free_slots ! obj_id_index" and untyped_slot = "untyped_slots ! untyped_index" and si_caps = si_caps and spec = spec and spec_object = "the (cdl_objects spec (obj_ids ! obj_id_index))" and R = "\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (take untyped_index (zip untyped_slots untyped_caps)) \* \* map (\(slot, cap). (si_cnode_id, slot) \c cap) (drop (Suc untyped_index) (zip untyped_slots untyped_caps)) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* R" and indices = "[index\[0.. is_full_untyped_cap (untyped_caps ! index)]" and untyped_slots = untyped_slots and free_cptrs=free_cptrs and t=t and obj_id_index=obj_id_index and obj_ids=obj_ids in retype_untyped_bij_success, (assumption|simp|clarsimp)+) apply (drule list_all_nth [where xs=free_slots], simp) apply (metis of_nat_less_pow offset_slot_si_cnode_size offset_slot' si_cnode_size_less_than_word_size) apply simp apply (drule list_all_nth [where xs=untyped_slots], simp) apply (metis (mono_tags) le_unat_uoi less_or_eq_imp_le nth_map si_cnode_size_less_than_word_size unat_power_lower32) apply force apply (drule list_all_nth [where xs=free_slots], simp) apply (metis nth_map' of_nat_less_pow si_cnode_size_less_than_word_size) apply (drule list_all_nth [where xs=untyped_slots], simp) apply (metis nth_map' of_nat_less_pow si_cnode_size_less_than_word_size) apply (frule (1) well_formed_object_untyped, simp) apply (clarsimp) apply (rule conjI) apply clarsimp apply (erule (2) take_nth_distinct) apply (rule conjI) apply (metis UN_subset_iff nth_mem) apply (rule retype_untyped_loop_inv_pre, simp+) apply clarsimp apply (rule_tac x="untyped_caps[untyped_index := remove_free_ids (untyped_caps ! untyped_index) ((cap_free_ids (untyped_caps ! untyped_index)) - available_ids')]" in exI) apply (rule_tac x="t(obj_ids ! obj_id_index \ new_id)" in exI) apply (rule_tac x="all_available_ids - {new_id}" in exI) apply (rule conjI) apply (rule retype_untyped_loop_inv_post, simp+) apply (subst map_object_empty_update, assumption+) apply (subst map_si_cap_at_update, assumption+) apply (subst remove_free_ids_simps) apply (rule list_all_nth, assumption, assumption) apply fast apply simp apply (rule conjI) apply (subst length_list_update, rule refl) apply (subst (asm) take_insert_nth, assumption) apply (rule conjI) apply (erule (1) list_all_update, simp) apply (rule conjI) apply (erule (1) list_all_update) apply (erule well_formed_untyped_cap_remove_free_ids) apply (rule conjI) apply (erule (1) distinct_sets_map_update) apply (subst cap_free_ids_remove_free_ids) apply clarsimp apply (rule conjI) apply (subst all_available_ids_updates [symmetric], (assumption|rule refl|clarsimp)+) apply fast apply (rule conjI) apply (subst ran_insert_new, simp, force) apply clarsimp apply (rule conjI) apply clarsimp apply (rule take_insert_nth) apply clarsimp apply (rule conjI) apply (subst all_available_ids_updates [symmetric], (assumption|rule refl)+) apply fast apply simp apply (subst cap_objects_remove_free_ids_Union [where n=untyped_index], assumption) apply clarsimp apply (drule list_all_nth [where P = well_formed_untyped_cap], simp) apply (drule list_all_nth [where P = is_untyped_cap], simp) apply (subst (asm) well_formed_untyped_cap_simps, assumption) apply (subst (asm) ran_insert_new, simp, force) apply (rule conjI) apply auto[1] apply blast apply (clarsimp simp: Ball_set_list_all[symmetric]) apply (erule_tac x=x in allE) apply (case_tac "x=untyped_index", simp_all) apply clarsimp apply (drule is_full_untyped_cap_simps) apply blast done lemma retype_untyped_bij_fail: "\well_formed spec; cdl_objects spec obj_id = Some spec_object; type = object_type spec_object; sz = of_nat (object_size_bits spec_object); free_cptr < 2 ^ si_cnode_size; untyped_cptr < 2 ^ si_cnode_size; used_ids \ available_ids = {}\ \ \\s. bij_betw_map t used_spec_ids used_ids \ obj_id \ used_spec_ids \ available_ids \ all_available_ids \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots]\ retype_untyped free_cptr untyped_cptr type sz \\rv s. rv \ (bij_betw_map t used_spec_ids used_ids \ obj_id \ used_spec_ids \ available_ids \ all_available_ids \ \(si_cnode_id, unat untyped_cptr) \c UntypedCap cover_ids available_ids \* (\* obj_id \ all_available_ids. (obj_id \o Untyped)) \* (si_cnode_id, unat free_cptr) \c NullCap \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ (\has_children (si_cnode_id,unat untyped_cptr) (kernel_state s) \ cover_ids = available_ids) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots])\" apply (subgoal_tac "sz = object_size_bits spec_object") apply (subgoal_tac "\new_object. default_object type (object_size_bits spec_object) minBound = Some new_object") apply (erule exE) apply (rule hoare_grab_asm)+ apply (rule hoare_weaken_pre) apply simp apply (frule offset_slot' [where slot=untyped_cptr, symmetric]) apply (frule offset_slot' [where slot=free_cptr, symmetric]) apply (rule hoare_strengthen_post) apply (rule retype_untyped_wp_fail [where available_ids=available_ids and all_available_ids=all_available_ids and cover_ids=cover_ids and untyped_slots=untyped_slots and indices = "[index\[0.. is_full_untyped_cap (untyped_caps ! index)]" and R=R], simp+) apply (metis lt_word_bits_lt_pow well_formed_object_size_bits_word_bits) apply (frule (1) well_formed_object_untyped, simp) apply clarsimp apply (subst list_all_imp_filter2, simp) apply clarsimp apply (subst (asm) list_all_imp_filter2, simp) apply (clarsimp simp: default_object_def split: cdl_object_type.splits) apply clarsimp done lemma conjI2: "\P \ Q; R\ \ P \ Q \ R" by fast lemma retype_untyped_loop_inv_fail: "\well_formed spec; distinct obj_ids; cdl_objects spec obj_id = Some object; obj_id_index < length obj_ids; untyped_index < length untyped_slots; obj_id_index < length free_slots; map of_nat untyped_slots = untyped_cptrs; map of_nat free_slots = free_cptrs; obj_id = obj_ids ! obj_id_index; free_cptr = free_cptrs ! obj_id_index; untyped_cptr = untyped_cptrs ! untyped_index; type = object_type object; object_size = of_nat (object_at_pointer_size_bits spec obj_id)\ \ \\s. \untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ list_all (\n. n < 2 ^ si_cnode_size) untyped_slots \ list_all (\n. n < 2 ^ si_cnode_size) free_slots \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take obj_id_index obj_ids)) (ran t) \ dom t = set (take obj_id_index obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)\ retype_untyped free_cptr untyped_cptr type object_size \\rv s. rv \ (\untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take obj_id_index obj_ids)) (ran t) \ dom t = set (take obj_id_index obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs))\" apply (subst list_all_imp_filter2)+ apply (rule valid_imp_ex)+ apply (rule hoare_ex_pre hoare_ex_pre_conj)+ apply (rule hoare_grab_asm2)+ apply (rule hoare_chain) apply (rule_tac used_spec_ids1 = "set (take obj_id_index obj_ids)" and available_ids1 = "cap_free_ids (untyped_caps ! untyped_index)" and all_available_ids1 = all_available_ids and used_ids1 = "ran t" and cover_ids1 = "cap_objects (untyped_caps ! untyped_index)" and free_cptr1 = free_cptr and untyped_cptr1 = untyped_cptr and t1 = t and R1 = "\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (take untyped_index (zip untyped_slots untyped_caps)) \* \* map (\(slot, cap). (si_cnode_id, slot) \c cap) (drop (Suc untyped_index) (zip untyped_slots untyped_caps)) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* R" and untyped_slots1 = untyped_slots and untyped_caps1 = untyped_caps and P' = "\s. si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)" and Q' = "\rv s. si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)" in hoare_vcg_conj_lift [OF retype_untyped_bij_fail], (assumption|simp|clarsimp)+) apply (drule list_all_nth [where xs=free_slots], simp) apply (metis of_nat_less_pow si_cnode_size_less_than_word_size) apply (drule list_all_nth [where xs=untyped_slots], simp) apply (metis nth_map' of_nat_less_pow si_cnode_size_less_than_word_size) apply clarsimp apply (drule list_all_nth [where xs=free_slots], simp) apply (metis (hide_lams, no_types) Diff_disjoint Int_commute UN_nth_mem disjoint_subset2) apply simp apply wp apply (clarsimp) apply (rule conjI) apply (metis take_nth_distinct) apply (rule conjI) apply force apply (subst unat_of_nat32) apply (drule list_all_nth [where xs=untyped_slots], simp) apply (metis si_cnode_size_less_than_word_size unat_less_word_bits unat_power_lower32) apply (subst unat_of_nat32) apply (drule list_all_nth [where xs=free_slots], simp) apply (metis si_cnode_size_less_than_word_size unat_less_word_bits unat_power_lower32) apply (rule conjI2) apply (subst unat_of_nat32) apply (metis (full_types) list_all_nth si_cnode_size_less_than_word_size unat_less_word_bits unat_power_lower32) apply (rule retype_untyped_loop_inv_pre, simp+) apply (subst list_all_imp_filter2, simp) apply clarsimp apply (rule_tac x=untyped_caps in exI) apply (rule_tac x=t in exI) apply (rule_tac x=all_available_ids in exI) apply (rule conjI) apply (rule_tac t = "zip untyped_slots untyped_caps" and i1 = untyped_index in ssubst[OF id_take_nth_drop], simp) apply (subst drop_Suc_nth [where xs="free_slots"], assumption) apply (drule list_all_nth, assumption)+ apply clarsimp apply (subst (asm) unat_of_nat32) apply (drule list_all_nth [where xs=untyped_slots], simp) apply (metis si_cnode_size_less_than_word_size unat_less_word_bits unat_power_lower32) apply (clarsimp simp: untyped_cap_eq sep_conj_assoc) apply (subst (asm) unat_of_nat32) apply (metis (full_types) si_cnode_size_less_than_word_size unat_less_word_bits unat_power_lower32) apply sep_solve apply (subst (asm) list_all_imp_filter2, simp) done lemma retype_untyped_loop_inv_helper: "\well_formed spec; distinct obj_ids; cdl_objects spec obj_id = Some object; obj_id_index < length obj_ids; untyped_index < length untyped_slots; obj_id_index < length free_slots; map of_nat untyped_slots = untyped_cptrs; map of_nat free_slots = free_cptrs; obj_id = obj_ids ! obj_id_index; free_cptr = free_cptrs ! obj_id_index; untyped_cptr = untyped_cptrs ! untyped_index; type = object_type object; object_size = of_nat (object_at_pointer_size_bits spec obj_id)\ \ \\s. \untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ list_all (\n. n < 2 ^ si_cnode_size) untyped_slots \ list_all (\n. n < 2 ^ si_cnode_size) free_slots \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take obj_id_index obj_ids)) (ran t) \ dom t = set (take obj_id_index obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)\ retype_untyped free_cptr untyped_cptr type object_size \\rv s. (\untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (if rv then obj_id_index else Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t (if rv then si_caps else si_caps(obj_id \ free_cptr)) spec) (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take (if rv then obj_id_index else Suc obj_id_index) obj_ids)) (ran t) \ dom t = set (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs))\" apply (rule hoare_strengthen_post) apply (rule valid_rv_split) apply (fact retype_untyped_loop_inv_fail) apply (fact retype_untyped_loop_inv_success) apply (case_tac r, simp_all) done lemma nth_mem_sub: "\set xs \ dom f; n < length xs\ \ f (xs ! n) = Some (the (f (xs ! n)))" by (metis Some_the nth_mem set_rev_mp) lemma retype_untyped_loop_inv: "\\s. \untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ well_formed spec \ set obj_ids \ dom (cdl_objects spec) \ distinct obj_ids \ obj_id_index < length obj_ids \ obj_id_index < length free_cptrs \ untyped_index < length untyped_cptrs \ length obj_ids \ length free_slots \ object_size = of_nat (object_at_pointer_size_bits spec obj_id) \ length untyped_slots = length untyped_caps \ map of_nat untyped_slots = untyped_cptrs \ map of_nat free_slots = free_cptrs \ obj_id = obj_ids ! obj_id_index \ free_cptr = free_cptrs ! obj_id_index \ untyped_cptr = untyped_cptrs ! untyped_index \ type = object_type (the (cdl_objects spec obj_id)) \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ list_all (\n. n < 2 ^ si_cnode_size) untyped_slots \ list_all (\n. n < 2 ^ si_cnode_size) free_slots \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take obj_id_index obj_ids)) (ran t) \ dom t = set (take obj_id_index obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index obj_ids) free_cptrs)\ retype_untyped free_cptr untyped_cptr type object_size \\rv s. (\untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (if rv then obj_id_index else Suc obj_id_index) free_slots) \* \* map (object_empty spec t) (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t (if rv then si_caps else si_caps(obj_id \ free_cptr)) spec) (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ obj_id_index < length obj_ids \ obj_id_index < length free_cptrs \ untyped_index < length untyped_cptrs \ length obj_ids \ length free_slots \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set (take (if rv then obj_id_index else Suc obj_id_index) obj_ids)) (ran t) \ dom t = set (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ (if rv then si_caps else si_caps(obj_id \ free_cptr)) = map_of (zip (take (if rv then obj_id_index else Suc obj_id_index) obj_ids) free_cptrs))\" apply (rule hoare_assume_pre) apply (rule hoare_chain) apply (rule retype_untyped_loop_inv_helper [where object="the (cdl_objects spec obj_id)" and obj_id_index=obj_id_index and obj_id = obj_id and untyped_index=untyped_index and untyped_slots=untyped_slots and obj_ids=obj_ids and free_slots=free_slots and R=R], (assumption|rule refl|clarsimp)+) apply (rule nth_mem_sub, assumption+) apply (assumption|rule refl|simp|clarsimp)+ apply (rule_tac x=untyped_capsa in exI) apply (rule_tac x=ta in exI) apply (rule_tac x=all_available_idsa in exI) apply clarsimp apply blast apply clarsimp apply (rule conjI) apply clarsimp apply blast apply clarsimp apply (rule_tac x=untyped_capsa in exI) apply (rule_tac x=ta in exI) apply (rule_tac x=all_available_idsa in exI) apply clarsimp apply (subst nth_map[symmetric, where f=of_nat], simp) apply (rule map_of_zip_take_update, simp+) done lemma if_not: "(if \P then a else b) = (if P then b else a)" by simp lemma bij_betw_map_empty [simp]: "bij_betw_map Map.empty {} {}" apply (clarsimp simp: bij_betw_map_def bij_betw_def) done lemma retype_untypeds_wp_helper: "\well_formed spec; set obj_ids = dom (cdl_objects spec); distinct obj_ids; map of_nat untyped_slots = untyped_cptrs; map of_nat free_slots = free_cptrs; list_all (\n. n < 2 ^ si_cnode_size) untyped_slots; list_all (\n. n < 2 ^ si_cnode_size) free_slots; length [obj\obj_ids. real_object_at obj spec] \ length free_cptrs\ \ \\s. \untyped_caps. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) free_slots \* (\* obj_id\(\cap\set untyped_caps. cap_free_ids cap). obj_id \o Untyped) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ length untyped_slots = length untyped_caps \ list_all is_full_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps)\ create_objects spec obj_ids untyped_cptrs free_cptrs \\(si_caps, free_cptrs') s. \untyped_caps t all_available_ids. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop (length [obj\obj_ids. real_object_at obj spec]) free_slots) \* \* map (object_empty spec t) [obj\obj_ids. real_object_at obj spec] \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) [obj\obj_ids. real_object_at obj spec] \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ inj_on t (set [obj\obj_ids. real_object_at obj spec]) \ dom t = set [obj\obj_ids. real_object_at obj spec] \ ran t \ (\cap\set untyped_caps. cap_objects cap) \ si_caps = map_of (zip [obj\obj_ids. real_object_at obj spec] free_cptrs) \ free_cptrs' = drop (length [obj\obj_ids. real_object_at obj spec]) free_cptrs\" apply (unfold create_objects_def) apply (rule hoare_weaken_pre) apply (wp|wpc)+ apply (rule whileLoop_wp [where I="\(obj_id_index, untyped_index, si_caps) s. \untyped_caps cover_ids available_ids all_available_ids t. \\* map (\(slot, cap). (si_cnode_id, slot) \c cap) (zip untyped_slots untyped_caps) \* \* map (\slot. (si_cnode_id, slot) \c NullCap) (drop obj_id_index free_slots) \* \* map (object_empty spec t) (take obj_id_index [obj\obj_ids. real_object_at obj spec]) \* (\* obj_id \ all_available_ids. obj_id \o Untyped) \* \* map (si_cap_at t si_caps spec) (take obj_id_index [obj\obj_ids. real_object_at obj spec]) \* si_tcb_id \f root_tcb \* (si_tcb_id, tcb_pending_op_slot) \c RunningCap \* (si_tcb_id, tcb_cspace_slot) \c si_cspace_cap \* si_cnode_id \f CNode (empty_cnode si_cnode_size) \* (si_cnode_id, unat seL4_CapInitThreadCNode) \c si_cnode_cap \* R\ s \ obj_id_index \ length [obj\obj_ids. real_object_at obj spec] \ obj_id_index \ length free_cptrs \ untyped_index \ length untyped_cptrs \ length untyped_slots = length untyped_caps \ list_all is_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ (\x\set untyped_caps. cap_free_ids x) \ all_available_ids \ bij_betw_map t (set $ take obj_id_index [obj\obj_ids. real_object_at obj spec]) (ran t) \ dom t = (set $ take obj_id_index [obj\obj_ids. real_object_at obj spec]) \ ran t \ ((\x\set untyped_caps. cap_objects x) - (\x\set untyped_caps. cap_free_ids x)) \ list_all (\index. \has_children (si_cnode_id,untyped_slots!index) (kernel_state s) \ is_full_untyped_cap (untyped_caps!index)) [0 ..< length untyped_slots] \ si_caps = map_of (zip (take obj_id_index [obj\obj_ids. real_object_at obj spec]) free_cptrs)"]) apply (rule hoare_weaken_pre) apply (wp valid_case_prod) apply (simp add: if_not) apply (rule hoare_strengthen_post) apply (rule_tac spec=spec and obj_id_index=obj_id_index and untyped_index=untyped_index and obj_ids="[obj\obj_ids. real_object_at obj spec]" and free_slots=free_slots and free_cptrs=free_cptrs and untyped_slots=untyped_slots and untyped_cptrs=untyped_cptrs and si_caps=si_caps and obj_id=obj_id and R=R in retype_untyped_loop_inv) apply (erule pre_post_ex)+ apply (erule exE)+ apply (rule_tac x=all_available_ids in exI) apply (rule_tac x=t in exI) apply fastforce apply wp apply (clarsimp simp: opt_object_def real_object_at_def) apply blast apply clarsimp apply (rename_tac s untyped_caps all_available_ids t obj_id_index untyped_index) apply (drule bij_betw_map_imp_inj_on) apply (subgoal_tac "obj_id_index = length [obj\obj_ids. real_object_at obj spec]") apply clarsimp apply blast apply linarith apply clarsimp apply (rule_tac x=untyped_caps in exI) apply (rule_tac x="\x\set untyped_caps. cap_free_ids x" in exI) apply (frule list_allI [where P'="is_untyped_cap"]) apply (simp add: is_full_untyped_cap_is_untyped_cap) apply (clarsimp simp: Ball_set_list_all[symmetric]) done lemma comp_tuple: "(\(a, b). P a b) \ (\(a, b). (Q a, R b)) = (\(a, b). P (Q a) (R b))" by auto lemma comp_apply: "((\a. P a) \ Q) = (\x. P (Q x))" by (fact comp_def) lemma real_object_at_inter_cdl_objects [simp]: "{obj_id. real_object_at obj_id spec} \ dom (cdl_objects spec) = {obj_id. real_object_at obj_id spec}" by (auto simp: real_object_at_def) lemma length_real_object_at_card: "\set obj_ids = dom (cdl_objects spec); distinct obj_ids\ \ length [obj\obj_ids . real_object_at obj spec] = card {obj_id. real_object_at obj_id spec}" by (clarsimp simp: distinct_length_filter) (* The \ \ need to be on the outside here to work with sep_wp. *) lemma create_objects_sep: "\\((\* (cptr, cap) \ set (zip untyped_cptrs untyped_caps). (si_cnode_id, unat cptr) \c cap) \* (\* cptr \ set free_cptrs. (si_cnode_id, unat cptr) \c NullCap) \* (\* obj_id\(\cap\set untyped_caps. cap_free_ids cap). obj_id \o Untyped) \* si_objects \* R) and K (well_formed spec \ set obj_ids = dom (cdl_objects spec) \ distinct obj_ids \ distinct free_cptrs \ distinct untyped_cptrs \ length untyped_cptrs = length untyped_caps \ list_all is_full_untyped_cap untyped_caps \ list_all well_formed_untyped_cap untyped_caps \ distinct_sets (map cap_free_ids untyped_caps) \ card {obj_id. real_object_at obj_id spec} \ length free_cptrs \ list_all (\n. n < 2 ^ si_cnode_size) free_cptrs \ list_all (\n. n < 2 ^ si_cnode_size) untyped_cptrs)\ \ create_objects spec obj_ids untyped_cptrs free_cptrs \\rv s. \t. \(objects_empty spec t {obj_id. real_object_at obj_id spec} \* si_caps_at t (fst rv) spec {obj_id. real_object_at obj_id spec} \* si_objects \* si_objects_extra_caps' {obj_id. real_object_at obj_id spec} free_cptrs untyped_cptrs \* R) and K (inj_on t {obj_id. real_object_at obj_id spec} \ dom t = {obj_id. real_object_at obj_id spec} \ (map_of (zip [obj\obj_ids. real_object_at obj spec] free_cptrs), drop (card {obj_id. real_object_at obj_id spec}) free_cptrs) = rv)\ s\" apply clarsimp apply (rule hoare_gen_asm_conj) apply (clarsimp simp: si_objects_def si_objects_extra_caps'_def) apply (rule hoare_assume_pre) apply (rule hoare_chain) apply (wp retype_untypeds_wp_helper [where R="(si_cnode_id, unat seL4_CapIRQControl) \c IrqControlCap \* si_asid \* R" and untyped_slots = "map unat untyped_cptrs" and free_slots = "map unat free_cptrs"], (simp|clarsimp)+) apply (fastforce simp: list_all_iff unat_less_2_si_cnode_size') apply (fastforce simp: list_all_iff unat_less_2_si_cnode_size') apply (clarsimp simp: length_real_object_at_card) apply (rule_tac x=untyped_caps in exI) apply (clarsimp simp: zip_map comp_tuple sep_conj_assoc) apply (subst comp_apply)+ apply (subst sep_list_conj_sep_map_set_conj, simp add: distinct_zipI1) apply (subst sep_list_conj_sep_map_set_conj, simp add: distinct_zipI1) apply sep_solve apply (clarsimp simp: length_real_object_at_card) apply (rule_tac x=t in exI) apply (clarsimp simp: sep_conj_exists sep_conj_assoc objects_empty_def si_caps_at_def) apply (rule_tac x=untyped_capsa in exI) apply (rule_tac x=all_available_ids in exI) apply (subst (asm) sep_list_conj_sep_map_set_conj [where xs="[obj\obj_ids . real_object_at obj spec]"], simp)+ apply (clarsimp simp: zip_map drop_map comp_def split_beta') apply (subst (asm) sep_list_conj_sep_map_set_conj, simp add: distinct_zipI1)+ apply sep_solve done end