(* * Copyright 2014, General Dynamics C4 Systems * * SPDX-License-Identifier: GPL-2.0-only *) theory IpcCancel_AI imports ArchSchedule_AI begin context begin interpretation Arch . requalify_facts arch_post_cap_deletion_pred_tcb_at end declare arch_post_cap_deletion_pred_tcb_at[wp] lemma blocked_cancel_ipc_simple: "\tcb_at t\ blocked_cancel_ipc ts t \\rv. st_tcb_at simple t\" by (simp add: blocked_cancel_ipc_def | wp sts_st_tcb_at')+ lemma cancel_signal_simple: "\\\ cancel_signal t ntfn \\rv. st_tcb_at simple t\" by (simp add: cancel_signal_def | wp sts_st_tcb_at')+ crunch typ_at: cancel_all_ipc "\s. P (typ_at T p s)" (wp: crunch_wps mapM_x_wp) lemma cancel_all_helper: " \valid_objs and (\s. \t \ set queue. st_tcb_at (\st. \ halted st) t s) \ mapM_x (\t. do y \ set_thread_state t Structures_A.Restart; do_extended_op (tcb_sched_enqueue_ext t) od) queue \\rv. valid_objs\" apply (rule hoare_strengthen_post) apply (rule mapM_x_wp [where S="set queue", simplified]) apply (wp, simp, wp hoare_vcg_const_Ball_lift sts_st_tcb_at_cases, simp) apply (clarsimp elim: pred_tcb_weakenE) apply (erule(1) my_BallE) apply (clarsimp simp: st_tcb_def2) apply (frule(1) valid_tcb_objs) apply (clarsimp simp: valid_tcb_def valid_tcb_state_def cte_wp_at_cases tcb_cap_cases_def dest!: get_tcb_SomeD) apply simp+ done lemma cancel_all_ipc_valid_objs: "\valid_objs and (\s. sym_refs (state_refs_of s))\ cancel_all_ipc ptr \\_. valid_objs\" apply (simp add: cancel_all_ipc_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (case_tac ep, simp_all add: get_ep_queue_def) apply (wp, simp) apply (wp cancel_all_helper hoare_vcg_const_Ball_lift | clarsimp simp: ep_queued_st_tcb_at obj_at_def valid_ep_def)+ done crunch typ_at: cancel_all_signals "\s. P (typ_at T p s)" (wp: crunch_wps mapM_x_wp) lemma unbind_notification_valid_objs_helper: "valid_ntfn ntfn s \ valid_ntfn (ntfn_set_bound_tcb ntfn None) s " by (clarsimp simp: valid_bound_tcb_def valid_ntfn_def split: option.splits ntfn.splits) lemma unbind_notification_valid_objs: "\valid_objs\ unbind_notification ptr \\rv. valid_objs\" unfolding unbind_notification_def apply (wp thread_set_valid_objs_triv set_simple_ko_valid_objs hoare_drop_imp | wpc | simp add: tcb_cap_cases_def | strengthen unbind_notification_valid_objs_helper)+ apply (wp thread_get_wp' | simp add:get_bound_notification_def)+ apply (clarsimp) apply (erule (1) obj_at_valid_objsE) apply (clarsimp simp:valid_obj_def valid_tcb_def)+ done lemma cancel_all_signals_valid_objs: "\valid_objs and (\s. sym_refs (state_refs_of s))\ cancel_all_signals ptr \\rv. valid_objs\" apply (simp add: cancel_all_signals_def unbind_maybe_notification_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (rule hoare_pre) apply (wp unbind_notification_valid_objs | wpc | simp_all add:unbind_maybe_notification_def)+ apply (wp cancel_all_helper hoare_vcg_const_Ball_lift set_simple_ko_valid_objs unbind_notification_valid_objs | clarsimp simp: ntfn_queued_st_tcb_at obj_at_def valid_ntfn_def valid_bound_tcb_def | wpc)+ apply (clarsimp split: option.splits) apply (erule (1) valid_objsE) apply (simp add: valid_obj_def valid_ntfn_def) done lemma get_ep_queue_inv[wp]: "\P\ get_ep_queue ep \\_. P\" by (cases ep, simp_all add: get_ep_queue_def) lemma cancel_all_ipc_st_tcb_at: assumes x[simp]: "P Structures_A.Restart" shows "\st_tcb_at P t\ cancel_all_ipc epptr \\rv. st_tcb_at P t\" unfolding cancel_all_ipc_def by (wp ep_cases_weak_wp mapM_x_wp' sts_st_tcb_at_cases | simp)+ lemmas cancel_all_ipc_makes_simple[wp] = cancel_all_ipc_st_tcb_at[where P=simple, simplified] lemma unbind_notification_st_tcb_at[wp]: "\st_tcb_at P t\ unbind_notification t' \\rv. st_tcb_at P t\" unfolding unbind_notification_def by (wp thread_set_no_change_tcb_state hoare_drop_imps | wpc | simp)+ lemma unbind_maybe_notification_st_tcb_at[wp]: "\st_tcb_at P t\ unbind_maybe_notification r \\rv. st_tcb_at P t \" unfolding unbind_maybe_notification_def apply (rule hoare_pre) apply (wp thread_set_no_change_tcb_state hoare_drop_imps| wpc | simp)+ done lemma cancel_all_signals_st_tcb_at: assumes x[simp]: "P Structures_A.Restart" shows "\st_tcb_at P t\ cancel_all_signals ntfnptr \\rv. st_tcb_at P t\" unfolding cancel_all_signals_def unbind_maybe_notification_def by (wp ntfn_cases_weak_wp mapM_x_wp' sts_st_tcb_at_cases hoare_drop_imps unbind_notification_st_tcb_at | simp | wpc)+ lemmas cancel_all_signals_makes_simple[wp] = cancel_all_signals_st_tcb_at[where P=simple, simplified] lemma get_blocking_object_inv[wp]: "\P\ get_blocking_object st \\_. P\" by (cases st, simp_all add: get_blocking_object_def) lemma blocked_ipc_st_tcb_at_general: "\st_tcb_at P t' and K (t = t' \ P Structures_A.Inactive)\ blocked_cancel_ipc st t \\rv. st_tcb_at P t'\" apply (simp add: blocked_cancel_ipc_def) apply (wp sts_st_tcb_at_cases static_imp_wp, simp+) done lemma cancel_signal_st_tcb_at_general: "\st_tcb_at P t' and K (t = t' \ (P Structures_A.Running \ P Structures_A.Inactive))\ cancel_signal t ntfn \\rv. st_tcb_at P t'\" apply (simp add: cancel_signal_def) apply (wp sts_st_tcb_at_cases ntfn_cases_weak_wp static_imp_wp) apply simp done lemma fast_finalise_misc[wp]: "\st_tcb_at simple t \ fast_finalise a b \\_. st_tcb_at simple t\" apply (case_tac a,simp_all) apply (wp|clarsimp)+ done locale IpcCancel_AI = fixes state_ext :: "('a::state_ext) itself" assumes arch_post_cap_deletion_typ_at[wp]: "\P T p acap. \\(s :: 'a state). P (typ_at T p s)\ arch_post_cap_deletion acap \\rv s. P (typ_at T p s)\" assumes arch_post_cap_deletion_idle_thread[wp]: "\P acap. \\(s :: 'a state). P (idle_thread s)\ arch_post_cap_deletion acap \\rv s. P (idle_thread s)\" crunches update_restart_pc for typ_at[wp]: "\s. P (typ_at ty ptr s)" (* NB: Q needed for following has_reply_cap proof *) and cte_wp_at[wp]: "\s. Q (cte_wp_at P cte s)" and idle_thread[wp]: "\s. P (idle_thread s)" and pred_tcb_at[wp]: "\s. pred_tcb_at P proj tcb s" and invs[wp]: "\s. invs s" lemma update_restart_pc_has_reply_cap[wp]: "\\s. \ has_reply_cap t s\ update_restart_pc t \\_ s. \ has_reply_cap t s\" apply (simp add: has_reply_cap_def) apply (wp hoare_vcg_all_lift) done crunch st_tcb_at_simple[wp]: reply_cancel_ipc "st_tcb_at simple t" (wp: crunch_wps select_wp sts_st_tcb_at_cases thread_set_no_change_tcb_state simp: crunch_simps unless_def fast_finalise.simps) lemma cancel_ipc_simple [wp]: "\\\ cancel_ipc t \\rv. st_tcb_at simple t\" apply (simp add: cancel_ipc_def) apply (rule hoare_seq_ext [OF _ gts_sp]) apply (case_tac state, simp_all) apply (wp hoare_strengthen_post [OF blocked_cancel_ipc_simple] hoare_strengthen_post [OF cancel_signal_simple] hoare_strengthen_post [OF reply_cancel_ipc_st_tcb_at_simple [where t=t]] sts_st_tcb_at_cases hoare_drop_imps | clarsimp elim!: pred_tcb_weakenE pred_tcb_at_tcb_at)+ done lemma blocked_cancel_ipc_typ_at[wp]: "\\s. P (typ_at T p s)\ blocked_cancel_ipc st t \\rv s. P (typ_at T p s)\" apply (simp add: blocked_cancel_ipc_def get_blocking_object_def get_ep_queue_def get_simple_ko_def) apply (wp get_object_wp|wpc)+ apply simp done lemma blocked_cancel_ipc_tcb_at [wp]: "\tcb_at t\ blocked_cancel_ipc st t' \\rv. tcb_at t\" by (simp add: tcb_at_typ) wp context IpcCancel_AI begin crunch typ_at[wp]: cancel_ipc, reply_cancel_ipc, unbind_maybe_notification "\(s :: 'a state). P (typ_at T p s)" (wp: crunch_wps hoare_vcg_if_splitE select_wp simp: crunch_simps unless_def) lemma cancel_ipc_tcb [wp]: "\tcb_at t\ cancel_ipc t' \\rv. (tcb_at t) :: 'a state \ bool\" by (simp add: tcb_at_typ) wp end lemma gbep_ret: "\ st = Structures_A.BlockedOnReceive epPtr pl' \ st = Structures_A.BlockedOnSend epPtr pl \ \ get_blocking_object st = return epPtr" by (auto simp add: get_blocking_object_def) lemma st_tcb_at_valid_st2: "\ st_tcb_at ((=) st) t s; valid_objs s \ \ valid_tcb_state st s" apply (clarsimp simp add: valid_objs_def get_tcb_def pred_tcb_at_def obj_at_def) apply (drule_tac x=t in bspec) apply (erule domI) apply (simp add: valid_obj_def valid_tcb_def) done definition "emptyable \ \p s. (tcb_at (fst p) s \ snd p = tcb_cnode_index 2) \ st_tcb_at halted (fst p) s" locale delete_one_abs = IpcCancel_AI state_ext for state_ext :: "('a :: state_ext) itself" + assumes delete_one_invs: "\p. \invs and emptyable p\ (cap_delete_one p :: (unit,'a) s_monad) \\rv. invs\" assumes delete_one_deletes: "\\\ (cap_delete_one sl :: (unit,'a) s_monad) \\rv. cte_wp_at (\c. c = cap.NullCap) sl\" assumes delete_one_caps_of_state: "\P p. \\s. cte_wp_at can_fast_finalise p s \ P ((caps_of_state s) (p \ cap.NullCap))\ (cap_delete_one p :: (unit,'a) s_monad) \\rv s. P (caps_of_state s)\" lemma reply_master_no_descendants_no_reply: "\ valid_mdb s; valid_reply_masters s; tcb_at t s \ \ descendants_of (t, tcb_cnode_index 2) (cdt s) = {} \ \ has_reply_cap t s" by (fastforce simp: invs_def valid_state_def valid_mdb_def has_reply_cap_def cte_wp_at_caps_of_state reply_mdb_def is_reply_cap_to_def reply_caps_mdb_def descendants_of_def cdt_parent_defs dest: reply_master_caps_of_stateD tranclD) lemma reply_cap_unique_descendant: "\ invs s; tcb_at t s \ \ \sl\descendants_of (t, tcb_cnode_index 2) (cdt s). \sl'. sl' \ sl \ sl' \ descendants_of (t, tcb_cnode_index 2) (cdt s)" apply (subgoal_tac "cte_wp_at (\c. (is_master_reply_cap c \ obj_ref_of c = t) \ c = cap.NullCap) (t, tcb_cnode_index 2) s") apply (clarsimp simp: invs_def valid_state_def valid_mdb_def2 is_cap_simps valid_reply_caps_def cte_wp_at_caps_of_state) apply (erule disjE) apply (fastforce simp: reply_mdb_def is_cap_simps dest: unique_reply_capsD) apply (fastforce dest: mdb_cte_at_Null_descendants) apply (clarsimp simp: tcb_cap_wp_at invs_valid_objs tcb_cap_cases_def is_cap_simps) done lemma reply_master_one_descendant: "\ invs s; tcb_at t s; descendants_of (t, tcb_cnode_index 2) (cdt s) \ {} \ \ \sl. descendants_of (t, tcb_cnode_index 2) (cdt s) = {sl}" by (fastforce elim: construct_singleton dest: reply_cap_unique_descendant) lemma ep_redux_simps2: "ep \ Structures_A.IdleEP \ valid_ep (case xs of [] \ Structures_A.endpoint.IdleEP | a # list \ update_ep_queue ep xs) = (\s. distinct xs \ (\t\set xs. tcb_at t s))" "ep \ Structures_A.IdleEP \ ep_q_refs_of (case xs of [] \ Structures_A.endpoint.IdleEP | a # list \ update_ep_queue ep xs) = (set xs \ {case ep of Structures_A.SendEP xs \ EPSend | Structures_A.RecvEP xs \ EPRecv})" by (cases ep, simp_all cong: list.case_cong add: ep_redux_simps)+ lemma gbi_ep_sp: "\P\ get_blocking_object st \\ep. P and K ((\d. st = Structures_A.BlockedOnReceive ep d) \ (\d. st = Structures_A.BlockedOnSend ep d))\" apply (cases st, simp_all add: get_blocking_object_def) apply (wp | simp)+ done lemma get_epq_sp: "\P\ get_ep_queue ep \\q. P and K (ep \ {Structures_A.SendEP q, Structures_A.RecvEP q})\" apply (simp add: get_ep_queue_def) apply (cases ep) apply (wp|simp)+ done lemma refs_in_tcb_bound_refs: "(x, ref) \ tcb_bound_refs ntfn \ ref = TCBBound" by (auto simp: tcb_bound_refs_def split: option.splits) lemma refs_in_ntfn_bound_refs: "(x, ref) \ ntfn_bound_refs tcb \ ref = NTFNBound" by (auto simp: ntfn_bound_refs_def split: option.splits) lemma blocked_cancel_ipc_invs: "\invs and st_tcb_at ((=) st) t\ blocked_cancel_ipc st t \\rv. invs\" apply (simp add: blocked_cancel_ipc_def) apply (rule hoare_seq_ext [OF _ gbi_ep_sp]) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (rule hoare_seq_ext [OF _ get_epq_sp]) apply (simp add: invs_def valid_state_def valid_pspace_def) apply (rule hoare_pre, wp valid_irq_node_typ sts_only_idle) apply (simp add: valid_tcb_state_def) apply (strengthen reply_cap_doesnt_exist_strg) apply simp apply (wp valid_irq_node_typ valid_ioports_lift) apply (subgoal_tac "ep \ Structures_A.IdleEP") apply (clarsimp simp: ep_redux_simps2 cong: if_cong) apply (frule(1) if_live_then_nonz_capD, (clarsimp simp: live_def)+) apply (frule ko_at_state_refs_ofD) apply (erule(1) obj_at_valid_objsE, clarsimp simp: valid_obj_def) apply (frule st_tcb_at_state_refs_ofD) apply (subgoal_tac "epptr \ set (remove1 t queue)") apply (case_tac ep, simp_all add: valid_ep_def)[1] apply (auto elim!: delta_sym_refs pred_tcb_weaken_strongerE simp: obj_at_def is_ep_def2 idle_not_queued refs_in_tcb_bound_refs dest: idle_no_refs split: if_split_asm)[2] apply (case_tac ep, simp_all add: valid_ep_def)[1] apply (clarsimp, drule(1) bspec, clarsimp simp: obj_at_def is_tcb_def)+ apply fastforce done lemma symreftype_inverse': "symreftype ref = ref' \ ref = symreftype ref'" by (cases ref) simp_all lemma cancel_signal_invs: "\invs and st_tcb_at ((=) (Structures_A.BlockedOnNotification ntfn)) t\ cancel_signal t ntfn \\rv. invs\" apply (simp add: cancel_signal_def invs_def valid_state_def valid_pspace_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (case_tac "ntfn_obj ntfna", simp_all)[1] apply (rule hoare_pre) apply (wp set_simple_ko_valid_objs valid_irq_node_typ sts_only_idle valid_ioports_lift | simp add: valid_tcb_state_def | strengthen reply_cap_doesnt_exist_strg | wpc)+ apply (clarsimp simp: ep_redux_simps cong: list.case_cong if_cong) apply (frule(1) if_live_then_nonz_capD, (clarsimp simp: live_def)+) apply (frule ko_at_state_refs_ofD) apply (frule st_tcb_at_state_refs_ofD) apply (erule(1) obj_at_valid_objsE, clarsimp simp: valid_obj_def valid_ntfn_def) apply (case_tac ntfna) apply clarsimp apply (rule conjI) apply (clarsimp simp: pred_tcb_at_def obj_at_def) apply clarsimp apply (rule conjI) apply (clarsimp split:option.split) apply (rule conjI, erule delta_sym_refs) apply (clarsimp split: if_split_asm)+ apply (fastforce dest: refs_in_tcb_bound_refs refs_in_ntfn_bound_refs symreftype_inverse') apply (fastforce simp: obj_at_def is_ntfn idle_not_queued dest: idle_no_refs elim: pred_tcb_weakenE) done lemma reply_mdb_cte_at_master_None: "\ reply_mdb m cs; mdb_cte_at (\p. \c. cs p = Some c \ cap.NullCap \ c) m; cs ptr = Some cap; is_master_reply_cap cap \ \ m ptr = None" unfolding reply_mdb_def reply_masters_mdb_def by (fastforce simp: is_cap_simps) lemma reply_slot_not_descendant: "\ptr. \ invs s; tcb_at t s \ \ (t, tcb_cnode_index 2) \ descendants_of ptr (cdt s)" apply (subgoal_tac "cte_wp_at (\c. is_master_reply_cap c \ c = cap.NullCap) (t, tcb_cnode_index 2) s") apply (fastforce simp: invs_def valid_state_def valid_mdb_def2 cte_wp_at_caps_of_state dest: reply_mdb_cte_at_master_None mdb_cte_at_Null_None descendants_of_NoneD) apply (clarsimp simp: tcb_cap_wp_at invs_valid_objs tcb_cap_cases_def) done lemma reply_cancel_ipc_invs: assumes delete: "\p. \invs and emptyable p\ (cap_delete_one p :: (unit,'z::state_ext) s_monad) \\rv. invs\" shows "\invs\ (reply_cancel_ipc t :: (unit,'z::state_ext) s_monad) \\rv. invs\" apply (simp add: reply_cancel_ipc_def) apply (wp delete select_wp) apply (rule_tac Q="\rv. invs" in hoare_post_imp) apply (fastforce simp: emptyable_def dest: reply_slot_not_descendant) apply (wp thread_set_invs_trivial) apply (auto simp: tcb_cap_cases_def)+ done lemma (in delete_one_abs) cancel_ipc_invs[wp]: "\invs\ (cancel_ipc t :: (unit,'a) s_monad) \\rv. invs\" apply (simp add: cancel_ipc_def) apply (rule hoare_seq_ext [OF _ gts_sp]) apply (case_tac state, simp_all) apply (auto intro!: hoare_weaken_pre [OF return_wp] hoare_weaken_pre [OF blocked_cancel_ipc_invs] hoare_weaken_pre [OF cancel_signal_invs] hoare_weaken_pre [OF reply_cancel_ipc_invs] delete_one_invs elim!: pred_tcb_weakenE) done context IpcCancel_AI begin lemma cancel_ipc_valid_cap: "\valid_cap c\ cancel_ipc p \\_. (valid_cap c) :: 'a state \ bool\" by (wp valid_cap_typ) lemma cancel_ipc_cte_at[wp]: "\cte_at p\ cancel_ipc t \\_. (cte_at p) :: 'a state \ bool\" by (wp valid_cte_at_typ) end lemma valid_ep_queue_subset: "\\s. valid_ep ep s\ get_ep_queue ep \\queue s. valid_ep (case (remove1 t queue) of [] \ Structures_A.endpoint.IdleEP | a # list \ update_ep_queue ep (remove1 t queue)) s\" apply (simp add: get_ep_queue_def) apply (case_tac ep, simp_all) apply wp apply (clarsimp simp: ep_redux_simps2 valid_ep_def) apply wp apply (clarsimp simp: ep_redux_simps2 valid_ep_def) done lemma blocked_cancel_ipc_valid_objs[wp]: "\valid_objs\ blocked_cancel_ipc st t \\_. valid_objs\" apply (simp add: blocked_cancel_ipc_def) apply (wp get_simple_ko_valid[where f=Endpoint, simplified valid_ep_def2[symmetric]] valid_ep_queue_subset | simp only: valid_inactive simp_thms cong: imp_cong | rule hoare_drop_imps | clarsimp)+ done lemma cancel_signal_valid_objs[wp]: "\valid_objs\ cancel_signal t ntfnptr \\_. valid_objs\" apply (simp add: cancel_signal_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (rule hoare_pre) apply (wp set_simple_ko_valid_objs | simp only: valid_inactive | simp | wpc)+ apply (clarsimp simp: ep_redux_simps cong: list.case_cong) apply (erule(1) obj_at_valid_objsE) apply (clarsimp simp: valid_obj_def valid_ntfn_def) apply (auto split: option.splits list.splits) done lemma tcb_in_valid_state: "\ st_tcb_at P t s; valid_objs s \ \ \st. P st \ valid_tcb_state st s" apply (clarsimp simp add: valid_objs_def pred_tcb_at_def obj_at_def) apply (erule my_BallE, erule domI) apply (simp add: valid_obj_def valid_tcb_def) apply blast done lemma no_refs_simple_strg: "st_tcb_at simple t s \ P {} \ st_tcb_at (\st. P (tcb_st_refs_of st)) t s" by (fastforce elim!: pred_tcb_weakenE)+ crunch it[wp]: cancel_all_ipc "\s. P (idle_thread s)" (wp: crunch_wps select_wp simp: unless_def crunch_simps) crunch it[wp]: cancel_all_signals, fast_finalise, unbind_notification "\s. P (idle_thread s)" (wp: crunch_wps select_wp simp: unless_def crunch_simps) context IpcCancel_AI begin crunch it[wp]: reply_cancel_ipc "\(s::'a state). P (idle_thread s)" (wp: crunch_wps select_wp simp: unless_def crunch_simps) crunch it[wp]: cancel_ipc "\(s :: 'a state). P (idle_thread s)" end lemma reply_cap_descends_from_master: "\ invs s; tcb_at t s \ \ \sl\descendants_of (t, tcb_cnode_index 2) (cdt s). \sl' R. sl' \ sl \ caps_of_state s sl' \ Some (cap.ReplyCap t False R)" apply (subgoal_tac "cte_wp_at (\c. (is_master_reply_cap c \ obj_ref_of c = t) \ c = cap.NullCap) (t, tcb_cnode_index 2) s") apply (clarsimp simp: invs_def valid_state_def valid_mdb_def2 is_cap_simps valid_reply_caps_def cte_wp_at_caps_of_state) apply (erule disjE) apply (unfold reply_mdb_def reply_masters_mdb_def)[1] apply (elim conjE) apply (erule_tac x="(t, tcb_cnode_index 2)" in allE) apply (erule_tac x=t in allE)+ apply (fastforce simp: unique_reply_caps_def is_cap_simps) apply (fastforce dest: mdb_cte_at_Null_descendants) apply (clarsimp simp: tcb_cap_wp_at invs_valid_objs tcb_cap_cases_def is_cap_simps) done lemma (in delete_one_abs) reply_cancel_ipc_no_reply_cap[wp]: notes hoare_pre shows "\invs and tcb_at t\ (reply_cancel_ipc t :: (unit,'a) s_monad) \\rv s. \ has_reply_cap t s\" apply (simp add: reply_cancel_ipc_def) apply wp apply (rule_tac Q="\rvp s. cte_wp_at (\c. c = cap.NullCap) x s \ (\sl R. sl \ x \ caps_of_state s sl \ Some (cap.ReplyCap t False R))" in hoare_strengthen_post) apply (wp hoare_vcg_conj_lift hoare_vcg_all_lift delete_one_deletes delete_one_caps_of_state) apply (clarsimp simp: has_reply_cap_def cte_wp_at_caps_of_state is_reply_cap_to_def) apply (case_tac "(aa, ba) = (a, b)",simp_all)[1] apply (wp hoare_vcg_all_lift select_wp | simp del: split_paired_All)+ apply (rule_tac Q="\_ s. invs s \ tcb_at t s" in hoare_post_imp) apply (erule conjE) apply (frule(1) reply_cap_descends_from_master) apply (auto dest: reply_master_no_descendants_no_reply[rotated -1])[1] apply (wp thread_set_invs_trivial | clarsimp simp: tcb_cap_cases_def)+ done lemma (in delete_one_abs) cancel_ipc_no_reply_cap[wp]: shows "\invs and tcb_at t\ (cancel_ipc t :: (unit,'a) s_monad) \\rv s. \ has_reply_cap t s\" apply (simp add: cancel_ipc_def) apply (wpsimp wp: hoare_post_imp [OF invs_valid_reply_caps] reply_cancel_ipc_no_reply_cap cancel_signal_invs cancel_signal_st_tcb_at_general blocked_cancel_ipc_invs blocked_ipc_st_tcb_at_general | strengthen reply_cap_doesnt_exist_strg)+ apply (rule_tac Q="\rv. st_tcb_at ((=) rv) t and invs" in hoare_strengthen_post) apply (wpsimp wp: gts_st_tcb) apply (fastforce simp: invs_def valid_state_def st_tcb_at_tcb_at elim!: pred_tcb_weakenE)+ done lemma (in delete_one_abs) suspend_invs[wp]: "\invs and tcb_at t and (\s. t \ idle_thread s)\ (suspend t :: (unit,'a) s_monad) \\rv. invs\" by (wp sts_invs_minor user_getreg_inv as_user_invs sts_invs_minor cancel_ipc_invs cancel_ipc_no_reply_cap | strengthen no_refs_simple_strg | simp add: suspend_def)+ context IpcCancel_AI begin lemma suspend_typ_at [wp]: "\\(s::'a state). P (typ_at T p s)\ suspend t \\rv s. P (typ_at T p s)\" by (wpsimp simp: suspend_def) lemma suspend_valid_cap: "\valid_cap c\ suspend tcb \\_. (valid_cap c) :: 'a state \ bool\" by (wp valid_cap_typ) lemma suspend_tcb[wp]: "\tcb_at t'\ suspend t \\rv. (tcb_at t') :: 'a state \ bool\" by (simp add: tcb_at_typ) wp end declare if_cong [cong del] crunch cte_wp_at[wp]: blocked_cancel_ipc "cte_wp_at P p" (wp: crunch_wps) crunch cte_wp_at[wp]: cancel_signal "cte_wp_at P p" (wp: crunch_wps) locale delete_one_pre = fixes state_ext_type :: "('a :: state_ext) itself" assumes delete_one_cte_wp_at_preserved: "(\cap. P cap \ \ can_fast_finalise cap) \ \cte_wp_at P sl\ (cap_delete_one sl' :: (unit,'a) s_monad) \\rv. cte_wp_at P sl\" lemma (in delete_one_pre) reply_cancel_ipc_cte_wp_at_preserved: "(\cap. P cap \ \ can_fast_finalise cap) \ \cte_wp_at P p\ (reply_cancel_ipc t :: (unit,'a) s_monad) \\rv. cte_wp_at P p\" unfolding reply_cancel_ipc_def apply (wpsimp wp: select_wp delete_one_cte_wp_at_preserved) apply (rule_tac Q="\_. cte_wp_at P p" in hoare_post_imp, clarsimp) apply (wpsimp wp: thread_set_cte_wp_at_trivial simp: ran_tcb_cap_cases) apply assumption done lemma (in delete_one_pre) cancel_ipc_cte_wp_at_preserved: "(\cap. P cap \ \ can_fast_finalise cap) \ \cte_wp_at P p\ (cancel_ipc t :: (unit,'a) s_monad) \\rv. cte_wp_at P p\" apply (simp add: cancel_ipc_def) apply (rule hoare_pre) apply (wp reply_cancel_ipc_cte_wp_at_preserved | wpcw | simp)+ done lemma (in delete_one_pre) suspend_cte_wp_at_preserved: "(\cap. P cap \ \ can_fast_finalise cap) \ \cte_wp_at P p\ (suspend tcb :: (unit,'a) s_monad) \\_. cte_wp_at P p\" by (simp add: suspend_def) (wpsimp wp: cancel_ipc_cte_wp_at_preserved)+ (* FIXME - eliminate *) lemma obj_at_exst_update: "obj_at P p (trans_state f s) = obj_at P p s" by (rule more_update.obj_at_update) lemma set_thread_state_bound_tcb_at[wp]: "\bound_tcb_at P t\ set_thread_state p ts \\_. bound_tcb_at P t\" unfolding set_thread_state_def set_object_def get_object_def by (wpsimp simp: pred_tcb_at_def obj_at_def get_tcb_def) crunch bound_tcb_at[wp]: cancel_all_ipc, empty_slot, is_final_cap, get_cap "bound_tcb_at P t" (wp: mapM_x_wp_inv) lemma fast_finalise_bound_tcb_at: "\\s. bound_tcb_at P t s \ (\tt b R. cap = ReplyCap tt b R) \ fast_finalise cap final \\_. bound_tcb_at P t\" by (case_tac cap, simp_all) lemma get_cap_reply_cap_helper: "\\s. \t b R. Some (ReplyCap t b R) = caps_of_state s slot \ get_cap slot \\rv s. \t b R. rv = ReplyCap t b R\" by (auto simp: valid_def get_cap_caps_of_state[symmetric]) lemma cap_delete_one_bound_tcb_at: "\\s. bound_tcb_at P t s \ (\t b R. caps_of_state s c = Some (ReplyCap t b R)) \ cap_delete_one c \\_. bound_tcb_at P t\" apply (clarsimp simp: unless_def cap_delete_one_def) apply (wp fast_finalise_bound_tcb_at) apply (wp hoare_vcg_if_lift2, simp) apply (wp hoare_conjI) apply (wp only:hoare_drop_imp) apply (wp hoare_vcg_conj_lift) apply (wp get_cap_reply_cap_helper hoare_drop_imp | clarsimp)+ done lemma valid_mdb_impl_reply_masters: "valid_mdb s \ reply_masters_mdb (cdt s) (caps_of_state s)" by (auto simp: valid_mdb_def reply_mdb_def) lemma caps_of_state_tcb_index_trans: "\get_tcb p s = Some tcb \ \ caps_of_state s (p, tcb_cnode_index n) = (tcb_cnode_map tcb) (tcb_cnode_index n)" apply (drule get_tcb_SomeD) apply (clarsimp simp: caps_of_state_def) apply (safe) apply (clarsimp simp: get_object_def get_cap_def) apply (simp add:set_eq_iff) apply (drule_tac x=cap in spec) apply (drule_tac x=s in spec) apply (clarsimp simp: in_monad) apply (clarsimp simp: get_cap_def get_object_def) apply (rule ccontr) apply (drule not_sym) apply (auto simp: set_eq_iff in_monad) done lemma descendants_of_nullcap: "\descendants_of (a, b) (cdt s) \ {}; valid_mdb s \ \ caps_of_state s (a, b) \ Some NullCap" apply clarsimp apply (drule_tac cs="caps_of_state s" and p="(a,b)" and m="(cdt s)" in mdb_cte_at_Null_descendants) apply (clarsimp simp: valid_mdb_def2)+ done lemma reply_cancel_ipc_bound_tcb_at[wp]: "\bound_tcb_at P t and valid_mdb and valid_objs and tcb_at p \ reply_cancel_ipc p \\_. bound_tcb_at P t\" unfolding reply_cancel_ipc_def apply (wpsimp wp: cap_delete_one_bound_tcb_at select_inv select_wp) apply (rule_tac Q="\_. bound_tcb_at P t and valid_mdb and valid_objs and tcb_at p" in hoare_strengthen_post) apply (wpsimp wp: thread_set_no_change_tcb_pred thread_set_mdb) apply (fastforce simp:tcb_cap_cases_def) apply (wpsimp wp: thread_set_valid_objs_triv simp: ran_tcb_cap_cases) apply clarsimp apply (frule valid_mdb_impl_reply_masters) apply (clarsimp simp: reply_masters_mdb_def) apply (spec p) apply (spec "tcb_cnode_index 2") apply (spec p) apply (clarsimp simp:tcb_at_def) apply (frule(1) valid_tcb_objs) apply (clarsimp simp: valid_tcb_def) apply (erule impE) apply (simp add: caps_of_state_tcb_index_trans tcb_cnode_map_def) apply (clarsimp simp: tcb_cap_cases_def is_master_reply_cap_def split:cap.splits ) apply (subgoal_tac "descendants_of (p, tcb_cnode_index 2) (cdt s) \ {}") prefer 2 apply simp apply (drule descendants_of_nullcap, simp) apply (simp add: caps_of_state_tcb_index_trans tcb_cnode_map_def) apply fastforce apply simp done crunch bound_tcb_at[wp]: cancel_ipc "bound_tcb_at P t" (ignore: set_object thread_set wp: mapM_x_wp_inv) context IpcCancel_AI begin lemma suspend_unlive: "\\(s::'a state). (bound_tcb_at ((=) None) t and valid_mdb and valid_objs) s \ suspend t \\rv. obj_at (Not \ live0) t\" apply (simp add: suspend_def set_thread_state_def set_object_def get_object_def) (* avoid creating two copies of obj_at *) supply hoare_vcg_if_split[wp_split del] if_splits[split del] apply (wp | simp only: obj_at_exst_update)+ apply (simp add: obj_at_def) apply (rule_tac Q="\_. bound_tcb_at ((=) None) t" in hoare_strengthen_post) supply hoare_vcg_if_split[wp_split] apply wp apply (auto simp: pred_tcb_def2)[1] apply (simp flip: if_split) apply wpsimp+ apply (simp add: pred_tcb_at_tcb_at) done end definition bound_refs_of_tcb :: "'a state \ machine_word \ (machine_word \ reftype) set" where "bound_refs_of_tcb s t \ case kheap s t of Some (TCB tcb) \ tcb_bound_refs (tcb_bound_notification tcb) | _ \ {}" lemma bound_refs_of_tcb_trans: "bound_refs_of_tcb (trans_state f s) x = bound_refs_of_tcb s x" by (clarsimp simp:bound_refs_of_tcb_def trans_state_def) lemma cancel_all_invs_helper: "\all_invs_but_sym_refs and (\s. (\x\set q. ex_nonz_cap_to x s) \ sym_refs (\x. if x \ set q then {r \ state_refs_of s x. snd r = TCBBound} else state_refs_of s x) \ sym_refs (\x. state_hyp_refs_of s x) \ (\x\set q. st_tcb_at (Not \ (halted or awaiting_reply)) x s))\ mapM_x (\t. do y \ set_thread_state t Structures_A.thread_state.Restart; do_extended_op (tcb_sched_enqueue_ext t) od) q \\rv. invs\" apply (simp add: invs_def valid_state_def valid_pspace_def) apply (rule mapM_x_inv_wp2) apply (clarsimp simp: ) apply wp apply (simp add:bound_refs_of_tcb_trans) apply wp[1] apply (rule hoare_pre, wp hoare_vcg_const_Ball_lift valid_irq_node_typ sts_only_idle) apply (rule sts_st_tcb_at_cases, simp) apply (strengthen reply_cap_doesnt_exist_strg) apply (auto simp: valid_tcb_state_def idle_no_ex_cap o_def if_split_asm elim!: rsubst[where P=sym_refs] st_tcb_weakenE intro!: ext) done lemma ep_no_bound_refs: "ep_at p s \ {r \ state_refs_of s p. snd r = TCBBound} = {}" by (clarsimp simp: obj_at_def state_refs_of_def refs_of_def is_ep ep_q_refs_of_def split: endpoint.splits) lemma obj_at_conj_distrib: "obj_at (\ko. P ko \ Q ko) p s \ obj_at (\ko. P ko) p s \ obj_at (\ko. Q ko) p s" by (auto simp:obj_at_def) lemma ep_q_refs_of_no_ntfn_bound: "(x, tp) \ ep_q_refs_of ep \ tp \ NTFNBound" by (auto simp: ep_q_refs_of_def split:endpoint.splits) lemma ep_q_refs_no_NTFNBound: "(x, NTFNBound) \ ep_q_refs_of ep" by (clarsimp simp: ep_q_refs_of_def split:endpoint.splits) lemma ep_list_tcb_at: "\ep_at p s; valid_objs s; state_refs_of s p = set q \ {k}; x \ set q \ \ tcb_at x s" apply (erule (1) obj_at_valid_objsE) apply (fastforce simp:is_ep valid_obj_def valid_ep_def state_refs_of_def split:endpoint.splits) done lemma tcb_at_no_ntfn_bound: "\ valid_objs s; tcb_at x s \ \ (t, NTFNBound) \ state_refs_of s x" by (auto elim!: obj_at_valid_objsE simp: state_refs_of_def is_tcb valid_obj_def tcb_bound_refs_def tcb_st_refs_of_def split:thread_state.splits option.splits) lemma ep_no_ntfn_bound: "\is_ep ko; refs_of ko = set q \ {NTFNBound}; y \ set q \ \ False" apply (subst (asm) set_eq_iff) apply (drule_tac x="(y, NTFNBound)" in spec) apply (clarsimp simp: refs_of_rev is_ep) done lemma cancel_all_ipc_invs_helper: assumes x: "\x ko. (x, symreftype k) \ refs_of ko \ (refs_of ko = {(x, symreftype k)} \ (\y. refs_of ko = {(x, symreftype k), (y, TCBBound)}))" shows "\invs and obj_at (\ko. is_ep ko \ refs_of ko = set q \ {k}) p\ do y \ set_endpoint p Structures_A.endpoint.IdleEP; y \ mapM_x (\t. do y \ set_thread_state t Structures_A.thread_state.Restart; do_extended_op (tcb_sched_action (tcb_sched_enqueue) t) od) q; do_extended_op reschedule_required od \\rv. invs\" apply (subst bind_assoc[symmetric]) apply (rule hoare_seq_ext) apply wp apply simp apply (rule hoare_pre) apply (wp cancel_all_invs_helper hoare_vcg_const_Ball_lift valid_irq_node_typ valid_ioports_lift) apply (clarsimp simp: invs_def valid_state_def valid_pspace_def valid_ep_def live_def) apply (rule conjI) apply (fastforce simp: live_def is_ep_def elim!: obj_at_weakenE split: kernel_object.splits) apply (rule conjI) apply clarsimp apply (drule(1) sym_refs_obj_atD, clarsimp) apply (drule(1) bspec, erule(1) if_live_then_nonz_capD) apply (rule refs_of_live, clarsimp) apply (rule conjI[rotated]) apply (subgoal_tac "\ep. ko_at (Endpoint ep) p s", clarsimp) apply (subgoal_tac "\rt. (x, rt) \ ep_q_refs_of ep", clarsimp) apply (fastforce elim!: ep_queued_st_tcb_at) apply (clarsimp simp: obj_at_def is_ep_def)+ apply (case_tac ko, simp_all) apply (frule(1) sym_refs_obj_atD) apply (frule obj_at_state_refs_ofD) apply (clarsimp dest!:obj_at_conj_distrib) apply (thin_tac "obj_at (\ko. refs_of ko = set q \ {k}) p s") apply (erule delta_sym_refs) apply (clarsimp simp: if_split_asm)+ apply (safe) apply (fastforce dest!:symreftype_inverse' ep_no_ntfn_bound) apply (clarsimp dest!: symreftype_inverse') apply (frule (3) ep_list_tcb_at) apply (frule_tac t=y in tcb_at_no_ntfn_bound, simp+) apply (clarsimp dest!: symreftype_inverse') apply (frule (3) ep_list_tcb_at) apply (clarsimp simp: obj_at_def is_tcb is_ep) apply (fastforce dest!: obj_at_state_refs_ofD x) apply (fastforce dest!: obj_at_state_refs_ofD x) apply (fastforce dest!: symreftype_inverse' ep_no_ntfn_bound) apply (clarsimp) apply (fastforce dest!: symreftype_inverse' ep_no_ntfn_bound) done lemma cancel_all_ipc_invs: "\invs\ cancel_all_ipc epptr \\rv. invs\" apply (simp add: cancel_all_ipc_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (case_tac ep, simp_all add: get_ep_queue_def) apply (wp, fastforce) apply (rule hoare_pre, rule cancel_all_ipc_invs_helper[where k=EPSend]) apply (fastforce simp: refs_of_rev tcb_bound_refs_def split: option.splits) apply (clarsimp elim!: obj_at_weakenE simp: is_ep) apply (rule hoare_pre, rule cancel_all_ipc_invs_helper[where k=EPRecv]) apply (fastforce simp: refs_of_rev tcb_bound_refs_def split: option.splits) apply (clarsimp elim!: obj_at_weakenE simp: is_ep) done lemma ntfn_q_refs_no_NTFNBound: "(x, NTFNBound) \ ntfn_q_refs_of ntfn" by (auto simp: ntfn_q_refs_of_def split:ntfn.splits) lemma ntfn_q_refs_no_TCBBound: "(x, TCBBound) \ ntfn_q_refs_of ntfn" by (auto simp: ntfn_q_refs_of_def split:ntfn.splits) lemma ntfn_bound_tcb_get_set[simp]: "ntfn_bound_tcb (ntfn_set_bound_tcb ntfn ntfn') = ntfn'" by auto lemma ntfn_obj_tcb_get_set[simp]: "ntfn_obj (ntfn_set_bound_tcb ntfn ntfn') = ntfn_obj ntfn" by auto lemma valid_ntfn_set_bound_None: "valid_ntfn ntfn s \ valid_ntfn (ntfn_set_bound_tcb ntfn None) s" by (auto simp: valid_ntfn_def split:ntfn.splits) lemma ntfn_bound_tcb_at: "\sym_refs (state_refs_of s); valid_objs s; kheap s ntfnptr = Some (Notification ntfn); ntfn_bound_tcb ntfn = Some tcbptr; P (Some ntfnptr)\ \ bound_tcb_at P tcbptr s" 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 elim!: valid_objsE) done lemma bound_tcb_bound_notification_at: "\sym_refs (state_refs_of s); valid_objs s; kheap s ntfnptr = Some (Notification ntfn); bound_tcb_at (\ptr. ptr = (Some ntfnptr)) tcbptr s \ \ ntfn_bound_tcb ntfn = Some tcbptr" apply (drule_tac x=tcbptr in sym_refsD[rotated]) apply (fastforce simp: state_refs_of_def pred_tcb_at_def obj_at_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 elim!: valid_objsE) done lemma unbind_notification_invs: shows "\invs\ unbind_notification t \\rv. invs\" apply (simp add: unbind_notification_def invs_def valid_state_def valid_pspace_def) apply (rule hoare_seq_ext [OF _ gbn_sp]) apply (case_tac ntfnptr, clarsimp, wp, simp) apply clarsimp apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (wp valid_irq_node_typ set_simple_ko_valid_objs valid_ioports_lift | clarsimp split del: if_split)+ apply (intro conjI impI; (match conclusion in "sym_refs r" for r \ \-\ | auto elim!: obj_at_weakenE obj_at_valid_objsE if_live_then_nonz_capD2 simp: live_def valid_ntfn_set_bound_None is_ntfn valid_obj_def )?) apply (clarsimp simp: if_split) apply (rule delta_sym_refs, assumption) apply (fastforce simp: obj_at_def is_tcb dest!: pred_tcb_at_tcb_at ko_at_state_refs_ofD split: if_split_asm) apply (clarsimp split: if_split_asm) apply (frule pred_tcb_at_tcb_at) apply (frule_tac p=t in obj_at_ko_at, clarsimp) apply (subst (asm) ko_at_state_refs_ofD, assumption) apply (fastforce simp: obj_at_def is_tcb ntfn_q_refs_no_NTFNBound tcb_at_no_ntfn_bound refs_of_rev tcb_ntfn_is_bound_def dest!: pred_tcb_at_tcb_at bound_tcb_at_state_refs_ofD) apply (subst (asm) ko_at_state_refs_ofD, assumption) apply (fastforce simp: ntfn_bound_refs_def obj_at_def ntfn_q_refs_no_TCBBound elim!: pred_tcb_weakenE dest!: bound_tcb_bound_notification_at refs_in_ntfn_bound_refs symreftype_inverse' split: option.splits) done crunch bound_tcb_at[wp]: cancel_all_signals "bound_tcb_at P t" (wp: mapM_x_wp_inv) lemma waiting_ntfn_list_tcb_at: "\valid_objs s; ko_at (Notification ntfn) ntfnptr s; ntfn_obj ntfn = WaitingNtfn x\ \ \t \ set x. tcb_at t s" by (fastforce elim!: obj_at_valid_objsE simp:valid_obj_def valid_ntfn_def) lemma tcb_at_ko_at: "tcb_at p s \ \tcb. ko_at (TCB tcb) p s" by (fastforce simp: obj_at_def is_tcb) lemma tcb_state_refs_no_tcb: "\valid_objs s; tcb_at y s; (x, ref) \ state_refs_of s y\ \ ~ tcb_at x s" apply (clarsimp simp: ko_at_state_refs_ofD dest!: tcb_at_ko_at) apply (erule (1) obj_at_valid_objsE) apply (clarsimp simp: is_tcb valid_obj_def) apply (erule disjE) apply (clarsimp simp: tcb_st_refs_of_def valid_tcb_def valid_tcb_state_def obj_at_def is_ep is_ntfn split:thread_state.splits) apply (clarsimp simp: tcb_bound_refs_def valid_tcb_def obj_at_def is_ntfn split:option.splits) done lemma cancel_all_signals_invs: "\invs\ cancel_all_signals ntfnptr \\rv. invs\" apply (simp add: cancel_all_signals_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (rule hoare_pre) apply (wp cancel_all_invs_helper set_simple_ko_valid_objs valid_irq_node_typ hoare_vcg_const_Ball_lift valid_ioports_lift | wpc | simp add: live_def)+ apply (clarsimp simp: invs_def valid_state_def valid_pspace_def) apply (rule conjI) apply (fastforce simp: valid_obj_def valid_ntfn_def elim!: obj_at_valid_objsE) apply (rule conjI) apply (fastforce simp: live_def elim!: if_live_then_nonz_capD) apply (rule conjI) apply (fastforce simp: is_ntfn elim!: ko_at_weakenE) apply (rule conjI) apply (fastforce simp: st_tcb_at_refs_of_rev dest: bspec sym_refs_ko_atD elim: st_tcb_ex_cap) apply (rule conjI[rotated]) apply (fastforce elim!: ntfn_queued_st_tcb_at) apply (rule delta_sym_refs, assumption) apply (fastforce dest!: refs_in_ntfn_bound_refs ko_at_state_refs_ofD split: if_split_asm) apply (clarsimp split:if_split_asm) apply (fastforce dest: waiting_ntfn_list_tcb_at refs_in_ntfn_bound_refs simp: obj_at_def is_tcb_def) apply (rule conjI) apply (fastforce dest: refs_in_ntfn_bound_refs symreftype_inverse') apply (frule (2) waiting_ntfn_list_tcb_at) apply (fastforce simp: st_tcb_at_refs_of_rev refs_in_tcb_bound_refs dest: bspec sym_refs_ko_atD st_tcb_at_state_refs_ofD) apply (fastforce simp: ntfn_bound_refs_def valid_obj_def valid_ntfn_def refs_of_rev dest!: symreftype_inverse' ko_at_state_refs_ofD split: option.splits elim!: obj_at_valid_objsE) done lemma cancel_all_unlive_helper: "\obj_at (\obj. \ live obj \ (\tcb. obj \ TCB tcb)) ptr\ mapM_x (\t. do y \ set_thread_state t Structures_A.Restart; do_extended_op (tcb_sched_enqueue_ext t) od) q \\rv. obj_at (Not \ live) ptr\" apply (rule hoare_strengthen_post [OF mapM_x_wp']) apply (simp add: set_thread_state_def set_object_def get_object_def) apply (wp | simp only: obj_at_exst_update)+ apply (clarsimp dest!: get_tcb_SomeD) apply (clarsimp simp: obj_at_def) apply (clarsimp elim!: obj_at_weakenE) done lemma cancel_all_ipc_unlive[wp]: "\\\ cancel_all_ipc ptr \\ rv. obj_at (Not \ live) ptr\" apply (simp add: cancel_all_ipc_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (case_tac ep, simp_all add: set_simple_ko_def get_ep_queue_def) apply wp apply (clarsimp simp: live_def elim!: obj_at_weakenE) apply (wp cancel_all_unlive_helper set_object_at_obj3 | simp only: obj_at_exst_update)+ apply (clarsimp simp: live_def) apply (wp cancel_all_unlive_helper set_object_at_obj3 | simp only: obj_at_exst_update)+ apply (clarsimp simp: live_def) done (* This lemma should be sufficient provided that each notification object is unbound BEFORE the 'cancel_all_signals' function is invoked. TODO: Check the abstract specification and the C and Haskell implementations that this is indeed the case. *) lemma cancel_all_signals_unlive[wp]: "\\s. obj_at (\ko. \ntfn. ko = Notification ntfn \ ntfn_bound_tcb ntfn = None) ntfnptr s\ cancel_all_signals ntfnptr \\ rv. obj_at (Not \ live) ntfnptr\" apply (simp add: cancel_all_signals_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (rule hoare_pre) apply (wp | wpc | simp add: unbind_maybe_notification_def)+ apply (rule_tac Q="\_. obj_at (is_ntfn and Not \ live) ntfnptr" in hoare_post_imp) apply (fastforce elim: obj_at_weakenE) apply (wp mapM_x_wp' sts_obj_at_impossible | simp add: is_ntfn)+ apply (simp add: set_simple_ko_def) apply (wp get_object_wp obj_set_prop_at) apply (auto simp: live_def pred_tcb_at_def obj_at_def) done crunch cte_wp_at[wp]: cancel_all_ipc "cte_wp_at P p" (wp: crunch_wps mapM_x_wp) crunch cte_wp_at[wp]: cancel_all_signals "cte_wp_at P p" (wp: crunch_wps mapM_x_wp thread_set_cte_wp_at_trivial simp: tcb_cap_cases_def) lemma cancel_badged_sends_filterM_helper': "\ys. \\s. all_invs_but_sym_refs s \ sym_refs (state_hyp_refs_of s) \ distinct (xs @ ys) \ ep_at epptr s \ ex_nonz_cap_to epptr s \ sym_refs ((state_refs_of s) (epptr := ((set (xs @ ys)) \ {EPSend}))) \ (\x \ set (xs @ ys). {r \ state_refs_of s x. snd r \ TCBBound} = {(epptr, TCBBlockedSend)})\ filterM (\t. do st \ get_thread_state t; if blocking_ipc_badge st = badge then do y \ set_thread_state t Structures_A.thread_state.Restart; y \ do_extended_op (tcb_sched_action action t); return False od else return True od) xs \\rv s. all_invs_but_sym_refs s \ sym_refs (state_hyp_refs_of s) \ ep_at epptr s \ (\x \ set (xs @ ys). tcb_at x s) \ ex_nonz_cap_to epptr s \ (\y \ set ys. {r \ state_refs_of s y. snd r \ TCBBound} = {(epptr, TCBBlockedSend)}) \ distinct rv \ distinct (xs @ ys) \ (set rv \ set xs) \ sym_refs ((state_refs_of s) (epptr := ((set rv \ set ys) \ {EPSend})))\" apply (rule rev_induct[where xs=xs]) apply (rule allI, simp) apply wp apply clarsimp apply (drule(1) bspec, drule singleton_eqD, clarsimp, drule state_refs_of_elemD) apply (clarsimp simp: st_tcb_at_refs_of_rev pred_tcb_at_def is_tcb elim!: obj_at_weakenE) apply (clarsimp simp: filterM_append bind_assoc simp del: set_append distinct_append) apply (drule spec, erule hoare_seq_ext[rotated]) apply (rule hoare_seq_ext [OF _ gts_sp]) apply (rule hoare_pre, wpsimp wp: valid_irq_node_typ sts_only_idle hoare_vcg_const_Ball_lift) apply (clarsimp simp: valid_tcb_state_def) apply (rule conjI[rotated]) apply blast apply clarsimp apply (thin_tac "obj_at f epptr s" for f s) apply (thin_tac "tcb_at x s" for x s) apply (thin_tac "sym_refs (state_hyp_refs_of s)" for s) apply (frule singleton_eqD, clarify, drule state_refs_of_elemD) apply (frule(1) if_live_then_nonz_capD) apply (rule refs_of_live, clarsimp) apply (clarsimp simp: st_tcb_at_refs_of_rev) apply (clarsimp simp: pred_tcb_def2 valid_idle_def) apply (rule conjI, clarsimp) apply (rule conjI, clarsimp) apply (drule(1) valid_reply_capsD, clarsimp simp: st_tcb_def2) apply (rule conjI, blast) apply (rule conjI, blast) apply (erule delta_sym_refs) apply (auto dest!: get_tcb_ko_atD ko_at_state_refs_ofD symreftype_inverse' refs_in_tcb_bound_refs split: if_split_asm)[2] done lemmas cancel_badged_sends_filterM_helper = spec [where x=Nil, OF cancel_badged_sends_filterM_helper', simplified] lemma cancel_badged_sends_invs_helper: "{r. snd r \ TCBBound \ (r \ tcb_st_refs_of ts \ r \ tcb_bound_refs ntfnptr)} = tcb_st_refs_of ts" by (auto simp add: tcb_st_refs_of_def tcb_bound_refs_def split: thread_state.splits option.splits) lemma cancel_badged_sends_invs[wp]: "\invs\ cancel_badged_sends epptr badge \\rv. invs\" apply (simp add: cancel_badged_sends_def) apply (rule hoare_seq_ext [OF _ get_simple_ko_sp]) apply (case_tac ep; simp) apply wpsimp apply (simp add: invs_def valid_state_def valid_pspace_def) apply (wpsimp wp: valid_irq_node_typ valid_ioports_lift) apply (simp add: fun_upd_def[symmetric] ep_redux_simps ep_at_def2[symmetric, simplified] cong: list.case_cong) apply (rule hoare_strengthen_post, rule cancel_badged_sends_filterM_helper[where epptr=epptr]) apply (auto intro:obj_at_weakenE)[1] apply (wpsimp wp: valid_irq_node_typ set_endpoint_ep_at valid_ioports_lift) apply (clarsimp simp: valid_ep_def conj_comms) apply (subst obj_at_weakenE, simp, fastforce) apply (clarsimp simp: is_ep_def) apply (frule(1) sym_refs_ko_atD, clarsimp) apply (frule(1) if_live_then_nonz_capD, (clarsimp simp: live_def)+) apply (erule(1) obj_at_valid_objsE) apply (clarsimp simp: valid_obj_def valid_ep_def st_tcb_at_refs_of_rev) apply (simp add: fun_upd_idem obj_at_def is_ep_def | subst fun_upd_def[symmetric])+ apply (clarsimp, drule(1) bspec) apply (drule st_tcb_at_state_refs_ofD) apply (clarsimp simp only: cancel_badged_sends_invs_helper Un_iff, clarsimp) apply (simp add: set_eq_subset) apply wpsimp done (* FIXME rule_format? *) lemma real_cte_emptyable_strg: "real_cte_at p s \ emptyable p s" by (clarsimp simp: emptyable_def obj_at_def is_tcb is_cap_table) end