(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: GPL-2.0-only *) theory Finalise_IF imports ArchArch_IF ArchIRQMasks_IF begin locale Finalise_IF_1 = fixes aag :: "'a subject_label PAS" assumes dmo_maskInterrupt_reads_respects: "reads_respects aag l \ (do_machine_op (maskInterrupt m irq))" and arch_post_cap_deletion_read_respects[wp]: "reads_respects aag l \ (arch_post_cap_deletion acap)" and equiv_asid_sa_update[simp]: "\f. equiv_asid asid (scheduler_action_update f s) s' = equiv_asid asid s s'" "\f. equiv_asid asid s (scheduler_action_update f s') = equiv_asid asid s s'" and equiv_asid_ready_queues_update[simp]: "\f. equiv_asid asid (ready_queues_update f s) s' = equiv_asid asid s s'" "\f. equiv_asid asid s (ready_queues_update f s') = equiv_asid asid s s'" and set_thread_state_reads_respects: "pas_domains_distinct aag \ reads_respects aag l (\s. is_subject aag (cur_thread s)) (set_thread_state ref ts)" and set_bound_notification_globals_equiv: "\globals_equiv s and valid_arch_state\ set_bound_notification ref nopt \\_. globals_equiv s\" and set_thread_state_runnable_reads_respects: "\ pas_domains_distinct aag; runnable ts \ \ reads_respects aag l \ (set_thread_state ref ts)" and set_bound_notification_none_reads_respects: "pas_domains_distinct aag \ reads_respects aag l \ (set_bound_notification ref None)" and thread_set_reads_respects: "pas_domains_distinct aag \ reads_respects aag l \ (thread_set x y)" and set_tcb_queue_reads_respects[wp]: "reads_respects aag l \ (set_tcb_queue d prio queue)" and set_notification_equiv_but_for_labels: "\equiv_but_for_labels aag L st and K (pasObjectAbs aag ntfnptr \ L)\ set_notification ntfnptr ntfn \\_. equiv_but_for_labels aag L st\" and prepare_thread_delete_reads_respects_f: "reads_respects_f aag l \ (prepare_thread_delete t)" and arch_finalise_cap_reads_respects: "reads_respects aag l (pas_refined aag and invs and cte_wp_at ((=) (ArchObjectCap cap)) slot and K (pas_cap_cur_auth aag (ArchObjectCap cap))) (arch_finalise_cap cap is_final)" and arch_finalise_cap_makes_halted: "\invs and valid_cap (ArchObjectCap acap) and (\s. ex = is_final_cap' (ArchObjectCap acap) s) and cte_wp_at ((=) (ArchObjectCap acap)) slot\ arch_finalise_cap acap ex \\rv s :: det_state. \t \ obj_refs_ac (fst rv). halted_if_tcb t s\" and set_notification_globals_equiv: "\globals_equiv st and valid_arch_state\ set_notification ntfnptr ntfn \\_. globals_equiv st\" and arch_post_cap_deletion_globals_equiv[wp]: "arch_post_cap_deletion acap \globals_equiv st\" and set_irq_state_globals_equiv: "set_irq_state state irq \globals_equiv st\" and arch_finalise_cap_globals_equiv: "\globals_equiv st and invs and valid_arch_cap acap\ arch_finalise_cap acap ex \\_. globals_equiv st\" and prepare_thread_delete_globals_equiv[wp]: "prepare_thread_delete t \globals_equiv st\" begin lemma set_irq_state_reads_respects: "reads_respects aag l \ (set_irq_state state irq)" unfolding set_irq_state_def fun_app_def apply (wp dmo_maskInterrupt_reads_respects) apply (subst equiv_valid_def2) apply (rule_tac P="\" and P'="\" in modify_ev2) apply (fastforce elim: affects_equivE reads_equivE equiv_forE intro: equiv_forI intro!: reads_equiv_interrupt_states_update affects_equiv_interrupt_states_update) apply wpsimp+ done lemma deleted_irq_handler_reads_respects: "reads_respects aag l \ (deleted_irq_handler irq)" unfolding deleted_irq_handler_def by (rule set_irq_state_reads_respects) lemma empty_slot_reads_respects: notes split_paired_All[simp del] split_paired_Ex[simp del] shows "reads_respects aag l (K (aag_can_read aag (fst slot))) (empty_slot slot free_irq)" unfolding empty_slot_def post_cap_deletion_def fun_app_def apply (simp add: bind_assoc[symmetric] cong: if_cong) apply (fold update_cdt_def) apply (simp add: bind_assoc empty_slot_ext_def cong: if_cong) apply (rule gen_asm_ev) apply (wp deleted_irq_handler_reads_respects set_cap_reads_respects set_original_reads_respects update_cdt_list_reads_respects update_cdt_reads_respects get_cap_wp get_cap_rev | wpsimp | frule aag_can_read_self, fastforce simp: equiv_for_def split: option.splits)+ by (fastforce simp: reads_equiv_def2 equiv_for_def elim: states_equiv_forE_cdt dest: aag_can_read_self split: option.splits) lemma scheduler_action_states_equiv[simp]: "states_equiv_for P Q R S st (scheduler_action_update f s) = states_equiv_for P Q R S st s" by (simp add: states_equiv_for_def equiv_for_def equiv_asids_def) crunch states_equiv[wp]: set_thread_state_ext "states_equiv_for P Q R S st" (ignore_del: set_thread_state_ext) end lemma requiv_get_tcb_eq': "\ reads_equiv aag s t; aag_can_read aag thread \ \ get_tcb thread s = get_tcb thread t" by (auto simp: reads_equiv_def2 get_tcb_def elim: states_equiv_forE_kheap dest!: aag_can_read_self) lemma set_scheduler_action_reads_respects[wp]: "reads_respects aag l \ (set_scheduler_action action)" by (simp add: set_scheduler_action_def equiv_valid_def2 equiv_valid_2_def modify_def bind_def put_def get_def reads_equiv_scheduler_action_update affects_equiv_scheduler_action_update) lemma set_thread_state_ext_reads_respects: "reads_respects aag l (\s. is_subject aag (cur_thread s)) (set_thread_state_ext ref)" apply (case_tac "is_subject aag ref") apply (simp add: set_thread_state_ext_def when_def get_thread_state_def | wp thread_get_rev)+ apply (simp add: reads_equiv_def) apply (simp add: set_thread_state_ext_def when_def) apply (simp add: equiv_valid_def2) apply (rule equiv_valid_rv_bind[where W="\\"]) apply (clarsimp simp: equiv_valid_2_def get_thread_state_def thread_get_def gets_the_def return_def bind_def assert_opt_def gets_def get_tcb_def fail_def get_def split: option.splits) apply clarsimp apply (rule equiv_valid_2_bind[where R'="(=)" and Q="\rv _. rv \ ref" and Q'="\rv _. rv \ ref"]) apply (rule gen_asm_ev2) apply (simp add: equiv_valid_def2[symmetric] | wp)+ apply (clarsimp simp: reads_equiv_def) apply (subst equiv_valid_def2[symmetric]) apply wp+ apply force done lemma set_thread_state_ext_owned_reads_respects: "reads_respects aag l (\s. aag_can_read aag ref) (set_thread_state_ext ref)" apply (simp add: set_thread_state_ext_def when_def get_thread_state_def | wp thread_get_rev)+ apply (simp add: reads_equiv_def) done lemma set_thread_state_owned_reads_respects: "reads_respects aag l (\s. aag_can_read aag ref) (set_thread_state ref ts)" apply (simp add: set_thread_state_def) apply (wp set_object_reads_respects gets_the_ev set_thread_state_ext_owned_reads_respects) by (fastforce intro: kheap_get_tcb_eq elim: reads_equivE equiv_forD) lemma set_bound_notification_owned_reads_respects: "reads_respects aag l (\s. is_subject aag ref) (set_bound_notification ref ntfn)" apply (simp add: set_bound_notification_def) apply (wp set_object_reads_respects gets_the_ev) apply (force elim: reads_equivE equiv_forE) done lemma get_thread_state_runnable[wp]: "\st_tcb_at runnable ref\ get_thread_state ref \\rv _. runnable rv\" by (wpsimp wp: gts_st_tcb_at) lemma set_thread_state_ext_runnable_reads_respects: "reads_respects aag l (st_tcb_at runnable ref) (set_thread_state_ext ref)" apply (simp add: set_thread_state_ext_def when_def) apply (simp add: equiv_valid_def2) apply (rule equiv_valid_rv_bind[where W="\\" and Q="\rv _. runnable rv"]) apply (clarsimp simp: equiv_valid_2_def get_thread_state_def thread_get_def gets_the_def return_def bind_def assert_opt_def gets_def get_tcb_def fail_def get_def split: option.splits) apply (rule gen_asm_ev2) apply (clarsimp simp: equiv_valid_def2[symmetric] | wp)+ apply (simp add: reads_equiv_def) apply wp done lemma set_simple_ko_reads_respects: "reads_respects aag l \ (set_simple_ko f ptr ep)" unfolding set_simple_ko_def apply (simp add: equiv_valid_def2) apply (rule equiv_valid_rv_bind) apply (rule equiv_valid_rv_guard_imp) apply (rule get_object_revrv) apply (simp, simp) apply (rule_tac R'="\\" in equiv_valid_2_bind) apply (rule_tac R'="\\" in equiv_valid_2_bind) apply (subst equiv_valid_def2[symmetric]) apply (rule set_object_reads_respects) apply (rule assert_ev2) apply (simp) apply (rule assert_inv)+ apply (rule assert_ev2) apply (simp) apply (rule assert_inv)+ apply (simp) apply (wp get_object_inv) done lemma get_ep_queue_reads_respects: "reads_respects aag l \ (get_ep_queue ep)" unfolding get_ep_queue_def apply (rule equiv_valid_guard_imp) apply (wp | wpc)+ apply (simp) done lemma get_object_reads_respects: "reads_respects aag l (K (aag_can_read aag ptr \ (aag_can_affect aag l ptr))) (get_object ptr)" apply (unfold get_object_def fun_app_def) apply (subst gets_apply) apply (wp gets_apply_ev | wp (once) hoare_drop_imps)+ apply (fastforce elim: reads_equivE affects_equivE equiv_forE) done lemma get_simple_ko_reads_respects: "reads_respects aag l (K (aag_can_read aag ptr \ aag_can_affect aag l ptr)) (get_simple_ko f ptr)" unfolding get_simple_ko_def by (wp get_object_reads_respects | wpc | simp)+ lemma get_epq_SendEP_ret: "\\s. \x\set list. P x\ get_ep_queue (SendEP list) \\rv s. \x\set rv. P x\" by (wpsimp simp: get_ep_queue_def) lemma get_epq_RecvEP_ret: "\\s. \x\set list. P x\ get_ep_queue (RecvEP list) \\rv s. \x\set rv. P x\" by (wpsimp simp: get_ep_queue_def) fun ep_queue_invisible where "ep_queue_invisible aag l (SendEP list) = labels_are_invisible aag l ((pasObjectAbs aag) ` (set list))" | "ep_queue_invisible aag l (RecvEP list) = labels_are_invisible aag l ((pasObjectAbs aag) ` (set list))" | "ep_queue_invisible aag l IdleEP = True" lemma obj_eq_st_tcb_at: "\ kheap s x = kheap s' x; st_tcb_at P x s' \ \ st_tcb_at P x s" by (clarsimp simp: st_tcb_at_def obj_at_def) lemma send_blocked_on_tcb_st_to_auth: "send_blocked_on epptr ts \ (epptr, SyncSend) \ tcb_st_to_auth ts" by (case_tac ts, simp_all) lemma receive_blocked_on_tcb_st_to_auth: "receive_blocked_on epptr ts \ (epptr, Receive) \ tcb_st_to_auth ts" by (case_tac ts, simp_all) lemma not_ep_queue_invisible: "\ \ ep_queue_invisible aag l eplist; eplist = SendEP list \ eplist = RecvEP list \ \ \t \ set list. aag_can_read aag t \ aag_can_affect aag l t" by (auto simp: labels_are_invisible_def) lemma ep_queued_st_tcb_at'': "\P. \ ko_at (Endpoint ep) ptr s; (t, rt) \ ep_q_refs_of ep; valid_objs s; sym_refs (state_refs_of s); \pl pl'. (rt = EPSend \ P (BlockedOnSend ptr pl)) \ (rt = EPRecv \ P (BlockedOnReceive ptr pl')) \ \ st_tcb_at P t s" apply (case_tac ep, simp_all) apply (frule (1) sym_refs_ko_atD, fastforce simp: st_tcb_at_def obj_at_def refs_of_rev)+ done lemma ep_queues_are_invisible_or_eps_are_equal': "\ (pasSubject aag, Reset, pasObjectAbs aag epptr) \ pasPolicy aag; ko_at (Endpoint ep) epptr s; ko_at (Endpoint ep') epptr s'; reads_equiv aag s s'; affects_equiv aag l s s'; valid_objs s; sym_refs (state_refs_of s); valid_objs s'; sym_refs (state_refs_of s'); pas_refined aag s; pas_refined aag s' \ \ (\ ep_queue_invisible aag l ep) \ ep = ep'" apply (rule impI) apply (case_tac "\list. ep = SendEP list \ ep = RecvEP list") apply (erule exE) apply (drule (1) not_ep_queue_invisible) apply clarsimp apply (erule disjE) apply (erule disjE) apply (drule_tac auth="SyncSend" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="send_blocked_on epptr" and s=s and t=t in ep_queued_st_tcb_at'') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 send_blocked_on_tcb_st_to_auth) apply blast apply assumption apply (fastforce dest: reads_affects_equiv_kheap_eq simp: obj_at_def) apply (drule_tac auth="SyncSend" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="send_blocked_on epptr" and s=s and t=t in ep_queued_st_tcb_at'') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 send_blocked_on_tcb_st_to_auth) apply blast apply (erule conjE, assumption) apply (drule_tac x=epptr in reads_affects_equiv_kheap_eq, simp+) apply (fastforce simp: obj_at_def) apply (erule disjE) apply (drule_tac auth="Receive" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="receive_blocked_on epptr" and s=s and t=t in ep_queued_st_tcb_at'') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 receive_blocked_on_tcb_st_to_auth) apply blast apply assumption apply (fastforce dest: reads_affects_equiv_kheap_eq simp: obj_at_def) apply (drule_tac auth="Receive" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="receive_blocked_on epptr" and s=s and t=t in ep_queued_st_tcb_at'') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 receive_blocked_on_tcb_st_to_auth) apply blast apply (erule conjE, assumption) apply (drule_tac x=epptr in reads_affects_equiv_kheap_eq, simp+) apply (fastforce simp: obj_at_def) apply (case_tac ep, auto) done lemma ep_queues_are_invisible_or_eps_are_equal: "\ (pasSubject aag, Reset, pasObjectAbs aag epptr) \ pasPolicy aag; ko_at (Endpoint ep) epptr s; ko_at (Endpoint ep') epptr s'; reads_equiv aag s s'; affects_equiv aag l s s'; valid_objs s; sym_refs (state_refs_of s); valid_objs s'; sym_refs (state_refs_of s'); pas_refined aag s; pas_refined aag s' \ \ (\ ep_queue_invisible aag l ep \ \ ep_queue_invisible aag l ep') \ ep = ep'" apply (rule impI) apply (erule disjE) apply (blast intro!: ep_queues_are_invisible_or_eps_are_equal'[rule_format]) apply (rule sym) apply (erule ep_queues_are_invisible_or_eps_are_equal'[rule_format]) by (assumption | erule reads_equiv_sym | erule affects_equiv_sym)+ lemma get_simple_ko_revrv: "inj C \ reads_equiv_valid_rv_inv R aag (\obj obj'. \s t. reads_equiv aag s t \ R s t \ P s \ P t \ ko_at (C obj) ptr s \ ko_at (C obj') ptr t) P (get_simple_ko C ptr)" apply (simp add: get_simple_ko_def) apply (rule_tac Q="\ rv. ko_at rv ptr and P" in equiv_valid_rv_bind) apply (rule equiv_valid_rv_guard_imp[OF equiv_valid_rv_trivial]) apply wpsimp+ apply (clarsimp simp add: assert_def fail_ev2_l fail_ev2_r simp del: imp_disjL split: option.split) apply (rule return_ev2) apply (auto simp: proj_inj)[1] apply (rule hoare_strengthen_post[OF get_object_sp]) apply simp done lemma get_endpoint_revrv: "reads_equiv_valid_rv_inv (affects_equiv aag l) aag (\ep ep'. (\ ep_queue_invisible aag l ep \ \ ep_queue_invisible aag l ep') \ ep = ep') (pas_refined aag and valid_objs and sym_refs \ state_refs_of and K ((pasSubject aag, Reset, pasObjectAbs aag epptr) \ pasPolicy aag)) (get_endpoint epptr)" apply (rule equiv_valid_2_rvrel_imp, rule get_simple_ko_revrv) apply (simp add: inj_Endpoint) apply (auto elim: ep_queues_are_invisible_or_eps_are_equal[rule_format]) done lemma gen_asm_ev2_r: "(P' \ equiv_valid_2 I A B R P \ f f') \ equiv_valid_2 I A B R P (\s. P') f f'" by (rule gen_asm_ev2_r') lemma gen_asm_ev2_l: "(P \ equiv_valid_2 I A B R \ P' f f') \ equiv_valid_2 I A B R (\s. P) P' f f'" by (rule gen_asm_ev2_l') lemma bind_return_unit2: "f = return () >>= (\_. f)" by simp lemma mapM_x_ev2_invisible: assumes domains_distinct: "pas_domains_distinct aag" assumes mam: "\ptr. modifies_at_most aag (L ptr) \ ((f :: obj_ref \ (unit, det_ext) s_monad) ptr)" assumes mam': "\ptr. modifies_at_most aag (L' ptr) \ ((f' :: obj_ref \ (unit, det_ext) s_monad) ptr)" shows "equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l) (=) (K (\x. x \ set list' \ (labels_are_invisible aag l (L' x)))) (K (\x. x \ set list \ (labels_are_invisible aag l (L x)))) (mapM_x f' list') (mapM_x f list)" apply (induct list) apply (induct_tac list') apply (simp add: mapM_x_Nil) apply (blast intro: return_ev2) apply (simp add: mapM_x_Cons mapM_x_Nil) apply (subst bind_return_unit[where f="return ()"]) apply (rule_tac R'="(=)" and P="\s. labels_are_invisible aag l (L' a)" in equiv_valid_2_bind_pre) apply simp apply (rule gen_asm_ev2_l) apply (rule equiv_valid_2_guard_imp[OF ev2_invisible[OF domains_distinct]], assumption+) apply (rule mam') apply (rule_tac P="\" in modifies_at_mostI) apply (wp | simp)+ apply (simp add: mapM_x_Cons) apply (subst bind_return_unit2) apply (rule_tac R'="(=)" and P'="\s. labels_are_invisible aag l (L a)" in equiv_valid_2_bind_pre) apply simp apply (rule gen_asm_ev2_r) apply (rule equiv_valid_2_guard_imp[OF ev2_invisible[OF domains_distinct]], assumption+) apply (rule_tac P="\" in modifies_at_mostI) apply (wp | simp)+ apply (rule mam) apply (wp | simp)+ done lemma ev2_inv: assumes inv: "\P. f \P\" assumes inv': "\P. g \P\" shows "equiv_valid_2 I A A \\ \ \ f g" apply (clarsimp simp: equiv_valid_2_def) apply (drule state_unchanged[OF inv]) apply (drule state_unchanged[OF inv']) by simp lemma mapM_x_ev2_r_invisible: assumes domains_distinct: "pas_domains_distinct aag" assumes mam: "\ptr. modifies_at_most aag (L ptr) \ ((f :: obj_ref \ (unit, det_ext) s_monad) ptr)" assumes inv: "\P. g \P\" shows "equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l) (=) \ (K (\x. x \ set list \ labels_are_invisible aag l (L x))) g (mapM_x f list)" apply (induct list) apply (simp add: mapM_x_Nil) apply (rule ev2_inv[OF inv]) apply wp apply (simp add: mapM_x_Cons) apply (subst bind_return_unit2) apply (rule_tac R'="(=)" and P'="\ s. labels_are_invisible aag l (L a)" in equiv_valid_2_bind_pre) apply simp apply (rule gen_asm_ev2_r) apply (rule equiv_valid_2_guard_imp[OF ev2_invisible[OF domains_distinct]], assumption+) apply (rule_tac P="\" in modifies_at_mostI) apply (wp | simp)+ apply (rule mam) apply (wp | simp)+ done (* MOVE *) lemma ev2_sym: assumes symI: "\x y. I x y \ I y x" assumes symA: "\x y. A x y \ A y x" assumes symB: "\x y. B x y \ B y x" assumes symR: "\x y. R x y \ R y x" shows "equiv_valid_2 I A B R P' P f' f \ equiv_valid_2 I A B R P P' f f'" apply (clarsimp simp: equiv_valid_2_def) apply (blast intro: symA symB symI symR) done lemma mapM_x_ev2_l_invisible: assumes domains_distinct: "pas_domains_distinct aag" assumes mam: "\ptr. modifies_at_most aag (L ptr) \ ((f :: obj_ref \ (unit, det_ext) s_monad) ptr)" assumes inv: "\P. g \P\" shows "equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l) (=) (K (\x. x \ set list \ labels_are_invisible aag l (L x))) \ (mapM_x f list) g" apply (rule ev2_sym[OF reads_equiv_sym affects_equiv_sym affects_equiv_sym]) apply (simp_all)[4] apply (rule mapM_x_ev2_r_invisible[OF domains_distinct mam inv]) done lemma not_label_is_invisible: "(\ labels_are_invisible aag l {(pasObjectAbs aag x)}) = (aag_can_read aag x \ aag_can_affect aag l x)" by (simp add: labels_are_invisible_def) lemma label_is_invisible: "(labels_are_invisible aag l {(pasObjectAbs aag x)}) = (\ (aag_can_read aag x \ aag_can_affect aag l x))" by (simp add: labels_are_invisible_def) lemma op_eq_unit_taut: "(=) = (\ (_:: unit) _. True)" by (rule ext | simp)+ lemma ev2_symmetric: "equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l) (=) P P f f' \ equiv_valid_2 (reads_equiv aag) (affects_equiv aag l) (affects_equiv aag l) (=) P P f' f" apply (clarsimp simp add: equiv_valid_2_def) apply (drule_tac x=t in spec) apply (drule_tac x=s in spec) apply (fastforce elim: affects_equiv_sym reads_equiv_sym) done lemma reads_respects_ethread_get: "reads_respects aag l (\_. is_subject aag thread) (ethread_get f thread)" apply (simp add: ethread_get_def) apply wp apply (drule aag_can_read_self) apply (fastforce simp: reads_equiv_def2 get_etcb_def equiv_for_def states_equiv_for_def) done lemma aag_can_read_self'[simp]: "aag_can_read_label aag (pasSubject aag)" by fastforce lemma gets_apply_ready_queues_reads_respects: "reads_respects aag l (\_. pasSubject aag \ pasDomainAbs aag d) (gets_apply ready_queues d)" apply (rule gets_apply_ev') apply (force elim: reads_equivE simp: equiv_for_def) done (* FIXME: move *) lemma equiv_valid_rv_trivial': assumes inv: "\P. f \P\" shows "equiv_valid_rv_inv I A \\ Q f" by (auto simp: equiv_valid_2_def dest: state_unchanged[OF inv]) lemma gets_cur_domain_ev: "reads_equiv_valid_inv A aag \ (gets cur_domain)" apply (rule equiv_valid_guard_imp) apply wp apply (simp add: reads_equiv_def) done crunch sched_act[wp]: set_simple_ko "\s. P (scheduler_action s)" (wp: crunch_wps) context Finalise_IF_1 begin lemma set_tcb_queue_modifies_at_most: "modifies_at_most aag L (\s. pasDomainAbs aag d \ L \ {}) (set_tcb_queue d prio queue)" apply (rule modifies_at_mostI) apply (simp add: set_tcb_queue_def modify_def, wp) apply (force simp: equiv_but_for_labels_def states_equiv_for_def equiv_for_def equiv_asids_def) done lemma tcb_sched_action_reads_respects: assumes domains_distinct: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag) (tcb_sched_action action t)" apply (simp add: tcb_sched_action_def get_tcb_queue_def) apply (subst gets_apply) apply (case_tac "aag_can_read aag t \ aag_can_affect aag l t") apply (simp add: ethread_get_def) apply wp apply (rule_tac Q="\s. pasObjectAbs aag t \ pasDomainAbs aag (tcb_domain rv)" in equiv_valid_guard_imp) apply (wp gets_apply_ev') apply (fastforce simp: reads_equiv_def affects_equiv_def equiv_for_def states_equiv_for_def) apply (wp | simp)+ apply (intro conjI impI allI | fastforce simp: get_etcb_def elim: reads_equivE affects_equivE equiv_forE)+ apply (clarsimp simp: pas_refined_def tcb_domain_map_wellformed_aux_def split: option.splits) apply (erule_tac x="(t, tcb_domain y)" in ballE, force) apply (force intro: domtcbs simp: get_etcb_def) apply (simp add: equiv_valid_def2 ethread_get_def) apply (rule equiv_valid_rv_bind) apply (wp equiv_valid_rv_trivial', simp) apply (rule equiv_valid_2_bind) prefer 2 apply (wp equiv_valid_rv_trivial, simp) apply (rule equiv_valid_2_bind) apply (rule_tac P=\ and P'=\ and L="{pasObjectAbs aag t}" and L'="{pasObjectAbs aag t}" in ev2_invisible[OF domains_distinct]) apply (blast | simp add: labels_are_invisible_def)+ apply (rule set_tcb_queue_modifies_at_most) apply (rule set_tcb_queue_modifies_at_most) apply (simp | wp)+ apply (clarsimp simp: equiv_valid_2_def gets_apply_def get_def bind_def return_def labels_are_invisible_def) apply wpsimp+ apply (force intro: domtcbs simp: get_etcb_def pas_refined_def tcb_domain_map_wellformed_aux_def) done lemma reschedule_required_reads_respects[wp]: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag) reschedule_required" apply (simp add: reschedule_required_def | wp tcb_sched_action_reads_respects | wpc)+ apply (simp add: reads_equiv_def) done lemma possible_switch_to_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag and pas_cur_domain aag and (\s. is_subject aag (cur_thread s))) (possible_switch_to tptr)" apply (simp add: possible_switch_to_def ethread_get_def) apply (case_tac "aag_can_read aag tptr \ aag_can_affect aag l tptr") apply (wp hoare_weak_lift_imp tcb_sched_action_reads_respects | wpc | simp)+ apply (clarsimp simp: get_etcb_def) apply ((intro conjI impI allI | elim aag_can_read_self reads_equivE affects_equivE equiv_forE conjE disjE | force)+)[1] apply clarsimp apply (wp (once), rename_tac cur_dom) apply (simp add: equiv_valid_def2) apply (rule_tac W="\\" and Q="\tcb. pas_refined aag and K (tcb_domain tcb \ cur_dom)" in equiv_valid_rv_bind) prefer 3 apply wp apply (monad_eq simp: get_etcb_def equiv_valid_2_def) apply (rule gen_asm_ev2') apply (simp add: equiv_valid_def2[symmetric]) apply (wp tcb_sched_action_reads_respects) apply (simp add: reads_equiv_def) apply (wp gets_cur_domain_ev)+ apply (clarsimp simp: get_etcb_def pas_refined_def tcb_domain_map_wellformed_aux_def) apply (frule_tac x="(tptr, tcb_domain y)" in bspec, force intro: domtcbs) apply (erule notE) apply (fastforce dest: domains_distinct[THEN pas_domains_distinct_inj]) done lemma cancel_all_ipc_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state and K (aag_can_read aag epptr)) (cancel_all_ipc epptr)" unfolding cancel_all_ipc_def fun_app_def by (wp mapM_x_ev'' tcb_sched_action_reads_respects set_thread_state_runnable_reads_respects set_thread_state_pas_refined hoare_vcg_ball_lift set_thread_state_runnable_valid_sched_action set_simple_ko_reads_respects get_ep_queue_reads_respects get_epq_SendEP_ret get_epq_RecvEP_ret get_simple_ko_reads_respects get_simple_ko_wp | wpc | clarsimp simp: ball_conj_distrib | rule subset_refl | wp (once) hoare_drop_imps | assumption | rule hoare_strengthen_post[where Q="\_. pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state", OF mapM_x_wp])+ end fun ntfn_queue_invisible where "ntfn_queue_invisible aag l (WaitingNtfn list) = labels_are_invisible aag l ((pasObjectAbs aag) ` (set list))" | "ntfn_queue_invisible aag l _ = True" lemma not_ntfn_queue_invisible: "\ \ ntfn_queue_invisible aag l eplist; eplist = WaitingNtfn list \ \ (\t \ set list. aag_can_read aag t \ aag_can_affect aag l t)" by (auto simp: labels_are_invisible_def) lemma ntfn_queues_are_invisible_or_ntfns_are_equal': "\ (pasSubject aag, Reset, pasObjectAbs aag ntfnptr) \ pasPolicy aag; ko_at (Notification ntfn) ntfnptr s; ko_at (Notification ntfn') ntfnptr s'; reads_equiv aag s s'; affects_equiv aag l s s'; valid_objs s; sym_refs (state_refs_of s); valid_objs s'; sym_refs (state_refs_of s'); pas_refined aag s; pas_refined aag s' \ \ \ ntfn_queue_invisible aag l (ntfn_obj ntfn) \ ntfn_obj ntfn = ntfn_obj ntfn'" apply (rule impI) apply (case_tac "\list. ntfn_obj ntfn = WaitingNtfn list") apply (erule exE) apply (drule (1) not_ntfn_queue_invisible) apply clarsimp apply (erule disjE) apply (drule_tac auth="Receive" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="receive_blocked_on ntfnptr" and s=s and t=t in ntfn_queued_st_tcb_at') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 receive_blocked_on_tcb_st_to_auth) apply blast apply assumption apply (fastforce dest: reads_affects_equiv_kheap_eq simp: obj_at_def) apply (drule_tac auth="Receive" and t="pasObjectAbs aag t" in reads_read_queued_thread_read_ep) apply blast apply (erule pas_refined_mem[rotated]) apply (rule sta_ts) apply (drule_tac P="receive_blocked_on ntfnptr" and s=s and t=t in ntfn_queued_st_tcb_at') apply (simp)+ apply (simp add: thread_st_auth_def split: option.splits) apply (clarsimp simp: tcb_states_of_state_def st_tcb_def2 receive_blocked_on_tcb_st_to_auth) apply blast apply (erule conjE, assumption) apply (drule_tac x=ntfnptr in reads_affects_equiv_kheap_eq, simp+) apply (fastforce simp: obj_at_def) apply (case_tac "ntfn_obj ntfn", auto) done lemma get_bound_notification_reads_respects': "reads_respects aag l (K(is_subject aag thread)) (get_bound_notification thread)" unfolding get_bound_notification_def thread_get_def apply (wp | simp)+ apply clarify apply (rule requiv_get_tcb_eq) apply simp+ done lemma thread_get_reads_respects: "reads_respects aag l (K (aag_can_read aag thread \ aag_can_affect aag l thread)) (thread_get f thread)" unfolding thread_get_def fun_app_def apply (wp gets_the_ev) apply (auto intro: reads_affects_equiv_get_tcb_eq) done lemma get_bound_notification_reads_respects: "reads_respects aag l (\ s. aag_can_read aag thread \ aag_can_affect aag l thread) (get_bound_notification thread)" unfolding get_bound_notification_def apply (rule equiv_valid_guard_imp) apply (wp thread_get_reads_respects | simp)+ done lemma bound_tcb_at_implies_read: "\ pas_refined aag s; is_subject aag t; bound_tcb_at ((=) (Some x)) t s \ \ aag_can_read_label aag (pasObjectAbs aag x)" apply (frule bound_tcb_at_implies_receive, simp) apply clarsimp apply (frule_tac l="pasSubject aag" and auth=Receive in reads_ep, simp) apply (auto simp: aag_can_read_read) done lemma bound_tcb_at_eq: "\ sym_refs (state_refs_of s); valid_objs s; kheap s ntfnptr = Some (Notification ntfn); ntfn_bound_tcb ntfn = Some tcbptr; bound_tcb_at ((=) (Some ntfnptr')) tcbptr s \ \ ntfnptr = ntfnptr'" apply (drule_tac x=ntfnptr in sym_refsD[rotated]) apply (fastforce simp: state_refs_of_def) apply (auto simp: pred_tcb_at_def obj_at_def valid_obj_def valid_ntfn_def is_tcb state_refs_of_def refs_of_rev simp del: refs_of_simps) done lemma unbind_notification_is_subj_reads_respects: "reads_respects aag l (pas_refined aag and invs and K (is_subject aag t)) (unbind_notification t)" apply (clarsimp simp: unbind_notification_def) apply (wp set_bound_notification_owned_reads_respects set_simple_ko_reads_respects get_simple_ko_reads_respects get_bound_notification_reads_respects gbn_wp[unfolded get_bound_notification_def, simplified] | wpc | simp add: get_bound_notification_def)+ apply (clarsimp) apply (rule bound_tcb_at_implies_read, auto) done context Finalise_IF_1 begin lemma cancel_all_signals_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state and K (aag_can_read aag ntfnptr)) (cancel_all_signals ntfnptr)" unfolding cancel_all_signals_def by (wp mapM_x_ev'' tcb_sched_action_reads_respects set_thread_state_runnable_reads_respects set_thread_state_pas_refined hoare_vcg_ball_lift set_thread_state_runnable_valid_sched_action set_simple_ko_reads_respects get_epq_SendEP_ret get_epq_RecvEP_ret get_simple_ko_reads_respects get_simple_ko_wp | wpc | clarsimp simp: ball_conj_distrib | rule subset_refl | wp (once) hoare_drop_imps | simp | rule hoare_strengthen_post[where Q="\_. pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state", OF mapM_x_wp])+ lemma unbind_maybe_notification_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag and invs and K (aag_can_read aag ntfnptr)) (unbind_maybe_notification ntfnptr)" unfolding unbind_maybe_notification_def by (wp set_bound_notification_none_reads_respects set_simple_ko_reads_respects get_simple_ko_reads_respects | wpc | simp)+ (* aag_can_read is transitive on endpoints but intransitive on notifications *) lemma fast_finalise_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (pas_refined aag and invs and K (fin \ (case cap of EndpointCap r badge rights \ aag_can_read aag r | NotificationCap r badge rights \ is_subject aag r | _ \ True))) (fast_finalise cap fin)" apply (case_tac cap, simp_all) by (wp equiv_valid_guard_imp[OF cancel_all_ipc_reads_respects] equiv_valid_guard_imp[OF cancel_all_signals_reads_respects] unbind_notification_is_subj_reads_respects unbind_maybe_notification_reads_respects get_simple_ko_reads_respects get_simple_ko_wp | simp add: when_def | wpc | intro conjI impI | fastforce simp: aag_cap_auth_def cap_auth_conferred_def cap_rights_to_auth_def)+ lemma cap_delete_one_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and invs and pas_refined aag and K (is_subject aag (fst slot))) (cap_delete_one slot)" unfolding cap_delete_one_def fun_app_def apply (unfold unless_def when_def) apply (rule equiv_valid_guard_imp) apply (wp is_final_cap_reads_respects reads_respects_f[OF empty_slot_reads_respects, where st=st] reads_respects_f[OF fast_finalise_reads_respects, where st=st] empty_slot_silc_inv | simp | elim conjE)+ apply (rule_tac Q="\rva s. rva = is_final_cap' rv s \ cte_wp_at ((=) rv) slot s \ silc_inv aag st s \ is_subject aag (fst slot) \ pasObjectAbs aag (fst slot) \ SilcLabel" in hoare_strengthen_post) apply wp apply (rule conjI) apply clarsimp apply (drule silc_inv) apply (erule_tac x=rv in allE, erule_tac x=slot in allE) apply simp apply (drule(1) intra_label_capD) apply (clarsimp simp: cap_points_to_label_def split: cap.splits) apply force apply (wp reads_respects_f[OF get_cap_rev] get_cap_auth_wp | simp | elim conjE)+ by (fastforce simp: cte_wp_at_caps_of_state silc_inv_def) lemma cap_delete_one_reads_respects_f_transferable: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and invs and pas_refined aag and K (aag_can_read_not_silc aag (fst slot)) and is_transferable_in slot) (cap_delete_one slot)" unfolding cap_delete_one_def fun_app_def apply (unfold unless_def when_def) apply (rule equiv_valid_guard_imp) apply (wp is_final_cap_reads_respects empty_slot_silc_inv reads_respects_f[OF empty_slot_reads_respects, where st=st] reads_respects_f[OF fast_finalise_reads_respects, where st=st] | simp | elim conjE)+ apply (rule_tac Q="\rva s. rva = is_final_cap' rv s \ cte_wp_at ((=) rv) slot s \ silc_inv aag st s \ is_transferable_in slot s \ aag_can_read_not_silc aag (fst slot)" in hoare_strengthen_post) apply wp apply (rule conjI) apply clarsimp apply (drule silc_inv) apply (erule_tac x=rv in allE, erule_tac x=slot in allE) apply simp apply (drule(1) intra_label_capD) apply (clarsimp simp: cap_points_to_label_def' cte_wp_at_caps_of_state split: cap.splits) apply (force elim: is_transferable_capE) apply (wp reads_respects_f[OF get_cap_rev] get_cap_wp | simp | elim conjE)+ by (fastforce simp: cte_wp_at_caps_of_state silc_inv_def) end lemma get_blocking_object_reads_respects: "reads_respects aag l \ (get_blocking_object state)" unfolding get_blocking_object_def apply (rule equiv_valid_guard_imp) apply (wp | wpc | simp)+ done fun tcb_st_to_auth' where "tcb_st_to_auth' (BlockedOnSend x pl) = SyncSend" | "tcb_st_to_auth' (BlockedOnReceive x pl) = Receive" | "tcb_st_to_auth' (BlockedOnNotification x) = Receive" lemma owns_thread_blocked_reads_endpoint: "\ pas_refined aag s; invs s; st_tcb_at (\ y. y = state) tptr s; is_subject aag tptr; state = BlockedOnReceive x pl \ state = BlockedOnSend x xb \ state = BlockedOnNotification x \ \ aag_can_read aag x" apply (rule_tac auth="tcb_st_to_auth' state" in reads_ep) apply (drule sym, simp, rule pas_refined_mem) apply (rule_tac s=s in sta_ts) apply (clarsimp simp: thread_st_auth_def tcb_states_of_state_def st_tcb_at_def get_tcb_def obj_at_def) apply fastforce apply assumption apply fastforce done lemma st_tcb_at_sym: "st_tcb_at ((=) x) t s = st_tcb_at (\ y. y = x) t s" by (auto simp: st_tcb_at_def obj_at_def) lemma blocked_cancel_ipc_reads_respects: "reads_respects aag l (pas_refined aag and invs and st_tcb_at ((=) state) tptr and K (is_subject aag tptr)) (blocked_cancel_ipc state tptr)" unfolding blocked_cancel_ipc_def apply (wp set_thread_state_owned_reads_respects set_simple_ko_reads_respects get_ep_queue_reads_respects get_simple_ko_reads_respects get_blocking_object_reads_respects | simp add: get_blocking_object_def | wpc)+ apply (fastforce intro: aag_can_read_self owns_thread_blocked_reads_endpoint simp: st_tcb_at_sym) done lemma select_singleton_ev: "equiv_valid_inv I B (K (\a. A = {a})) (select A)" by (fastforce simp: equiv_valid_def2 equiv_valid_2_def select_def) lemma thread_set_fault_pas_refined': "\pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state\ thread_set (tcb_fault_update fault) thread \\_. pas_refined aag\" by (wp thread_set_pas_refined | simp)+ (* FIXME MERGE names *) lemmas thread_set_fault_empty_invs = thread_set_tcb_fault_reset_invs lemma get_thread_state_rev: "reads_equiv_valid_inv A aag (K (aag_can_read aag ref)) (get_thread_state ref)" unfolding get_thread_state_def by (rule thread_get_rev) lemma get_irq_slot_reads_respects: "reads_respects aag l (K (is_subject_irq aag irq)) (get_irq_slot irq)" unfolding get_irq_slot_def apply (rule equiv_valid_guard_imp) apply (rule gets_ev) apply (simp add: reads_equiv_def states_equiv_for_def equiv_for_def affects_equiv_def) apply (drule aag_can_read_irq_self) apply (simp) done lemma thread_set_tcb_at: "\\s. Q s\ thread_set x ptr \\_ s. P s\ \ \\s. tcb_at ptr s \ Q s\ thread_set x ptr \\_ s. P s\" apply (rule use_spec(1)) apply (case_tac "tcb_at ptr s") apply (clarsimp simp add: spec_valid_def valid_def) apply (simp add: spec_valid_def thread_set_def set_object_def[abs_def]) apply (wp get_object_wp) apply (force simp: get_tcb_def obj_at_def is_tcb_def split: option.splits Structures_A.kernel_object.splits) done (* FIXME: Why was the [wp] attribute on this lemma clobbered by interpretation of the Arch locale? *) lemmas [wp] = thread_set_fault_valid_global_refs lemma cancel_signal_owned_reads_respects: "reads_respects aag l (K (is_subject aag threadptr \ (aag_can_read aag ntfnptr \ aag_can_affect aag l ntfnptr))) (cancel_signal threadptr ntfnptr)" unfolding cancel_signal_def by (wp set_thread_state_owned_reads_respects set_simple_ko_reads_respects get_simple_ko_reads_respects hoare_drop_imps | wpc | simp)+ lemma as_user_get_register_reads_respects: "reads_respects aag l (K (is_subject aag thread)) (as_user thread (getRegister reg))" by (fastforce simp: equiv_valid_guard_imp[OF as_user_reads_respects] det_getRegister) lemma update_restart_pc_reads_respects[wp]: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects aag l (silc_inv aag s and K (is_subject aag thread)) (update_restart_pc thread)" unfolding update_restart_pc_def apply (subst as_user_bind) apply (wpsimp wp: as_user_set_register_reads_respects' as_user_get_register_reads_respects) done context Finalise_IF_1 begin lemma reply_cancel_ipc_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and pas_refined aag and invs and tcb_at tptr and K (is_subject aag tptr)) (reply_cancel_ipc tptr)" unfolding reply_cancel_ipc_def apply (rule gen_asm_ev) apply (wp cap_delete_one_reads_respects_f_transferable[where st=st] select_singleton_ev select_inv assert_wp reads_respects_f[OF get_cap_rev, where st=st] reads_respects_f[OF thread_set_reads_respects, where st=st] reads_respects_f[OF gets_descendants_of_revrv[folded equiv_valid_def2]] | simp add: when_def split del: if_split | elim conjE)+ apply (rule_tac Q="\ rv s. silc_inv aag st s \ invs s \ pas_refined aag s \ tcb_at tptr s \ is_subject aag tptr" in hoare_strengthen_post) apply (wp thread_set_tcb_fault_update_silc_inv hoare_vcg_imp_lift hoare_vcg_ball_lift thread_set_fault_empty_invs thread_set_fault_pas_refined' | wps | simp)+ apply clarsimp apply (rule conjI,rule TrueI) apply clarsimp apply (frule(1) reply_cap_descends_from_master0) apply (frule all_children_subjectReads[THEN all_children_descendants_of],force,force) apply (fastforce simp: cte_wp_at_caps_of_state elim: silc_inv_no_transferable'[where slot = "(a,b)" for a b,simplified]) by fastforce lemma cancel_ipc_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and pas_refined aag and invs and tcb_at t and (K (is_subject aag t))) (cancel_ipc t)" unfolding cancel_ipc_def apply (wp reads_respects_f[OF blocked_cancel_ipc_reads_respects, where st=st and Q="\"] reply_cancel_ipc_reads_respects_f[where st=st] reads_respects_f[OF cancel_signal_owned_reads_respects, where st=st and Q="\"] reads_respects_f[OF get_thread_state_rev, where st=st and Q="\"] gts_wp | wpc | simp add: blocked_cancel_ipc_def | erule conjE)+ apply (clarsimp simp: st_tcb_at_def obj_at_def) apply (rule owns_thread_blocked_reads_endpoint) apply (simp add: st_tcb_at_def obj_at_def | blast)+ done lemma suspend_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and pas_refined aag and invs and tcb_at thread and K (is_subject aag thread)) (suspend thread)" unfolding suspend_def apply (wp reads_respects_f[OF set_thread_state_owned_reads_respects, where st=st and Q="\"] reads_respects_f[OF tcb_sched_action_reads_respects, where st=st and Q=\] reads_respects_f[OF get_thread_state_rev, where st=st and Q="\"] reads_respects_f[OF update_restart_pc_reads_respects, where st=st and Q="\"] gts_wp set_thread_state_pas_refined | simp)+ apply (wp cancel_ipc_reads_respects_f[where st=st] cancel_ipc_silc_inv)+ apply clarsimp apply (wp hoare_allI hoare_drop_imps) apply clarsimp apply (wp cancel_ipc_silc_inv)+ apply auto done lemma deleting_irq_handler_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and invs and pas_refined aag and K (is_subject_irq aag irq)) (deleting_irq_handler irq)" unfolding deleting_irq_handler_def by (wp cap_delete_one_reads_respects_f reads_respects_f[OF get_irq_slot_reads_respects] | simp | blast)+ lemma finalise_cap_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and pas_refined aag and invs and cte_wp_at ((=) cap) slot and K (pas_cap_cur_auth aag cap) and K (final \ (case cap of EndpointCap r badge rights \ is_subject aag r | NotificationCap r badge rights \ is_subject aag r | _ \ True))) (finalise_cap cap final)" apply (case_tac cap, simp_all split del: if_split) apply ((wp cancel_all_ipc_reads_respects cancel_all_signals_reads_respects prepare_thread_delete_reads_respects_f suspend_reads_respects_f[where st=st] deleting_irq_handler_reads_respects unbind_notification_is_subj_reads_respects unbind_maybe_notification_reads_respects unbind_notification_invs unbind_maybe_notification_invs | simp add: when_def invs_valid_objs invs_sym_refs aag_cap_auth_def cap_auth_conferred_def cap_rights_to_auth_def cap_links_irq_def aag_has_Control_iff_owns cte_wp_at_caps_of_state split del: if_split | rule aag_Control_into_owns_irq | clarsimp split del: if_split | rule conjI | wp (once) reads_respects_f[where st=st] | blast | clarsimp | force dest: caps_of_state_valid simp: valid_cap_def)+)[11] apply (rule equiv_valid_guard_imp) by (wp arch_finalise_cap_reads_respects reads_respects_f[where st=st] arch_finalise_cap_silc_inv | simp | elim conjE)+ end lemma cap_swap_for_delete_reads_respects: "reads_respects aag l (K (is_subject aag (fst slot1) \ is_subject aag (fst slot2))) (cap_swap_for_delete slot1 slot2)" unfolding cap_swap_for_delete_def apply (simp add: when_def) apply (rule conjI, rule impI) apply (rule equiv_valid_guard_imp) apply (wp cap_swap_reads_respects get_cap_rev) apply (simp) apply (rule impI, wp) done lemma owns_cnode_owns_obj_ref_of_child_cnodes_threads_and_zombies: "\ pas_refined aag s; is_subject aag (fst slot); cte_wp_at ((=) cap) slot s; is_cnode_cap cap \ is_thread_cap cap \ is_zombie cap \ \ is_subject aag (obj_ref_of cap)" apply (frule (1) cap_cur_auth_caps_of_state[rotated]) apply (simp add: cte_wp_at_caps_of_state) apply (clarsimp simp: aag_cap_auth_def) apply (case_tac cap, simp_all add: is_zombie_def) apply (drule_tac x=Control in bspec) apply (clarsimp simp: cap_auth_conferred_def) apply (erule (1) aag_Control_into_owns) apply (drule_tac x=Control in bspec) apply (clarsimp simp: cap_auth_conferred_def) apply (erule (1) aag_Control_into_owns) apply (drule_tac x=Control in bspec) apply (clarsimp simp: cap_auth_conferred_def) apply (erule (1) aag_Control_into_owns) done lemmas only_timer_irq_inv_irq_state_independent_A[intro!] = irq_state_independent_A_only_timer_irq_inv lemma rec_del_only_timer_irq: "\only_timer_irq_inv irq (st :: det_state)\ rec_del call \\_. only_timer_irq irq\" apply (simp add: only_timer_irq_inv_def) apply (rule hoare_pre, rule only_timer_irq_pres) apply (rule hoare_pre, wp rec_del_irq_masks) apply (wp rec_del_domain_sep_inv | force | rule hoare_pre, wp (once) rec_del_domain_sep_inv)+ done lemma rec_del_only_timer_irq_inv: "\only_timer_irq_inv irq (st :: det_state)\ rec_del call \\_. only_timer_irq_inv irq st\" apply (simp add: only_timer_irq_inv_def) apply (rule hoare_wp_simps) apply (rule hoare_conjI) apply (wp rec_del_domain_sep_inv rec_del_only_timer_irq | force simp: only_timer_irq_inv_def)+ done lemma set_cap_only_timer_irq_inv: "\only_timer_irq_inv irq (st :: det_state) and K (domain_sep_inv_cap False cap)\ set_cap cap slot \\_. only_timer_irq_inv irq st\" apply (simp add: only_timer_irq_inv_def) apply (wp only_timer_irq_pres set_cap_domain_sep_inv | force)+ done lemma finalise_cap_only_timer_irq_inv: "\only_timer_irq_inv irq (st :: det_state)\ finalise_cap cap final \\_. only_timer_irq_inv irq st\" apply (simp add: only_timer_irq_inv_def) apply (wp only_timer_irq_pres | force)+ done context Finalise_IF_1 begin lemma rec_del_spec_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" notes drop_spec_valid[wp_split del] drop_spec_validE[wp_split del] drop_spec_ev[wp_split del] rec_del.simps[simp del] shows "spec_reads_respects_f s aag l (silc_inv aag st and only_timer_irq_inv irq st' and einvs and simple_sched_action and pas_refined aag and valid_rec_del_call call and emptyable (slot_rdcall call) and (\s. \ exposed_rdcall call \ ex_cte_cap_wp_to (\cp. cap_irqs cp = {}) (slot_rdcall call) s) and K (case call of CTEDeleteCall slot exposed \ is_subject aag (fst slot) | FinaliseSlotCall slot exposed \ is_subject aag (fst slot) | ReduceZombieCall cap slot exposed \ is_subject aag (fst slot) \ is_subject aag (obj_ref_of cap))) (rec_del call)" proof (induct s rule: rec_del.induct, simp_all only: rec_del_fails drop_spec_ev[OF fail_ev_pre]) case (1 slot exposed s) show ?case apply (rule spec_equiv_valid_guard_imp) apply (simp add: rec_del.simps split_def when_def) apply (wp drop_spec_ev[OF returnOk_ev_pre] drop_spec_ev[OF liftE_ev] hoareE_TrueI reads_respects_f[OF empty_slot_reads_respects, where st=st] empty_slot_silc_inv) apply (rule "1.hyps") apply (rule_tac Q'="\r s. silc_inv aag st s \ is_subject aag (fst slot)" in hoare_post_imp_R) apply (wp validE_validE_R'[OF rec_del_silc_inv_not_transferable] | fastforce simp: silc_inv_def)+ done next case (2 slot exposed s) show ?case apply (simp add: rec_del.simps) apply (rule spec_equiv_valid_guard_imp) apply (wp drop_spec_ev[OF returnOk_ev] drop_spec_ev[OF liftE_ev] set_cap_reads_respects_f "2.hyps" preemption_point_inv' drop_spec_ev[OF preemption_point_reads_respects_f[where st=st and st'=st']] validE_validE_R'[OF rec_del_silc_inv_not_transferable] rec_del_invs rec_del_respects(2) rec_del_only_timer_irq_inv | simp add: split_def split del: if_split | (rule irq_state_independent_A_conjI, simp)+)+ apply (rule_tac Q'="\rv s. emptyable (slot_rdcall (ReduceZombieCall (fst rvb) slot exposed)) s \ (\ exposed \ ex_cte_cap_wp_to (\cp. cap_irqs cp = {}) slot s) \ is_subject aag (fst slot)" in hoare_post_imp_R) apply (wp rec_del_emptyable reduce_zombie_cap_to) apply simp apply (wp drop_spec_ev[OF liftE_ev] set_cap_reads_respects_f[where st=st] set_cap_silc_inv[where st=st] | simp)+ apply (wp replace_cap_invs set_cap_cte_wp_at set_cap_sets final_cap_same_objrefs set_cap_cte_cap_wp_to hoare_vcg_const_Ball_lift hoare_weak_lift_imp drop_spec_ev[OF liftE_ev] finalise_cap_reads_respects set_cap_silc_inv set_cap_only_timer_irq_inv set_cap_pas_refined_not_transferable | simp add: cte_wp_at_eq_simp | erule finalise_cap_not_reply_master[simplified Inr_in_liftE_simp])+ apply (rule hoare_strengthen_post) apply (rule_tac Q="\fin s. silc_inv aag st s \ only_timer_irq_inv irq st' s \ (\ cap_points_to_label aag (fst fin) (pasObjectAbs aag (fst slot)) \ (\lslot. lslot \ slots_holding_overlapping_caps (fst fin) s \ pasObjectAbs aag (fst lslot) = SilcLabel)) \ einvs s \ replaceable s slot (fst fin) rv \ cte_wp_at ((=) rv) slot s \ s \ (fst fin) \ ex_cte_cap_wp_to (appropriate_cte_cap rv) slot s \ (\t\obj_refs_ac (fst fin). halted_if_tcb t s) \ pas_refined aag s \ emptyable slot s \ simple_sched_action s \ pas_cap_cur_auth aag (fst fin) \ is_subject aag (fst slot) \ (case (fst fin) of Zombie _ _ _ \ is_subject aag (obj_ref_of (fst fin)) | _ \ True) \ (is_zombie (fst fin) \ fst fin = NullCap) \ (is_zombie (fst fin) \ fst fin = NullCap)" in hoare_vcg_conj_lift) apply (wp finalise_cap_replaceable Finalise_AC_1.finalise_cap_makes_halted finalise_cap_invs finalise_cap_auth' finalise_cap_ret_is_subject finalise_cap_ret' finalise_cap_silc_inv finalise_cap_ret_is_silc finalise_cap_only_timer_irq_inv)[1] apply (rule finalise_cap_cases[where slot=slot]) apply (clarsimp simp: cte_wp_at_caps_of_state) apply (erule disjE) apply (clarsimp simp: cap_irq_opt_def cte_wp_at_def is_zombie_def gen_obj_refs_eq split: cap.split_asm if_split_asm elim!: ranE dest!: caps_of_state_cteD) apply (clarsimp cong: conj_cong simp: conj_comms) apply (rename_tac word option nat) apply (drule_tac s="{word}" in sym) apply (clarsimp simp: invs_psp_aligned invs_arch_state invs_vspace_objs) apply (rule conjI, fastforce) apply (clarsimp, rule conjI) apply (erule replaceable_zombie_not_transferable)(* WHY *) apply (rule conjI) apply (fastforce simp: silc_inv_def) apply (rule conjI) apply (fastforce simp: domain_sep_inv_def domain_sep_inv_cap_def only_timer_irq_inv_def) apply (rule conjI[rotated], force) apply (clarsimp simp: ex_cte_cap_wp_to_def)+ apply (rule_tac x="a" in exI, rule_tac x="b" in exI) apply (clarsimp simp: cte_wp_at_def appropriate_cte_cap_def) apply (drule_tac x="cap" in fun_cong) apply (clarsimp simp: appropriate_cte_cap_def split: cap.splits) apply (clarsimp cong: conj_cong simp: conj_comms) apply (wp drop_spec_ev[OF liftE_ev] is_final_cap_reads_respects | simp)+ apply (rule_tac Q="\rva s. rva = is_final_cap' rv s \ cte_wp_at ((=) rv) slot s \ only_timer_irq_inv irq st' s \ silc_inv aag st s \ pas_refined aag s \ pas_cap_cur_auth aag rv \ invs s \ valid_list s \ valid_sched s \ simple_sched_action s \ s \ rv \ is_subject aag (fst slot) \ emptyable slot s \ ex_cte_cap_wp_to (appropriate_cte_cap rv) slot s" in hoare_strengthen_post) apply (wp is_final_cap_is_final | simp)+ apply clarsimp apply (rule conjI) apply clarsimp apply (frule silc_inv) apply (erule_tac x=rv in allE, erule_tac x=slot in allE) apply simp apply (erule disjE) apply (drule(1) intra_label_capD) apply (clarsimp simp: cap_points_to_label_def split: cap.splits) apply (simp add: silc_inv_def) apply (force simp: owns_cnode_owns_obj_ref_of_child_cnodes_threads_and_zombies) apply (wp drop_spec_ev reads_respects_f[OF get_cap_rev, where st=st and Q="\"] get_cap_wp | simp)+ apply (clarsimp cong: conj_cong simp: invs_valid_objs invs_arch_state invs_psp_aligned) apply (intro conjI impI | clarsimp | assumption | fastforce dest: silc_inv_not_subject)+ apply (erule (1) cap_cur_auth_caps_of_state[rotated]) apply (simp add: cte_wp_at_caps_of_state) apply (fastforce dest: cte_wp_at_valid_objs_valid_cap simp: invs_valid_objs) apply (drule if_unsafe_then_capD) apply (simp add: invs_ifunsafe) apply simp apply (clarsimp simp: ex_cte_cap_wp_to_def) done next case (3 ptr bits n slot s) show ?case apply (simp add: rec_del.simps) apply (rule spec_equiv_valid_guard_imp) apply (wp drop_spec_ev[OF liftE_ev] drop_spec_ev[OF returnOk_ev] reads_respects_f[OF cap_swap_for_delete_reads_respects] cap_swap_for_delete_silc_inv drop_spec_ev[OF assertE_ev])+ apply (fastforce simp: silc_inv_def) done next case (4 ptr bits n slot s) show ?case apply (simp add: rec_del.simps) apply (rule spec_equiv_valid_guard_imp) apply (wp drop_spec_ev[OF returnOk_ev] drop_spec_ev[OF liftE_ev] set_cap_reads_respects_f drop_spec_ev[OF assertE_ev] get_cap_wp "4.hyps" reads_respects_f[OF get_cap_rev, where st=st and Q="\"] validE_validE_R'[OF rec_del_silc_inv_not_transferable] | simp add: in_monad)+ apply (rule_tac Q'="\ _. silc_inv aag st and K (pasObjectAbs aag (fst slot) \ SilcLabel \ is_subject aag (fst slot))" in hoare_post_imp_R) prefer 2 apply (clarsimp) apply (rule conjI, assumption) apply (rule impI) apply (drule silc_invD) apply assumption apply (simp add: intra_label_cap_def) apply (rule exI) apply (rule conjI) apply assumption apply (fastforce simp: cap_points_to_label_def) apply (clarsimp simp: slots_holding_overlapping_caps_def2 ctes_wp_at_def) apply (wp validE_validE_R'[OF rec_del_silc_inv_not_transferable] | simp)+ apply (clarsimp simp: zombie_is_cap_toE cte_wp_at_caps_of_state zombie_ptr_emptyable silc_inv_def) done qed lemmas rec_del_reads_respects_f = use_spec_ev[OF rec_del_spec_reads_respects_f] end (* FIXME MOVE in lib *) lemma ev_pre_cont: "equiv_valid I A B \ f" by (simp add: equiv_valid_def2 equiv_valid_2_def) lemma finalise_cap_transferable_ev: "equiv_valid_inv I A (K(is_transferable_cap cap)) (finalise_cap cap final)" by (rule gen_asm_ev) (erule is_transferable_capE; wpsimp wp: return_ev) lemma rec_del_Finalise_transferable_read_respects_f: "reads_respects_f aag l (silc_inv aag st and is_transferable_in slot and K(aag_can_read_not_silc aag (fst slot))) (rec_del (FinaliseSlotCall slot exposed))" apply (subst rec_del.simps[abs_def]) apply (wp | wpc | simp)+ apply ((wp ev_pre_cont hoare_pre_cont)+)[3] apply simp apply (wp liftE_ev finalise_cap_transferable_ev | simp)+ apply (rule hoare_post_imp[OF _ finalise_cap_transferable[where P=\]], fastforce) apply (wpsimp wp: is_final_cap_reads_respects hoare_drop_imp get_cap_wp reads_respects_f[OF get_cap_rev, where st=st and Q="\"])+ by (fastforce simp: cte_wp_at_caps_of_state) lemma rec_del_Finalise_transferableE_R: "\(\s. is_transferable (caps_of_state s slot)) and P\ rec_del (FinaliseSlotCall slot exposed) \\_. P\, -" apply (rule hoare_pre) apply (simp add: validE_R_def) apply (rule hoare_post_impErr) apply (rule rec_del_Finalise_transferable) by force+ context Finalise_IF_1 begin lemma rec_del_CTEDeleteCall_reads_respects_f: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and only_timer_irq_inv irq st' and einvs and simple_sched_action and pas_refined aag and emptyable slot and cdt_change_allowed' aag slot and (\s. \ exposed \ ex_cte_cap_wp_to (\cp. cap_irqs cp = {}) slot s)) (rec_del (CTEDeleteCall slot exposed))" apply (cases "is_subject aag (fst slot)") apply (rule equiv_valid_guard_imp) apply (wp rec_del_reads_respects_f) apply fastforce apply (subst rec_del.simps[abs_def]) apply (wp when_ev reads_respects_f[OF empty_slot_reads_respects] empty_slot_silc_inv rec_del_Finalise_transferable_read_respects_f hoare_vcg_all_lift_R hoare_drop_impE_R rec_del_Finalise_transferableE_R | wpc | simp)+ apply clarsimp apply (frule(3) cca_can_read[OF invs_mdb invs_valid_objs]) apply (frule(2) cdt_change_allowed_not_silc[rotated 2], force, force) apply (frule(1) cca_to_transferable_or_subject[rotated 2], force, force) apply force done lemma cap_delete_reads_respects: assumes domains_distinct[wp]: "pas_domains_distinct aag" shows "reads_respects_f aag l (silc_inv aag st and only_timer_irq_inv irq st' and einvs and simple_sched_action and pas_refined aag and emptyable slot and K (is_subject aag (fst slot))) (cap_delete slot)" unfolding cap_delete_def by (wp rec_del_spec_reads_respects_f | rule use_spec_ev | simp | elim conjE | force)+ end lemma globals_equiv_interrupt_states_update: "globals_equiv st (s\interrupt_states := x\) = globals_equiv st s" by (auto simp: globals_equiv_def idle_equiv_def) lemma cancel_all_ipc_globals_equiv': "cancel_all_ipc epptr \globals_equiv st and valid_arch_state\" unfolding cancel_all_ipc_def by (wp mapM_x_wp[OF _ subset_refl] set_thread_state_globals_equiv set_simple_ko_globals_equiv hoare_vcg_all_lift get_object_inv dxo_wp_weak | wpc | simp | wp (once) hoare_drop_imps)+ lemma cancel_all_ipc_globals_equiv: "\globals_equiv st and valid_arch_state\ cancel_all_ipc epptr \\_. globals_equiv st\" by (fastforce intro: hoare_strengthen_post[OF cancel_all_ipc_globals_equiv']) crunch valid_global_objs: fast_finalise "valid_global_objs" (wp: crunch_wps dxo_wp_weak ignore: reschedule_required) lemma cancel_all_signals_globals_equiv': "cancel_all_signals epptr \globals_equiv st and valid_arch_state\" unfolding cancel_all_signals_def by (wp mapM_x_wp[OF _ subset_refl] set_thread_state_globals_equiv set_simple_ko_globals_equiv hoare_vcg_all_lift get_object_inv dxo_wp_weak | wpc | simp | wp (once) hoare_drop_imps)+ lemma cancel_all_signals_globals_equiv: "\globals_equiv st and valid_arch_state\ cancel_all_signals epptr \\_. globals_equiv st\" by (fastforce intro: hoare_strengthen_post[OF cancel_all_signals_globals_equiv']) context Finalise_IF_1 begin lemma unbind_notification_globals_equiv: "\globals_equiv st and valid_arch_state\ unbind_notification t \\_. globals_equiv st\" unfolding unbind_notification_def by (wpsimp wp: gbn_wp set_bound_notification_globals_equiv set_notification_globals_equiv) lemma unbind_maybe_notification_globals_equiv: "\globals_equiv st and valid_arch_state\ unbind_maybe_notification a \\_. globals_equiv st\" unfolding unbind_maybe_notification_def by (wpsimp wp: gbn_wp set_bound_notification_globals_equiv set_notification_globals_equiv get_simple_ko_wp) lemma fast_finalise_globals_equiv: "\globals_equiv st and valid_arch_state\ fast_finalise cap final \\_. globals_equiv st\" apply (cases cap) by (wpsimp wp: cancel_all_ipc_globals_equiv cancel_all_signals_globals_equiv unbind_maybe_notification_globals_equiv simp: when_def split_del: if_split)+ crunch globals_equiv[wp]: deleted_irq_handler "globals_equiv st" lemma empty_slot_globals_equiv: "\globals_equiv st and valid_arch_state\ empty_slot s b \\_. globals_equiv st\" unfolding empty_slot_def post_cap_deletion_def by (wpsimp wp: set_cap_globals_equiv'' set_original_globals_equiv hoare_vcg_if_lift2 set_cdt_globals_equiv dxo_wp_weak hoare_drop_imps hoare_vcg_all_lift) crunch globals_equiv: cap_delete_one "globals_equiv st" (wp: set_cap_globals_equiv'' hoare_drop_imps simp: crunch_simps unless_def) (*FIXME: Lots of this stuff should be in arch *) crunch globals_equiv[wp]: deleting_irq_handler "globals_equiv st" crunch globals_equiv[wp]: cancel_ipc "globals_equiv st" (wp: mapM_x_wp select_inv hoare_drop_imps hoare_vcg_if_lift2 simp: unless_def) lemma suspend_globals_equiv[ wp]: "\globals_equiv st and (\s. t \ idle_thread s) and valid_arch_state\ suspend t \\_. globals_equiv st\" unfolding suspend_def update_restart_pc_def apply (wp tcb_sched_action_extended.globals_equiv dxo_wp_weak) apply simp apply (wp set_thread_state_globals_equiv) apply wp+ apply clarsimp apply (rule hoare_vcg_conj_lift) prefer 2 apply (rule hoare_drop_imps) apply wp+ apply (rule hoare_drop_imps) apply wp+ apply auto done crunches unbind_notification for valid_arch_state[wp]: valid_arch_state lemma finalise_cap_globals_equiv: "\globals_equiv st and invs and valid_cap cap and (\s. \p. cap = ThreadCap p \ p \ idle_thread s)\ finalise_cap cap b \\ _. globals_equiv st\" apply (induct cap; simp) by (wp cancel_all_ipc_globals_equiv cancel_all_ipc_valid_global_objs cancel_all_signals_globals_equiv cancel_all_signals_valid_global_objs arch_finalise_cap_globals_equiv unbind_maybe_notification_globals_equiv unbind_notification_globals_equiv liftM_wp when_def | clarsimp simp: valid_cap_def | intro impI conjI)+ end end