(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: GPL-2.0-only *) theory TcbAcc_R imports CSpace_R ArchMove_R begin context begin interpretation Arch . (*FIXME: arch_split*) declare if_weak_cong [cong] declare result_in_set_wp[wp] declare hoare_in_monad_post[wp] declare trans_state_update'[symmetric,simp] declare empty_fail_sequence_x[simp] declare storeWordUser_typ_at' [wp] (* Auxiliaries and basic properties of priority bitmap functions *) lemma countLeadingZeros_word_clz[simp]: "countLeadingZeros w = word_clz w" unfolding countLeadingZeros_def word_clz_def by (simp add: to_bl_upt) lemma wordLog2_word_log2[simp]: "wordLog2 = word_log2" apply (rule ext) unfolding wordLog2_def word_log2_def by (simp add: word_size wordBits_def) lemmas bitmap_fun_defs = addToBitmap_def removeFromBitmap_def modifyReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL1Bitmap_def getReadyQueuesL2Bitmap_def (* lookupBitmapPriority is a cleaner version of getHighestPrio *) definition "lookupBitmapPriority d \ \s. l1IndexToPrio (word_log2 (ksReadyQueuesL1Bitmap s d)) || of_nat (word_log2 (ksReadyQueuesL2Bitmap s (d, invertL1Index (word_log2 (ksReadyQueuesL1Bitmap s d)))))" lemma getHighestPrio_def'[simp]: "getHighestPrio d = gets (lookupBitmapPriority d)" unfolding getHighestPrio_def gets_def by (fastforce simp: gets_def get_bind_apply lookupBitmapPriority_def bitmap_fun_defs) (* isHighestPrio_def' is a cleaner version of isHighestPrio_def *) lemma isHighestPrio_def': "isHighestPrio d p = gets (\s. ksReadyQueuesL1Bitmap s d = 0 \ lookupBitmapPriority d s \ p)" unfolding isHighestPrio_def bitmap_fun_defs getHighestPrio_def' apply (rule ext) apply (clarsimp simp: gets_def bind_assoc return_def NonDetMonad.bind_def get_def split: if_splits) done lemma getHighestPrio_inv[wp]: "\ P \ getHighestPrio d \\_. P \" unfolding bitmap_fun_defs by simp lemma valid_bitmapQ_bitmapQ_simp: "\ valid_bitmapQ s \ \ bitmapQ d p s = (ksReadyQueues s (d, p) \ [])" unfolding valid_bitmapQ_def by simp lemma prioToL1Index_l1IndexToPrio_or_id: "\ unat (w'::priority) < 2 ^ wordRadix ; w < 2^(size w' - wordRadix) \ \ prioToL1Index ((l1IndexToPrio w) || w') = w" unfolding l1IndexToPrio_def prioToL1Index_def apply (simp add: shiftr_over_or_dist shiftr_le_0 wordRadix_def') apply (subst shiftl_shiftr_id, simp, simp add: word_size) apply (rule word_of_nat_less) apply simp apply (subst unat_of_nat_eq, simp_all add: word_size) done lemma bitmapQ_no_L1_orphansD: "\ bitmapQ_no_L1_orphans s ; ksReadyQueuesL1Bitmap s d !! i \ \ ksReadyQueuesL2Bitmap s (d, invertL1Index i) \ 0 \ i < l2BitmapSize" unfolding bitmapQ_no_L1_orphans_def by simp lemma l1IndexToPrio_wordRadix_mask[simp]: "l1IndexToPrio i && mask wordRadix = 0" unfolding l1IndexToPrio_def by (simp add: wordRadix_def') definition (* when in the middle of updates, a particular queue might not be entirely valid *) valid_queues_no_bitmap_except :: "machine_word \ kernel_state \ bool" where "valid_queues_no_bitmap_except t' \ \s. (\d p. (\t \ set (ksReadyQueues s (d, p)). t \ t' \ obj_at' (inQ d p and runnable' \ tcbState) t s) \ distinct (ksReadyQueues s (d, p)) \ (d > maxDomain \ p > maxPriority \ ksReadyQueues s (d,p) = []))" lemma valid_queues_no_bitmap_exceptI[intro]: "valid_queues_no_bitmap s \ valid_queues_no_bitmap_except t s" unfolding valid_queues_no_bitmap_except_def valid_queues_no_bitmap_def by simp lemma st_tcb_at_coerce_abstract: assumes t: "st_tcb_at' P t c" assumes sr: "(a, c) \ state_relation" shows "st_tcb_at (\st. \st'. thread_state_relation st st' \ P st') t a" using assms apply (clarsimp simp: state_relation_def pred_tcb_at'_def obj_at'_def objBits_simps) apply (erule(1) pspace_dom_relatedE) apply (erule(1) obj_relation_cutsE, simp_all) apply (clarsimp simp: st_tcb_at_def obj_at_def other_obj_relation_def tcb_relation_def split: Structures_A.kernel_object.split_asm if_split_asm RISCV64_A.arch_kernel_obj.split_asm)+ apply fastforce done lemma st_tcb_at_runnable_coerce_concrete: assumes t: "st_tcb_at runnable t a" assumes sr: "(a, c) \ state_relation" assumes tcb: "tcb_at' t c" shows "st_tcb_at' runnable' t c" using t apply - apply (rule ccontr) apply (drule pred_tcb_at'_Not[THEN iffD2, OF conjI, OF tcb]) apply (drule st_tcb_at_coerce_abstract[OF _ sr]) apply (clarsimp simp: st_tcb_def2) apply (case_tac "tcb_state tcb"; simp) done lemma pspace_relation_tcb_at': assumes p: "pspace_relation (kheap a) (ksPSpace c)" assumes t: "tcb_at t a" assumes aligned: "pspace_aligned' c" assumes distinct: "pspace_distinct' c" shows "tcb_at' t c" using assms apply (clarsimp simp: obj_at_def) apply (drule(1) pspace_relation_absD) apply (clarsimp simp: is_tcb other_obj_relation_def) apply (simp split: kernel_object.split_asm) apply (drule(2) aligned_distinct_obj_atI'[where 'a=tcb], simp) apply (erule obj_at'_weakenE) apply simp done lemma tcb_at_cross: "\ tcb_at t s; pspace_aligned s; pspace_distinct s; pspace_relation (kheap s) (ksPSpace s') \ \ tcb_at' t s'" apply (drule (2) pspace_distinct_cross) apply (drule (1) pspace_aligned_cross) apply (erule (3) pspace_relation_tcb_at') done lemma st_tcb_at_runnable_cross: "\ st_tcb_at runnable t s; pspace_aligned s; pspace_distinct s; (s, s') \ state_relation \ \ st_tcb_at' runnable' t s'" apply (frule (1) pspace_distinct_cross, fastforce simp: state_relation_def) apply (frule pspace_aligned_cross, fastforce simp: state_relation_def) apply (prop_tac "tcb_at t s", clarsimp simp: st_tcb_at_def obj_at_def is_tcb) apply (drule (2) tcb_at_cross, fastforce simp: state_relation_def) apply (erule (2) st_tcb_at_runnable_coerce_concrete) done lemma cur_tcb_cross: "\ cur_tcb s; pspace_aligned s; pspace_distinct s; (s,s') \ state_relation \ \ cur_tcb' s'" apply (clarsimp simp: cur_tcb'_def cur_tcb_def state_relation_def) apply (erule (3) tcb_at_cross) done lemma valid_objs_valid_tcbE: "\s t.\ valid_objs' s; tcb_at' t s; \tcb. valid_tcb' tcb s \ R s tcb \ \ obj_at' (R s) t s" apply (clarsimp simp add: valid_objs'_def ran_def typ_at'_def ko_wp_at'_def valid_obj'_def valid_tcb'_def obj_at'_def) apply (fastforce simp: projectKO_def projectKO_opt_tcb return_def valid_tcb'_def) done lemma valid_objs'_maxDomain: "\s t. \ valid_objs' s; tcb_at' t s \ \ obj_at' (\tcb. tcbDomain tcb \ maxDomain) t s" apply (erule (1) valid_objs_valid_tcbE) apply (clarsimp simp: valid_tcb'_def) done lemma valid_objs'_maxPriority: "\s t. \ valid_objs' s; tcb_at' t s \ \ obj_at' (\tcb. tcbPriority tcb \ maxPriority) t s" apply (erule (1) valid_objs_valid_tcbE) apply (clarsimp simp: valid_tcb'_def) done lemma doMachineOp_irq_states': assumes masks: "\P. \\s. P (irq_masks s)\ f \\_ s. P (irq_masks s)\" shows "\valid_irq_states'\ doMachineOp f \\rv. valid_irq_states'\" apply (simp add: doMachineOp_def split_def) apply wp apply clarsimp apply (drule use_valid) apply (rule_tac P="\m. m = irq_masks (ksMachineState s)" in masks) apply simp apply simp done lemma dmo_invs': assumes masks: "\P. \\s. P (irq_masks s)\ f \\_ s. P (irq_masks s)\" shows "\(\s. \m. \(r,m')\fst (f m). \p. pointerInUserData p s \ pointerInDeviceData p s \ underlying_memory m' p = underlying_memory m p) and invs'\ doMachineOp f \\r. invs'\" apply (simp add: doMachineOp_def split_def) apply wp apply clarsimp apply (subst invs'_machine) apply (drule use_valid) apply (rule_tac P="\m. m = irq_masks (ksMachineState s)" in masks, simp+) apply (fastforce simp add: valid_machine_state'_def) apply assumption done lemma dmo_invs_no_cicd': assumes masks: "\P. \\s. P (irq_masks s)\ f \\_ s. P (irq_masks s)\" shows "\(\s. \m. \(r,m')\fst (f m). \p. pointerInUserData p s \ pointerInDeviceData p s \ underlying_memory m' p = underlying_memory m p) and invs_no_cicd'\ doMachineOp f \\r. invs_no_cicd'\" apply (simp add: doMachineOp_def split_def) apply wp apply clarsimp apply (subst invs_no_cicd'_machine) apply (drule use_valid) apply (rule_tac P="\m. m = irq_masks (ksMachineState s)" in masks, simp+) apply (fastforce simp add: valid_machine_state'_def) apply assumption done lemma dmo_lift': assumes f: "\P\ f \Q\" shows "\\s. P (ksMachineState s)\ doMachineOp f \\rv s. Q rv (ksMachineState s)\" apply (simp add: doMachineOp_def split_def) apply wp apply clarsimp apply (erule (1) use_valid [OF _ f]) done lemma doMachineOp_getActiveIRQ_IRQ_active: "\valid_irq_states'\ doMachineOp (getActiveIRQ in_kernel) \\rv s. \irq. rv = Some irq \ intStateIRQTable (ksInterruptState s) irq \ IRQInactive\" apply (rule hoare_lift_Pf3 [where f="ksInterruptState"]) prefer 2 apply wp apply (simp add: irq_state_independent_H_def) apply assumption apply (rule dmo_lift') apply (rule getActiveIRQ_masked) done lemma doMachineOp_getActiveIRQ_IRQ_active': "\valid_irq_states'\ doMachineOp (getActiveIRQ in_kernel) \\rv s. rv = Some irq \ intStateIRQTable (ksInterruptState s) irq \ IRQInactive\" apply (rule hoare_post_imp) prefer 2 apply (rule doMachineOp_getActiveIRQ_IRQ_active) apply simp done lemma preemptionPoint_irq [wp]: "\valid_irq_states'\ preemptionPoint -, \\irq s. intStateIRQTable (ksInterruptState s) irq \ IRQInactive\" apply (simp add: preemptionPoint_def setWorkUnits_def modifyWorkUnits_def getWorkUnits_def) apply (wp hoare_whenE_wp|wpc)+ apply (rule hoare_post_imp) prefer 2 apply (rule doMachineOp_getActiveIRQ_IRQ_active) apply clarsimp apply wp+ apply clarsimp done lemmas doMachineOp_obj_at = doMachineOp_obj_at' lemma updateObject_tcb_inv: "\P\ updateObject (obj::tcb) ko p q n \\rv. P\" by simp (rule updateObject_default_inv) lemma setObject_update_TCB_corres': assumes tcbs: "tcb_relation tcb tcb' \ tcb_relation tcbu tcbu'" assumes tables: "\(getF, v) \ ran tcb_cap_cases. getF tcbu = getF tcb" assumes tables': "\(getF, v) \ ran tcb_cte_cases. getF tcbu' = getF tcb'" assumes r: "r () ()" assumes exst: "exst_same tcb' tcbu'" shows "corres r (ko_at (TCB tcb) add) (ko_at' tcb' add) (set_object add (TCB tcbu)) (setObject add tcbu')" apply (rule_tac F="tcb_relation tcb tcb' \ exst_same tcb' tcbu'" in corres_req) apply (clarsimp simp: state_relation_def obj_at_def obj_at'_def) apply (frule(1) pspace_relation_absD) apply (clarsimp simp: other_obj_relation_def exst) apply (rule corres_guard_imp) apply (rule corres_rel_imp) apply (rule setObject_other_corres[where P="(=) tcb'"]) apply (rule ext)+ apply simp defer apply (simp add: is_other_obj_relation_type_def objBits_simps' other_obj_relation_def tcbs r)+ apply (fastforce elim!: obj_at_weakenE dest: bspec[OF tables]) apply (subst(asm) eq_commute, assumption) apply (clarsimp simp: obj_at'_def objBits_simps) apply (subst map_to_ctes_upd_tcb, assumption+) apply (simp add: ps_clear_def3 field_simps objBits_defs mask_def) apply (subst if_not_P) apply (fastforce dest: bspec [OF tables', OF ranI]) apply simp done lemma setObject_update_TCB_corres: "\ tcb_relation tcb tcb' \ tcb_relation tcbu tcbu'; \(getF, v) \ ran tcb_cap_cases. getF tcbu = getF tcb; \(getF, v) \ ran tcb_cte_cases. getF tcbu' = getF tcb'; r () (); exst_same tcb' tcbu'\ \ corres r (\s. get_tcb add s = Some tcb) (\s'. (tcb', s') \ fst (getObject add s')) (set_object add (TCB tcbu)) (setObject add tcbu')" apply (rule corres_guard_imp) apply (erule (3) setObject_update_TCB_corres', force) apply fastforce apply (clarsimp simp: getObject_def in_monad split_def obj_at'_def loadObject_default_def objBits_simps' in_magnitude_check) done lemma getObject_TCB_corres: "corres tcb_relation (tcb_at t and pspace_aligned and pspace_distinct) \ (gets_the (get_tcb t)) (getObject t)" apply (rule corres_cross_over_guard[where Q="tcb_at' t"]) apply (fastforce simp: tcb_at_cross state_relation_def) apply (rule corres_guard_imp) apply (rule corres_gets_the) apply (rule corres_get_tcb) apply (simp add: tcb_at_def) apply assumption done lemma threadGet_corres: assumes x: "\tcb tcb'. tcb_relation tcb tcb' \ r (f tcb) (f' tcb')" shows "corres r (tcb_at t and pspace_aligned and pspace_distinct) \ (thread_get f t) (threadGet f' t)" apply (simp add: thread_get_def threadGet_def) apply (fold liftM_def) apply simp apply (rule corres_rel_imp) apply (rule getObject_TCB_corres) apply (simp add: x) done lemma threadGet_inv [wp]: "\P\ threadGet f t \\rv. P\" by (simp add: threadGet_def getObject_inv_tcb | wp)+ lemma ball_tcb_cte_casesI: "\ P (tcbCTable, tcbCTable_update); P (tcbVTable, tcbVTable_update); P (tcbReply, tcbReply_update); P (tcbCaller, tcbCaller_update); P (tcbIPCBufferFrame, tcbIPCBufferFrame_update) \ \ \x \ ran tcb_cte_cases. P x" by (simp add: tcb_cte_cases_def cteSizeBits_def) lemma all_tcbI: "\ \a b c d e f g h i j k l m n p q. P (Thread a b c d e f g h i j k l m n p q) \ \ \tcb. P tcb" by (rule allI, case_tac tcb, simp) lemma threadset_corresT: assumes x: "\tcb tcb'. tcb_relation tcb tcb' \ tcb_relation (f tcb) (f' tcb')" assumes y: "\tcb. \(getF, setF) \ ran tcb_cap_cases. getF (f tcb) = getF tcb" assumes z: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (f' tcb) = getF tcb" assumes e: "\tcb'. exst_same tcb' (f' tcb')" shows "corres dc (tcb_at t and pspace_aligned and pspace_distinct) \ (thread_set f t) (threadSet f' t)" apply (simp add: thread_set_def threadSet_def) apply (rule corres_guard_imp) apply (rule corres_split[OF getObject_TCB_corres]) apply (rule setObject_update_TCB_corres') apply (erule x) apply (rule y) apply (clarsimp simp: bspec_split [OF spec [OF z]]) apply fastforce apply simp apply (rule e) apply wp+ apply (clarsimp simp add: tcb_at_def obj_at_def) apply (drule get_tcb_SomeD) apply fastforce apply simp done lemmas threadset_corres = threadset_corresT [OF _ _ all_tcbI, OF _ ball_tcb_cap_casesI ball_tcb_cte_casesI] lemma pspace_relation_tcb_at: assumes p: "pspace_relation (kheap a) (ksPSpace c)" assumes t: "tcb_at' t c" shows "tcb_at t a" using assms apply (clarsimp simp: obj_at'_def) apply (erule(1) pspace_dom_relatedE) apply (erule(1) obj_relation_cutsE) apply (clarsimp simp: other_obj_relation_def is_tcb obj_at_def split: Structures_A.kernel_object.split_asm if_split_asm RISCV64_A.arch_kernel_obj.split_asm)+ done lemma threadSet_corres_noopT: assumes x: "\tcb tcb'. tcb_relation tcb tcb' \ tcb_relation tcb (fn tcb')" assumes y: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (fn tcb) = getF tcb" assumes e: "\tcb'. exst_same tcb' (fn tcb')" shows "corres dc (tcb_at t and pspace_aligned and pspace_distinct) \ (return v) (threadSet fn t)" proof - have S: "\t s. tcb_at t s \ return v s = (thread_set id t >>= (\x. return v)) s" apply (clarsimp simp: tcb_at_def) apply (simp add: return_def thread_set_def gets_the_def assert_def assert_opt_def simpler_gets_def set_object_def get_object_def put_def get_def bind_def) apply (subgoal_tac "kheap s(t \ TCB tcb) = kheap s", simp) apply (simp add: map_upd_triv get_tcb_SomeD)+ done show ?thesis apply (rule stronger_corres_guard_imp) apply (subst corres_cong [OF refl refl S refl refl]) defer apply (subst bind_return [symmetric], rule corres_underlying_split [OF threadset_corresT]) apply (simp add: x) apply simp apply (rule y) apply (rule e) apply (rule corres_noop [where P=\ and P'=\]) apply simp apply (rule no_fail_pre, wpsimp+)[1] apply wpsimp+ done qed lemmas threadSet_corres_noop = threadSet_corres_noopT [OF _ all_tcbI, OF _ ball_tcb_cte_casesI] lemma threadSet_corres_noop_splitT: assumes x: "\tcb tcb'. tcb_relation tcb tcb' \ tcb_relation tcb (fn tcb')" assumes y: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (fn tcb) = getF tcb" assumes z: "corres r P Q' m m'" assumes w: "\P'\ threadSet fn t \\x. Q'\" assumes e: "\tcb'. exst_same tcb' (fn tcb')" shows "corres r (tcb_at t and pspace_aligned and pspace_distinct and P) P' m (threadSet fn t >>= (\rv. m'))" apply (rule corres_guard_imp) apply (subst return_bind[symmetric]) apply (rule corres_split_nor[OF threadSet_corres_noopT]) apply (simp add: x) apply (rule y) apply (rule e) apply (rule z) apply (wp w)+ apply simp apply simp done lemmas threadSet_corres_noop_split = threadSet_corres_noop_splitT [OF _ all_tcbI, OF _ ball_tcb_cte_casesI] lemma threadSet_tcb' [wp]: "\tcb_at' t\ threadSet f t' \\rv. tcb_at' t\" by (simp add: threadSet_def) wp lemma threadSet_nosch[wp]: "\\s. P (ksSchedulerAction s)\ threadSet f t \\rv s. P (ksSchedulerAction s)\" unfolding threadSet_def by (simp add: updateObject_default_def | wp setObject_nosch)+ (* The function "thread_set f p" updates a TCB at p using function f. It should not be used to change capabilities, though. *) lemma setObject_tcb_valid_objs: "\valid_objs' and (tcb_at' t and valid_obj' (injectKO v))\ setObject t (v :: tcb) \\rv. valid_objs'\" apply (rule setObject_valid_objs') apply (clarsimp simp: updateObject_default_def in_monad) done lemma setObject_tcb_at': "\tcb_at' t'\ setObject t (v :: tcb) \\rv. tcb_at' t'\" apply (rule obj_at_setObject1) apply (clarsimp simp: updateObject_default_def return_def in_monad) apply (simp add: objBits_simps) done lemma setObject_sa_unchanged: "\\s. P (ksSchedulerAction s)\ setObject t (v :: tcb) \\rv s. P (ksSchedulerAction s)\" apply (simp add: setObject_def split_def) apply (wp | simp add: updateObject_default_def)+ done lemma setObject_queues_unchanged: assumes inv: "\P p q n obj. \P\ updateObject v obj p q n \\r. P\" shows "\\s. P (ksReadyQueues s)\ setObject t v \\rv s. P (ksReadyQueues s)\" apply (simp add: setObject_def split_def) apply (wp inv | simp)+ done lemma setObject_queues_unchanged_tcb[wp]: "\\s. P (ksReadyQueues s)\ setObject t (v :: tcb) \\rv s. P (ksReadyQueues s)\" apply (rule setObject_queues_unchanged) apply (wp|simp add: updateObject_default_def)+ done lemma setObject_queuesL1_unchanged_tcb[wp]: "\\s. P (ksReadyQueuesL1Bitmap s)\ setObject t (v :: tcb) \\rv s. P (ksReadyQueuesL1Bitmap s)\" by (clarsimp simp: setObject_def split_def) (wp | simp add: updateObject_default_def)+ lemma setObject_queuesL2_unchanged_tcb[wp]: "\\s. P (ksReadyQueuesL2Bitmap s)\ setObject t (v :: tcb) \\rv s. P (ksReadyQueuesL2Bitmap s)\" by (clarsimp simp: setObject_def split_def) (wp | simp add: updateObject_default_def)+ lemma setObject_tcb_ctes_of[wp]: "\\s. P (ctes_of s) \ obj_at' (\t. \(getF, setF) \ ran tcb_cte_cases. getF t = getF v) t s\ setObject t v \\rv s. P (ctes_of s)\" apply (rule setObject_ctes_of) apply (clarsimp simp: updateObject_default_def in_monad prod_eq_iff obj_at'_def objBits_simps' in_magnitude_check) apply fastforce apply (clarsimp simp: updateObject_default_def in_monad prod_eq_iff obj_at'_def objBits_simps in_magnitude_check bind_def) done lemma setObject_tcb_mdb' [wp]: "\ valid_mdb' and obj_at' (\t. \(getF, setF) \ ran tcb_cte_cases. getF t = getF v) t\ setObject t (v :: tcb) \\rv. valid_mdb'\" unfolding valid_mdb'_def pred_conj_def by (rule setObject_tcb_ctes_of) lemma setObject_tcb_state_refs_of'[wp]: "\\s. P ((state_refs_of' s) (t := tcb_st_refs_of' (tcbState v) \ tcb_bound_refs' (tcbBoundNotification v)))\ setObject t (v :: tcb) \\rv s. P (state_refs_of' s)\" by (wp setObject_state_refs_of', simp_all add: objBits_simps' fun_upd_def) lemma setObject_tcb_iflive': "\\s. if_live_then_nonz_cap' s \ (live' (injectKO v) \ ex_nonz_cap_to' t s) \ obj_at' (\t. \(getF, setF) \ ran tcb_cte_cases. getF t = getF v) t s\ setObject t (v :: tcb) \\rv. if_live_then_nonz_cap'\" apply (rule setObject_iflive') apply (simp add: objBits_simps')+ apply (clarsimp simp: updateObject_default_def in_monad obj_at'_def in_magnitude_check objBits_simps' prod_eq_iff) apply fastforce apply (clarsimp simp: updateObject_default_def bind_def) done lemma setObject_tcb_idle': "\\s. valid_idle' s \ (t = ksIdleThread s \ idle_tcb' v)\ setObject t (v :: tcb) \\rv. valid_idle'\" apply (rule hoare_pre) apply (rule setObject_idle') apply (simp add: objBits_simps')+ apply (simp add: updateObject_default_inv) apply (simp add: idle_tcb_ps_def) done lemma setObject_tcb_irq_node'[wp]: "\\s. P (irq_node' s)\ setObject t (v :: tcb) \\rv s. P (irq_node' s)\" apply (simp add: setObject_def split_def) apply (wp updateObject_default_inv | simp)+ done lemma setObject_tcb_ifunsafe': "\if_unsafe_then_cap' and obj_at' (\t. \(getF, setF) \ ran tcb_cte_cases. getF t = getF v) t\ setObject t (v :: tcb) \\rv. if_unsafe_then_cap'\" unfolding pred_conj_def apply (rule setObject_ifunsafe') apply (clarsimp simp: updateObject_default_def in_monad obj_at'_def in_magnitude_check objBits_simps' prod_eq_iff) apply fastforce apply (clarsimp simp: updateObject_default_def bind_def) apply wp done lemma setObject_tcb_arch' [wp]: "\\s. P (ksArchState s)\ setObject t (v :: tcb) \\rv s. P (ksArchState s)\" apply (simp add: setObject_def split_def updateObject_default_def) apply wp apply simp done lemma setObject_tcb_valid_arch' [wp]: "\valid_arch_state'\ setObject t (v :: tcb) \\rv. valid_arch_state'\" by (wp valid_arch_state_lift' setObject_typ_at') lemma setObject_tcb_refs' [wp]: "\\s. P (global_refs' s)\ setObject t (v::tcb) \\rv s. P (global_refs' s)\" apply (clarsimp simp: setObject_def split_def updateObject_default_def) apply wp apply (simp add: global_refs'_def) done lemma setObject_tcb_valid_globals' [wp]: "\valid_global_refs' and obj_at' (\tcb. (\(getF, setF) \ ran tcb_cte_cases. getF tcb = getF v)) t\ setObject t (v :: tcb) \\rv. valid_global_refs'\" unfolding pred_conj_def valid_global_refs'_def apply (rule hoare_lift_Pf2 [where f="global_refs'"]) apply (rule hoare_lift_Pf2 [where f="gsMaxObjectSize"]) apply (rule setObject_ctes_of) apply (clarsimp simp: updateObject_default_def in_monad obj_at'_def in_magnitude_check objBits_simps' prod_eq_iff) apply fastforce apply (clarsimp simp: updateObject_default_def in_monad prod_eq_iff obj_at'_def objBits_simps in_magnitude_check bind_def) apply (wp | wp setObject_ksPSpace_only updateObject_default_inv | simp)+ done lemma setObject_tcb_irq_states' [wp]: "\valid_irq_states'\ setObject t (v :: tcb) \\rv. valid_irq_states'\" apply (rule hoare_pre) apply (rule hoare_use_eq [where f=ksInterruptState, OF setObject_ksInterrupt]) apply (simp, rule updateObject_default_inv) apply (rule hoare_use_eq [where f=ksMachineState, OF setObject_ksMachine]) apply (simp, rule updateObject_default_inv) apply wp apply assumption done lemma getObject_tcb_wp: "\\s. tcb_at' p s \ (\t::tcb. ko_at' t p s \ Q t s)\ getObject p \Q\" by (clarsimp simp: getObject_def valid_def in_monad split_def objBits_simps' loadObject_default_def obj_at'_def in_magnitude_check) lemma setObject_tcb_pspace_no_overlap': "\pspace_no_overlap' w s and tcb_at' t\ setObject t (tcb::tcb) \\rv. pspace_no_overlap' w s\" apply (clarsimp simp: setObject_def split_def valid_def in_monad) apply (clarsimp simp: obj_at'_def) apply (erule (1) ps_clear_lookupAround2) apply (rule order_refl) apply (erule is_aligned_no_overflow) apply simp apply (clarsimp simp: updateObject_default_def in_monad objBits_simps in_magnitude_check) apply (fastforce simp: pspace_no_overlap'_def objBits_simps) done lemma threadSet_pspace_no_overlap' [wp]: "\pspace_no_overlap' w s\ threadSet f t \\rv. pspace_no_overlap' w s\" apply (simp add: threadSet_def) apply (wp setObject_tcb_pspace_no_overlap' getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemma threadSet_global_refsT: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\valid_global_refs'\ threadSet F t \\rv. valid_global_refs'\" apply (simp add: threadSet_def) apply (wp setObject_tcb_valid_globals' getObject_tcb_wp) apply (clarsimp simp: obj_at'_def bspec_split [OF spec [OF x]]) done lemmas threadSet_global_refs[wp] = threadSet_global_refsT [OF all_tcbI, OF ball_tcb_cte_casesI] lemma threadSet_valid_pspace'T_P: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" assumes z: "\tcb. (P \ Q (tcbState tcb)) \ (\s. valid_tcb_state' (tcbState tcb) s \ valid_tcb_state' (tcbState (F tcb)) s)" assumes v: "\tcb. (P \ Q' (tcbBoundNotification tcb)) \ (\s. valid_bound_ntfn' (tcbBoundNotification tcb) s \ valid_bound_ntfn' (tcbBoundNotification (F tcb)) s)" assumes y: "\tcb. is_aligned (tcbIPCBuffer tcb) msg_align_bits \ is_aligned (tcbIPCBuffer (F tcb)) msg_align_bits" assumes u: "\tcb. tcbDomain tcb \ maxDomain \ tcbDomain (F tcb) \ maxDomain" assumes w: "\tcb. tcbPriority tcb \ maxPriority \ tcbPriority (F tcb) \ maxPriority" assumes w': "\tcb. tcbMCP tcb \ maxPriority \ tcbMCP (F tcb) \ maxPriority" shows "\valid_pspace' and (\s. P \ st_tcb_at' Q t s \ bound_tcb_at' Q' t s)\ threadSet F t \\rv. valid_pspace'\" apply (simp add: valid_pspace'_def threadSet_def) apply (rule hoare_pre, wp setObject_tcb_valid_objs getObject_tcb_wp) apply (clarsimp simp: obj_at'_def pred_tcb_at'_def) apply (erule(1) valid_objsE') apply (clarsimp simp add: valid_obj'_def valid_tcb'_def bspec_split [OF spec [OF x]] z split_paired_Ball y u w v w') done lemmas threadSet_valid_pspace'T = threadSet_valid_pspace'T_P[where P=False, simplified] lemmas threadSet_valid_pspace' = threadSet_valid_pspace'T [OF all_tcbI all_tcbI all_tcbI all_tcbI, OF ball_tcb_cte_casesI] lemma threadSet_ifunsafe'T: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\if_unsafe_then_cap'\ threadSet F t \\rv. if_unsafe_then_cap'\" apply (simp add: threadSet_def) apply (wp setObject_tcb_ifunsafe' getObject_tcb_wp) apply (clarsimp simp: obj_at'_def bspec_split [OF spec [OF x]]) done lemmas threadSet_ifunsafe' = threadSet_ifunsafe'T [OF all_tcbI, OF ball_tcb_cte_casesI] lemma threadSet_state_refs_of'_helper[simp]: "{r. (r \ tcb_st_refs_of' ts \ r \ tcb_bound_refs' ntfnptr) \ snd r = TCBBound} = tcb_bound_refs' ntfnptr" by (auto simp: tcb_st_refs_of'_def tcb_bound_refs'_def split: thread_state.splits) lemma threadSet_state_refs_of'_helper'[simp]: "{r. (r \ tcb_st_refs_of' ts \ r \ tcb_bound_refs' ntfnptr) \ snd r \ TCBBound} = tcb_st_refs_of' ts" by (auto simp: tcb_st_refs_of'_def tcb_bound_refs'_def split: thread_state.splits) lemma threadSet_state_refs_of'T_P: assumes x: "\tcb. (P' \ Q (tcbState tcb)) \ tcb_st_refs_of' (tcbState (F tcb)) = f' (tcb_st_refs_of' (tcbState tcb))" assumes y: "\tcb. (P' \ Q' (tcbBoundNotification tcb)) \ tcb_bound_refs' (tcbBoundNotification (F tcb)) = g' (tcb_bound_refs' (tcbBoundNotification tcb))" shows "\\s. P ((state_refs_of' s) (t := f' {r \ state_refs_of' s t. snd r \ TCBBound} \ g' {r \ state_refs_of' s t. snd r = TCBBound})) \ (P' \ st_tcb_at' Q t s \ bound_tcb_at' Q' t s)\ threadSet F t \\rv s. P (state_refs_of' s)\" apply (simp add: threadSet_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def pred_tcb_at'_def elim!: rsubst[where P=P] intro!: ext) apply (cut_tac s=s and p=t and 'a=tcb in ko_at_state_refs_ofD') apply (simp add: obj_at'_def) apply (clarsimp simp: x y) done lemmas threadSet_state_refs_of'T = threadSet_state_refs_of'T_P [where P'=False, simplified] lemmas threadSet_state_refs_of' = threadSet_state_refs_of'T [OF all_tcbI all_tcbI] lemma threadSet_iflive'T: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\\s. if_live_then_nonz_cap' s \ ((\tcb. \ bound (tcbBoundNotification tcb) \ bound (tcbBoundNotification (F tcb)) \ ko_at' tcb t s) \ ex_nonz_cap_to' t s) \ ((\tcb. (tcbState tcb = Inactive \ tcbState tcb = IdleThreadState) \ tcbState (F tcb) \ Inactive \ tcbState (F tcb) \ IdleThreadState \ ko_at' tcb t s) \ ex_nonz_cap_to' t s) \ ((\tcb. \ tcbQueued tcb \ tcbQueued (F tcb) \ ko_at' tcb t s) \ ex_nonz_cap_to' t s)\ threadSet F t \\rv. if_live_then_nonz_cap'\" apply (simp add: threadSet_def) apply (wp setObject_tcb_iflive' getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) apply (subst conj_assoc[symmetric], subst imp_disjL[symmetric]) apply (subst conj_assoc[symmetric], subst imp_disjL[symmetric]) apply (rule conjI) apply (rule impI, clarsimp) apply (erule if_live_then_nonz_capE') apply (clarsimp simp: ko_wp_at'_def) apply (clarsimp simp: bspec_split [OF spec [OF x]]) done lemmas threadSet_iflive' = threadSet_iflive'T [OF all_tcbI, OF ball_tcb_cte_casesI] lemma threadSet_cte_wp_at'T: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\\s. P' (cte_wp_at' P p s)\ threadSet F t \\rv s. P' (cte_wp_at' P p s)\" apply (simp add: threadSet_def) apply (rule hoare_seq_ext [where B="\rv s. P' (cte_wp_at' P p s) \ obj_at' ((=) rv) t s"]) apply (rename_tac tcb) apply (rule setObject_cte_wp_at2') apply (clarsimp simp: updateObject_default_def in_monad objBits_simps' obj_at'_def in_magnitude_check prod_eq_iff) apply (case_tac tcb, clarsimp simp: bspec_split [OF spec [OF x]]) apply (clarsimp simp: updateObject_default_def in_monad bind_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemmas threadSet_cte_wp_at' = threadSet_cte_wp_at'T [OF all_tcbI, OF ball_tcb_cte_casesI] lemma threadSet_ctes_ofT: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\\s. P (ctes_of s)\ threadSet F t \\rv s. P (ctes_of s)\" apply (simp add: threadSet_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) apply (case_tac obj) apply (simp add: bspec_split [OF spec [OF x]]) done lemmas threadSet_ctes_of = threadSet_ctes_ofT [OF all_tcbI, OF ball_tcb_cte_casesI] lemmas threadSet_cap_to' = ex_nonz_cap_to_pres' [OF threadSet_cte_wp_at'] lemma threadSet_idle'T: assumes x: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" shows "\\s. valid_idle' s \ (t = ksIdleThread s \ (\tcb. ko_at' tcb t s \ idle_tcb' tcb \ idle_tcb' (F tcb)))\ threadSet F t \\rv. valid_idle'\" apply (simp add: threadSet_def) apply (wp setObject_tcb_idle' getObject_tcb_wp) apply (clarsimp simp: obj_at'_def valid_idle'_def pred_tcb_at'_def) done lemmas threadSet_idle' = threadSet_idle'T [OF all_tcbI, OF ball_tcb_cte_casesI] lemma set_tcb_valid_bitmapQ[wp]: "\ valid_bitmapQ \ setObject t (f tcb :: tcb) \\_. valid_bitmapQ \" apply (rule setObject_tcb_pre) apply (simp add: bitmapQ_defs setObject_def split_def) apply (wp hoare_Ball_helper hoare_vcg_all_lift updateObject_default_inv | simp add: bitmapQ_def)+ done lemma set_tcb_bitmapQ_no_L1_orphans[wp]: "\ bitmapQ_no_L1_orphans \ setObject t (f tcb :: tcb) \\_. bitmapQ_no_L1_orphans \" apply (rule setObject_tcb_pre) apply (simp add: bitmapQ_defs setObject_def split_def) apply (wp hoare_Ball_helper hoare_vcg_all_lift updateObject_default_inv | simp add: bitmapQ_def)+ done lemma set_tcb_bitmapQ_no_L2_orphans[wp]: "\ bitmapQ_no_L2_orphans \ setObject t (f tcb :: tcb) \\_. bitmapQ_no_L2_orphans \" apply (rule setObject_tcb_pre) apply (simp add: bitmapQ_defs setObject_def split_def) apply (wp hoare_Ball_helper hoare_vcg_all_lift updateObject_default_inv | simp add: bitmapQ_def)+ done lemma threadSet_valid_queues_no_bitmap: "\ valid_queues_no_bitmap and (\s. \d p. (\tcb. (inQ d p tcb \ runnable' (tcbState tcb)) \ \(inQ d p (f tcb) \ runnable' (tcbState (f tcb)))) \ obj_at' (\tcb. (inQ d p tcb \ runnable' (tcbState tcb)) \ \(inQ d p (f tcb) \ runnable' (tcbState (f tcb)))) t s \ t \ set (ksReadyQueues s (d, p)) )\ threadSet f t \\rv. valid_queues_no_bitmap \" apply (simp add: threadSet_def) apply wp apply (simp add: Invariants_H.valid_queues_no_bitmap_def' pred_tcb_at'_def) apply (wp setObject_queues_unchanged_tcb hoare_Ball_helper hoare_vcg_all_lift setObject_tcb_strongest)[1] apply (wp getObject_tcb_wp) apply (clarsimp simp: valid_queues_no_bitmap_def' pred_tcb_at'_def) apply (clarsimp simp: obj_at'_def) apply (fastforce) done lemma threadSet_valid_bitmapQ[wp]: "\ valid_bitmapQ \ threadSet f t \ \rv. valid_bitmapQ \" unfolding bitmapQ_defs threadSet_def by (clarsimp simp: setObject_def split_def) (wp | simp add: updateObject_default_def)+ lemma threadSet_valid_bitmapQ_no_L1_orphans[wp]: "\ bitmapQ_no_L1_orphans \ threadSet f t \ \rv. bitmapQ_no_L1_orphans \" unfolding bitmapQ_defs threadSet_def by (clarsimp simp: setObject_def split_def) (wp | simp add: updateObject_default_def)+ lemma threadSet_valid_bitmapQ_no_L2_orphans[wp]: "\ bitmapQ_no_L2_orphans \ threadSet f t \ \rv. bitmapQ_no_L2_orphans \" unfolding bitmapQ_defs threadSet_def by (clarsimp simp: setObject_def split_def) (wp | simp add: updateObject_default_def)+ lemma threadSet_valid_queues: "\Invariants_H.valid_queues and (\s. \d p. (\tcb. (inQ d p tcb \ runnable' (tcbState tcb)) \ \(inQ d p (f tcb) \ runnable' (tcbState (f tcb)))) \ obj_at' (\tcb. (inQ d p tcb \ runnable' (tcbState tcb)) \ \(inQ d p (f tcb) \ runnable' (tcbState (f tcb)))) t s \ t \ set (ksReadyQueues s (d, p)) )\ threadSet f t \\rv. Invariants_H.valid_queues\" unfolding valid_queues_def by (wp threadSet_valid_queues_no_bitmap;simp) definition addToQs :: "(Structures_H.tcb \ Structures_H.tcb) \ machine_word \ (domain \ priority \ machine_word list) \ (domain \ priority \ machine_word list)" where "addToQs F t \ \qs (qdom, prio). if (\ko. \ inQ qdom prio (F ko)) then t # qs (qdom, prio) else qs (qdom, prio)" lemma addToQs_set_def: "(t' \ set (addToQs F t qs (qdom, prio))) = (t' \ set (qs (qdom, prio)) \ (t' = t \ (\ko. \ inQ qdom prio (F ko))))" by (auto simp add: addToQs_def) lemma threadSet_valid_queues_addToQs: "\\s. (\ko qdom prio. ko_at' ko t s \ inQ qdom prio (F ko) \ \ inQ qdom prio ko \ t \ set (ksReadyQueues s (qdom, prio))) \ valid_queues' (ksReadyQueues_update (addToQs F t) s)\ threadSet F t \\rv. valid_queues'\" apply (simp add: valid_queues'_def threadSet_def obj_at'_real_def split del: if_split) apply (simp only: imp_conv_disj) apply (wp hoare_vcg_all_lift hoare_vcg_disj_lift) apply (wp setObject_ko_wp_at | simp add: objBits_simps')+ apply (wp getObject_tcb_wp updateObject_default_inv | simp split del: if_split)+ apply (clarsimp simp: obj_at'_def ko_wp_at'_def objBits_simps addToQs_set_def split del: if_split cong: if_cong) apply (fastforce split: if_split_asm) done lemma threadSet_valid_queues_Qf: "\\s. (\ko qdom prio. ko_at' ko t s \ inQ qdom prio (F ko) \ \ inQ qdom prio ko \ t \ set (ksReadyQueues s (qdom, prio))) \ valid_queues' (ksReadyQueues_update Qf s) \ (\prio. set (Qf (ksReadyQueues s) prio) \ set (addToQs F t (ksReadyQueues s) prio))\ threadSet F t \\rv. valid_queues'\" apply (wp threadSet_valid_queues_addToQs) apply (clarsimp simp: valid_queues'_def subset_iff) done lemma addToQs_subset: "set (qs p) \ set (addToQs F t qs p)" by (clarsimp simp: addToQs_def split_def) lemmas threadSet_valid_queues' = threadSet_valid_queues_Qf [where Qf=id, simplified ksReadyQueues_update_id id_apply addToQs_subset simp_thms] lemma threadSet_cur: "\\s. cur_tcb' s\ threadSet f t \\rv s. cur_tcb' s\" apply (simp add: threadSet_def cur_tcb'_def) apply (wp hoare_lift_Pf [OF setObject_tcb_at'] setObject_ct_inv) done lemma modifyReadyQueuesL1Bitmap_obj_at[wp]: "\obj_at' P t\ modifyReadyQueuesL1Bitmap a b \\rv. obj_at' P t\" apply (simp add: modifyReadyQueuesL1Bitmap_def getReadyQueuesL1Bitmap_def) apply wp apply (fastforce intro: obj_at'_pspaceI) done crunches setThreadState, setBoundNotification for valid_arch' [wp]: valid_arch_state' (simp: unless_def crunch_simps) crunch ksInterrupt'[wp]: threadSet "\s. P (ksInterruptState s)" (wp: setObject_ksInterrupt updateObject_default_inv) crunch ksArchState[wp]: threadSet "\s. P (ksArchState s)" lemma threadSet_typ_at'[wp]: "\\s. P (typ_at' T p s)\ threadSet t F \\rv s. P (typ_at' T p s)\" by (simp add: threadSet_def, wp setObject_typ_at') lemmas threadSet_typ_at_lifts[wp] = typ_at_lifts [OF threadSet_typ_at'] crunch irq_states' [wp]: threadSet valid_irq_states' crunch pspace_domain_valid [wp]: threadSet "pspace_domain_valid" lemma threadSet_obj_at'_really_strongest: "\\s. tcb_at' t s \ obj_at' (\obj. if t = t' then P (f obj) else P obj) t' s\ threadSet f t \\rv. obj_at' P t'\" apply (simp add: threadSet_def) apply (rule hoare_wp_splits) apply (rule setObject_tcb_strongest) apply (simp only: imp_conv_disj) apply (subst simp_thms(32)[symmetric], rule hoare_vcg_disj_lift) apply (rule hoare_post_imp [where Q="\rv s. \ tcb_at' t s \ tcb_at' t s"]) apply simp apply (subst simp_thms(21)[symmetric], rule hoare_vcg_conj_lift) apply (rule getObject_inv_tcb) apply (rule hoare_strengthen_post [OF getObject_ko_at]) apply simp apply (simp add: objBits_simps') apply (erule obj_at'_weakenE) apply simp apply (cases "t = t'", simp_all) apply (rule OMG_getObject_tcb) apply wp done (* FIXME: move *) lemma tcb_at_typ_at': "tcb_at' p s = typ_at' TCBT p s" unfolding typ_at'_def apply (rule iffI) apply (clarsimp simp add: obj_at'_def ko_wp_at'_def) apply (clarsimp simp add: obj_at'_def ko_wp_at'_def) apply (case_tac ko; simp) done (* FIXME: move *) lemma not_obj_at': "(\obj_at' (\tcb::tcb. P tcb) t s) = (\typ_at' TCBT t s \ obj_at' (Not \ P) t s)" apply (simp add: obj_at'_real_def typ_at'_def ko_wp_at'_def objBits_simps) apply (rule iffI) apply (clarsimp) apply (case_tac ko) apply (clarsimp)+ done (* FIXME: move *) lemma not_obj_at_elim': assumes typat: "typ_at' TCBT t s" and nobj: "\obj_at' (\tcb::tcb. P tcb) t s" shows "obj_at' (Not \ P) t s" using assms apply - apply (drule not_obj_at' [THEN iffD1]) apply (clarsimp) done (* FIXME: move *) lemmas tcb_at_not_obj_at_elim' = not_obj_at_elim' [OF tcb_at_typ_at' [THEN iffD1]] (* FIXME: move *) lemma lift_neg_pred_tcb_at': assumes typat: "\P T p. \\s. P (typ_at' T p s)\ f \\_ s. P (typ_at' T p s)\" and sttcb: "\S p. \pred_tcb_at' proj S p\ f \\_. pred_tcb_at' proj S p\" shows "\\s. P (pred_tcb_at' proj S p s)\ f \\_ s. P (pred_tcb_at' proj S p s)\" apply (rule_tac P=P in P_bool_lift) apply (rule sttcb) apply (simp add: pred_tcb_at'_def not_obj_at') apply (wp hoare_convert_imp) apply (rule typat) prefer 2 apply assumption apply (rule hoare_chain [OF sttcb]) apply (fastforce simp: pred_tcb_at'_def comp_def) apply (clarsimp simp: pred_tcb_at'_def elim!: obj_at'_weakenE) done lemma threadSet_obj_at'_strongish[wp]: "\obj_at' (\obj. if t = t' then P (f obj) else P obj) t'\ threadSet f t \\rv. obj_at' P t'\" by (simp add: hoare_weaken_pre [OF threadSet_obj_at'_really_strongest]) lemma threadSet_pred_tcb_no_state: assumes "\tcb. proj (tcb_to_itcb' (f tcb)) = proj (tcb_to_itcb' tcb)" shows "\\s. P (pred_tcb_at' proj P' t' s)\ threadSet f t \\rv s. P (pred_tcb_at' proj P' t' s)\" proof - have pos: "\P' t' t. \pred_tcb_at' proj P' t'\ threadSet f t \\rv. pred_tcb_at' proj P' t'\" apply (simp add: pred_tcb_at'_def) apply (wp threadSet_obj_at'_strongish) apply clarsimp apply (erule obj_at'_weakenE) apply (insert assms) apply clarsimp done show ?thesis apply (rule_tac P=P in P_bool_lift) apply (rule pos) apply (rule_tac Q="\_ s. \ tcb_at' t' s \ pred_tcb_at' proj (\tcb. \ P' tcb) t' s" in hoare_post_imp) apply (erule disjE) apply (clarsimp dest!: pred_tcb_at') apply (clarsimp) apply (frule_tac P=P' and Q="\tcb. \ P' tcb" in pred_tcb_at_conj') apply (clarsimp)+ apply (wp hoare_convert_imp) apply (simp add: typ_at_tcb' [symmetric]) apply (wp pos)+ apply (clarsimp simp: pred_tcb_at'_def not_obj_at' elim!: obj_at'_weakenE) done qed lemma threadSet_ct[wp]: "\\s. P (ksCurThread s)\ threadSet f t \\rv s. P (ksCurThread s)\" apply (simp add: threadSet_def) apply (wp setObject_ct_inv) done lemma threadSet_cd[wp]: "\\s. P (ksCurDomain s)\ threadSet f t \\rv s. P (ksCurDomain s)\" apply (simp add: threadSet_def) apply (wp setObject_cd_inv) done lemma threadSet_ksDomSchedule[wp]: "\\s. P (ksDomSchedule s)\ threadSet f t \\rv s. P (ksDomSchedule s)\" apply (simp add: threadSet_def) apply (wp setObject_ksDomSchedule_inv) done lemma threadSet_it[wp]: "\\s. P (ksIdleThread s)\ threadSet f t \\rv s. P (ksIdleThread s)\" apply (simp add: threadSet_def) apply (wp setObject_it_inv) done lemma threadSet_sch_act: "(\tcb. tcbState (F tcb) = tcbState tcb \ tcbDomain (F tcb) = tcbDomain tcb) \ \\s. sch_act_wf (ksSchedulerAction s) s\ threadSet F t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (wp sch_act_wf_lift threadSet_pred_tcb_no_state | simp add: tcb_in_cur_domain'_def)+ apply (rule_tac f="ksCurDomain" in hoare_lift_Pf) apply (wp threadSet_obj_at'_strongish | simp)+ done lemma threadSet_sch_actT_P: assumes z: "\ P \ (\tcb. tcbState (F tcb) = tcbState tcb \ tcbDomain (F tcb) = tcbDomain tcb)" assumes z': "P \ (\tcb. tcbState (F tcb) = Inactive \ tcbDomain (F tcb) = tcbDomain tcb ) \ (\st. Q st \ st = Inactive)" shows "\\s. sch_act_wf (ksSchedulerAction s) s \ (P \ st_tcb_at' Q t s)\ threadSet F t \\rv s. sch_act_wf (ksSchedulerAction s) s\" using z z' apply (case_tac P, simp_all add: threadSet_sch_act) apply (clarsimp simp: valid_def) apply (frule_tac P1="\sa. sch_act_wf sa s" in use_valid [OF _ threadSet_nosch], assumption) apply (frule_tac P1="(=) (ksCurThread s)" in use_valid [OF _ threadSet_ct], rule refl) apply (frule_tac P1="(=) (ksCurDomain s)" in use_valid [OF _ threadSet_cd], rule refl) apply (case_tac "ksSchedulerAction b", simp_all add: ct_in_state'_def pred_tcb_at'_def) apply (subgoal_tac "t \ ksCurThread s") apply (drule_tac t'1="ksCurThread s" and P1="activatable' \ tcbState" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp simp: o_def) apply (clarsimp simp: o_def) apply (fastforce simp: obj_at'_def) apply (rename_tac word) apply (subgoal_tac "t \ word") apply (frule_tac t'1=word and P1="runnable' \ tcbState" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp simp: o_def) apply (rule conjI) apply (clarsimp simp: o_def) apply (clarsimp simp: tcb_in_cur_domain'_def) apply (frule_tac t'1=word and P1="\tcb. ksCurDomain b = tcbDomain tcb" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp simp: o_def)+ apply (fastforce simp: obj_at'_def) done lemma threadSet_ksMachine[wp]: "\\s. P (ksMachineState s)\ threadSet F t \\_ s. P (ksMachineState s)\" apply (simp add: threadSet_def) by (wp setObject_ksMachine updateObject_default_inv | simp)+ lemma threadSet_vms'[wp]: "\valid_machine_state'\ threadSet F t \\rv. valid_machine_state'\" apply (simp add: valid_machine_state'_def pointerInUserData_def pointerInDeviceData_def) by (intro hoare_vcg_all_lift hoare_vcg_disj_lift; wp) lemma threadSet_not_inQ: "\ct_not_inQ and (\s. (\tcb. tcbQueued (F tcb) \ \ tcbQueued tcb) \ ksSchedulerAction s = ResumeCurrentThread \ t \ ksCurThread s)\ threadSet F t \\_. ct_not_inQ\" apply (simp add: threadSet_def ct_not_inQ_def) apply (wp) apply (rule hoare_convert_imp [OF setObject_nosch]) apply (rule updateObject_tcb_inv) apply (wps setObject_ct_inv) apply (wp setObject_tcb_strongest getObject_tcb_wp)+ apply (case_tac "t = ksCurThread s") apply (clarsimp simp: obj_at'_def)+ done lemma threadSet_invs_trivial_helper[simp]: "{r \ state_refs_of' s t. snd r \ TCBBound} \ {r \ state_refs_of' s t. snd r = TCBBound} = state_refs_of' s t" by auto lemma threadSet_ct_idle_or_in_cur_domain': "(\tcb. tcbDomain (F tcb) = tcbDomain tcb) \ \ct_idle_or_in_cur_domain'\ threadSet F t \\_. ct_idle_or_in_cur_domain'\" apply (rule ct_idle_or_in_cur_domain'_lift) apply (wp hoare_vcg_disj_lift| simp)+ done crunch ksDomScheduleIdx[wp]: threadSet "\s. P (ksDomScheduleIdx s)" (wp: setObject_ksPSpace_only updateObject_default_inv) crunch gsUntypedZeroRanges[wp]: threadSet "\s. P (gsUntypedZeroRanges s)" (wp: setObject_ksPSpace_only updateObject_default_inv) lemma setObject_tcb_ksDomScheduleIdx [wp]: "\\s. P (ksDomScheduleIdx s) \ setObject t (v::tcb) \\_ s. P (ksDomScheduleIdx s)\" apply (simp add:setObject_def updateObject_default_def in_monad) apply wpsimp done lemma threadSet_valid_dom_schedule': "\ valid_dom_schedule'\ threadSet F t \\_. valid_dom_schedule'\" unfolding threadSet_def by (wp setObject_ksDomSchedule_inv hoare_Ball_helper) lemma threadSet_invs_trivialT: assumes x: "\tcb. \(getF,setF) \ ran tcb_cte_cases. getF (F tcb) = getF tcb" assumes z: "\tcb. tcbState (F tcb) = tcbState tcb \ tcbDomain (F tcb) = tcbDomain tcb" assumes w: "\tcb. is_aligned (tcbIPCBuffer tcb) msg_align_bits \ is_aligned (tcbIPCBuffer (F tcb)) msg_align_bits" assumes a: "\tcb. tcbBoundNotification (F tcb) = tcbBoundNotification tcb" assumes w: "\tcb. is_aligned (tcbIPCBuffer tcb) msg_align_bits \ is_aligned (tcbIPCBuffer (F tcb)) msg_align_bits" assumes v: "\tcb. tcbDomain tcb \ maxDomain \ tcbDomain (F tcb) \ maxDomain" assumes u: "\tcb. tcbPriority tcb \ maxPriority \ tcbPriority (F tcb) \ maxPriority" assumes b: "\tcb. tcbMCP tcb \ maxPriority \ tcbMCP (F tcb) \ maxPriority" shows "\\s. invs' s \ (\d p. (\tcb. inQ d p tcb \ \ inQ d p (F tcb)) \ t \ set (ksReadyQueues s (d, p))) \ (\ko d p. ko_at' ko t s \ inQ d p (F ko) \ \ inQ d p ko \ t \ set (ksReadyQueues s (d, p))) \ ((\tcb. \ tcbQueued tcb \ tcbQueued (F tcb)) \ ex_nonz_cap_to' t s \ t \ ksCurThread s) \ (\tcb. tcbQueued (F tcb) \ ksSchedulerAction s = ResumeCurrentThread \ tcbQueued tcb \ t \ ksCurThread s)\ threadSet F t \\rv. invs'\" proof - from z have domains: "\tcb. tcbDomain (F tcb) = tcbDomain tcb" by blast note threadSet_sch_actT_P[where P=False, simplified] have y: "\tcb. tcb_st_refs_of' (tcbState (F tcb)) = tcb_st_refs_of' (tcbState tcb) \ valid_tcb_state' (tcbState (F tcb)) = valid_tcb_state' (tcbState tcb)" by (auto simp: z) show ?thesis apply (simp add: invs'_def valid_state'_def split del: if_split) apply (rule hoare_pre) apply (wp x w v u b threadSet_valid_pspace'T threadSet_sch_actT_P[where P=False, simplified] threadSet_valid_queues threadSet_state_refs_of'T[where f'=id] threadSet_iflive'T threadSet_ifunsafe'T threadSet_idle'T threadSet_global_refsT irqs_masked_lift valid_irq_node_lift valid_irq_handlers_lift'' threadSet_ctes_ofT threadSet_not_inQ threadSet_ct_idle_or_in_cur_domain' threadSet_valid_dom_schedule' threadSet_valid_queues' threadSet_cur untyped_ranges_zero_lift |clarsimp simp: y z a domains cteCaps_of_def |rule refl)+ apply (clarsimp simp: obj_at'_def pred_tcb_at'_def) apply (clarsimp simp: cur_tcb'_def valid_irq_node'_def valid_queues'_def o_def) by (fastforce simp: domains ct_idle_or_in_cur_domain'_def tcb_in_cur_domain'_def z a) qed lemmas threadSet_invs_trivial = threadSet_invs_trivialT [OF all_tcbI all_tcbI all_tcbI all_tcbI, OF ball_tcb_cte_casesI] lemma zobj_refs'_capRange: "s \' cap \ zobj_refs' cap \ capRange cap" by (cases cap; simp add: valid_cap'_def capAligned_def capRange_def is_aligned_no_overflow) lemma global'_no_ex_cap: "\valid_global_refs' s; valid_pspace' s\ \ \ ex_nonz_cap_to' (ksIdleThread s) s" apply (clarsimp simp: ex_nonz_cap_to'_def valid_global_refs'_def valid_refs'_def2 valid_pspace'_def) apply (drule cte_wp_at_norm', clarsimp) apply (frule(1) cte_wp_at_valid_objs_valid_cap', clarsimp) apply (clarsimp simp: cte_wp_at'_def dest!: zobj_refs'_capRange, blast) done lemma getObject_tcb_sp: "\P\ getObject r \\t::tcb. P and ko_at' t r\" by (wp getObject_obj_at'; simp) lemma threadSet_valid_objs': "\valid_objs' and (\s. \tcb. valid_tcb' tcb s \ valid_tcb' (f tcb) s)\ threadSet f t \\rv. valid_objs'\" apply (simp add: threadSet_def) apply wp prefer 2 apply (rule getObject_tcb_sp) apply (rule hoare_weaken_pre) apply (rule setObject_tcb_valid_objs) prefer 2 apply assumption apply (clarsimp simp: valid_obj'_def) apply (frule (1) ko_at_valid_objs') apply simp apply (simp add: valid_obj'_def) apply (clarsimp elim!: obj_at'_weakenE) done lemma asUser_corres': assumes y: "corres_underlying Id False True r \ \ f g" shows "corres r (tcb_at t and pspace_aligned and pspace_distinct) \ (as_user t f) (asUser t g)" proof - note arch_tcb_context_get_def[simp] note atcbContextGet_def[simp] note arch_tcb_context_set_def[simp] note atcbContextSet_def[simp] have L1: "corres (\tcb con. (arch_tcb_context_get o tcb_arch) tcb = con) (tcb_at t and pspace_aligned and pspace_distinct) \ (gets_the (get_tcb t)) (threadGet (atcbContextGet o tcbArch) t)" apply (rule corres_cross_over_guard[where Q="tcb_at' t"]) apply (fastforce simp: tcb_at_cross state_relation_def) apply (rule corres_guard_imp) apply (rule corres_gets_the) apply (simp add: threadGet_def) apply (rule corres_rel_imp [OF corres_get_tcb]) apply (simp add: tcb_relation_def arch_tcb_relation_def) apply (simp add: tcb_at_def)+ done have L2: "\tcb tcb' con con'. \ tcb_relation tcb tcb'; con = con'\ \ tcb_relation (tcb \ tcb_arch := arch_tcb_context_set con (tcb_arch tcb) \) (tcb' \ tcbArch := atcbContextSet con' (tcbArch tcb') \)" by (simp add: tcb_relation_def arch_tcb_relation_def) have L3: "\r add tcb tcb' con con'. \ r () (); con = con'\ \ corres r (\s. get_tcb add s = Some tcb) (\s'. (tcb', s') \ fst (getObject add s')) (set_object add (TCB (tcb \ tcb_arch := arch_tcb_context_set con (tcb_arch tcb) \))) (setObject add (tcb' \ tcbArch := atcbContextSet con' (tcbArch tcb') \))" by (rule setObject_update_TCB_corres [OF L2], (simp add: tcb_cte_cases_def tcb_cap_cases_def cteSizeBits_def exst_same_def)+) have L4: "\con con'. con = con' \ corres (\(irv, nc) (irv', nc'). r irv irv' \ nc = nc') \ \ (select_f (f con)) (select_f (g con'))" using y by (fastforce simp: corres_underlying_def select_f_def split_def Id_def) show ?thesis apply (rule corres_cross_over_guard[where Q="tcb_at' t"]) apply (fastforce simp: tcb_at_cross state_relation_def) apply (simp add: as_user_def asUser_def) apply (rule corres_guard_imp) apply (rule_tac r'="\tcb con. (arch_tcb_context_get o tcb_arch) tcb = con" in corres_split) apply simp apply (rule L1[simplified]) apply (rule corres_split[OF L4]) apply simp apply clarsimp apply (rule corres_split_nor) apply (simp add: threadSet_def) apply (rule corres_symb_exec_r) apply (rule L3[simplified]) prefer 5 apply (rule no_fail_pre_and, wp) apply (wp select_f_inv | simp)+ done qed lemma asUser_corres: assumes y: "corres_underlying Id False True r \ \ f g" shows "corres r (tcb_at t and invs) (tcb_at' t and invs') (as_user t f) (asUser t g)" apply (rule corres_guard_imp) apply (rule asUser_corres' [OF y]) apply (simp add: invs_def valid_state_def valid_pspace_def) apply (simp add: invs'_def valid_state'_def valid_pspace'_def) done lemma asUser_inv: assumes x: "\P. \P\ f \\x. P\" shows "\P\ asUser t f \\x. P\" proof - have P: "\a b input. (a, b) \ fst (f input) \ b = input" by (rule use_valid [OF _ x], assumption, rule refl) have R: "\x. tcbArch_update (\_. tcbArch x) x = x" by (case_tac x, simp) show ?thesis apply (simp add: asUser_def split_def threadGet_def threadSet_def liftM_def bind_assoc) apply (clarsimp simp: valid_def in_monad getObject_def setObject_def loadObject_default_def objBits_simps' modify_def split_def updateObject_default_def in_magnitude_check select_f_def dest!: P) apply (simp add: R map_upd_triv) done qed lemma asUser_getRegister_corres: "corres (=) (tcb_at t and pspace_aligned and pspace_distinct) \ (as_user t (getRegister r)) (asUser t (getRegister r))" apply (rule asUser_corres') apply (clarsimp simp: getRegister_def) done lemma user_getreg_inv'[wp]: "\P\ asUser t (getRegister r) \\x. P\" apply (rule asUser_inv) apply (simp_all add: getRegister_def) done lemma asUser_typ_at' [wp]: "\\s. P (typ_at' T p s)\ asUser t' f \\rv s. P (typ_at' T p s)\" by (simp add: asUser_def bind_assoc split_def, wp select_f_inv) lemmas asUser_typ_ats[wp] = typ_at_lifts [OF asUser_typ_at'] lemma asUser_invs[wp]: "\invs' and tcb_at' t\ asUser t m \\rv. invs'\" apply (simp add: asUser_def split_def) apply (wp hoare_drop_imps | simp)+ apply (wp threadSet_invs_trivial hoare_drop_imps | simp)+ done lemma asUser_nosch[wp]: "\\s. P (ksSchedulerAction s)\ asUser t m \\rv s. P (ksSchedulerAction s)\" apply (simp add: asUser_def split_def) apply (wp hoare_drop_imps | simp)+ done crunch aligned'[wp]: asUser pspace_aligned' (simp: crunch_simps wp: crunch_wps) crunch distinct'[wp]: asUser pspace_distinct' (simp: crunch_simps wp: crunch_wps) lemma asUser_valid_objs [wp]: "\valid_objs'\ asUser t f \\rv. valid_objs'\" apply (simp add: asUser_def split_def) apply (wp threadSet_valid_objs' hoare_drop_imps | simp add: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def)+ done lemma asUser_valid_pspace'[wp]: "\valid_pspace'\ asUser t m \\rv. valid_pspace'\" apply (simp add: asUser_def split_def) apply (wp threadSet_valid_pspace' hoare_drop_imps | simp)+ done lemma asUser_valid_queues[wp]: "\Invariants_H.valid_queues\ asUser t m \\rv. Invariants_H.valid_queues\" apply (simp add: asUser_def split_def) apply (wp hoare_drop_imps | simp)+ apply (wp threadSet_valid_queues hoare_drop_imps | simp)+ done lemma asUser_ifunsafe'[wp]: "\if_unsafe_then_cap'\ asUser t m \\rv. if_unsafe_then_cap'\" apply (simp add: asUser_def split_def) apply (wp threadSet_ifunsafe' hoare_drop_imps | simp)+ done lemma asUser_st_refs_of'[wp]: "\\s. P (state_refs_of' s)\ asUser t m \\rv s. P (state_refs_of' s)\" apply (simp add: asUser_def split_def) apply (wp threadSet_state_refs_of' hoare_drop_imps | simp)+ done lemma asUser_iflive'[wp]: "\if_live_then_nonz_cap'\ asUser t m \\rv. if_live_then_nonz_cap'\" apply (simp add: asUser_def split_def) apply (wp threadSet_iflive' hoare_drop_imps | clarsimp | auto)+ done lemma asUser_cur_tcb[wp]: "\cur_tcb'\ asUser t m \\rv. cur_tcb'\" apply (simp add: asUser_def split_def) apply (wp threadSet_cur hoare_drop_imps | simp)+ done lemma asUser_cte_wp_at'[wp]: "\cte_wp_at' P p\ asUser t m \\rv. cte_wp_at' P p\" apply (simp add: asUser_def split_def) apply (wp threadSet_cte_wp_at' hoare_drop_imps | simp)+ done lemma asUser_cap_to'[wp]: "\ex_nonz_cap_to' p\ asUser t m \\rv. ex_nonz_cap_to' p\" by (wp ex_nonz_cap_to_pres') lemma asUser_pred_tcb_at' [wp]: "\pred_tcb_at' proj P t\ asUser t' f \\_. pred_tcb_at' proj P t\" apply (simp add: asUser_def split_def) apply (wp threadSet_pred_tcb_no_state) apply (case_tac tcb) apply (simp add: tcb_to_itcb'_def) apply (wpsimp wp: select_f_inv)+ done crunches asUser for ct[wp]: "\s. P (ksCurThread s)" and cur_domain[wp]: "\s. P (ksCurDomain s)" (simp: crunch_simps wp: hoare_drop_imps getObject_inv_tcb setObject_ct_inv) lemma asUser_tcb_in_cur_domain'[wp]: "\tcb_in_cur_domain' t'\ asUser t m \\_. tcb_in_cur_domain' t'\" apply (simp add: asUser_def tcb_in_cur_domain'_def threadGet_def) apply (wp | wpc | simp)+ apply (rule_tac f="ksCurDomain" in hoare_lift_Pf) apply (wp threadSet_obj_at'_strongish getObject_tcb_wp | simp)+ apply (clarsimp simp: obj_at'_def) done lemma asUser_tcbDomain_inv[wp]: "\obj_at' (\tcb. P (tcbDomain tcb)) t'\ asUser t m \\_. obj_at' (\tcb. P (tcbDomain tcb)) t'\" apply (simp add: asUser_def tcb_in_cur_domain'_def threadGet_def) apply (wp threadSet_obj_at'_strongish getObject_tcb_wp | wpc | simp | clarsimp simp: obj_at'_def)+ done lemma asUser_tcbPriority_inv[wp]: "\obj_at' (\tcb. P (tcbPriority tcb)) t'\ asUser t m \\_. obj_at' (\tcb. P (tcbPriority tcb)) t'\" apply (simp add: asUser_def tcb_in_cur_domain'_def threadGet_def) apply (wp threadSet_obj_at'_strongish getObject_tcb_wp | wpc | simp | clarsimp simp: obj_at'_def)+ done lemma asUser_sch_act_wf[wp]: "\\s. sch_act_wf (ksSchedulerAction s) s\ asUser t m \\rv s. sch_act_wf (ksSchedulerAction s) s\" by (wp sch_act_wf_lift) lemma asUser_idle'[wp]: "\valid_idle'\ asUser t m \\rv. valid_idle'\" apply (simp add: asUser_def split_def) apply (wpsimp wp: threadSet_idle' select_f_inv) done lemma no_fail_asUser [wp]: "no_fail \ f \ no_fail (tcb_at' t) (asUser t f)" apply (simp add: asUser_def split_def) apply wp apply (simp add: no_fail_def) apply (wp hoare_drop_imps) apply simp done lemma asUser_setRegister_corres: "corres dc (tcb_at t and pspace_aligned and pspace_distinct) \ (as_user t (setRegister r v)) (asUser t (setRegister r v))" apply (simp add: setRegister_def) apply (rule asUser_corres') apply (rule corres_modify'; simp) done lemma getThreadState_corres: "corres thread_state_relation (tcb_at t and pspace_aligned and pspace_distinct) \ (get_thread_state t) (getThreadState t)" apply (simp add: get_thread_state_def getThreadState_def) apply (rule threadGet_corres) apply (simp add: tcb_relation_def) done lemma gts_wf'[wp]: "\tcb_at' t and invs'\ getThreadState t \valid_tcb_state'\" apply (simp add: getThreadState_def threadGet_def liftM_def) apply (wp getObject_tcb_wp) apply clarsimp apply (drule obj_at_ko_at', clarsimp) apply (frule ko_at_valid_objs', fastforce, simp) apply (fastforce simp: valid_obj'_def valid_tcb'_def) done lemma gts_st_tcb_at'[wp]: "\st_tcb_at' P t\ getThreadState t \\rv s. P rv\" apply (simp add: getThreadState_def threadGet_def liftM_def) apply wp apply (rule hoare_chain) apply (rule obj_at_getObject) apply (clarsimp simp: loadObject_default_def in_monad) apply assumption apply simp apply (simp add: pred_tcb_at'_def) done lemma gts_inv'[wp]: "\P\ getThreadState t \\rv. P\" by (simp add: getThreadState_def) wp lemma getBoundNotification_corres: "corres (=) (tcb_at t and pspace_aligned and pspace_distinct) \ (get_bound_notification t) (getBoundNotification t)" apply (simp add: get_bound_notification_def getBoundNotification_def) apply (rule threadGet_corres) apply (simp add: tcb_relation_def) done lemma gbn_bound_tcb_at'[wp]: "\bound_tcb_at' P t\ getBoundNotification t \\rv s. P rv\" apply (simp add: getBoundNotification_def threadGet_def liftM_def) apply wp apply (rule hoare_strengthen_post) apply (rule obj_at_getObject) apply (clarsimp simp: loadObject_default_def in_monad) apply simp apply (simp add: pred_tcb_at'_def) done lemma gbn_inv'[wp]: "\P\ getBoundNotification t \\rv. P\" by (simp add: getBoundNotification_def) wp lemma isStopped_def2: "isStopped t = liftM (Not \ activatable') (getThreadState t)" apply (unfold isStopped_def fun_app_def) apply (fold liftM_def) apply (rule arg_cong [where f="\f. liftM f (getThreadState t)"]) apply (rule ext) apply (simp split: Structures_H.thread_state.split) done lemma isRunnable_def2: "isRunnable t = liftM runnable' (getThreadState t)" apply (simp add: isRunnable_def isStopped_def2 liftM_def) apply (rule bind_eqI, rule ext, rule arg_cong) apply (case_tac state) apply (clarsimp)+ done lemma isStopped_inv[wp]: "\P\ isStopped t \\rv. P\" by (simp add: isStopped_def2 | wp gts_inv')+ lemma isRunnable_inv[wp]: "\P\ isRunnable t \\rv. P\" by (simp add: isRunnable_def2 | wp gts_inv')+ lemma isRunnable_wp[wp]: "\\s. Q (st_tcb_at' (runnable') t s) s\ isRunnable t \Q\" apply (simp add: isRunnable_def2) apply (wpsimp simp: getThreadState_def threadGet_def wp: getObject_tcb_wp) apply (clarsimp simp: getObject_def valid_def in_monad st_tcb_at'_def loadObject_default_def obj_at'_def split_def objBits_simps in_magnitude_check) done lemma setQueue_obj_at[wp]: "\obj_at' P t\ setQueue d p q \\rv. obj_at' P t\" apply (simp add: setQueue_def) apply wp apply (fastforce intro: obj_at'_pspaceI) done lemma setQueue_nosch[wp]: "\\s. P (ksSchedulerAction s)\ setQueue d p ts \\rv s. P (ksSchedulerAction s)\" apply (simp add: setQueue_def) apply wp apply simp done lemma gq_wp[wp]: "\\s. Q (ksReadyQueues s (d, p)) s\ getQueue d p \Q\" by (simp add: getQueue_def, wp) lemma no_fail_getQueue [wp]: "no_fail \ (getQueue d p)" by (simp add: getQueue_def) lemma no_fail_setQueue [wp]: "no_fail \ (setQueue d p xs)" by (simp add: setQueue_def) lemma in_magnitude_check': "\ is_aligned x n; (1 :: machine_word) < 2 ^ n; ksPSpace s x = Some y; ps = ksPSpace s \ \ ((v, s') \ fst (magnitudeCheck x (snd (lookupAround2 x ps)) n s)) = (s' = s \ ps_clear x n s)" by (simp add: in_magnitude_check) lemma cdt_relation_trans_state[simp]: "cdt_relation (swp cte_at (trans_state f s)) m m' = cdt_relation (swp cte_at s) m m'" by (simp add: cdt_relation_def) lemma getObject_obj_at_tcb: "\obj_at' (\t. P t t) p\ getObject p \\t::tcb. obj_at' (P t) p\" apply (wp getObject_tcb_wp) apply (drule obj_at_ko_at') apply clarsimp apply (rule exI, rule conjI, assumption) apply (erule obj_at'_weakenE) apply simp done lemma threadGet_obj_at': "\obj_at' (\t. P (f t) t) t\ threadGet f t \\rv. obj_at' (P rv) t\" by (simp add: threadGet_def o_def | wp getObject_obj_at_tcb)+ lemma fun_if_triv[simp]: "(\x. if x = y then f y else f x) = f" by (force) lemma corres_get_etcb: "corres (etcb_relation) (is_etcb_at t) (tcb_at' t) (gets_the (get_etcb t)) (getObject t)" apply (rule corres_no_failI) apply wp apply (clarsimp simp add: get_etcb_def gets_the_def gets_def get_def assert_opt_def bind_def return_def fail_def split: option.splits ) apply (frule in_inv_by_hoareD [OF getObject_inv_tcb]) apply (clarsimp simp add: is_etcb_at_def obj_at'_def projectKO_def projectKO_opt_tcb split_def getObject_def loadObject_default_def in_monad) apply (case_tac bb) apply (simp_all add: fail_def return_def) apply (clarsimp simp add: state_relation_def ekheap_relation_def) apply (drule bspec) apply clarsimp apply blast apply (clarsimp simp add: other_obj_relation_def lookupAround2_known1) done lemma ethreadget_corres: assumes x: "\etcb tcb'. etcb_relation etcb tcb' \ r (f etcb) (f' tcb')" shows "corres r (is_etcb_at t) (tcb_at' t) (ethread_get f t) (threadGet f' t)" apply (simp add: ethread_get_def threadGet_def) apply (fold liftM_def) apply simp apply (rule corres_rel_imp) apply (rule corres_get_etcb) apply (simp add: x) done lemma setQueue_corres: "corres dc \ \ (set_tcb_queue d p q) (setQueue d p q)" apply (rule corres_no_failI) apply wp apply (clarsimp simp: setQueue_def in_monad set_tcb_queue_def return_def simpler_modify_def) apply (fastforce simp: state_relation_def ready_queues_relation_def) done lemma getQueue_corres: "corres (=) \ \ (get_tcb_queue qdom prio) (getQueue qdom prio)" apply (clarsimp simp add: getQueue_def state_relation_def ready_queues_relation_def get_tcb_queue_def gets_def) apply (fold gets_def) apply simp done lemma no_fail_return: "no_fail x (return y)" by wp lemma addToBitmap_noop_corres: "corres dc \ \ (return ()) (addToBitmap d p)" unfolding addToBitmap_def modifyReadyQueuesL1Bitmap_def getReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL2Bitmap_def by (rule corres_noop) (wp | simp add: state_relation_def | rule no_fail_pre)+ lemma addToBitmap_if_null_noop_corres: (* used this way in Haskell code *) "corres dc \ \ (return ()) (if null queue then addToBitmap d p else return ())" by (cases "null queue", simp_all add: addToBitmap_noop_corres) lemma removeFromBitmap_corres_noop: "corres dc \ \ (return ()) (removeFromBitmap tdom prioa)" unfolding removeFromBitmap_def by (rule corres_noop) (wp | simp add: bitmap_fun_defs state_relation_def | rule no_fail_pre)+ crunch typ_at'[wp]: addToBitmap "\s. P (typ_at' T p s)" (wp: hoare_drop_imps setCTE_typ_at') crunch typ_at'[wp]: removeFromBitmap "\s. P (typ_at' T p s)" (wp: hoare_drop_imps setCTE_typ_at') lemmas addToBitmap_typ_ats [wp] = typ_at_lifts [OF addToBitmap_typ_at'] lemmas removeFromBitmap_typ_ats [wp] = typ_at_lifts [OF removeFromBitmap_typ_at'] lemma tcbSchedEnqueue_corres: "corres dc (tcb_at t and is_etcb_at t and pspace_aligned and pspace_distinct) (Invariants_H.valid_queues and valid_queues') (tcb_sched_action (tcb_sched_enqueue) t) (tcbSchedEnqueue t)" proof - have ready_queues_helper: "\t tcb a b. \ ekheap a t = Some tcb; obj_at' tcbQueued t b ; valid_queues' b ; ekheap_relation (ekheap a) (ksPSpace b) \ \ t \ set (ksReadyQueues b (tcb_domain tcb, tcb_priority tcb))" unfolding valid_queues'_def by (fastforce dest: ekheap_relation_absD simp: obj_at'_def inQ_def etcb_relation_def) show ?thesis unfolding tcbSchedEnqueue_def tcb_sched_action_def apply (rule corres_cross_over_guard[where P'=Q and Q="tcb_at' t and Q" for Q]) apply (fastforce simp: tcb_at_cross state_relation_def) apply (rule corres_symb_exec_r [OF _ _ threadGet_inv, where Q'="\rv. tcb_at' t and Invariants_H.valid_queues and valid_queues' and obj_at' (\obj. tcbQueued obj = rv) t"]) defer apply (wp threadGet_obj_at'; simp_all) apply (rule no_fail_pre, wp, blast) apply (case_tac queued; simp_all) apply (rule corres_no_failI; simp add: no_fail_return) apply (clarsimp simp: in_monad ethread_get_def gets_the_def bind_assoc assert_opt_def exec_gets is_etcb_at_def get_etcb_def get_tcb_queue_def set_tcb_queue_def simpler_modify_def ready_queues_relation_def state_relation_def tcb_sched_enqueue_def) apply (rule ready_queues_helper; auto) apply (clarsimp simp: when_def) apply (rule stronger_corres_guard_imp) apply (rule corres_split[where r'="(=)", OF ethreadget_corres]) apply (simp add: etcb_relation_def) apply (rule corres_split[where r'="(=)", OF ethreadget_corres]) apply (simp add: etcb_relation_def) apply (rule corres_split[where r'="(=)"]) apply simp apply (rule getQueue_corres) apply (rule corres_split_noop_rhs2) apply simp apply (simp add: tcb_sched_enqueue_def split del: if_split) apply (rule_tac P=\ and Q="K (t \ set queuea)" in corres_assume_pre) apply simp apply (rule setQueue_corres[unfolded dc_def]) apply (rule corres_split_noop_rhs2) apply (fastforce intro: addToBitmap_noop_corres) apply (fastforce intro: threadSet_corres_noop simp: tcb_relation_def exst_same_def) apply (wp getObject_tcb_wp | simp add: threadGet_def)+ apply (fastforce simp: valid_queues_def valid_queues_no_bitmap_def obj_at'_def inQ_def project_inject) done qed definition weak_sch_act_wf :: "scheduler_action \ kernel_state \ bool" where "weak_sch_act_wf sa = (\s. \t. sa = SwitchToThread t \ st_tcb_at' runnable' t s \ tcb_in_cur_domain' t s)" lemma weak_sch_act_wf_updateDomainTime[simp]: "weak_sch_act_wf m (ksDomainTime_update f s) = weak_sch_act_wf m s" by (simp add:weak_sch_act_wf_def tcb_in_cur_domain'_def ) lemma setSchedulerAction_corres: "sched_act_relation sa sa' \ corres dc \ \ (set_scheduler_action sa) (setSchedulerAction sa')" apply (simp add: setSchedulerAction_def set_scheduler_action_def) apply (rule corres_no_failI) apply wp apply (clarsimp simp: in_monad simpler_modify_def state_relation_def) done lemma getSchedulerAction_corres: "corres sched_act_relation \ \ (gets scheduler_action) getSchedulerAction" apply (simp add: getSchedulerAction_def) apply (clarsimp simp: state_relation_def) done lemma rescheduleRequired_corres: "corres dc (weak_valid_sched_action and valid_etcbs and pspace_aligned and pspace_distinct) (Invariants_H.valid_queues and valid_queues') (reschedule_required) rescheduleRequired" apply (simp add: rescheduleRequired_def reschedule_required_def) apply (rule corres_guard_imp) apply (rule corres_split[OF getSchedulerAction_corres]) apply (rule_tac P="case action of switch_thread t \ P t | _ \ \" and P'="case actiona of SwitchToThread t \ P' t | _ \ \" for P P' in corres_split[where r'=dc]) apply (case_tac action) apply simp apply simp apply (rule tcbSchedEnqueue_corres) apply simp apply (rule setSchedulerAction_corres) apply simp apply (wp | wpc | simp)+ apply (force dest: st_tcb_weakenE simp: in_monad weak_valid_sched_action_def valid_etcbs_def st_tcb_at_def obj_at_def is_tcb split: Deterministic_A.scheduler_action.split) apply (clarsimp split: scheduler_action.splits) done lemma rescheduleRequired_corres_simple: "corres dc \ sch_act_simple (set_scheduler_action choose_new_thread) rescheduleRequired" apply (simp add: rescheduleRequired_def) apply (rule corres_symb_exec_r[where Q'="\rv s. rv = ResumeCurrentThread \ rv = ChooseNewThread"]) apply (rule corres_symb_exec_r) apply (rule setSchedulerAction_corres, simp) apply (wp | clarsimp split: scheduler_action.split)+ apply (wp | clarsimp simp: sch_act_simple_def split: scheduler_action.split)+ apply (simp add: getSchedulerAction_def) done lemma weak_sch_act_wf_lift: assumes pre: "\P. \\s. P (sa s)\ f \\rv s. P (sa s)\" "\t. \st_tcb_at' runnable' t\ f \\rv. st_tcb_at' runnable' t\" "\t. \tcb_in_cur_domain' t\ f \\rv. tcb_in_cur_domain' t\" shows "\\s. weak_sch_act_wf (sa s) s\ f \\rv s. weak_sch_act_wf (sa s) s\" apply (simp only: weak_sch_act_wf_def imp_conv_disj) apply (intro hoare_vcg_all_lift hoare_vcg_conj_lift hoare_vcg_disj_lift pre | simp)+ done lemma asUser_weak_sch_act_wf[wp]: "\\s. weak_sch_act_wf (ksSchedulerAction s) s\ asUser t m \\rv s. weak_sch_act_wf (ksSchedulerAction s) s\" by (wp weak_sch_act_wf_lift) lemma doMachineOp_weak_sch_act_wf[wp]: "\\s. weak_sch_act_wf (ksSchedulerAction s) s\ doMachineOp m \\rv s. weak_sch_act_wf (ksSchedulerAction s) s\" by (simp add: doMachineOp_def split_def tcb_in_cur_domain'_def | wp weak_sch_act_wf_lift)+ lemma weak_sch_act_wf_setQueue[wp]: "\\s. weak_sch_act_wf (ksSchedulerAction s) s \ setQueue qdom prio queue \\_ s. weak_sch_act_wf (ksSchedulerAction s) s \" by (simp add: setQueue_def weak_sch_act_wf_def tcb_in_cur_domain'_def | wp)+ lemma threadSet_tcbDomain_triv: assumes "\tcb. tcbDomain (f tcb) = tcbDomain tcb" shows "\tcb_in_cur_domain' t'\ threadSet f t \\_. tcb_in_cur_domain' t'\" apply (simp add: tcb_in_cur_domain'_def) apply (rule_tac f="ksCurDomain" in hoare_lift_Pf) apply (wp threadSet_obj_at'_strongish getObject_tcb_wp | simp add: assms)+ done lemmas threadSet_weak_sch_act_wf = weak_sch_act_wf_lift[OF threadSet_nosch threadSet_pred_tcb_no_state threadSet_tcbDomain_triv, simplified] lemma removeFromBitmap_nosch[wp]: "\\s. P (ksSchedulerAction s)\ removeFromBitmap d p \\rv s. P (ksSchedulerAction s)\" unfolding removeFromBitmap_def by (simp add: bitmap_fun_defs|wp setObject_nosch)+ lemma addToBitmap_nosch[wp]: "\\s. P (ksSchedulerAction s)\ addToBitmap d p \\rv s. P (ksSchedulerAction s)\" unfolding addToBitmap_def by (simp add: bitmap_fun_defs|wp setObject_nosch)+ lemmas removeFromBitmap_weak_sch_act_wf[wp] = weak_sch_act_wf_lift[OF removeFromBitmap_nosch] lemmas addToBitmap_weak_sch_act_wf[wp] = weak_sch_act_wf_lift[OF addToBitmap_nosch] crunch st_tcb_at'[wp]: removeFromBitmap "st_tcb_at' P t" crunch pred_tcb_at'[wp]: removeFromBitmap "pred_tcb_at' proj P t" crunch not_st_tcb_at'[wp]: removeFromBitmap "\s. \ (st_tcb_at' P' t) s" crunch not_pred_tcb_at'[wp]: removeFromBitmap "\s. \ (pred_tcb_at' proj P' t) s" crunch st_tcb_at'[wp]: addToBitmap "st_tcb_at' P' t" crunch pred_tcb_at'[wp]: addToBitmap "pred_tcb_at' proj P' t" crunch not_st_tcb_at'[wp]: addToBitmap "\s. \ (st_tcb_at' P' t) s" crunch not_pred_tcb_at'[wp]: addToBitmap "\s. \ (pred_tcb_at' proj P' t) s" crunch obj_at'[wp]: removeFromBitmap "obj_at' P t" crunch obj_at'[wp]: addToBitmap "obj_at' P t" lemma removeFromBitmap_tcb_in_cur_domain'[wp]: "\tcb_in_cur_domain' t\ removeFromBitmap tdom prio \\ya. tcb_in_cur_domain' t\" unfolding tcb_in_cur_domain'_def removeFromBitmap_def apply (rule_tac f="\s. ksCurDomain s" in hoare_lift_Pf) apply (wp setObject_cte_obj_at_tcb' | simp add: bitmap_fun_defs)+ done lemma addToBitmap_tcb_in_cur_domain'[wp]: "\tcb_in_cur_domain' t\ addToBitmap tdom prio \\ya. tcb_in_cur_domain' t\" unfolding tcb_in_cur_domain'_def addToBitmap_def apply (rule_tac f="\s. ksCurDomain s" in hoare_lift_Pf) apply (wp setObject_cte_obj_at_tcb' | simp add: bitmap_fun_defs)+ done lemma tcbSchedDequeue_weak_sch_act_wf[wp]: "\ \s. weak_sch_act_wf (ksSchedulerAction s) s \ tcbSchedDequeue a \ \_ s. weak_sch_act_wf (ksSchedulerAction s) s \" apply (simp add: tcbSchedDequeue_def) apply (wp threadSet_weak_sch_act_wf removeFromBitmap_weak_sch_act_wf | simp add: crunch_simps)+ done lemma dequeue_nothing_eq[simp]: "t \ set list \ tcb_sched_dequeue t list = list" apply (clarsimp simp: tcb_sched_dequeue_def) apply (induct list) apply simp apply clarsimp done lemma gets_the_exec: "f s \ None \ (do x \ gets_the f; g x od) s = g (the (f s)) s" apply (clarsimp simp add: gets_the_def bind_def gets_def get_def return_def assert_opt_def) done lemma tcbSchedDequeue_corres: "corres dc (is_etcb_at t and tcb_at t and pspace_aligned and pspace_distinct) (Invariants_H.valid_queues) (tcb_sched_action tcb_sched_dequeue t) (tcbSchedDequeue t)" apply (rule corres_cross_over_guard[where P'=Q and Q="tcb_at' t and Q" for Q]) apply (fastforce simp: tcb_at_cross state_relation_def) apply (simp only: tcbSchedDequeue_def tcb_sched_action_def) apply (rule corres_symb_exec_r[OF _ _ threadGet_inv, where Q'="\rv. tcb_at' t and Invariants_H.valid_queues and obj_at' (\obj. tcbQueued obj = rv) t"]) defer apply (wp threadGet_obj_at', simp, simp) apply (rule no_fail_pre, wp, simp) apply (case_tac queued) defer apply (simp add: when_def) apply (rule corres_no_failI) apply (wp) apply (clarsimp simp: in_monad ethread_get_def set_tcb_queue_def is_etcb_at_def state_relation_def) apply (subgoal_tac "t \ set (ready_queues a (tcb_domain y) (tcb_priority y))") prefer 2 subgoal by (force simp: tcb_sched_dequeue_def Invariants_H.valid_queues_def valid_queues_no_bitmap_def ready_queues_relation_def obj_at'_def inQ_def project_inject) apply (subst gets_the_exec) apply (simp add: get_etcb_def) apply (subst gets_the_exec) apply (simp add: get_etcb_def) apply (simp add: exec_gets simpler_modify_def get_etcb_def ready_queues_relation_def cong: if_cong get_tcb_queue_def) apply (simp add: when_def) apply (rule corres_guard_imp) apply (rule corres_split[where r'="(=)"]) apply (rule ethreadget_corres, simp add: etcb_relation_def) apply (rule corres_split[where r'="(=)"]) apply (rule ethreadget_corres, simp add: etcb_relation_def) apply (rule corres_split[where r'="(=)"]) apply (simp, rule getQueue_corres) apply (rule corres_split_noop_rhs2) apply (simp add: tcb_sched_dequeue_def) apply (rule setQueue_corres) apply (rule corres_split_noop_rhs) apply (clarsimp, rule removeFromBitmap_corres_noop) apply (rule threadSet_corres_noop; simp_all add: tcb_relation_def exst_same_def) apply (wp | simp)+ done lemma thread_get_test: "do cur_ts \ get_thread_state cur; g (test cur_ts) od = do t \ (thread_get (\tcb. test (tcb_state tcb)) cur); g t od" apply (simp add: get_thread_state_def thread_get_def) done lemma thread_get_isRunnable_corres: "corres (=) (tcb_at t and pspace_aligned and pspace_distinct) \ (thread_get (\tcb. runnable (tcb_state tcb)) t) (isRunnable t)" apply (simp add: isRunnable_def getThreadState_def threadGet_def thread_get_def) apply (fold liftM_def) apply simp apply (rule corres_rel_imp) apply (rule getObject_TCB_corres) apply (clarsimp simp add: tcb_relation_def thread_state_relation_def) apply (case_tac "tcb_state x",simp_all) done lemma setThreadState_corres: "thread_state_relation ts ts' \ corres dc (tcb_at t and pspace_aligned and pspace_distinct) \ (set_thread_state t ts) (setThreadState ts' t)" (is "?tsr \ corres dc ?Pre ?Pre' ?sts ?sts'") apply (simp add: set_thread_state_def setThreadState_def) apply (simp add: set_thread_state_ext_def[abs_def]) apply (subst bind_assoc[symmetric], subst thread_set_def[simplified, symmetric]) apply (rule corres_guard_imp) apply (rule corres_split[where r'=dc]) apply (rule threadset_corres, (simp add: tcb_relation_def exst_same_def)+) apply (subst thread_get_test[where test="runnable"]) apply (rule corres_split[OF thread_get_isRunnable_corres]) apply (rule corres_split[OF getCurThread_corres]) apply (rule corres_split[OF getSchedulerAction_corres]) apply (simp only: when_def) apply (rule corres_if[where Q=\ and Q'=\]) apply (rule iffI) apply clarsimp+ apply (case_tac rva,simp_all)[1] apply (wp rescheduleRequired_corres_simple corres_return_trivial | simp)+ apply (wp hoare_vcg_conj_lift[where Q'="\\"] | simp add: sch_act_simple_def)+ done lemma setBoundNotification_corres: "corres dc (tcb_at t and pspace_aligned and pspace_distinct) \ (set_bound_notification t ntfn) (setBoundNotification ntfn t)" apply (simp add: set_bound_notification_def setBoundNotification_def) apply (subst thread_set_def[simplified, symmetric]) apply (rule threadset_corres, simp_all add:tcb_relation_def exst_same_def) done crunches rescheduleRequired, tcbSchedDequeue, setThreadState, setBoundNotification for tcb'[wp]: "tcb_at' addr" crunches rescheduleRequired, removeFromBitmap for valid_objs'[wp]: valid_objs' (simp: unless_def crunch_simps) lemma tcbSchedDequeue_valid_objs' [wp]: "\ valid_objs' \ tcbSchedDequeue t \\_. valid_objs' \" unfolding tcbSchedDequeue_def apply (wp threadSet_valid_objs') apply (clarsimp simp add: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def) apply wp apply (simp add: if_apply_def2) apply (wp hoare_drop_imps) apply (wp | simp cong: if_cong add: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def if_apply_def2)+ done lemma sts_valid_objs': "\valid_objs' and valid_tcb_state' st\ setThreadState st t \\rv. valid_objs'\" apply (simp add: setThreadState_def setQueue_def isRunnable_def isStopped_def) apply (wp threadSet_valid_objs') apply (simp add: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def) apply (wp threadSet_valid_objs' | simp)+ apply (clarsimp simp: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def) done lemma sbn_valid_objs': "\valid_objs' and valid_bound_ntfn' ntfn\ setBoundNotification ntfn t \\rv. valid_objs'\" apply (simp add: setBoundNotification_def) apply (wp threadSet_valid_objs') apply (simp add: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def) done lemma ssa_wp[wp]: "\\s. P (s \ksSchedulerAction := sa\)\ setSchedulerAction sa \\_. P\" by (wpsimp simp: setSchedulerAction_def) crunches rescheduleRequired, tcbSchedDequeue for aligned'[wp]: "pspace_aligned'" and distinct'[wp]: "pspace_distinct'" and ctes_of[wp]: "\s. P (ctes_of s)" crunches rescheduleRequired, tcbSchedDequeue for no_0_obj'[wp]: "no_0_obj'" and pspace_canonical'[wp]: "pspace_canonical'" and pspace_in_kernel_mappings'[wp]: pspace_in_kernel_mappings' lemma sts'_valid_pspace'_inv[wp]: "\ valid_pspace' and tcb_at' t and valid_tcb_state' st \ setThreadState st t \ \rv. valid_pspace' \" apply (simp add: valid_pspace'_def) apply (rule hoare_pre) apply (wp sts_valid_objs') apply (simp add: setThreadState_def threadSet_def setQueue_def bind_assoc valid_mdb'_def) apply (wp getObject_obj_at_tcb | simp)+ apply (clarsimp simp: valid_mdb'_def) apply (drule obj_at_ko_at') apply clarsimp apply (erule obj_at'_weakenE) apply (simp add: tcb_cte_cases_def cteSizeBits_def) done crunch ct[wp]: setQueue "\s. P (ksCurThread s)" crunch cur_domain[wp]: setQueue "\s. P (ksCurDomain s)" crunch ct'[wp]: addToBitmap "\s. P (ksCurThread s)" crunch ct'[wp]: removeFromBitmap "\s. P (ksCurThread s)" lemma setQueue_tcb_in_cur_domain'[wp]: "\tcb_in_cur_domain' t\ setQueue d p xs \\_. tcb_in_cur_domain' t\" apply (simp add: setQueue_def tcb_in_cur_domain'_def) apply wp apply (simp add: ps_clear_def obj_at'_def) done lemma sbn'_valid_pspace'_inv[wp]: "\ valid_pspace' and tcb_at' t and valid_bound_ntfn' ntfn \ setBoundNotification ntfn t \ \rv. valid_pspace' \" apply (simp add: valid_pspace'_def) apply (rule hoare_pre) apply (wp sbn_valid_objs') apply (simp add: setBoundNotification_def threadSet_def bind_assoc valid_mdb'_def) apply (wp getObject_obj_at_tcb | simp)+ apply (clarsimp simp: valid_mdb'_def) apply (drule obj_at_ko_at') apply clarsimp apply (erule obj_at'_weakenE) apply (simp add: tcb_cte_cases_def cteSizeBits_def) done crunch pred_tcb_at'[wp]: setQueue "\s. P (pred_tcb_at' proj P' t s)" lemma setQueue_sch_act: "\\s. sch_act_wf (ksSchedulerAction s) s\ setQueue d p xs \\rv s. sch_act_wf (ksSchedulerAction s) s\" by (wp sch_act_wf_lift) lemma setQueue_valid_bitmapQ_except[wp]: "\ valid_bitmapQ_except d p \ setQueue d p ts \\_. valid_bitmapQ_except d p \" unfolding setQueue_def bitmapQ_defs by (wp, clarsimp simp: bitmapQ_def) lemma setQueue_valid_bitmapQ: (* enqueue only *) "\ valid_bitmapQ and (\s. (ksReadyQueues s (d, p) = []) = (ts = [])) \ setQueue d p ts \\_. valid_bitmapQ \" unfolding setQueue_def bitmapQ_defs by (wp, clarsimp simp: bitmapQ_def) lemma setQueue_valid_queues': "\valid_queues' and (\s. \t. obj_at' (inQ d p) t s \ t \ set ts)\ setQueue d p ts \\_. valid_queues'\" by (wp | simp add: valid_queues'_def setQueue_def)+ lemma setQueue_cur: "\\s. cur_tcb' s\ setQueue d p ts \\rv s. cur_tcb' s\" unfolding setQueue_def cur_tcb'_def by (wp, clarsimp) lemma ssa_sch_act[wp]: "\sch_act_wf sa\ setSchedulerAction sa \\rv s. sch_act_wf (ksSchedulerAction s) s\" by (simp add: setSchedulerAction_def | wp)+ lemma threadSet_runnable_sch_act: "(\tcb. runnable' (tcbState (F tcb)) \ tcbDomain (F tcb) = tcbDomain tcb \ tcbPriority (F tcb) = tcbPriority tcb) \ \\s. sch_act_wf (ksSchedulerAction s) s\ threadSet F t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (clarsimp simp: valid_def) apply (frule_tac P1="(=) (ksSchedulerAction s)" in use_valid [OF _ threadSet_nosch], rule refl) apply (frule_tac P1="(=) (ksCurThread s)" in use_valid [OF _ threadSet_ct], rule refl) apply (frule_tac P1="(=) (ksCurDomain s)" in use_valid [OF _ threadSet_cd], rule refl) apply (case_tac "ksSchedulerAction b", simp_all add: sch_act_simple_def ct_in_state'_def pred_tcb_at'_def) apply (drule_tac t'1="ksCurThread s" and P1="activatable' \ tcbState" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp elim!: obj_at'_weakenE) apply (simp add: o_def) apply (rename_tac word) apply (rule conjI) apply (frule_tac t'1=word and P1="runnable' \ tcbState" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp elim!: obj_at'_weakenE, clarsimp simp: obj_at'_def) apply (simp add: tcb_in_cur_domain'_def) apply (frule_tac t'1=word and P1="\tcb. ksCurDomain b = tcbDomain tcb" in use_valid [OF _ threadSet_obj_at'_really_strongest]) apply (clarsimp simp: o_def tcb_in_cur_domain'_def) apply clarsimp done lemma threadSet_pred_tcb_at_state: "\\s. tcb_at' t s \ (if p = t then obj_at' (\tcb. P (proj (tcb_to_itcb' (f tcb)))) t s else pred_tcb_at' proj P p s)\ threadSet f t \\_. pred_tcb_at' proj P p\" apply (rule hoare_chain) apply (rule threadSet_obj_at'_really_strongest) prefer 2 apply (simp add: pred_tcb_at'_def) apply (clarsimp split: if_splits simp: pred_tcb_at'_def o_def) done lemma threadSet_tcbDomain_triv': "\tcb_in_cur_domain' t' and K (t \ t')\ threadSet f t \\_. tcb_in_cur_domain' t'\" apply (simp add: tcb_in_cur_domain'_def) apply (rule hoare_assume_pre) apply simp apply (rule_tac f="ksCurDomain" in hoare_lift_Pf) apply (wp threadSet_obj_at'_strongish getObject_tcb_wp | simp)+ done lemma threadSet_sch_act_wf: "\\s. sch_act_wf (ksSchedulerAction s) s \ sch_act_not t s \ (ksCurThread s = t \ \(\tcb. activatable' (tcbState (F tcb))) \ ksSchedulerAction s \ ResumeCurrentThread) \ threadSet F t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (rule hoare_lift_Pf2 [where f=ksSchedulerAction]) prefer 2 apply wp apply (case_tac x, simp_all) apply (simp add: ct_in_state'_def) apply (rule hoare_lift_Pf2 [where f=ksCurThread]) prefer 2 apply wp[1] apply (wp threadSet_pred_tcb_at_state) apply clarsimp apply wp apply (clarsimp) apply (wp threadSet_pred_tcb_at_state threadSet_tcbDomain_triv' | clarsimp)+ done lemma rescheduleRequired_sch_act'[wp]: "\\\ rescheduleRequired \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp)+ done lemma setObject_queued_pred_tcb_at'[wp]: "\pred_tcb_at' proj P t' and obj_at' ((=) tcb) t\ setObject t (tcbQueued_update f tcb) \\_. pred_tcb_at' proj P t'\" apply (simp add: pred_tcb_at'_def) apply (rule hoare_pre) apply (wp setObject_tcb_strongest) apply (clarsimp simp: obj_at'_def tcb_to_itcb'_def) done lemma setObject_queued_ct_activatable'[wp]: "\ct_in_state' activatable' and obj_at' ((=) tcb) t\ setObject t (tcbQueued_update f tcb) \\_. ct_in_state' activatable'\" apply (clarsimp simp: ct_in_state'_def pred_tcb_at'_def) apply (rule hoare_pre) apply (wps setObject_ct_inv) apply (wp setObject_tcb_strongest) apply (clarsimp simp: obj_at'_def) done lemma threadSet_queued_sch_act_wf[wp]: "\\s. sch_act_wf (ksSchedulerAction s) s\ threadSet (tcbQueued_update f) t \\_ s. sch_act_wf (ksSchedulerAction s) s\" including no_pre apply (simp add: sch_act_wf_cases split: scheduler_action.split) apply (wp hoare_vcg_conj_lift) apply (simp add: threadSet_def) apply (wp static_imp_wp) apply (wps setObject_sa_unchanged) apply (wp static_imp_wp getObject_tcb_wp)+ apply (clarsimp simp: obj_at'_def) apply (wp hoare_vcg_all_lift hoare_vcg_conj_lift hoare_convert_imp)+ apply (simp add: threadSet_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) apply (wp tcb_in_cur_domain'_lift | simp add: obj_at'_def)+ done lemma tcbSchedEnqueue_pred_tcb_at'[wp]: "\\s. pred_tcb_at' proj P' t' s \ tcbSchedEnqueue t \\_ s. pred_tcb_at' proj P' t' s\" apply (simp add: tcbSchedEnqueue_def when_def unless_def) apply (wp threadSet_pred_tcb_no_state crunch_wps | clarsimp simp: tcb_to_itcb'_def)+ done lemma tcbSchedDequeue_sch_act_wf[wp]: "\\s. sch_act_wf (ksSchedulerAction s) s\ tcbSchedDequeue t \\_ s. sch_act_wf (ksSchedulerAction s) s\" unfolding tcbSchedDequeue_def by (wp setQueue_sch_act | wp sch_act_wf_lift | simp add: if_apply_def2)+ crunch nosch: tcbSchedDequeue "\s. P (ksSchedulerAction s)" lemma sts_sch_act': "\\s. (\ runnable' st \ sch_act_not t s) \ sch_act_wf (ksSchedulerAction s) s\ setThreadState st t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (simp add: setThreadState_def) apply (wp | simp)+ prefer 2 apply assumption apply (case_tac "runnable' st") apply ((wp threadSet_runnable_sch_act hoare_drop_imps | simp)+)[1] apply (rule_tac Q="\rv s. st_tcb_at' (Not \ runnable') t s \ (ksCurThread s \ t \ ksSchedulerAction s \ ResumeCurrentThread \ sch_act_wf (ksSchedulerAction s) s)" in hoare_post_imp) apply (clarsimp simp: pred_tcb_at'_def obj_at'_def) apply (simp only: imp_conv_disj) apply (wp threadSet_pred_tcb_at_state threadSet_sch_act_wf hoare_vcg_disj_lift|simp)+ done lemma sts_sch_act[wp]: "\\s. (\ runnable' st \ sch_act_simple s) \ sch_act_wf (ksSchedulerAction s) s\ setThreadState st t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (simp add: setThreadState_def) apply wp apply simp prefer 2 apply assumption apply (case_tac "runnable' st") apply (rule_tac Q="\s. sch_act_wf (ksSchedulerAction s) s" in hoare_pre_imp, simp) apply ((wp hoare_drop_imps threadSet_runnable_sch_act | simp)+)[1] apply (rule_tac Q="\rv s. st_tcb_at' (Not \ runnable') t s \ (ksCurThread s \ t \ ksSchedulerAction s \ ResumeCurrentThread \ sch_act_wf (ksSchedulerAction s) s)" in hoare_post_imp) apply (clarsimp simp: pred_tcb_at'_def obj_at'_def) apply (simp only: imp_conv_disj) apply (rule hoare_pre) apply (wp threadSet_pred_tcb_at_state threadSet_sch_act_wf hoare_vcg_disj_lift|simp)+ apply (auto simp: sch_act_simple_def) done lemma sbn_sch_act': "\\s. sch_act_wf (ksSchedulerAction s) s\ setBoundNotification ntfn t \\rv s. sch_act_wf (ksSchedulerAction s) s\" apply (simp add: setBoundNotification_def) apply (wp threadSet_sch_act | simp)+ done lemma ssa_sch_act_simple[wp]: "sa = ResumeCurrentThread \ sa = ChooseNewThread \ \\\ setSchedulerAction sa \\rv. sch_act_simple\" unfolding setSchedulerAction_def sch_act_simple_def by (wp | simp)+ lemma sch_act_simple_lift: "(\P. \\s. P (ksSchedulerAction s)\ f \\rv s. P (ksSchedulerAction s)\) \ \sch_act_simple\ f \\rv. sch_act_simple\" by (simp add: sch_act_simple_def) assumption lemma rescheduleRequired_sch_act_simple[wp]: "\sch_act_simple\ rescheduleRequired \\rv. sch_act_simple\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp)+ done crunch no_sa[wp]: tcbSchedDequeue "\s. P (ksSchedulerAction s)" lemma sts_sch_act_simple[wp]: "\sch_act_simple\ setThreadState st t \\rv. sch_act_simple\" apply (simp add: setThreadState_def) apply (wp hoare_drop_imps | rule sch_act_simple_lift | simp)+ done lemma setQueue_after: "(setQueue d p q >>= (\rv. threadSet f t)) = (threadSet f t >>= (\rv. setQueue d p q))" apply (simp add: setQueue_def) apply (rule oblivious_modify_swap) apply (simp add: threadSet_def getObject_def setObject_def loadObject_default_def split_def projectKO_def2 alignCheck_assert magnitudeCheck_assert updateObject_default_def) apply (intro oblivious_bind, simp_all) done lemma tcbSchedEnqueue_sch_act[wp]: "\\s. sch_act_wf (ksSchedulerAction s) s\ tcbSchedEnqueue t \\_ s. sch_act_wf (ksSchedulerAction s) s\" by (simp add: tcbSchedEnqueue_def unless_def) (wp setQueue_sch_act | wp sch_act_wf_lift | clarsimp)+ lemma tcbSchedEnqueue_weak_sch_act[wp]: "\\s. weak_sch_act_wf (ksSchedulerAction s) s\ tcbSchedEnqueue t \\_ s. weak_sch_act_wf (ksSchedulerAction s) s\" apply (simp add: tcbSchedEnqueue_def unless_def) apply (wp setQueue_sch_act threadSet_weak_sch_act_wf | clarsimp)+ done lemma threadGet_wp: "\\s. tcb_at' t s \ (\tcb. ko_at' tcb t s \ P (f tcb) s)\ threadGet f t \P\" apply (simp add: threadGet_def) apply (wp getObject_tcb_wp) apply clarsimp done lemma threadGet_const: "\\s. tcb_at' t s \ obj_at' (P \ f) t s\ threadGet f t \\rv s. P (rv)\" apply (simp add: threadGet_def liftM_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done schematic_goal l2BitmapSize_def': (* arch specific consequence *) "l2BitmapSize = numeral ?X" by (simp add: l2BitmapSize_def wordBits_def word_size numPriorities_def) lemma prioToL1Index_size [simp]: "prioToL1Index w < l2BitmapSize" unfolding prioToL1Index_def wordRadix_def l2BitmapSize_def' by (fastforce simp: shiftr_div_2n' nat_divide_less_eq intro: order_less_le_trans[OF unat_lt2p]) lemma prioToL1Index_max: "prioToL1Index p < 2 ^ wordRadix" unfolding prioToL1Index_def wordRadix_def by (insert unat_lt2p[where x=p], simp add: shiftr_div_2n') lemma prioToL1Index_bit_set: "((2 :: machine_word) ^ prioToL1Index p) !! prioToL1Index p" using l2BitmapSize_def' by (fastforce simp: nth_w2p_same intro: order_less_le_trans[OF prioToL1Index_size]) lemma prioL2Index_bit_set: fixes p :: priority shows "((2::machine_word) ^ unat (ucast p && (mask wordRadix :: machine_word))) !! unat (p && mask wordRadix)" apply (simp add: nth_w2p wordRadix_def ucast_and_mask[symmetric] unat_ucast_upcast is_up) apply (rule unat_less_helper) apply (insert and_mask_less'[where w=p and n=wordRadix], simp add: wordRadix_def) done lemma addToBitmap_bitmapQ: "\ \s. True \ addToBitmap d p \\_. bitmapQ d p \" unfolding addToBitmap_def modifyReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL1Bitmap_def getReadyQueuesL2Bitmap_def by (wpsimp simp: bitmap_fun_defs bitmapQ_def prioToL1Index_bit_set prioL2Index_bit_set simp_del: bit_exp_iff) lemma addToBitmap_valid_queues_no_bitmap_except: " \ valid_queues_no_bitmap_except t \ addToBitmap d p \\_. valid_queues_no_bitmap_except t \" unfolding addToBitmap_def modifyReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL1Bitmap_def getReadyQueuesL2Bitmap_def valid_queues_no_bitmap_except_def by (wp, clarsimp) crunch norq[wp]: addToBitmap "\s. P (ksReadyQueues s)" (wp: updateObject_cte_inv hoare_drop_imps) crunch norq[wp]: removeFromBitmap "\s. P (ksReadyQueues s)" (wp: updateObject_cte_inv hoare_drop_imps) lemma prioToL1Index_lt: "2 ^ wordRadix \ x \ prioToL1Index p < x" unfolding prioToL1Index_def wordRadix_def by (insert unat_lt2p[where x=p], simp add: shiftr_div_2n') lemma prioToL1Index_bits_low_high_eq: "\ pa \ p; prioToL1Index pa = prioToL1Index (p::priority) \ \ unat (pa && mask wordRadix) \ unat (p && mask wordRadix)" unfolding prioToL1Index_def by (fastforce simp: nth_w2p wordRadix_def is_up bits_low_high_eq) lemma prioToL1Index_bit_not_set: "\ (~~ ((2 :: machine_word) ^ prioToL1Index p)) !! prioToL1Index p" apply (subst word_ops_nth_size, simp_all add: prioToL1Index_bit_set del: bit_exp_iff) apply (fastforce simp: prioToL1Index_def wordRadix_def word_size intro: order_less_le_trans[OF word_shiftr_lt]) done lemma prioToL1Index_complement_nth_w2p: fixes p pa :: priority shows "(~~ ((2 :: machine_word) ^ prioToL1Index p)) !! prioToL1Index p' = (prioToL1Index p \ prioToL1Index p')" by (fastforce simp: complement_nth_w2p prioToL1Index_lt wordRadix_def word_size)+ lemma valid_bitmapQ_exceptE: "\ valid_bitmapQ_except d' p' s ; d \ d' \ p \ p' \ \ bitmapQ d p s = (ksReadyQueues s (d, p) \ [])" unfolding valid_bitmapQ_except_def by blast lemma invertL1Index_eq_cancelD: "\ invertL1Index i = invertL1Index j ; i < l2BitmapSize ; j < l2BitmapSize \ \ i = j" by (simp add: invertL1Index_def l2BitmapSize_def') lemma invertL1Index_eq_cancel: "\ i < l2BitmapSize ; j < l2BitmapSize \ \ (invertL1Index i = invertL1Index j) = (i = j)" by (rule iffI, simp_all add: invertL1Index_eq_cancelD) lemma removeFromBitmap_bitmapQ_no_L1_orphans[wp]: "\ bitmapQ_no_L1_orphans \ removeFromBitmap d p \\_. bitmapQ_no_L1_orphans \" unfolding bitmap_fun_defs apply (wp | simp add: bitmap_fun_defs bitmapQ_no_L1_orphans_def)+ apply (fastforce simp: invertL1Index_eq_cancel prioToL1Index_bit_not_set prioToL1Index_complement_nth_w2p) done lemma removeFromBitmap_bitmapQ_no_L2_orphans[wp]: "\ bitmapQ_no_L2_orphans and bitmapQ_no_L1_orphans \ removeFromBitmap d p \\_. bitmapQ_no_L2_orphans \" unfolding bitmap_fun_defs apply (wp, clarsimp simp: bitmap_fun_defs bitmapQ_no_L2_orphans_def)+ apply (rule conjI, clarsimp) apply (clarsimp simp: complement_nth_w2p l2BitmapSize_def') apply clarsimp apply metis done lemma removeFromBitmap_valid_bitmapQ_except: "\ valid_bitmapQ_except d p \ removeFromBitmap d p \\_. valid_bitmapQ_except d p \" proof - have unat_ucast_mask[simp]: "\x. unat ((ucast (p::priority) :: machine_word) && mask x) = unat (p && mask x)" by (simp add: ucast_and_mask[symmetric] unat_ucast_upcast is_up) note bit_exp_iff[simp del] bit_not_iff[simp del] bit_not_exp_iff[simp del] show ?thesis unfolding removeFromBitmap_def apply (simp add: let_into_return[symmetric]) unfolding bitmap_fun_defs when_def apply wp apply clarsimp apply (rule conjI) (* after clearing bit in L2, all bits in L2 field are clear *) apply clarsimp apply (subst valid_bitmapQ_except_def, clarsimp)+ apply (clarsimp simp: bitmapQ_def) apply (rule conjI; clarsimp) apply (rename_tac p') apply (rule conjI; clarsimp simp: invertL1Index_eq_cancel) apply (drule_tac p=p' in valid_bitmapQ_exceptE[where d=d], clarsimp) apply (clarsimp simp: bitmapQ_def) apply (drule_tac n'="unat (p' && mask wordRadix)" in no_other_bits_set) apply (erule (1) prioToL1Index_bits_low_high_eq) apply (rule order_less_le_trans[OF word_unat_mask_lt]) apply ((simp add: wordRadix_def' word_size)+)[2] apply (rule order_less_le_trans[OF word_unat_mask_lt]) apply ((simp add: wordRadix_def' word_size)+)[3] apply (drule_tac p=p' and d=d in valid_bitmapQ_exceptE, simp) apply (clarsimp simp: bitmapQ_def prioToL1Index_complement_nth_w2p) apply (drule_tac p=pa and d=da in valid_bitmapQ_exceptE, simp) apply (clarsimp simp: bitmapQ_def prioToL1Index_complement_nth_w2p) (* after clearing bit in L2, some bits in L2 field are still set *) apply clarsimp apply (subst valid_bitmapQ_except_def, clarsimp)+ apply (clarsimp simp: bitmapQ_def invertL1Index_eq_cancel) apply (rule conjI; clarsimp) apply (frule (1) prioToL1Index_bits_low_high_eq) apply (drule_tac d=d and p=pa in valid_bitmapQ_exceptE, simp) apply (clarsimp simp: bitmapQ_def) apply (subst complement_nth_w2p) apply (rule order_less_le_trans[OF word_unat_mask_lt]) apply ((simp add: wordRadix_def' word_size)+)[3] apply (clarsimp simp: valid_bitmapQ_except_def bitmapQ_def) done qed lemma addToBitmap_bitmapQ_no_L1_orphans[wp]: "\ bitmapQ_no_L1_orphans \ addToBitmap d p \\_. bitmapQ_no_L1_orphans \" unfolding bitmap_fun_defs bitmapQ_defs using word_unat_mask_lt[where w=p and m=wordRadix] apply wp apply (clarsimp simp: word_or_zero prioToL1Index_bit_set ucast_and_mask[symmetric] unat_ucast_upcast is_up wordRadix_def' word_size nth_w2p wordBits_def numPriorities_def) done lemma addToBitmap_bitmapQ_no_L2_orphans[wp]: "\ bitmapQ_no_L2_orphans \ addToBitmap d p \\_. bitmapQ_no_L2_orphans \" unfolding bitmap_fun_defs bitmapQ_defs supply bit_exp_iff[simp del] apply wp apply clarsimp apply (fastforce simp: invertL1Index_eq_cancel prioToL1Index_bit_set) done lemma addToBitmap_valid_bitmapQ_except: "\ valid_bitmapQ_except d p and bitmapQ_no_L2_orphans \ addToBitmap d p \\_. valid_bitmapQ_except d p \" unfolding bitmap_fun_defs bitmapQ_defs apply wp apply (clarsimp simp: bitmapQ_def invertL1Index_eq_cancel ucast_and_mask[symmetric] unat_ucast_upcast is_up nth_w2p) apply (fastforce simp: priority_mask_wordRadix_size[simplified wordBits_def'] dest: prioToL1Index_bits_low_high_eq) done lemma addToBitmap_valid_bitmapQ: " \ valid_bitmapQ_except d p and bitmapQ_no_L2_orphans and (\s. ksReadyQueues s (d,p) \ []) \ addToBitmap d p \\_. valid_bitmapQ \" proof - have "\ valid_bitmapQ_except d p and bitmapQ_no_L2_orphans and (\s. ksReadyQueues s (d,p) \ []) \ addToBitmap d p \\_. valid_bitmapQ_except d p and bitmapQ_no_L2_orphans and (\s. bitmapQ d p s \ ksReadyQueues s (d,p) \ []) \" by (wp addToBitmap_valid_queues_no_bitmap_except addToBitmap_valid_bitmapQ_except addToBitmap_bitmapQ_no_L2_orphans addToBitmap_bitmapQ; simp) thus ?thesis by - (erule hoare_strengthen_post; fastforce elim: valid_bitmap_valid_bitmapQ_exceptE) qed lemma threadGet_const_tcb_at: "\\s. tcb_at' t s \ obj_at' (P s \ f) t s\ threadGet f t \\rv s. P s rv \" apply (simp add: threadGet_def liftM_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemma threadGet_const_tcb_at_imp_lift: "\\s. tcb_at' t s \ obj_at' (P s \ f) t s \ obj_at' (Q s \ f) t s \ threadGet f t \\rv s. P s rv \ Q s rv \" apply (simp add: threadGet_def liftM_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemma valid_queues_no_bitmap_objD: "\ valid_queues_no_bitmap s; t \ set (ksReadyQueues s (d, p))\ \ obj_at' (inQ d p and runnable' \ tcbState) t s" unfolding valid_queues_no_bitmap_def by metis lemma setQueue_bitmapQ_no_L1_orphans[wp]: "\ bitmapQ_no_L1_orphans \ setQueue d p ts \\rv. bitmapQ_no_L1_orphans \" unfolding setQueue_def bitmapQ_no_L1_orphans_def null_def by (wp, auto) lemma setQueue_bitmapQ_no_L2_orphans[wp]: "\ bitmapQ_no_L2_orphans \ setQueue d p ts \\rv. bitmapQ_no_L2_orphans \" unfolding setQueue_def bitmapQ_no_L2_orphans_def null_def by (wp, auto) lemma setQueue_sets_queue[wp]: "\d p ts P. \ \s. P ts \ setQueue d p ts \\rv s. P (ksReadyQueues s (d, p)) \" unfolding setQueue_def by (wp, simp) lemma tcbSchedEnqueueOrAppend_valid_queues: (* f is either (t#ts) or (ts @ [t]), so we define its properties generally *) assumes f_set[simp]: "\ts. t \ set (f ts)" assumes f_set_insert[simp]: "\ts. set (f ts) = insert t (set ts)" assumes f_not_empty[simp]: "\ts. f ts \ []" assumes f_distinct: "\ts. \ distinct ts ; t \ set ts \ \ distinct (f ts)" shows "\Invariants_H.valid_queues and st_tcb_at' runnable' t and valid_objs' \ do queued \ threadGet tcbQueued t; unless queued $ do tdom \ threadGet tcbDomain t; prio \ threadGet tcbPriority t; queue \ getQueue tdom prio; setQueue tdom prio $ f queue; when (null queue) $ addToBitmap tdom prio; threadSet (tcbQueued_update (\_. True)) t od od \\_. Invariants_H.valid_queues\" proof - define could_run where "could_run == \d p t. obj_at' (\tcb. inQ d p (tcbQueued_update (\_. True) tcb) \ runnable' (tcbState tcb)) t" have addToBitmap_could_run: "\d p. \\s. \d p. t \ set (ksReadyQueues s (d, p)) \ could_run d p t s\ addToBitmap d p \\_ s. \d p. t \ set (ksReadyQueues s (d, p)) \ could_run d p t s\" unfolding bitmap_fun_defs by (wp, clarsimp simp: could_run_def) have setQueue_valid_queues_no_bitmap_except: "\d p ts. \ valid_queues_no_bitmap_except t and (\s. ksReadyQueues s (d, p) = ts \ p \ maxPriority \ d \ maxDomain \ t \ set ts) \ setQueue d p (f ts) \\rv. valid_queues_no_bitmap_except t\" unfolding setQueue_def valid_queues_no_bitmap_except_def null_def by (wp, auto intro: f_distinct) have threadSet_valid_queues_could_run: "\f. \ valid_queues_no_bitmap_except t and (\s. \d p. t \ set (ksReadyQueues s (d,p)) \ could_run d p t s) and valid_bitmapQ and bitmapQ_no_L2_orphans and bitmapQ_no_L1_orphans \ threadSet (tcbQueued_update (\_. True)) t \\rv. Invariants_H.valid_queues \" unfolding threadSet_def could_run_def apply (rule hoare_seq_ext[OF _ getObject_tcb_sp]) apply (rule hoare_pre) apply (simp add: valid_queues_def valid_queues_no_bitmap_def) apply (wp setObject_queues_unchanged_tcb hoare_Ball_helper hoare_vcg_all_lift setObject_tcb_strongest) apply (clarsimp simp: valid_queues_no_bitmap_except_def obj_at'_def) done have setQueue_could_run: "\d p ts. \ valid_queues and (\_. t \ set ts) and (\s. could_run d p t s) \ setQueue d p ts \\rv s. (\d p. t \ set (ksReadyQueues s (d, p)) \ could_run d p t s)\" unfolding setQueue_def valid_queues_def could_run_def by wp (fastforce dest: valid_queues_no_bitmap_objD simp: obj_at'_def inQ_def) note hoare_vcg_if_lift[wp] hoare_vcg_conj_lift[wp] hoare_vcg_const_imp_lift[wp] show ?thesis unfolding tcbSchedEnqueue_def null_def apply (rule hoare_pre) apply (rule hoare_seq_ext) apply (simp add: unless_def) apply (wp threadSet_valid_queues_could_run) apply (wp addToBitmap_could_run addToBitmap_valid_bitmapQ addToBitmap_valid_queues_no_bitmap_except addToBitmap_bitmapQ_no_L2_orphans)+ apply (wp setQueue_valid_queues_no_bitmap_except setQueue_could_run setQueue_valid_bitmapQ_except setQueue_sets_queue setQueue_valid_bitmapQ)+ apply (wp threadGet_const_tcb_at_imp_lift | simp add: if_apply_def2)+ apply clarsimp apply (frule pred_tcb_at') apply (frule (1) valid_objs'_maxDomain) apply (frule (1) valid_objs'_maxPriority) apply (clarsimp simp: valid_queues_def st_tcb_at'_def obj_at'_def valid_queues_no_bitmap_exceptI) apply (fastforce dest!: valid_queues_no_bitmap_objD simp: obj_at'_def inQ_def could_run_def) done qed lemma tcbSchedEnqueue_valid_queues[wp]: "\Invariants_H.valid_queues and st_tcb_at' runnable' t and valid_objs' \ tcbSchedEnqueue t \\_. Invariants_H.valid_queues\" unfolding tcbSchedEnqueue_def by (fastforce intro: tcbSchedEnqueueOrAppend_valid_queues) lemma tcbSchedAppend_valid_queues[wp]: "\Invariants_H.valid_queues and st_tcb_at' runnable' t and valid_objs' \ tcbSchedAppend t \\_. Invariants_H.valid_queues\" unfolding tcbSchedAppend_def by (fastforce intro: tcbSchedEnqueueOrAppend_valid_queues) lemma rescheduleRequired_valid_queues[wp]: "\\s. Invariants_H.valid_queues s \ valid_objs' s \ weak_sch_act_wf (ksSchedulerAction s) s\ rescheduleRequired \\_. Invariants_H.valid_queues\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp)+ apply (fastforce simp: weak_sch_act_wf_def elim: valid_objs'_maxDomain valid_objs'_maxPriority) done lemma rescheduleRequired_valid_queues_sch_act_simple: "\Invariants_H.valid_queues and sch_act_simple\ rescheduleRequired \\_. Invariants_H.valid_queues\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp | fastforce simp: Invariants_H.valid_queues_def sch_act_simple_def)+ done lemma rescheduleRequired_valid_bitmapQ_sch_act_simple: "\ valid_bitmapQ and sch_act_simple\ rescheduleRequired \\_. valid_bitmapQ \" including no_pre apply (simp add: rescheduleRequired_def sch_act_simple_def) apply (rule_tac B="\rv s. valid_bitmapQ s \ (rv = ResumeCurrentThread \ rv = ChooseNewThread)" in hoare_seq_ext) apply wpsimp apply (case_tac x; simp) apply (wp, fastforce) done lemma rescheduleRequired_bitmapQ_no_L1_orphans_sch_act_simple: "\ bitmapQ_no_L1_orphans and sch_act_simple\ rescheduleRequired \\_. bitmapQ_no_L1_orphans \" including no_pre apply (simp add: rescheduleRequired_def sch_act_simple_def) apply (rule_tac B="\rv s. bitmapQ_no_L1_orphans s \ (rv = ResumeCurrentThread \ rv = ChooseNewThread)" in hoare_seq_ext) apply wpsimp apply (case_tac x; simp) apply (wp, fastforce) done lemma rescheduleRequired_bitmapQ_no_L2_orphans_sch_act_simple: "\ bitmapQ_no_L2_orphans and sch_act_simple\ rescheduleRequired \\_. bitmapQ_no_L2_orphans \" including no_pre apply (simp add: rescheduleRequired_def sch_act_simple_def) apply (rule_tac B="\rv s. bitmapQ_no_L2_orphans s \ (rv = ResumeCurrentThread \ rv = ChooseNewThread)" in hoare_seq_ext) apply wpsimp apply (case_tac x; simp) apply (wp, fastforce) done lemma sts_valid_bitmapQ_sch_act_simple: "\valid_bitmapQ and sch_act_simple\ setThreadState st t \\_. valid_bitmapQ \" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_valid_bitmapQ_sch_act_simple threadSet_valid_bitmapQ [THEN hoare_strengthen_post]) apply (clarsimp simp: sch_act_simple_def Invariants_H.valid_queues_def inQ_def)+ done lemma sts_valid_bitmapQ_no_L2_orphans_sch_act_simple: "\ bitmapQ_no_L2_orphans and sch_act_simple\ setThreadState st t \\_. bitmapQ_no_L2_orphans \" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_bitmapQ_no_L2_orphans_sch_act_simple threadSet_valid_bitmapQ_no_L2_orphans [THEN hoare_strengthen_post]) apply (clarsimp simp: sch_act_simple_def Invariants_H.valid_queues_def inQ_def)+ done lemma sts_valid_bitmapQ_no_L1_orphans_sch_act_simple: "\ bitmapQ_no_L1_orphans and sch_act_simple\ setThreadState st t \\_. bitmapQ_no_L1_orphans \" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_bitmapQ_no_L1_orphans_sch_act_simple threadSet_valid_bitmapQ_no_L1_orphans [THEN hoare_strengthen_post]) apply (clarsimp simp: sch_act_simple_def Invariants_H.valid_queues_def inQ_def)+ done lemma sts_valid_queues: "\\s. Invariants_H.valid_queues s \ ((\p. t \ set(ksReadyQueues s p)) \ runnable' st)\ setThreadState st t \\rv. Invariants_H.valid_queues\" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_valid_queues_sch_act_simple threadSet_valid_queues [THEN hoare_strengthen_post]) apply (clarsimp simp: sch_act_simple_def Invariants_H.valid_queues_def inQ_def)+ done lemma sbn_valid_queues: "\\s. Invariants_H.valid_queues s\ setBoundNotification ntfn t \\rv. Invariants_H.valid_queues\" apply (simp add: setBoundNotification_def) apply (wp threadSet_valid_queues [THEN hoare_strengthen_post]) apply (clarsimp simp: sch_act_simple_def Invariants_H.valid_queues_def inQ_def)+ done lemma addToBitmap_valid_queues'[wp]: "\ valid_queues' \ addToBitmap d p \\_. valid_queues' \" unfolding valid_queues'_def addToBitmap_def modifyReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL1Bitmap_def getReadyQueuesL2Bitmap_def by (wp, simp) lemma tcbSchedEnqueue_valid_queues'[wp]: "\valid_queues' and st_tcb_at' runnable' t \ tcbSchedEnqueue t \\_. valid_queues'\" apply (simp add: tcbSchedEnqueue_def) apply (rule hoare_pre) apply (rule_tac B="\rv. valid_queues' and obj_at' (\obj. tcbQueued obj = rv) t" in hoare_seq_ext) apply (rename_tac queued) apply (case_tac queued; simp_all add: unless_def when_def) apply (wp threadSet_valid_queues' setQueue_valid_queues' | simp)+ apply (subst conj_commute, wp) apply (rule hoare_pre_post, assumption) apply (clarsimp simp: addToBitmap_def modifyReadyQueuesL1Bitmap_def modifyReadyQueuesL2Bitmap_def getReadyQueuesL1Bitmap_def getReadyQueuesL2Bitmap_def) apply wp apply fastforce apply wp apply (subst conj_commute) apply clarsimp apply (rule_tac Q="\rv. valid_queues' and obj_at' (\obj. \ tcbQueued obj) t and obj_at' (\obj. tcbPriority obj = prio) t and obj_at' (\obj. tcbDomain obj = tdom) t and (\s. t \ set (ksReadyQueues s (tdom, prio)))" in hoare_post_imp) apply (clarsimp simp: valid_queues'_def obj_at'_def inQ_def) apply (wp setQueue_valid_queues' | simp | simp add: setQueue_def)+ apply (wp getObject_tcb_wp | simp add: threadGet_def)+ apply (clarsimp simp: obj_at'_def inQ_def valid_queues'_def) apply (wp getObject_tcb_wp | simp add: threadGet_def)+ apply (clarsimp simp: obj_at'_def) done lemma rescheduleRequired_valid_queues'_weak[wp]: "\\s. valid_queues' s \ weak_sch_act_wf (ksSchedulerAction s) s\ rescheduleRequired \\_. valid_queues'\" apply (simp add: rescheduleRequired_def) apply wpsimp apply (clarsimp simp: weak_sch_act_wf_def) done lemma rescheduleRequired_valid_queues'_sch_act_simple: "\valid_queues' and sch_act_simple\ rescheduleRequired \\_. valid_queues'\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp | fastforce simp: valid_queues'_def sch_act_simple_def)+ done lemma setThreadState_valid_queues'[wp]: "\\s. valid_queues' s\ setThreadState st t \\rv. valid_queues'\" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_valid_queues'_sch_act_simple) apply (rule_tac Q="\_. valid_queues'" in hoare_post_imp) apply (clarsimp simp: sch_act_simple_def) apply (wp threadSet_valid_queues') apply (fastforce simp: inQ_def obj_at'_def pred_tcb_at'_def) done lemma setBoundNotification_valid_queues'[wp]: "\\s. valid_queues' s\ setBoundNotification ntfn t \\rv. valid_queues'\" apply (simp add: setBoundNotification_def) apply (wp threadSet_valid_queues') apply (fastforce simp: inQ_def obj_at'_def pred_tcb_at'_def) done lemma valid_tcb'_tcbState_update: "\ valid_tcb_state' st s; valid_tcb' tcb s \ \ valid_tcb' (tcbState_update (\_. st) tcb) s" apply (clarsimp simp: valid_tcb'_def tcb_cte_cases_def cteSizeBits_def valid_tcb_state'_def) done lemma setThreadState_valid_objs'[wp]: "\ valid_tcb_state' st and valid_objs' \ setThreadState st t \ \_. valid_objs' \" apply (simp add: setThreadState_def) apply (wp threadSet_valid_objs' | clarsimp simp: valid_tcb'_tcbState_update)+ done lemma rescheduleRequired_ksQ: "\\s. sch_act_simple s \ P (ksReadyQueues s p)\ rescheduleRequired \\_ s. P (ksReadyQueues s p)\" including no_pre apply (simp add: rescheduleRequired_def sch_act_simple_def) apply (rule_tac B="\rv s. (rv = ResumeCurrentThread \ rv = ChooseNewThread) \ P (ksReadyQueues s p)" in hoare_seq_ext) apply wpsimp apply (case_tac x; simp) apply wp done lemma setSchedulerAction_ksQ[wp]: "\\s. P (ksReadyQueues s)\ setSchedulerAction act \\_ s. P (ksReadyQueues s)\" by (wp, simp) lemma threadSet_ksQ[wp]: "\\s. P (ksReadyQueues s)\ threadSet f t \\rv s. P (ksReadyQueues s)\" by (simp add: threadSet_def | wp updateObject_default_inv)+ lemma sbn_ksQ: "\\s. P (ksReadyQueues s p)\ setBoundNotification ntfn t \\rv s. P (ksReadyQueues s p)\" by (simp add: setBoundNotification_def, wp) lemma sts_ksQ: "\\s. sch_act_simple s \ P (ksReadyQueues s p)\ setThreadState st t \\_ s. P (ksReadyQueues s p)\" apply (simp add: setThreadState_def) apply (wp rescheduleRequired_ksQ) apply (rule_tac Q="\_ s. P (ksReadyQueues s p)" in hoare_post_imp) apply (clarsimp simp: sch_act_simple_def)+ apply (wp, simp) done lemma setQueue_ksQ[wp]: "\\s. P ((ksReadyQueues s)((d, p) := q))\ setQueue d p q \\rv s. P (ksReadyQueues s)\" by (simp add: setQueue_def fun_upd_def[symmetric] | wp)+ lemma tcbSchedEnqueue_ksQ: "\\s. t' \ set (ksReadyQueues s p) \ t' \ t \ tcbSchedEnqueue t \\_ s. t' \ set (ksReadyQueues s p)\" apply (simp add: tcbSchedEnqueue_def unless_def) apply (wpsimp wp: hoare_vcg_imp_lift threadGet_wp) apply (drule obj_at_ko_at') apply fastforce done lemma rescheduleRequired_ksQ': "\\s. t \ set (ksReadyQueues s p) \ sch_act_not t s \ rescheduleRequired \\_ s. t \ set (ksReadyQueues s p)\" apply (simp add: rescheduleRequired_def) apply (wpsimp wp: tcbSchedEnqueue_ksQ) done lemma threadSet_tcbState_st_tcb_at': "\\s. P st \ threadSet (tcbState_update (\_. st)) t \\_. st_tcb_at' P t\" apply (simp add: threadSet_def pred_tcb_at'_def) apply (wpsimp wp: setObject_tcb_strongest) done lemma isRunnable_const: "\st_tcb_at' runnable' t\ isRunnable t \\runnable _. runnable \" by (rule isRunnable_wp) lemma sts_ksQ': "\\s. (runnable' st \ ksCurThread s \ t) \ P (ksReadyQueues s p)\ setThreadState st t \\_ s. P (ksReadyQueues s p)\" apply (simp add: setThreadState_def) apply (rule hoare_pre_disj') apply (rule hoare_seq_ext [OF _ hoare_vcg_conj_lift [OF threadSet_tcbState_st_tcb_at' [where P=runnable'] threadSet_ksQ]]) apply (rule hoare_seq_ext [OF _ hoare_vcg_conj_lift [OF isRunnable_const isRunnable_inv]]) apply (clarsimp simp: when_def) apply (case_tac x) apply (clarsimp, wp)[1] apply (clarsimp) apply (rule hoare_seq_ext [OF _ hoare_vcg_conj_lift [OF threadSet_ct threadSet_ksQ]]) apply (rule hoare_seq_ext [OF _ isRunnable_inv]) apply (rule hoare_seq_ext [OF _ hoare_vcg_conj_lift [OF gct_wp gct_wp]]) apply (rename_tac ct) apply (case_tac "ct\t") apply (clarsimp simp: when_def) apply (wp)[1] apply (clarsimp) done lemma valid_ipc_buffer_ptr'D: assumes yv: "y < unat max_ipc_words" and buf: "valid_ipc_buffer_ptr' a s" shows "pointerInUserData (a + of_nat y * 8) s" using buf unfolding valid_ipc_buffer_ptr'_def pointerInUserData_def apply clarsimp apply (subgoal_tac "(a + of_nat y * 8) && ~~ mask pageBits = a && ~~ mask pageBits") apply simp apply (rule mask_out_first_mask_some [where n = msg_align_bits]) apply (erule is_aligned_add_helper [THEN conjunct2]) apply (rule word_less_power_trans_ofnat [where k = 3, simplified]) apply (rule order_less_le_trans [OF yv]) apply (simp add: msg_align_bits max_ipc_words) apply (simp add: msg_align_bits) apply (simp_all add: msg_align_bits pageBits_def) done lemma in_user_frame_eq: assumes y: "y < unat max_ipc_words" and al: "is_aligned a msg_align_bits" shows "in_user_frame (a + of_nat y * 8) s = in_user_frame a s" proof - have "\sz. (a + of_nat y * 8) && ~~ mask (pageBitsForSize sz) = a && ~~ mask (pageBitsForSize sz)" apply (rule mask_out_first_mask_some [where n = msg_align_bits]) apply (rule is_aligned_add_helper [OF al, THEN conjunct2]) apply (rule word_less_power_trans_ofnat [where k = 3, simplified]) apply (rule order_less_le_trans [OF y]) apply (simp add: msg_align_bits max_ipc_words) apply (simp add: msg_align_bits) apply (simp add: msg_align_bits pageBits_def) apply (case_tac sz, simp_all add: msg_align_bits bit_simps) done thus ?thesis by (simp add: in_user_frame_def) qed lemma loadWordUser_corres: assumes y: "y < unat max_ipc_words" shows "corres (=) \ (valid_ipc_buffer_ptr' a) (load_word_offs a y) (loadWordUser (a + of_nat y * 8))" unfolding loadWordUser_def apply (rule corres_stateAssert_assume [rotated]) apply (erule valid_ipc_buffer_ptr'D[OF y]) apply (rule corres_guard_imp) apply (simp add: load_word_offs_def word_size_def) apply (rule_tac F = "is_aligned a msg_align_bits" in corres_gen_asm2) apply (rule corres_machine_op) apply (rule corres_Id [OF refl refl]) apply (rule no_fail_pre) apply wp apply (erule aligned_add_aligned) apply (rule is_aligned_mult_triv2 [where n = 3, simplified]) apply (simp add: word_bits_conv msg_align_bits)+ apply (simp add: valid_ipc_buffer_ptr'_def msg_align_bits) done lemma storeWordUser_corres: assumes y: "y < unat max_ipc_words" shows "corres dc (in_user_frame a) (valid_ipc_buffer_ptr' a) (store_word_offs a y w) (storeWordUser (a + of_nat y * 8) w)" apply (simp add: storeWordUser_def bind_assoc[symmetric] store_word_offs_def word_size_def) apply (rule corres_guard2_imp) apply (rule_tac F = "is_aligned a msg_align_bits" in corres_gen_asm2) apply (rule corres_guard1_imp) apply (rule_tac r'=dc in corres_split) apply (simp add: stateAssert_def) apply (rule_tac r'=dc in corres_split) apply (rule corres_trivial) apply simp apply (rule corres_assert) apply wp+ apply (rule corres_machine_op) apply (rule corres_Id [OF refl]) apply simp apply (rule no_fail_pre) apply (wp no_fail_storeWord) apply (erule_tac n=msg_align_bits in aligned_add_aligned) apply (rule is_aligned_mult_triv2 [where n = 3, simplified]) apply (simp add: word_bits_conv msg_align_bits)+ apply wp+ apply (simp add: in_user_frame_eq[OF y]) apply simp apply (rule conjI) apply (frule (1) valid_ipc_buffer_ptr'D [OF y]) apply (simp add: valid_ipc_buffer_ptr'_def) done lemma load_word_corres: "corres (=) \ (typ_at' UserDataT (a && ~~ mask pageBits) and (\s. is_aligned a word_size_bits)) (do_machine_op (loadWord a)) (loadWordUser a)" unfolding loadWordUser_def apply (rule corres_gen_asm2) apply (rule corres_stateAssert_assume [rotated]) apply (simp add: pointerInUserData_def) apply (rule corres_guard_imp) apply simp apply (rule corres_machine_op) apply (rule corres_Id [OF refl refl]) apply (rule no_fail_pre) apply (wpsimp simp: word_size_bits_def)+ done lemmas msgRegisters_unfold = RISCV64_H.msgRegisters_def msg_registers_def RISCV64.msgRegisters_def [unfolded upto_enum_def, simplified, unfolded fromEnum_def enum_register, simplified, unfolded toEnum_def enum_register, simplified] lemma thread_get_registers: "thread_get (arch_tcb_get_registers \ tcb_arch) t = as_user t (gets user_regs)" apply (simp add: thread_get_def as_user_def arch_tcb_get_registers_def arch_tcb_context_get_def arch_tcb_context_set_def) apply (rule bind_cong [OF refl]) apply (clarsimp simp: gets_the_member) apply (simp add: get_def the_run_state_def set_object_def get_object_def put_def bind_def return_def gets_def) apply (drule get_tcb_SomeD) apply (clarsimp simp: map_upd_triv select_f_def image_def return_def) done lemma getMRs_corres: "corres (=) (tcb_at t and pspace_aligned and pspace_distinct) (case_option \ valid_ipc_buffer_ptr' buf) (get_mrs t buf mi) (getMRs t buf (message_info_map mi))" proof - have S: "get = gets id" by (simp add: gets_def) have T: "corres (\con regs. regs = map con msg_registers) (tcb_at t and pspace_aligned and pspace_distinct) \ (thread_get (arch_tcb_get_registers o tcb_arch) t) (asUser t (mapM getRegister RISCV64_H.msgRegisters))" apply (subst thread_get_registers) apply (rule asUser_corres') apply (subst mapM_gets) apply (simp add: getRegister_def) apply (simp add: S RISCV64_H.msgRegisters_def msg_registers_def) done show ?thesis apply (case_tac mi, simp add: get_mrs_def getMRs_def split del: if_split) apply (case_tac buf) apply (rule corres_guard_imp) apply (rule corres_split [where R = "\_. \" and R' = "\_. \", OF T]) apply simp apply wp+ apply simp apply simp apply (rule corres_guard_imp) apply (rule corres_split[OF T]) apply (simp only: option.simps return_bind fun_app_def load_word_offs_def doMachineOp_mapM ef_loadWord) apply (rule corres_split_eqr) apply (simp only: mapM_map_simp msgMaxLength_def msgLengthBits_def msg_max_length_def o_def upto_enum_word) apply (rule corres_mapM [where r'="(=)" and S="{a. fst a = snd a \ fst a < unat max_ipc_words}"]) apply simp apply simp apply (simp add: word_size wordSize_def wordBits_def) apply (rule loadWordUser_corres) apply simp apply wp+ apply simp apply (unfold msgRegisters_unfold)[1] apply simp apply (clarsimp simp: set_zip) apply (simp add: msgRegisters_unfold max_ipc_words nth_append) apply (rule corres_trivial, simp) apply (wp hoare_vcg_all_lift | simp add: valid_ipc_buffer_ptr'_def)+ done qed lemmas doMachineOp_return = submonad_doMachineOp.return lemma doMachineOp_bind: "\ empty_fail a; \x. empty_fail (b x) \ \ doMachineOp (a >>= b) = (doMachineOp a >>= (\rv. doMachineOp (b rv)))" by (blast intro: submonad_bind submonad_doMachineOp) lemma zipWithM_x_corres: assumes x: "\x x' y y'. ((x, y), (x', y')) \ S \ corres dc P P' (f x y) (f' x' y')" assumes y: "\x x' y y'. ((x, y), (x', y')) \ S \ \P\ f x y \\rv. P\" and z: "\x x' y y'. ((x, y), (x', y')) \ S \ \P'\ f' x' y' \\rv. P'\" and a: "set (zip (zip xs ys) (zip xs' ys')) \ S" and b: "length (zip xs ys) = length (zip xs' ys')" shows "corres dc P P' (zipWithM_x f xs ys) (zipWithM_x f' xs' ys')" apply (simp add: zipWithM_x_mapM) apply (rule corres_underlying_split) apply (rule corres_mapM) apply (rule dc_simp)+ apply clarsimp apply (rule x) apply assumption apply (clarsimp simp: y) apply (clarsimp simp: z) apply (rule b) apply (rule a) apply (rule corres_trivial, simp) apply (rule hoare_post_taut)+ done lemma valid_ipc_buffer_ptr'_def2: "valid_ipc_buffer_ptr' = (\p s. (is_aligned p msg_align_bits \ typ_at' UserDataT (p && ~~ mask pageBits) s))" apply (rule ext, rule ext) apply (simp add: valid_ipc_buffer_ptr'_def) done lemma storeWordUser_valid_ipc_buffer_ptr' [wp]: "\valid_ipc_buffer_ptr' p\ storeWordUser p' w \\_. valid_ipc_buffer_ptr' p\" unfolding valid_ipc_buffer_ptr'_def2 by (wp hoare_vcg_all_lift storeWordUser_typ_at') lemma thread_set_as_user_registers: "thread_set (\tcb. tcb \ tcb_arch := arch_tcb_set_registers (f (arch_tcb_get_registers (tcb_arch tcb))) (tcb_arch tcb) \) t = as_user t (modify (modify_registers f))" proof - have P: "\f. det (modify f)" by (simp add: modify_def) thus ?thesis apply (simp add: as_user_def P thread_set_def) apply (clarsimp simp: select_f_def simpler_modify_def bind_def image_def modify_registers_def arch_tcb_set_registers_def arch_tcb_get_registers_def arch_tcb_context_set_def arch_tcb_context_get_def) done qed lemma UserContext_fold: "UserContext (foldl (\s (x, y). s(x := y)) (user_regs s) xs) = foldl (\s (r, v). UserContext ((user_regs s)(r := v))) s xs" apply (induct xs arbitrary: s; simp) apply (clarsimp split: prod.splits) by (metis user_context.sel(1)) lemma setMRs_corres: assumes m: "mrs' = mrs" shows "corres (=) (tcb_at t and pspace_aligned and pspace_distinct and case_option \ in_user_frame buf) (case_option \ valid_ipc_buffer_ptr' buf) (set_mrs t buf mrs) (setMRs t buf mrs')" proof - have setRegister_def2: "setRegister = (\r v. modify (\s. UserContext ((user_regs s)(r := v))))" by ((rule ext)+, simp add: setRegister_def) have S: "\xs ys n m. m - n \ length xs \ (zip xs (drop n (take m ys))) = zip xs (drop n ys)" by (simp add: zip_take_triv2 drop_take) note upt.simps[simp del] upt_rec_numeral[simp del] show ?thesis using m unfolding setMRs_def set_mrs_def apply (clarsimp cong: option.case_cong split del: if_split) apply (subst bind_assoc[symmetric]) apply (fold thread_set_def[simplified]) apply (subst thread_set_as_user_registers) apply (cases buf) apply (clarsimp simp: msgRegisters_unfold setRegister_def2 zipWithM_x_Nil zipWithM_x_modify take_min_len zip_take_triv2 min.commute) apply (rule corres_guard_imp) apply (rule corres_split_nor[OF asUser_corres']) apply (rule corres_modify') apply (fastforce simp: fold_fun_upd[symmetric] msgRegisters_unfold UserContext_fold modify_registers_def cong: if_cong simp del: the_index.simps) apply simp apply (rule corres_trivial, simp) apply ((wp |simp)+)[4] \ \buf = Some a\ using if_split[split del] apply (clarsimp simp: msgRegisters_unfold setRegister_def2 zipWithM_x_Nil zipWithM_x_modify take_min_len zip_take_triv2 min.commute msgMaxLength_def msgLengthBits_def) apply (simp add: msg_max_length_def) apply (rule corres_guard_imp) apply (rule corres_split_nor[OF asUser_corres']) apply (rule corres_modify') apply (simp only: msgRegisters_unfold cong: if_cong) apply (fastforce simp: fold_fun_upd[symmetric] modify_registers_def UserContext_fold) apply simp apply (rule corres_split_nor) apply (rule_tac S="{((x, y), (x', y')). y = y' \ x' = (a + (of_nat x * 8)) \ x < unat max_ipc_words}" in zipWithM_x_corres) apply (fastforce intro: storeWordUser_corres) apply wp+ apply (clarsimp simp add: S msgMaxLength_def msg_max_length_def set_zip) apply (simp add: wordSize_def wordBits_def word_size max_ipc_words upt_Suc_append[symmetric] upto_enum_word) apply simp apply (rule corres_trivial, clarsimp simp: min.commute) apply wp+ apply (wp | clarsimp simp: valid_ipc_buffer_ptr'_def)+ done qed lemma copyMRs_corres: "corres (=) (tcb_at s and tcb_at r and pspace_aligned and pspace_distinct and case_option \ in_user_frame sb and case_option \ in_user_frame rb and K (unat n \ msg_max_length)) (case_option \ valid_ipc_buffer_ptr' sb and case_option \ valid_ipc_buffer_ptr' rb) (copy_mrs s sb r rb n) (copyMRs s sb r rb n)" proof - have U: "unat n \ msg_max_length \ map (toEnum :: nat \ machine_word) [7 ..< Suc (unat n)] = map of_nat [7 ..< Suc (unat n)]" unfolding msg_max_length_def by auto note R'=msgRegisters_unfold[THEN meta_eq_to_obj_eq, THEN arg_cong[where f=length]] note R=R'[simplified] have as_user_bit: "\v :: machine_word. corres dc (tcb_at s and tcb_at r and pspace_aligned and pspace_distinct) \ (mapM (\ra. do v \ as_user s (getRegister ra); as_user r (setRegister ra v) od) (take (unat n) msg_registers)) (mapM (\ra. do v \ asUser s (getRegister ra); asUser r (setRegister ra v) od) (take (unat n) msgRegisters))" apply (rule corres_guard_imp) apply (rule_tac S=Id in corres_mapM, simp+) apply (rule corres_split_eqr[OF asUser_getRegister_corres asUser_setRegister_corres]) apply (wp | clarsimp simp: msg_registers_def msgRegisters_def)+ done have wordSize[simp]: "of_nat wordSize = 8" by (simp add: wordSize_def wordBits_def word_size) show ?thesis apply (rule corres_assume_pre) apply (simp add: copy_mrs_def copyMRs_def word_size cong: option.case_cong split del: if_split del: upt.simps) apply (cases sb) apply (simp add: R) apply (rule corres_guard_imp) apply (rule corres_split_nor[OF as_user_bit]) apply (rule corres_trivial, simp) apply wp+ apply simp apply simp apply (cases rb) apply (simp add: R) apply (rule corres_guard_imp) apply (rule corres_split_nor[OF as_user_bit]) apply (rule corres_trivial, simp) apply wp+ apply simp apply simp apply (simp add: R del: upt.simps) apply (rule corres_guard_imp) apply (rename_tac sb_ptr rb_ptr) apply (rule corres_split_nor[OF as_user_bit]) apply (rule corres_split_eqr) apply (rule_tac S="{(x, y). y = of_nat x \ x < unat max_ipc_words}" in corres_mapM, simp+) apply (rule corres_split_eqr) apply (rule loadWordUser_corres) apply simp apply (rule storeWordUser_corres) apply simp apply (wp hoare_vcg_all_lift | simp)+ apply (clarsimp simp: upto_enum_def) apply arith apply (subst set_zip) apply (simp add: upto_enum_def U del: upt.simps) apply (clarsimp simp del: upt.simps) apply (clarsimp simp: msg_max_length_def word_le_nat_alt nth_append max_ipc_words) apply (erule order_less_trans) apply simp apply (rule corres_trivial, simp) apply (wp hoare_vcg_all_lift mapM_wp' | simp add: valid_ipc_buffer_ptr'_def)+ done qed lemma cte_at_tcb_at_32': "tcb_at' t s \ cte_at' (t + 32) s" apply (simp add: cte_at'_obj_at') apply (rule disjI2, rule bexI[where x=32]) apply simp apply fastforce done lemma get_tcb_cap_corres: "tcb_cap_cases ref = Some (getF, v) \ corres cap_relation (tcb_at t and valid_objs) (tcb_at' t and pspace_aligned' and pspace_distinct') (liftM getF (gets_the (get_tcb t))) (getSlotCap (cte_map (t, ref)))" apply (simp add: getSlotCap_def liftM_def[symmetric]) apply (rule corres_no_failI) apply (rule no_fail_pre, wp) apply (cases v, simp) apply (frule tcb_cases_related) apply (clarsimp simp: cte_at'_obj_at') apply (drule spec[where x=t]) apply (drule bspec, erule domI) apply simp apply clarsimp apply (clarsimp simp: gets_the_def simpler_gets_def bind_def assert_opt_def tcb_at_def return_def dest!: get_tcb_SomeD) apply (drule use_valid [OF _ getCTE_sp[where P="(=) s'" for s'], OF _ refl]) apply (clarsimp simp: get_tcb_def return_def) apply (drule pspace_relation_ctes_ofI[OF state_relation_pspace_relation]) apply (rule cte_wp_at_tcbI[where t="(t, ref)"], fastforce+)[1] apply assumption+ apply (clarsimp simp: cte_wp_at_ctes_of) done lemmas get_vtable_cap_corres = get_tcb_cap_corres[where ref="tcb_cnode_index 1", simplified, OF conjI [OF refl refl]] lemma pspace_dom_dom: "dom ps \ pspace_dom ps" unfolding pspace_dom_def apply clarsimp apply (rule rev_bexI [OF domI], assumption) apply (simp add: obj_relation_cuts_def2 image_Collect cte_map_def range_composition [symmetric] split: Structures_A.kernel_object.splits arch_kernel_obj.splits cong: arch_kernel_obj.case_cong) apply safe apply (drule wf_cs_0) apply clarsimp apply (rule_tac x = n in exI) apply (clarsimp simp: of_bl_def) apply (rule range_eqI [where x = 0], simp)+ apply (rename_tac vmpage_size) apply (rule exI [where x = 0]) apply (case_tac vmpage_size, simp_all add: bit_simps) done lemma no_0_obj_kheap: assumes no0: "no_0_obj' s'" and psr: "pspace_relation (kheap s) (ksPSpace s')" shows "kheap s 0 = None" proof (rule ccontr) assume "kheap s 0 \ None" hence "0 \ dom (kheap s)" .. hence "0 \ pspace_dom (kheap s)" by (rule set_mp [OF pspace_dom_dom]) moreover from no0 have "0 \ dom (ksPSpace s')" unfolding no_0_obj'_def by clarsimp ultimately show False using psr by (clarsimp simp: pspace_relation_def) qed lemmas valid_ipc_buffer_cap_simps = valid_ipc_buffer_cap_def [split_simps cap.split arch_cap.split] lemma lookupIPCBuffer_corres': "corres (=) (tcb_at t and valid_objs and pspace_aligned and pspace_distinct) (no_0_obj') (lookup_ipc_buffer w t) (lookupIPCBuffer w t)" apply (rule corres_cross_over_guard[where P'=Q and Q="pspace_aligned' and pspace_distinct' and Q" for Q]) apply (fastforce simp: pspace_aligned_cross pspace_distinct_cross state_relation_def) apply (simp add: lookup_ipc_buffer_def RISCV64_H.lookupIPCBuffer_def) apply (rule corres_guard_imp) apply (rule corres_split_eqr[OF threadGet_corres]) apply (simp add: tcb_relation_def) apply (simp add: getThreadBufferSlot_def locateSlot_conv) apply (rule corres_split[OF getSlotCap_corres]) apply (simp add: cte_map_def tcb_cnode_index_def cte_level_bits_def tcbIPCBufferSlot_def) apply (rule_tac F="valid_ipc_buffer_cap rv buffer_ptr" in corres_gen_asm) apply (rule_tac P="valid_cap rv" and Q="no_0_obj'" in corres_assume_pre) apply (simp add: Let_def split: cap.split arch_cap.split split del: if_split cong: if_cong) apply (safe, simp_all add: isCap_simps valid_ipc_buffer_cap_simps split:bool.split_asm)[1] apply (rename_tac word rights vmpage_size d option) apply (subgoal_tac "word + (buffer_ptr && mask (pageBitsForSize vmpage_size)) \ 0") apply (simp add: cap_aligned_def valid_ipc_buffer_cap_def vmrights_map_def vm_read_only_def vm_read_write_def) apply auto[1] apply (subgoal_tac "word \ 0") apply (subgoal_tac "word \ word + (buffer_ptr && mask (pageBitsForSize vmpage_size))") apply fastforce apply (rule_tac b="2 ^ (pageBitsForSize vmpage_size) - 1" in word_plus_mono_right2) apply (clarsimp simp: valid_cap_def cap_aligned_def intro!: is_aligned_no_overflow') apply (clarsimp simp: word_bits_def bit_simps intro!: word_less_sub_1 and_mask_less') apply (case_tac vmpage_size, simp_all add: bit_simps)[1] apply (drule state_relation_pspace_relation) apply (clarsimp simp: valid_cap_def obj_at_def no_0_obj_kheap obj_relation_cuts_def3 no_0_obj'_def split: if_split_asm) apply (wp get_cap_valid_ipc get_cap_aligned)+ apply (wp thread_get_obj_at_eq)+ apply (clarsimp elim!: tcb_at_cte_at) apply clarsimp done lemma lookupIPCBuffer_corres: "corres (=) (tcb_at t and invs) (no_0_obj') (lookup_ipc_buffer w t) (lookupIPCBuffer w t)" using lookupIPCBuffer_corres' by (rule corres_guard_imp, auto simp: invs'_def valid_state'_def) crunch inv[wp]: lookupIPCBuffer P (wp: crunch_wps simp: crunch_simps) crunch pred_tcb_at'[wp]: rescheduleRequired "pred_tcb_at' proj P t" lemma setThreadState_st_tcb': "\\\ setThreadState st t \\rv. st_tcb_at' (\s. s = st) t\" apply (simp add: setThreadState_def) apply (wp threadSet_pred_tcb_at_state | simp add: if_apply_def2)+ done lemma setThreadState_st_tcb: "\\s. P st\ setThreadState st t \\rv. st_tcb_at' P t\" apply (cases "P st") apply simp apply (rule hoare_post_imp [OF _ setThreadState_st_tcb']) apply (erule pred_tcb'_weakenE, simp) apply simp done lemma setBoundNotification_bound_tcb': "\\\ setBoundNotification ntfn t \\rv. bound_tcb_at' (\s. s = ntfn) t\" apply (simp add: setBoundNotification_def) apply (wp threadSet_pred_tcb_at_state | simp add: if_apply_def2)+ done lemma setBoundNotification_bound_tcb: "\\s. P ntfn\ setBoundNotification ntfn t \\rv. bound_tcb_at' P t\" apply (cases "P ntfn") apply simp apply (rule hoare_post_imp [OF _ setBoundNotification_bound_tcb']) apply (erule pred_tcb'_weakenE, simp) apply simp done crunches rescheduleRequired, tcbSchedDequeue, setThreadState, setBoundNotification for ct'[wp]: "\s. P (ksCurThread s)" lemma ct_in_state'_decomp: assumes x: "\\s. t = (ksCurThread s)\ f \\rv s. t = (ksCurThread s)\" assumes y: "\Pre\ f \\rv. st_tcb_at' Prop t\" shows "\\s. Pre s \ t = (ksCurThread s)\ f \\rv. ct_in_state' Prop\" apply (rule hoare_post_imp [where Q="\rv s. t = ksCurThread s \ st_tcb_at' Prop t s"]) apply (clarsimp simp add: ct_in_state'_def) apply (rule hoare_vcg_precond_imp) apply (wp x y) apply simp done lemma ct_in_state'_set: "\\s. tcb_at' t s \ P st \ t = ksCurThread s\ setThreadState st t \\rv. ct_in_state' P\" apply (rule hoare_vcg_precond_imp) apply (rule ct_in_state'_decomp[where t=t]) apply (wp setThreadState_ct') apply (wp setThreadState_st_tcb) apply clarsimp done crunches setQueue, rescheduleRequired, tcbSchedDequeue for idle'[wp]: "valid_idle'" (simp: crunch_simps) lemma sts_valid_idle'[wp]: "\valid_idle' and valid_pspace' and (\s. t = ksIdleThread s \ idle' ts)\ setThreadState ts t \\rv. valid_idle'\" apply (simp add: setThreadState_def) apply (wpsimp wp: threadSet_idle' simp: idle_tcb'_def) done lemma sbn_valid_idle'[wp]: "\valid_idle' and valid_pspace' and (\s. t = ksIdleThread s \ \bound ntfn)\ setBoundNotification ntfn t \\rv. valid_idle'\" apply (simp add: setBoundNotification_def) apply (wpsimp wp: threadSet_idle' simp: idle_tcb'_def) done lemma gts_sp': "\P\ getThreadState t \\rv. st_tcb_at' (\st. st = rv) t and P\" apply (simp add: getThreadState_def threadGet_def) apply wp apply (simp add: o_def pred_tcb_at'_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemma gbn_sp': "\P\ getBoundNotification t \\rv. bound_tcb_at' (\st. st = rv) t and P\" apply (simp add: getBoundNotification_def threadGet_def) apply wp apply (simp add: o_def pred_tcb_at'_def) apply (wp getObject_tcb_wp) apply (clarsimp simp: obj_at'_def) done lemma tcbSchedDequeue_tcbState_obj_at'[wp]: "\obj_at' (P \ tcbState) t'\ tcbSchedDequeue t \\rv. obj_at' (P \ tcbState) t'\" apply (simp add: tcbSchedDequeue_def) apply (wp | simp add: o_def split del: if_split cong: if_cong)+ done crunch typ_at'[wp]: setQueue "\s. P' (typ_at' P t s)" lemma setQueue_pred_tcb_at[wp]: "\\s. P' (pred_tcb_at' proj P t s)\ setQueue d p q \\rv s. P' (pred_tcb_at' proj P t s)\" unfolding pred_tcb_at'_def apply (rule_tac P=P' in P_bool_lift) apply (rule setQueue_obj_at) apply (rule_tac Q="\_ s. \typ_at' TCBT t s \ obj_at' (Not \ (P \ proj \ tcb_to_itcb')) t s" in hoare_post_imp, simp add: not_obj_at' o_def) apply (wp hoare_vcg_disj_lift) apply (clarsimp simp: not_obj_at' o_def) done lemma tcbSchedDequeue_pred_tcb_at'[wp]: "\\s. P' (pred_tcb_at' proj P t' s)\ tcbSchedDequeue t \\_ s. P' (pred_tcb_at' proj P t' s)\" apply (rule_tac P=P' in P_bool_lift) apply (simp add: tcbSchedDequeue_def) apply (wp threadSet_pred_tcb_no_state | clarsimp simp: tcb_to_itcb'_def)+ apply (simp add: tcbSchedDequeue_def) apply (wp threadSet_pred_tcb_no_state | clarsimp simp: tcb_to_itcb'_def)+ done lemma sts_st_tcb': "\if t = t' then K (P st) else st_tcb_at' P t\ setThreadState st t' \\_. st_tcb_at' P t\" apply (cases "t = t'", simp_all add: setThreadState_def split del: if_split) apply ((wp threadSet_pred_tcb_at_state | simp)+)[1] apply (wp threadSet_obj_at'_really_strongest | simp add: pred_tcb_at'_def)+ done lemma sts_bound_tcb_at': "\bound_tcb_at' P t\ setThreadState st t' \\_. bound_tcb_at' P t\" apply (cases "t = t'", simp_all add: setThreadState_def split del: if_split) apply ((wp threadSet_pred_tcb_at_state | simp)+)[1] apply (wp threadSet_obj_at'_really_strongest | simp add: pred_tcb_at'_def)+ done lemma sbn_st_tcb': "\st_tcb_at' P t\ setBoundNotification ntfn t' \\_. st_tcb_at' P t\" apply (cases "t = t'", simp_all add: setBoundNotification_def split del: if_split) apply ((wp threadSet_pred_tcb_at_state | simp)+)[1] apply (wp threadSet_obj_at'_really_strongest | simp add: pred_tcb_at'_def)+ done lemma sbn_bound_tcb_at': "\if t = t' then K (P ntfn) else bound_tcb_at' P t\ setBoundNotification ntfn t' \\_. bound_tcb_at' P t\" apply (cases "t = t'", simp_all add: setBoundNotification_def split del: if_split) apply ((wp threadSet_pred_tcb_at_state | simp)+)[1] apply (wp threadSet_obj_at'_really_strongest | simp add: pred_tcb_at'_def)+ done crunches rescheduleRequired, tcbSchedDequeue, setThreadState, setBoundNotification for typ_at'[wp]: "\s. P (typ_at' T p s)" lemmas setThreadState_typ_ats[wp] = typ_at_lifts [OF setThreadState_typ_at'] lemmas setBoundNotification_typ_ats[wp] = typ_at_lifts [OF setBoundNotification_typ_at'] crunches setThreadState, setBoundNotification for aligned'[wp]: pspace_aligned' and distinct'[wp]: pspace_distinct' and cte_wp_at'[wp]: "cte_wp_at' P p" crunch refs_of'[wp]: rescheduleRequired "\s. P (state_refs_of' s)" (wp: threadSet_state_refs_of') lemma setThreadState_state_refs_of'[wp]: "\\s. P ((state_refs_of' s) (t := tcb_st_refs_of' st \ {r \ state_refs_of' s t. snd r = TCBBound}))\ setThreadState st t \\rv s. P (state_refs_of' s)\" by (simp add: setThreadState_def fun_upd_def | wp threadSet_state_refs_of')+ lemma setBoundNotification_state_refs_of'[wp]: "\\s. P ((state_refs_of' s) (t := tcb_bound_refs' ntfn \ {r \ state_refs_of' s t. snd r \ TCBBound}))\ setBoundNotification ntfn t \\rv s. P (state_refs_of' s)\" by (simp add: setBoundNotification_def Un_commute fun_upd_def | wp threadSet_state_refs_of' )+ lemma sts_cur_tcb'[wp]: "\cur_tcb'\ setThreadState st t \\rv. cur_tcb'\" by (wp cur_tcb_lift) lemma sbn_cur_tcb'[wp]: "\cur_tcb'\ setBoundNotification ntfn t \\rv. cur_tcb'\" by (wp cur_tcb_lift) crunch iflive'[wp]: setQueue if_live_then_nonz_cap' crunch nonz_cap[wp]: setQueue "ex_nonz_cap_to' t" crunch iflive'[wp]: addToBitmap if_live_then_nonz_cap' crunch nonz_cap[wp]: addToBitmap "ex_nonz_cap_to' t" crunch iflive'[wp]: removeFromBitmap if_live_then_nonz_cap' crunch nonz_cap[wp]: removeFromBitmap "ex_nonz_cap_to' t" lemma tcbSchedEnqueue_iflive'[wp]: "\if_live_then_nonz_cap' and ex_nonz_cap_to' tcb\ tcbSchedEnqueue tcb \\_. if_live_then_nonz_cap'\" apply (simp add: tcbSchedEnqueue_def unless_def) apply (wp threadSet_iflive' hoare_drop_imps | simp add: crunch_simps)+ done lemma rescheduleRequired_iflive'[wp]: "\if_live_then_nonz_cap' and (\s. \t. ksSchedulerAction s = SwitchToThread t \ st_tcb_at' runnable' t s)\ rescheduleRequired \\rv. if_live_then_nonz_cap'\" apply (simp add: rescheduleRequired_def) apply (wp | wpc | simp)+ apply (clarsimp simp: pred_tcb_at'_def obj_at'_real_def) apply (erule(1) if_live_then_nonz_capD') apply fastforce done lemma sts_iflive'[wp]: "\\s. if_live_then_nonz_cap' s \ (st \ Inactive \ \ idle' st \ ex_nonz_cap_to' t s)\ setThreadState st t \\rv. if_live_then_nonz_cap'\" apply (simp add: setThreadState_def setQueue_def) apply (rule hoare_pre) apply (wp | simp)+ apply (rule_tac Q="\rv. if_live_then_nonz_cap'" in hoare_post_imp) apply clarsimp apply (wp threadSet_iflive' | simp)+ apply auto done lemma sbn_iflive'[wp]: "\\s. if_live_then_nonz_cap' s \ (bound ntfn \ ex_nonz_cap_to' t s)\ setBoundNotification ntfn t \\rv. if_live_then_nonz_cap'\" apply (simp add: setBoundNotification_def) apply (rule hoare_pre) apply (wp threadSet_iflive' | simp)+ apply auto done crunches setThreadState, setBoundNotification for ifunsafe'[wp]: "if_unsafe_then_cap'" lemma st_tcb_ex_cap'': "\ st_tcb_at' P t s; if_live_then_nonz_cap' s; \st. P st \ st \ Inactive \ \ idle' st \ \ ex_nonz_cap_to' t s" by (clarsimp simp: pred_tcb_at'_def obj_at'_real_def elim!: ko_wp_at'_weakenE if_live_then_nonz_capE') lemma bound_tcb_ex_cap'': "\ bound_tcb_at' P t s; if_live_then_nonz_cap' s; \ntfn. P ntfn \ bound ntfn \ \ ex_nonz_cap_to' t s" by (clarsimp simp: pred_tcb_at'_def obj_at'_real_def elim!: ko_wp_at'_weakenE if_live_then_nonz_capE') crunches setThreadState, setBoundNotification for arch' [wp]: "\s. P (ksArchState s)" (simp: unless_def crunch_simps) crunches setThreadState, setBoundNotification for it' [wp]: "\s. P (ksIdleThread s)" (wp: getObject_inv_tcb simp: updateObject_default_def unless_def crunch_simps) crunch it' [wp]: removeFromBitmap "\s. P (ksIdleThread s)" lemma sts_ctes_of [wp]: "\\s. P (ctes_of s)\ setThreadState st t \\rv s. P (ctes_of s)\" apply (simp add: setThreadState_def) apply (wp threadSet_ctes_ofT | simp add: tcb_cte_cases_def cteSizeBits_def)+ done lemma sbn_ctes_of [wp]: "\\s. P (ctes_of s)\ setBoundNotification ntfn t \\rv s. P (ctes_of s)\" apply (simp add: setBoundNotification_def) apply (wp threadSet_ctes_ofT | simp add: tcb_cte_cases_def cteSizeBits_def)+ done crunches setThreadState, setBoundNotification for ksInterruptState[wp]: "\s. P (ksInterruptState s)" (simp: unless_def crunch_simps) crunches setThreadState, setBoundNotification for gsMaxObjectSize[wp]: "\s. P (gsMaxObjectSize s)" (simp: unless_def crunch_simps wp: setObject_ksPSpace_only updateObject_default_inv) lemmas setThreadState_irq_handlers[wp] = valid_irq_handlers_lift'' [OF sts_ctes_of setThreadState_ksInterruptState] lemmas setBoundNotification_irq_handlers[wp] = valid_irq_handlers_lift'' [OF sbn_ctes_of setBoundNotification_ksInterruptState] lemma sts_global_reds' [wp]: "\valid_global_refs'\ setThreadState st t \\_. valid_global_refs'\" by (rule valid_global_refs_lift'; wp) lemma sbn_global_reds' [wp]: "\valid_global_refs'\ setBoundNotification ntfn t \\_. valid_global_refs'\" by (rule valid_global_refs_lift'; wp) crunches setThreadState, setBoundNotification for irq_states' [wp]: valid_irq_states' (simp: unless_def crunch_simps) lemma addToBitmap_ksMachine[wp]: "\\s. P (ksMachineState s)\ addToBitmap d p \\rv s. P (ksMachineState s)\" unfolding bitmap_fun_defs by (wp, simp) lemma removeFromBitmap_ksMachine[wp]: "\\s. P (ksMachineState s)\ removeFromBitmap d p \\rv s. P (ksMachineState s)\" unfolding bitmap_fun_defs by (wp|simp add: bitmap_fun_defs)+ lemma tcbSchedEnqueue_ksMachine[wp]: "\\s. P (ksMachineState s)\ tcbSchedEnqueue x \\_ s. P (ksMachineState s)\" by (simp add: tcbSchedEnqueue_def unless_def setQueue_def | wp)+ crunches setThreadState, setBoundNotification for ksMachine[wp]: "\s. P (ksMachineState s)" and pspace_domain_valid[wp]: "pspace_domain_valid" lemma setThreadState_vms'[wp]: "\valid_machine_state'\ setThreadState F t \\rv. valid_machine_state'\" apply (simp add: valid_machine_state'_def pointerInUserData_def pointerInDeviceData_def) apply (intro hoare_vcg_all_lift hoare_vcg_disj_lift; wp) done lemma ct_not_inQ_addToBitmap[wp]: "\ ct_not_inQ \ addToBitmap d p \\_. ct_not_inQ \" unfolding bitmap_fun_defs by (wp, clarsimp simp: ct_not_inQ_def) lemma ct_not_inQ_removeFromBitmap[wp]: "\ ct_not_inQ \ removeFromBitmap d p \\_. ct_not_inQ \" unfolding bitmap_fun_defs by (wp|simp add: bitmap_fun_defs ct_not_inQ_def comp_def)+ lemma setBoundNotification_vms'[wp]: "\valid_machine_state'\ setBoundNotification ntfn t \\rv. valid_machine_state'\" apply (simp add: valid_machine_state'_def pointerInUserData_def pointerInDeviceData_def) apply (intro hoare_vcg_all_lift hoare_vcg_disj_lift; wp) done lemma tcbSchedEnqueue_ct_not_inQ: "\ct_not_inQ and (\s. ksSchedulerAction s = ResumeCurrentThread \ ksCurThread s \ t)\ tcbSchedEnqueue t \\_. ct_not_inQ\" (is "\?PRE\ _ \_\") proof - have ts: "\?PRE\ threadSet (tcbQueued_update (\_. True)) t \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def) apply (rule_tac Q="\s. ksSchedulerAction s = ResumeCurrentThread \ obj_at' (Not \ tcbQueued) (ksCurThread s) s \ ksCurThread s \ t" in hoare_pre_imp, clarsimp) apply (rule hoare_convert_imp [OF threadSet_nosch]) apply (rule hoare_weaken_pre) apply (wps setObject_ct_inv) apply (rule threadSet_obj_at'_strongish) apply (clarsimp simp: comp_def) done have sq: "\d p q. \ct_not_inQ\ setQueue d p q \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def setQueue_def) apply (wp) apply (clarsimp) done show ?thesis apply (simp add: tcbSchedEnqueue_def unless_def null_def) apply (wp ts sq hoare_convert_imp [OF addToBitmap_nosch addToBitmap_ct'])+ apply (rule_tac Q="\_. ?PRE" in hoare_post_imp, clarsimp) apply (wp sq hoare_convert_imp [OF setQueue_nosch setQueue_ct])+ apply (rule_tac Q="\_. ?PRE" in hoare_post_imp, clarsimp) apply wp apply assumption done qed lemma tcbSchedAppend_ct_not_inQ: "\ct_not_inQ and (\s. ksSchedulerAction s = ResumeCurrentThread \ ksCurThread s \ t)\ tcbSchedAppend t \\_. ct_not_inQ\" (is "\?PRE\ _ \_\") proof - have ts: "\?PRE\ threadSet (tcbQueued_update (\_. True)) t \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def) apply (rule_tac Q="\s. ksSchedulerAction s = ResumeCurrentThread \ obj_at' (Not \ tcbQueued) (ksCurThread s) s \ ksCurThread s \ t" in hoare_pre_imp, clarsimp) apply (rule hoare_convert_imp [OF threadSet_nosch]) apply (rule hoare_weaken_pre) apply (wps setObject_ct_inv) apply (rule threadSet_obj_at'_strongish) apply (clarsimp simp: comp_def) done have sq: "\d p q. \ct_not_inQ\ setQueue d p q \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def setQueue_def) apply (wp) apply (clarsimp) done show ?thesis apply (simp add: tcbSchedAppend_def unless_def null_def) apply (wp ts sq hoare_convert_imp [OF addToBitmap_nosch addToBitmap_ct'])+ apply (rule_tac Q="\_. ?PRE" in hoare_post_imp, clarsimp) apply (wp sq hoare_convert_imp [OF setQueue_nosch setQueue_ct])+ apply (rule_tac Q="\_. ?PRE" in hoare_post_imp, clarsimp) apply wp apply assumption done qed lemma setSchedulerAction_direct: "\\\ setSchedulerAction sa \\_ s. ksSchedulerAction s = sa\" by (wpsimp simp: setSchedulerAction_def) lemma rescheduleRequired_ct_not_inQ: "\\\ rescheduleRequired \\_. ct_not_inQ\" apply (simp add: rescheduleRequired_def ct_not_inQ_def) apply (rule_tac Q="\_ s. ksSchedulerAction s = ChooseNewThread" in hoare_post_imp, clarsimp) apply (wp setSchedulerAction_direct) done crunch nosch[wp]: tcbSchedEnqueue "\s. P (ksSchedulerAction s)" (simp: unless_def) crunch nosch[wp]: tcbSchedAppend "\s. P (ksSchedulerAction s)" (simp: unless_def) lemma rescheduleRequired_sa_cnt[wp]: "\\s. True \ rescheduleRequired \\_ s. ksSchedulerAction s = ChooseNewThread \" unfolding rescheduleRequired_def setSchedulerAction_def by wpsimp lemma possibleSwitchTo_ct_not_inQ: "\ct_not_inQ and (\s. ksSchedulerAction s = ResumeCurrentThread \ ksCurThread s \ t)\ possibleSwitchTo t \\_. ct_not_inQ\" (is "\?PRE\ _ \_\") apply (simp add: possibleSwitchTo_def curDomain_def) apply (wpsimp wp: static_imp_wp rescheduleRequired_ct_not_inQ tcbSchedEnqueue_ct_not_inQ threadGet_wp | (rule hoare_post_imp[OF _ rescheduleRequired_sa_cnt], fastforce))+ apply (fastforce simp: obj_at'_def) done lemma threadSet_tcbState_update_ct_not_inQ[wp]: "\ct_not_inQ\ threadSet (tcbState_update f) t \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def) apply (rule hoare_convert_imp [OF threadSet_nosch]) apply (simp add: threadSet_def) apply (wp) apply (wps setObject_ct_inv) apply (rule setObject_tcb_strongest) prefer 2 apply assumption apply (clarsimp) apply (rule hoare_conjI) apply (rule hoare_weaken_pre) apply (wps, wp static_imp_wp) apply (wp OMG_getObject_tcb)+ apply (clarsimp simp: comp_def) apply (wp hoare_drop_imp) done lemma threadSet_tcbBoundNotification_update_ct_not_inQ[wp]: "\ct_not_inQ\ threadSet (tcbBoundNotification_update f) t \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def) apply (rule hoare_convert_imp [OF threadSet_nosch]) apply (simp add: threadSet_def) apply (wp) apply (wps setObject_ct_inv) apply (rule setObject_tcb_strongest) prefer 2 apply assumption apply (clarsimp) apply (rule hoare_conjI) apply (rule hoare_weaken_pre) apply wps apply (wp static_imp_wp) apply (wp OMG_getObject_tcb) apply (clarsimp simp: comp_def) apply (wp hoare_drop_imp) done lemma setThreadState_ct_not_inQ: "\ct_not_inQ\ setThreadState st t \\_. ct_not_inQ\" (is "\?PRE\ _ \_\") including no_pre apply (simp add: setThreadState_def) apply (wp rescheduleRequired_ct_not_inQ) apply (rule_tac Q="\_. ?PRE" in hoare_post_imp, clarsimp) apply (wp) done lemma setBoundNotification_ct_not_inQ: "\ct_not_inQ\ setBoundNotification ntfn t \\_. ct_not_inQ\" (is "\?PRE\ _ \_\") by (simp add: setBoundNotification_def, wp) crunch ct_not_inQ[wp]: setQueue "ct_not_inQ" lemma tcbSchedDequeue_ct_not_inQ[wp]: "\ct_not_inQ\ tcbSchedDequeue t \\_. ct_not_inQ\" proof - have TSNIQ: "\F t. \ct_not_inQ and (\_. \tcb. \tcbQueued (F tcb))\ threadSet F t \\_. ct_not_inQ\" apply (simp add: ct_not_inQ_def) apply (wp hoare_convert_imp [OF threadSet_nosch]) apply (simp add: threadSet_def) apply (wp) apply (wps setObject_ct_inv) apply (wp setObject_tcb_strongest getObject_tcb_wp)+ apply (case_tac "t = ksCurThread s") apply (clarsimp simp: obj_at'_def)+ done show ?thesis apply (simp add: tcbSchedDequeue_def) apply (wp TSNIQ | simp cong: if_cong)+ done qed lemma tcbSchedEnqueue_not_st: "(\tcb st qd. P (tcb\tcbState := st, tcbQueued := qd\) \ P tcb) \ \obj_at' P t'\ tcbSchedEnqueue t \\_. obj_at' P t'\" apply (simp add: tcbSchedEnqueue_def unless_def) apply (wp threadGet_wp | simp)+ apply (clarsimp simp: obj_at'_def) apply (case_tac obja) apply fastforce done lemma setThreadState_not_st: "(\tcb st qd. P (tcb\tcbState := st, tcbQueued := qd\) \ P tcb) \ \obj_at' P t'\ setThreadState st t \\_. obj_at' P t'\" apply (simp add: setThreadState_def rescheduleRequired_def) apply (wp hoare_vcg_conj_lift tcbSchedEnqueue_not_st | wpc | rule hoare_drop_imps | simp)+ apply (clarsimp simp: obj_at'_def) apply (case_tac obj) apply fastforce done crunch ct_idle_or_in_cur_domain'[wp]: setQueue ct_idle_or_in_cur_domain' (simp: ct_idle_or_in_cur_domain'_def tcb_in_cur_domain'_def) crunch ksDomSchedule[wp]: setQueue "\s. P (ksDomSchedule s)" crunch ksCurDomain[wp]: addToBitmap "\s. P (ksCurDomain s)" (wp: crunch_wps ) crunch ksDomSchedule[wp]: addToBitmap "\s. P (ksDomSchedule s)" (wp: crunch_wps ) crunch ksCurDomain[wp]: removeFromBitmap "\s. P (ksCurDomain s)" (wp: crunch_wps ) crunch ksDomSchedule[wp]: removeFromBitmap "\s. P (ksDomSchedule s)" (wp: crunch_wps ) lemma addToBitmap_ct_idle_or_in_cur_domain'[wp]: "\ ct_idle_or_in_cur_domain' \ addToBitmap d p \ \_. ct_idle_or_in_cur_domain' \" apply (rule ct_idle_or_in_cur_domain'_lift) apply (wp hoare_vcg_disj_lift| rule obj_at_setObject2 | clarsimp simp: updateObject_default_def in_monad setNotification_def)+ done lemma removeFromBitmap_ct_idle_or_in_cur_domain'[wp]: "\ ct_idle_or_in_cur_domain' \ removeFromBitmap d p \ \_. ct_idle_or_in_cur_domain' \" apply (rule ct_idle_or_in_cur_domain'_lift) apply (wp hoare_vcg_disj_lift| rule obj_at_setObject2 | clarsimp simp: updateObject_default_def in_monad setNotification_def)+ done lemma tcbSchedEnqueue_ksCurDomain[wp]: "\ \s. P (ksCurDomain s)\ tcbSchedEnqueue tptr \\_ s. P (ksCurDomain s)\" apply (simp add: tcbSchedEnqueue_def unless_def) apply wpsimp done lemma tcbSchedEnqueue_ksDomSchedule[wp]: "\ \s. P (ksDomSchedule s)\ tcbSchedEnqueue tptr \\_ s. P (ksDomSchedule s)\" apply (simp add: tcbSchedEnqueue_def unless_def) apply wpsimp done lemma tcbSchedEnqueue_ct_idle_or_in_cur_domain'[wp]: "\ct_idle_or_in_cur_domain'\ tcbSchedEnqueue tptr \\_. ct_idle_or_in_cur_domain'\" apply (simp add: tcbSchedEnqueue_def unless_def) apply (wp threadSet_ct_idle_or_in_cur_domain' | simp)+ done lemma setSchedulerAction_spec: "\\\setSchedulerAction ChooseNewThread \\rv. ct_idle_or_in_cur_domain'\" apply (simp add:setSchedulerAction_def) apply wp apply (simp add:ct_idle_or_in_cur_domain'_def) done lemma rescheduleRequired_ct_idle_or_in_cur_domain'[wp]: "\\\ rescheduleRequired \\rv. ct_idle_or_in_cur_domain'\" apply (simp add: rescheduleRequired_def) apply (wp setSchedulerAction_spec) done lemma rescheduleRequired_ksCurDomain[wp]: "\ \s. P (ksCurDomain s) \ rescheduleRequired \\_ s. P (ksCurDomain s) \" apply (simp add: rescheduleRequired_def) apply wpsimp done lemma rescheduleRequired_ksDomSchedule[wp]: "\ \s. P (ksDomSchedule s) \ rescheduleRequired \\_ s. P (ksDomSchedule s) \" by (simp add: rescheduleRequired_def) wpsimp lemma setThreadState_ct_idle_or_in_cur_domain'[wp]: "\ct_idle_or_in_cur_domain'\ setThreadState st tptr \\rv. ct_idle_or_in_cur_domain'\" apply (simp add: setThreadState_def) apply (wp threadSet_ct_idle_or_in_cur_domain' hoare_drop_imps | simp)+ done lemma setThreadState_ksCurDomain[wp]: "\ \s. P (ksCurDomain s) \ setThreadState st tptr \\_ s. P (ksCurDomain s) \" apply (simp add: setThreadState_def) apply wpsimp done lemma setThreadState_ksDomSchedule[wp]: "\ \s. P (ksDomSchedule s) \ setThreadState st tptr \\_ s. P (ksDomSchedule s) \" apply (simp add: setThreadState_def) apply wpsimp done lemma setBoundNotification_ct_idle_or_in_cur_domain'[wp]: "\ct_idle_or_in_cur_domain'\ setBoundNotification t a \\rv. ct_idle_or_in_cur_domain'\" apply (simp add: setBoundNotification_def) apply (wp threadSet_ct_idle_or_in_cur_domain' hoare_drop_imps | simp)+ done lemma setBoundNotification_ksCurDomain[wp]: "\ \s. P (ksCurDomain s) \ setBoundNotification st tptr \\_ s. P (ksCurDomain s) \" apply (simp add: setBoundNotification_def) apply wpsimp done lemma setBoundNotification_ksDomSchedule[wp]: "\ \s. P (ksDomSchedule s) \ setBoundNotification st tptr \\_ s. P (ksDomSchedule s) \" apply (simp add: setBoundNotification_def) apply wpsimp done crunches rescheduleRequired, setBoundNotification, setThreadState for ksDomScheduleIdx[wp]: "\s. P (ksDomScheduleIdx s)" and gsUntypedZeroRanges[wp]: "\s. P (gsUntypedZeroRanges s)" lemma sts_utr[wp]: "\untyped_ranges_zero'\ setThreadState st t \\_. untyped_ranges_zero'\" apply (simp add: cteCaps_of_def) apply (wp untyped_ranges_zero_lift) done lemma sts_invs_minor': "\st_tcb_at' (\st'. tcb_st_refs_of' st' = tcb_st_refs_of' st \ (st \ Inactive \ \ idle' st \ st' \ Inactive \ \ idle' st')) t and (\s. t = ksIdleThread s \ idle' st) and (\s. (\p. t \ set(ksReadyQueues s p)) \ runnable' st) and (\s. runnable' st \ obj_at' tcbQueued t s \ st_tcb_at' runnable' t s) and sch_act_simple and invs'\ setThreadState st t \\rv. invs'\" including no_pre apply (simp add: invs'_def valid_state'_def) apply (rule hoare_pre) apply (wp sts_valid_queues valid_irq_node_lift irqs_masked_lift setThreadState_ct_not_inQ | simp add: cteCaps_of_def o_def)+ apply (clarsimp simp: sch_act_simple_def) apply (intro conjI) apply clarsimp defer apply (clarsimp dest!: st_tcb_at_state_refs_ofD' elim!: rsubst[where P=sym_refs] intro!: ext) apply (clarsimp elim!: st_tcb_ex_cap'') apply (frule tcb_in_valid_state', clarsimp+) apply (cases st, simp_all add: valid_tcb_state'_def split: Structures_H.thread_state.split_asm) done lemma sts_cap_to'[wp]: "\ex_nonz_cap_to' p\ setThreadState st t \\rv. ex_nonz_cap_to' p\" by (wp ex_nonz_cap_to_pres') lemma sts_pred_tcb_neq': "\pred_tcb_at' proj P t and K (t \ t')\ setThreadState st t' \\_. pred_tcb_at' proj P t\" apply (simp add: setThreadState_def) apply (wp threadSet_pred_tcb_at_state | simp)+ done lemma sbn_pred_tcb_neq': "\pred_tcb_at' proj P t and K (t \ t')\ setBoundNotification ntfn t' \\_. pred_tcb_at' proj P t\" apply (simp add: setBoundNotification_def) apply (wp threadSet_pred_tcb_at_state | simp)+ done lemmas isTS_defs = isRunning_def isBlockedOnSend_def isBlockedOnReceive_def isBlockedOnNotification_def isBlockedOnReply_def isRestart_def isInactive_def isIdleThreadState_def lemma sts_st_tcb_at'_cases: "\\s. ((t = t') \ (P ts \ tcb_at' t' s)) \ ((t \ t') \ st_tcb_at' P t' s)\ setThreadState ts t \\rv. st_tcb_at' P t'\" apply (wp sts_st_tcb') apply fastforce done lemma threadSet_ct_running': "(\tcb. tcbState (f tcb) = tcbState tcb) \ \ct_running'\ threadSet f t \\rv. ct_running'\" apply (simp add: ct_in_state'_def) apply (rule hoare_lift_Pf [where f=ksCurThread]) apply (wp threadSet_pred_tcb_no_state; simp) apply wp done lemma setThreadState_tcb_in_cur_domain'[wp]: "\tcb_in_cur_domain' t'\ setThreadState st t \\_. tcb_in_cur_domain' t'\" apply (simp add: tcb_in_cur_domain'_def) apply (rule hoare_pre) apply wps apply (wp setThreadState_not_st | simp)+ done lemma asUser_global_refs': "\valid_global_refs'\ asUser t f \\rv. valid_global_refs'\" apply (simp add: asUser_def split_def) apply (wpsimp wp: threadSet_global_refs select_f_inv) done lemma sch_act_sane_lift: assumes "\P. \\s. P (ksSchedulerAction s)\ f \\rv s. P (ksSchedulerAction s)\" assumes "\P. \\s. P (ksCurThread s)\ f \\rv s. P (ksCurThread s)\" shows "\sch_act_sane\ f \\rv. sch_act_sane\" apply (simp add: sch_act_sane_def) apply (rule hoare_vcg_all_lift) apply (rule hoare_lift_Pf [where f=ksCurThread]) apply (wp assms)+ done lemma storeWord_invs'[wp]: "\pointerInUserData p and invs'\ doMachineOp (storeWord p w) \\rv. invs'\" proof - have aligned_offset_ignore: "\l. l<8 \ p && mask word_size_bits = 0 \ p + l && ~~ mask 12 = p && ~~ mask 12" proof - fix l assume al: "p && mask word_size_bits = 0" assume "(l::machine_word) < 8" hence less: "l<2^word_size_bits" by (simp add: word_size_bits_def) have le: "(word_size_bits::nat) \ 12" by (simp add: word_size_bits_def) show "?thesis l" by (rule is_aligned_add_helper[simplified is_aligned_mask, THEN conjunct2, THEN mask_out_first_mask_some, OF al less le]) qed show ?thesis apply (wp dmo_invs' no_irq_storeWord no_irq) apply (clarsimp simp: storeWord_def invs'_def valid_state'_def) apply (clarsimp simp: valid_machine_state'_def pointerInUserData_def assert_def simpler_modify_def fail_def bind_def return_def aligned_offset_ignore bit_simps upto0_7_def split: if_split_asm) done qed lemma storeWord_invs_no_cicd'[wp]: "\pointerInUserData p and invs_no_cicd'\ doMachineOp (storeWord p w) \\rv. invs_no_cicd'\" proof - have aligned_offset_ignore: "\l. l<8 \ p && mask 3 = 0 \ p + l && ~~ mask 12 = p && ~~ mask 12" proof - fix l assume al: "p && mask 3 = 0" assume "(l::machine_word) < 8" hence less: "l<2^3" by simp have le: "(3::nat) \ 12" by simp show "?thesis l" by (rule is_aligned_add_helper[simplified is_aligned_mask, THEN conjunct2, THEN mask_out_first_mask_some, OF al less le]) qed show ?thesis apply (wp dmo_invs_no_cicd' no_irq_storeWord no_irq) apply (clarsimp simp: storeWord_def invs'_def valid_state'_def) apply (clarsimp simp: valid_machine_state'_def pointerInUserData_def assert_def simpler_modify_def fail_def bind_def return_def pageBits_def aligned_offset_ignore upto0_7_def split: if_split_asm) done qed lemma storeWordUser_invs[wp]: "\invs'\ storeWordUser p w \\rv. invs'\" by (simp add: storeWordUser_def | wp)+ lemma hoare_valid_ipc_buffer_ptr_typ_at': "(\q. \typ_at' UserDataT q\ a \\_. typ_at' UserDataT q\) \ \valid_ipc_buffer_ptr' p\ a \\_. valid_ipc_buffer_ptr' p\" unfolding valid_ipc_buffer_ptr'_def2 including no_pre apply wp apply assumption done lemma gts_wp': "\\s. \st. st_tcb_at' ((=) st) t s \ P st s\ getThreadState t \P\" apply (rule hoare_post_imp) prefer 2 apply (rule gts_sp') apply (clarsimp simp: pred_tcb_at'_def obj_at'_def) done lemma gbn_wp': "\\s. \ntfn. bound_tcb_at' ((=) ntfn) t s \ P ntfn s\ getBoundNotification t \P\" apply (rule hoare_post_imp) prefer 2 apply (rule gbn_sp') apply (clarsimp simp: pred_tcb_at'_def obj_at'_def) done lemmas threadSet_irq_handlers' = valid_irq_handlers_lift'' [OF threadSet_ctes_ofT] lemma get_cap_corres_all_rights_P: "cte_ptr' = cte_map cte_ptr \ corres (\x y. cap_relation x y \ P x) (cte_wp_at P cte_ptr) (pspace_aligned' and pspace_distinct') (get_cap cte_ptr) (getSlotCap cte_ptr')" apply (simp add: getSlotCap_def mask_cap_def) apply (subst bind_return [symmetric]) apply (rule corres_guard_imp) apply (rule corres_split[OF get_cap_corres_P [where P=P]]) apply (insert cap_relation_masks, simp) apply (wp getCTE_wp')+ apply simp apply fastforce done lemma asUser_irq_handlers': "\valid_irq_handlers'\ asUser t f \\rv. valid_irq_handlers'\" apply (simp add: asUser_def split_def) apply (wpsimp wp: threadSet_irq_handlers' [OF all_tcbI, OF ball_tcb_cte_casesI] select_f_inv) done (* the brave can try to move this up to near setObject_update_TCB_corres' *) definition non_exst_same :: "Structures_H.tcb \ Structures_H.tcb \ bool" where "non_exst_same tcb tcb' \ \d p ts. tcb' = tcb\tcbDomain := d, tcbPriority := p, tcbTimeSlice := ts\" fun non_exst_same' :: "Structures_H.kernel_object \ Structures_H.kernel_object \ bool" where "non_exst_same' (KOTCB tcb) (KOTCB tcb') = non_exst_same tcb tcb'" | "non_exst_same' _ _ = True" lemma non_exst_same_prio_upd[simp]: "non_exst_same tcb (tcbPriority_update f tcb)" by (cases tcb, simp add: non_exst_same_def) lemma non_exst_same_timeSlice_upd[simp]: "non_exst_same tcb (tcbTimeSlice_update f tcb)" by (cases tcb, simp add: non_exst_same_def) lemma non_exst_same_domain_upd[simp]: "non_exst_same tcb (tcbDomain_update f tcb)" by (cases tcb, simp add: non_exst_same_def) lemma set_eobject_corres': assumes e: "etcb_relation etcb tcb'" assumes z: "\s. obj_at' P ptr s \ map_to_ctes ((ksPSpace s) (ptr \ KOTCB tcb')) = map_to_ctes (ksPSpace s)" shows "corres dc (tcb_at ptr and is_etcb_at ptr) (obj_at' (\ko. non_exst_same ko tcb') ptr and obj_at' P ptr) (set_eobject ptr etcb) (setObject ptr tcb')" apply (rule corres_no_failI) apply (rule no_fail_pre) apply wp apply (clarsimp simp: obj_at'_def) apply (unfold set_eobject_def setObject_def) apply (clarsimp simp: in_monad split_def bind_def gets_def get_def Bex_def put_def return_def modify_def get_object_def updateObject_default_def in_magnitude_check objBits_simps') apply (clarsimp simp add: state_relation_def z) apply (clarsimp simp add: obj_at_def is_etcb_at_def) apply (simp only: pspace_relation_def dom_fun_upd2 simp_thms) apply (elim conjE) apply (frule bspec, erule domI) apply (rule conjI) apply (rule ballI, drule(1) bspec) apply (drule domD) apply (clarsimp simp: is_other_obj_relation_type) apply (drule(1) bspec) apply (clarsimp simp: non_exst_same_def) apply (case_tac bb; simp) apply (clarsimp simp: obj_at'_def other_obj_relation_def cte_relation_def tcb_relation_def split: if_split_asm)+ apply (clarsimp simp: aobj_relation_cuts_def split: RISCV64_A.arch_kernel_obj.splits) apply (rename_tac arch_kernel_obj obj d p ts) apply (case_tac arch_kernel_obj; simp) apply (clarsimp simp: pte_relation_def is_tcb_def split: if_split_asm)+ apply (simp only: ekheap_relation_def dom_fun_upd2 simp_thms) apply (frule bspec, erule domI) apply (rule ballI, drule(1) bspec) apply (drule domD) apply (clarsimp simp: obj_at'_def) apply (insert e) apply (clarsimp simp: other_obj_relation_def etcb_relation_def is_other_obj_relation_type split: Structures_A.kernel_object.splits kernel_object.splits arch_kernel_obj.splits) done lemma set_eobject_corres: assumes tcbs: "non_exst_same tcb' tcbu'" assumes e: "etcb_relation etcb tcb' \ etcb_relation etcbu tcbu'" assumes tables': "\(getF, v) \ ran tcb_cte_cases. getF tcbu' = getF tcb'" assumes r: "r () ()" shows "corres r (tcb_at add and (\s. ekheap s add = Some etcb)) (ko_at' tcb' add) (set_eobject add etcbu) (setObject add tcbu')" apply (rule_tac F="non_exst_same tcb' tcbu' \ etcb_relation etcbu tcbu'" in corres_req) apply (clarsimp simp: state_relation_def obj_at_def obj_at'_def) apply (frule(1) pspace_relation_absD) apply (clarsimp simp: other_obj_relation_def ekheap_relation_def e tcbs) apply (drule bspec, erule domI) apply (clarsimp simp: e) apply (erule conjE) apply (rule corres_guard_imp) apply (rule corres_rel_imp) apply (rule set_eobject_corres'[where P="(=) tcb'"]) apply simp defer apply (simp add: r) apply (fastforce simp: is_etcb_at_def elim!: obj_at_weakenE) apply (subst(asm) eq_commute) apply (clarsimp simp: obj_at'_def) apply (clarsimp simp: obj_at'_def objBits_simps) apply (subst map_to_ctes_upd_tcb, assumption+) apply (simp add: ps_clear_def3 field_simps objBits_defs mask_def) apply (subst if_not_P) apply (fastforce dest: bspec [OF tables', OF ranI]) apply simp done lemma ethread_set_corresT: assumes x: "\tcb'. non_exst_same tcb' (f' tcb')" assumes z: "\tcb. \(getF, setF) \ ran tcb_cte_cases. getF (f' tcb) = getF tcb" assumes e: "\etcb tcb'. etcb_relation etcb tcb' \ etcb_relation (f etcb) (f' tcb')" shows "corres dc (tcb_at t and valid_etcbs) (tcb_at' t) (ethread_set f t) (threadSet f' t)" apply (simp add: ethread_set_def threadSet_def bind_assoc) apply (rule corres_guard_imp) apply (rule corres_split[OF corres_get_etcb set_eobject_corres]) apply (rule x) apply (erule e) apply (simp add: z)+ apply wp+ apply clarsimp apply (simp add: valid_etcbs_def tcb_at_st_tcb_at[symmetric]) apply (force simp: tcb_at_def get_etcb_def obj_at_def) apply simp done lemmas ethread_set_corres = ethread_set_corresT [OF _ all_tcbI, OF _ ball_tcb_cte_casesI] lemma archTcbUpdate_aux2: "(\tcb. tcb\ tcbArch := f (tcbArch tcb)\) = tcbArch_update f" by (rule ext, case_tac tcb, simp) end end