(* * Copyright 2022, Proofcraft Pty Ltd * Copyright 2014, General Dynamics C4 Systems * * SPDX-License-Identifier: GPL-2.0-only *) (* Contains proofs that fastpath + callKernel is semantically identical to callKernel. *) theory Fastpath_Equiv imports Fastpath_Defs IsolatedThreadAction Refine.RAB_FN begin lemma setCTE_obj_at'_queued: "\obj_at' (\tcb. P (tcbQueued tcb)) t\ setCTE p v \\rv. obj_at' (\tcb. P (tcbQueued tcb)) t\" unfolding setCTE_def by (rule setObject_cte_obj_at_tcb', simp+) crunch obj_at'_queued: cteInsert "obj_at' (\tcb. P (tcbQueued tcb)) t" (wp: setCTE_obj_at'_queued crunch_wps) crunch obj_at'_not_queued: emptySlot "obj_at' (\a. \ tcbQueued a) p" (wp: setCTE_obj_at'_queued) lemma getEndpoint_obj_at': "\obj_at' P ptr\ getEndpoint ptr \\rv s. P rv\" apply (wp getEndpoint_wp) apply (clarsimp simp: obj_at'_def projectKOs) done lemmas setEndpoint_obj_at_tcb' = setEndpoint_obj_at'_tcb lemma tcbSchedEnqueue_tcbContext[wp]: "\obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\ tcbSchedEnqueue t' \\rv. obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\" apply (rule tcbSchedEnqueue_obj_at_unchangedT[OF all_tcbI]) apply simp done lemma setCTE_tcbContext: "\obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\ setCTE slot cte \\rv. obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\" apply (simp add: setCTE_def) apply (rule setObject_cte_obj_at_tcb', simp_all) done context begin interpretation Arch . (*FIXME: arch_split*) lemma seThreadState_tcbContext: "\obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\ setThreadState a b \\_. obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\" apply (rule setThreadState_obj_at_unchanged) apply (clarsimp simp: atcbContext_def)+ done lemma setBoundNotification_tcbContext: "\obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\ setBoundNotification a b \\_. obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t\" apply (rule setBoundNotification_obj_at_unchanged) apply (clarsimp simp: atcbContext_def)+ done declare comp_apply [simp del] crunch tcbContext[wp]: deleteCallerCap "obj_at' (\tcb. P ((atcbContextGet o tcbArch) tcb)) t" (wp: setEndpoint_obj_at_tcb' setBoundNotification_tcbContext setNotification_tcb crunch_wps seThreadState_tcbContext simp: crunch_simps unless_def) declare comp_apply [simp] crunch ksArch[wp]: asUser "\s. P (ksArchState s)" (wp: crunch_wps) definition tcbs_of :: "kernel_state => word32 => tcb option" where "tcbs_of s = (%x. if tcb_at' x s then projectKO_opt (the (ksPSpace s x)) else None)" lemma obj_at_tcbs_of: "obj_at' P t s = (EX tcb. tcbs_of s t = Some tcb & P tcb)" apply (simp add: tcbs_of_def split: if_split) apply (intro conjI impI) apply (clarsimp simp: obj_at'_def projectKOs) apply (clarsimp simp: obj_at'_weakenE[OF _ TrueI]) done lemma st_tcb_at_tcbs_of: "st_tcb_at' P t s = (EX tcb. tcbs_of s t = Some tcb & P (tcbState tcb))" by (simp add: st_tcb_at'_def obj_at_tcbs_of) lemma tcbs_of_ko_at': "\ tcbs_of s p = Some tcb \ \ ko_at' tcb p s" by (simp add: obj_at_tcbs_of) lemma tcbs_of_valid_tcb': "\ valid_objs' s; tcbs_of s p = Some tcb \ \ valid_tcb' tcb s" by (frule tcbs_of_ko_at') (drule (1) ko_at_valid_objs', auto simp: projectKOs valid_obj'_def) lemma acc_CNodeCap_repr: "isCNodeCap cap \ cap = CNodeCap (capCNodePtr cap) (capCNodeBits cap) (capCNodeGuard cap) (capCNodeGuardSize cap)" by (clarsimp simp: isCap_simps) lemma valid_cnode_cap_cte_at': "\ s \' c; isCNodeCap c; ptr = capCNodePtr c; v < 2 ^ capCNodeBits c \ \ cte_at' (ptr + v * 2^cteSizeBits) s" apply (drule less_mask_eq) apply (drule(1) valid_cap_cte_at'[where addr=v]) apply (simp add: mult.commute mult.left_commute) done lemmas valid_cnode_cap_cte_at'' = valid_cnode_cap_cte_at'[simplified objBits_defs, simplified] declare of_int_sint_scast[simp] lemma of_bl_from_bool: "of_bl [x] = from_bool x" by (cases x, simp_all add: from_bool_def) lemma dmo_clearExMonitor_setCurThread_swap: "(do _ \ doMachineOp ARM.clearExMonitor; setCurThread thread od) = (do _ \ setCurThread thread; doMachineOp ARM.clearExMonitor od)" apply (simp add: setCurThread_def doMachineOp_def split_def) apply (rule oblivious_modify_swap[symmetric]) apply (intro oblivious_bind, simp_all) done lemma pd_at_asid_inj': "pd_at_asid' pd asid s \ pd_at_asid' pd' asid s \ pd' = pd" by (clarsimp simp: pd_at_asid'_def obj_at'_def) lemma bind_case_sum_rethrow: "rethrowFailure fl f >>= case_sum e g = f >>= case_sum (e \ fl) g" apply (simp add: rethrowFailure_def handleE'_def bind_assoc) apply (rule bind_cong[OF refl]) apply (simp add: throwError_bind split: sum.split) done declare empty_fail_assertE[iff] declare empty_fail_resolveAddressBits[iff] lemma lookupExtraCaps_null: "msgExtraCaps info = 0 \ lookupExtraCaps thread buffer info = returnOk []" by (clarsimp simp: lookupExtraCaps_def getExtraCPtrs_def liftE_bindE upto_enum_step_def mapM_Nil split: Types_H.message_info.split option.split) lemma isRecvEP_endpoint_case: "isRecvEP ep \ case_endpoint f g h ep = f (epQueue ep)" by (clarsimp simp: isRecvEP_def split: endpoint.split_asm) lemma unifyFailure_catch_If: "catch (unifyFailure f >>=E g) h = f >>= (\rv. if isRight rv then catch (g (theRight rv)) h else h ())" apply (simp add: unifyFailure_def rethrowFailure_def handleE'_def catch_def bind_assoc bind_bindE_assoc cong: if_cong) apply (rule bind_cong[OF refl]) apply (simp add: throwError_bind isRight_def return_returnOk split: sum.split) done lemma st_tcb_at_not_in_ep_queue: "\ st_tcb_at' P t s; ko_at' ep epptr s; sym_refs (state_refs_of' s); ep \ IdleEP; \ts. P ts \ tcb_st_refs_of' ts = {} \ \ t \ set (epQueue ep)" apply clarsimp apply (drule(1) sym_refs_ko_atD') apply (cases ep, simp_all add: st_tcb_at_refs_of_rev') apply (fastforce simp: st_tcb_at'_def obj_at'_def projectKOs)+ done lemma st_tcb_at_not_in_ntfn_queue: "\ st_tcb_at' P t s; ko_at' ntfn ntfnptr s; sym_refs (state_refs_of' s); ntfnObj ntfn = WaitingNtfn xs; \ts. P ts \ (ntfnptr, TCBSignal) \ tcb_st_refs_of' ts \ \ t \ set xs" apply (drule(1) sym_refs_ko_atD') apply (clarsimp simp: st_tcb_at_refs_of_rev') apply (drule_tac x="(t, NTFNSignal)" in bspec, simp) apply (fastforce simp: st_tcb_at'_def obj_at'_def projectKOs ko_wp_at'_def tcb_bound_refs'_def) done lemma sym_refs_upd_sD: "\ sym_refs ((state_refs_of' s) (p := S)); valid_pspace' s; ko_at' ko p s; refs_of' (injectKO koEx) = S; objBits koEx = objBits ko \ \ \s'. sym_refs (state_refs_of' s') \ (\p' (ko' :: endpoint). ko_at' ko' p' s \ injectKO ko' \ injectKO ko \ ko_at' ko' p' s') \ (\p' (ko' :: Structures_H.notification). ko_at' ko' p' s \ injectKO ko' \ injectKO ko \ ko_at' ko' p' s') \ (ko_at' koEx p s')" apply (rule exI, rule conjI) apply (rule state_refs_of'_upd[where ko'="injectKO koEx" and ptr=p and s=s, THEN ssubst[where P=sym_refs], rotated 2]) apply simp+ apply (clarsimp simp: obj_at'_def ko_wp_at'_def projectKOs) apply (clarsimp simp: project_inject objBits_def) apply (clarsimp simp: obj_at'_def ps_clear_upd projectKOs split: if_split) apply (clarsimp simp: project_inject objBits_def) apply auto done lemma sym_refs_upd_tcb_sD: "\ sym_refs ((state_refs_of' s) (p := {r \ state_refs_of' s p. snd r = TCBBound})); valid_pspace' s; ko_at' (tcb :: tcb) p s \ \ \s'. sym_refs (state_refs_of' s') \ (\p' (ko' :: endpoint). ko_at' ko' p' s \ ko_at' ko' p' s') \ (\p' (ko' :: Structures_H.notification). ko_at' ko' p' s \ ko_at' ko' p' s') \ (st_tcb_at' ((=) Running) p s')" apply (drule(2) sym_refs_upd_sD[where koEx="makeObject\tcbState := Running, tcbBoundNotification := tcbBoundNotification tcb\"]) apply (clarsimp dest!: ko_at_state_refs_ofD') apply (simp add: objBits_simps) apply (erule exEI) apply clarsimp apply (auto simp: st_tcb_at'_def elim!: obj_at'_weakenE) done lemma updateCap_cte_wp_at_cteMDBNode: "\cte_wp_at' (\cte. P (cteMDBNode cte)) p\ updateCap ptr cap \\rv. cte_wp_at' (\cte. P (cteMDBNode cte)) p\" apply (wp updateCap_cte_wp_at_cases) apply (simp add: o_def) done lemma ctes_of_Some_cte_wp_at: "ctes_of s p = Some cte \ cte_wp_at' P p s = P cte" by (clarsimp simp: cte_wp_at_ctes_of) lemma user_getreg_wp: "\\s. tcb_at' t s \ (\rv. obj_at' (\tcb. (atcbContextGet o tcbArch) tcb r = rv) t s \ Q rv s)\ asUser t (getRegister r) \Q\" apply (rule_tac Q="\rv s. \rv'. rv' = rv \ Q rv' s" in hoare_post_imp) apply simp apply (rule hoare_pre, wp hoare_vcg_ex_lift user_getreg_rv) apply (clarsimp simp: obj_at'_def) done lemma setUntypedCapAsFull_replyCap[simp]: "setUntypedCapAsFull cap (ReplyCap curThread False cg) slot = return ()" by (clarsimp simp:setUntypedCapAsFull_def isCap_simps) lemma option_case_liftM_getNotification_wp: "\\s. \rv. (case x of None \ rv = v | Some p \ obj_at' (\ntfn. f ntfn = rv) p s) \ Q rv s\ case x of None \ return v | Some ptr \ liftM f $ getNotification ptr \ Q \" apply (rule hoare_pre, (wpc; wp getNotification_wp)) apply (auto simp: obj_at'_def) done lemma threadSet_st_tcb_at_state: "\\s. tcb_at' t s \ (if p = t then obj_at' (\tcb. P (tcbState (f tcb))) t s else st_tcb_at' P p s)\ threadSet f t \\_. st_tcb_at' P p\" apply (rule hoare_chain) apply (rule threadSet_obj_at'_really_strongest) prefer 2 apply (simp add: st_tcb_at'_def) apply (clarsimp split: if_splits simp: st_tcb_at'_def o_def) done lemma recv_ep_queued_st_tcb_at': "\ ko_at' (Structures_H.endpoint.RecvEP ts) epptr s ; t \ set ts; sym_refs (state_refs_of' s) \ \ st_tcb_at' isBlockedOnReceive t s" apply (drule obj_at_ko_at') apply clarsimp apply (drule (1) sym_refs_ko_atD') apply (clarsimp simp: pred_tcb_at'_def obj_at'_real_def refs_of_rev') apply (erule_tac x=t in ballE; clarsimp?) apply (erule ko_wp_at'_weakenE) apply (clarsimp simp: isBlockedOnReceive_def projectKOs) done lemma valid_ep_typ_at_lift': "\ \p. \typ_at' TCBT p\ f \\rv. typ_at' TCBT p\ \ \ \\s. valid_ep' ep s\ f \\rv s. valid_ep' ep s\" apply (cases ep, simp_all add: valid_ep'_def) apply (wp hoare_vcg_const_Ball_lift typ_at_lifts | assumption)+ done lemma threadSet_tcbState_valid_objs: "\valid_tcb_state' st and valid_objs'\ threadSet (tcbState_update (\_. st)) t \\rv. valid_objs'\" apply (wp threadSet_valid_objs') apply (clarsimp simp: valid_tcb'_def tcb_cte_cases_def) done lemma possibleSwitchTo_rewrite: "monadic_rewrite True True (\s. obj_at' (\tcb. tcbPriority tcb = destPrio \ tcbDomain tcb = destDom) t s \ ksSchedulerAction s = ResumeCurrentThread \ ksCurThread s = thread \ ksCurDomain s = curDom \ destDom = curDom) (possibleSwitchTo t) (setSchedulerAction (SwitchToThread t))" supply if_split[split del] apply (simp add: possibleSwitchTo_def) (* under current preconditions both branch conditions are false *) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp wp: threadGet_wp cd_wp\) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp wp: threadGet_wp cd_wp\) (* discard unused getters before setSchedulerAction *) apply (simp add: getCurThread_def curDomain_def gets_bind_ign getSchedulerAction_def) apply (monadic_rewrite_symb_exec_l_drop, rule monadic_rewrite_refl) apply (auto simp: obj_at'_def) done lemma scheduleSwitchThreadFastfail_False_wp: "\\s. ct \ it \ cprio \ tprio \ scheduleSwitchThreadFastfail ct it cprio tprio \\rv s. \ rv \" unfolding scheduleSwitchThreadFastfail_def by (wp threadGet_wp) (auto dest!: obj_at_ko_at' simp: le_def obj_at'_def) lemma lookupBitmapPriority_lift: assumes prqL1: "\P. \\s. P (ksReadyQueuesL1Bitmap s)\ f \\_ s. P (ksReadyQueuesL1Bitmap s)\" and prqL2: "\P. \\s. P (ksReadyQueuesL2Bitmap s)\ f \\_ s. P (ksReadyQueuesL2Bitmap s)\" shows "\\s. P (lookupBitmapPriority d s) \ f \\_ s. P (lookupBitmapPriority d s) \" unfolding lookupBitmapPriority_def apply (rule hoare_pre) apply (wps prqL1 prqL2) apply wpsimp+ done (* slow path additionally requires current thread not idle *) definition "fastpathBestSwitchCandidate t \ \s. ksReadyQueuesL1Bitmap s (ksCurDomain s) = 0 \ (\tprio. obj_at' (\tcb. tcbPriority tcb = tprio) t s \ (obj_at' (\tcb. tcbPriority tcb \ tprio) (ksCurThread s) s \ lookupBitmapPriority (ksCurDomain s) s \ tprio))" lemma fastpathBestSwitchCandidateI: "\ ksReadyQueuesL1Bitmap s (ksCurDomain s) = 0 \ tcbPriority ctcb \ tcbPriority ttcb \ lookupBitmapPriority (ksCurDomain s) s \ tcbPriority ttcb; ko_at' ttcb t s; ko_at' ctcb (ksCurThread s) s\ \ fastpathBestSwitchCandidate t s" unfolding fastpathBestSwitchCandidate_def by normalise_obj_at' lemma fastpathBestSwitchCandidate_lift: assumes ct[wp]: "\P. \\s. P (ksCurThread s) \ f \ \_ s. P (ksCurThread s) \" assumes cd[wp]: "\P. \\s. P (ksCurDomain s) \ f \ \_ s. P (ksCurDomain s) \" assumes l1[wp]: "\P. \\s. P (ksReadyQueuesL1Bitmap s) \ f \ \_ s. P (ksReadyQueuesL1Bitmap s) \" assumes l2[wp]: "\P. \\s. P (ksReadyQueuesL2Bitmap s) \ f \ \_ s. P (ksReadyQueuesL2Bitmap s) \" assumes p[wp]: "\P t. \ obj_at' (\tcb. P (tcbPriority tcb)) t \ f \ \_. obj_at' (\tcb. P (tcbPriority tcb)) t \" shows "\ tcb_at' t and fastpathBestSwitchCandidate t \ f \\rv. fastpathBestSwitchCandidate t \" unfolding fastpathBestSwitchCandidate_def lookupBitmapPriority_def l1IndexToPrio_def apply (rule hoare_pre) apply (rule hoare_lift_Pf2[where f=ksCurDomain]) apply (wp hoare_vcg_disj_lift hoare_vcg_all_lift) apply (rule hoare_lift_Pf2[where f=ksCurThread]) apply (rule hoare_lift_Pf2[where f=ksReadyQueuesL1Bitmap]) apply (rule hoare_lift_Pf2[where f=ksReadyQueuesL2Bitmap]) apply (wp hoare_vcg_imp_lift') apply (strengthen not_obj_at'_strengthen) apply (wpsimp simp: comp_def wp: l1 l2 hoare_vcg_disj_lift)+ apply (drule (1) tcb_at_not_obj_at_elim'[rotated]) apply (rename_tac tprio, erule_tac x=tprio in allE) apply clarsimp apply (drule (1) tcb_at_not_obj_at_elim'[rotated]) apply (clarsimp simp: obj_at'_def) done lemma fastpathBestSwitchCandidate_ksSchedulerAction_simp[simp]: "fastpathBestSwitchCandidate t (s\ksSchedulerAction := a\) = fastpathBestSwitchCandidate t s" unfolding fastpathBestSwitchCandidate_def lookupBitmapPriority_def by simp lemma sched_act_SwitchToThread_rewrite: "\ sa = SwitchToThread t \ monadic_rewrite F E Q (m_sw t) f \ \ monadic_rewrite F E ((\_. sa = SwitchToThread t) and Q) (case_scheduler_action m_res m_ch (\t. m_sw t) sa) f" apply (cases sa; simp add: monadic_rewrite_impossible) apply (rename_tac t') apply (case_tac "t' = t"; simp add: monadic_rewrite_impossible) done lemma schedule_rewrite_ct_not_runnable': "monadic_rewrite True True (\s. ksSchedulerAction s = SwitchToThread t \ ct_in_state' (Not \ runnable') s \ (ksCurThread s \ ksIdleThread s) \ fastpathBestSwitchCandidate t s) (schedule) (do setSchedulerAction ResumeCurrentThread; switchToThread t od)" supply subst_all [simp del] apply (simp add: schedule_def) (* switching to t *) apply (monadic_rewrite_l sched_act_SwitchToThread_rewrite[where t=t]) (* not wasRunnable, skip enqueue *) apply (simp add: when_def) apply (monadic_rewrite_l monadic_rewrite_if_l_False) (* fastpath: \ (fastfail \ \ highest) *) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp simp: isHighestPrio_def' wp: hoare_vcg_imp_lift hoare_vcg_disj_lift threadGet_wp'' scheduleSwitchThreadFastfail_False_wp\) (* fastpath: no scheduleChooseNewThread *) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp simp: isHighestPrio_def' wp: hoare_vcg_imp_lift hoare_vcg_disj_lift threadGet_wp'' scheduleSwitchThreadFastfail_False_wp\) (* remove no-ops *) apply (repeat 10 monadic_rewrite_symb_exec_l) (* until switchToThread *) apply (simp add: setSchedulerAction_def) apply (subst oblivious_modify_swap[symmetric], rule oblivious_switchToThread_schact) apply (rule monadic_rewrite_refl) apply (wpsimp wp: empty_fail_isRunnable simp: isHighestPrio_def')+ apply (clarsimp simp: ct_in_state'_def not_pred_tcb_at'_strengthen fastpathBestSwitchCandidate_def) apply normalise_obj_at' done lemma resolveAddressBits_points_somewhere: "\\s. \slot. Q slot s\ resolveAddressBits cp cptr bits \Q\,-" apply (rule_tac Q'="\rv s. \rv. Q rv s" in hoare_post_imp_R) apply wp apply clarsimp done lemma foldr_copy_register_tsrs: "foldr (\r . copy_register_tsrs x y r r (\x. x)) rs s = (s (y := TCBStateRegs (tsrState (s y)) (\r. if r \ set rs then tsrContext (s x) r else tsrContext (s y) r)))" apply (induct rs) apply simp apply (simp add: copy_register_tsrs_def fun_eq_iff split: if_split) done lemmas cteInsert_obj_at'_not_queued = cteInsert_obj_at'_queued[of "\a. \ a"] lemma monadic_rewrite_threadGet: "monadic_rewrite E F (obj_at' (\tcb. f tcb = v) t) (threadGet f t) (return v)" unfolding getThreadState_def threadGet_def apply (simp add: liftM_def) apply monadic_rewrite_symb_exec_l apply (rule_tac P="\_. f x = v" in monadic_rewrite_pre_imp_eq) apply blast apply (wpsimp wp: OMG_getObject_tcb simp: obj_tcb_at')+ done lemma monadic_rewrite_getThreadState: "monadic_rewrite E F (obj_at' (\tcb. tcbState tcb = v) t) (getThreadState t) (return v)" unfolding getThreadState_def by (rule monadic_rewrite_threadGet) lemma setCTE_obj_at'_tcbIPCBuffer: "\obj_at' (\tcb. P (tcbIPCBuffer tcb)) t\ setCTE p v \\rv. obj_at' (\tcb. P (tcbIPCBuffer tcb)) t\" unfolding setCTE_def by (rule setObject_cte_obj_at_tcb', simp+) context notes if_cong[cong] begin crunches cteInsert, asUser for obj_at'_tcbIPCBuffer[wp]: "obj_at' (\tcb. P (tcbIPCBuffer tcb)) t" (wp: setCTE_obj_at'_queued crunch_wps threadSet_obj_at'_really_strongest) end crunches cteInsert, threadSet, asUser, emptySlot for ksReadyQueuesL1Bitmap_inv[wp]: "\s. P (ksReadyQueuesL1Bitmap s)" and ksReadyQueuesL2Bitmap_inv[wp]: "\s. P (ksReadyQueuesL2Bitmap s)" (wp: hoare_drop_imps) crunch ksReadyQueuesL1Bitmap_inv[wp]: setEndpoint "\s. P (ksReadyQueuesL1Bitmap s)" (wp: setObject_ksPSpace_only updateObject_default_inv) crunch ksReadyQueuesL2Bitmap_inv[wp]: setEndpoint "\s. P (ksReadyQueuesL2Bitmap s)" (wp: setObject_ksPSpace_only updateObject_default_inv) lemma setThreadState_runnable_bitmap_inv: "runnable' ts \ \ \s. P (ksReadyQueuesL1Bitmap s) \ setThreadState ts t \\rv s. P (ksReadyQueuesL1Bitmap s) \" "runnable' ts \ \ \s. Q (ksReadyQueuesL2Bitmap s) \ setThreadState ts t \\rv s. Q (ksReadyQueuesL2Bitmap s) \" by (simp_all add: setThreadState_runnable_simp, wp+) (* FIXME move *) crunches curDomain for (no_fail) no_fail[intro!, wp, simp] lemma fastpath_callKernel_SysCall_corres: "monadic_rewrite True False (invs' and ct_in_state' ((=) Running) and (\s. ksSchedulerAction s = ResumeCurrentThread) and (\s. ksDomainTime s \ 0)) (callKernel (SyscallEvent SysCall)) (fastpaths SysCall)" supply if_cong[cong] option.case_cong[cong] if_split[split del] supply empty_fail_getMRs[wp] (* FIXME *) supply empty_fail_getEndpoint[wp] (* FIXME *) apply (rule monadic_rewrite_introduce_alternative[OF callKernel_def[simplified atomize_eq]]) apply (rule monadic_rewrite_guard_imp) apply (simp add: handleEvent_def handleCall_def handleInvocation_def liftE_bindE_handle bind_assoc getMessageInfo_def) apply (simp add: catch_liftE_bindE unlessE_throw_catch_If unifyFailure_catch_If catch_liftE getMessageInfo_def alternative_bind fastpaths_def cong: if_cong) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply (rename_tac msgInfo) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply monadic_rewrite_symb_exec_r apply (rename_tac tcbFault) apply (rule monadic_rewrite_alternative_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: split_def Syscall_H.syscall_def liftE_bindE_handle bind_assoc capFaultOnFailure_def) apply (simp only: bindE_bind_linearise[where f="rethrowFailure fn f'" for fn f'] bind_case_sum_rethrow) apply (simp add: lookupCapAndSlot_def lookupSlotForThread_def bindE_assoc liftE_bind_return_bindE_returnOk split_def getThreadCSpaceRoot_def locateSlot_conv returnOk_liftE[symmetric] const_def getSlotCap_def) apply (simp only: liftE_bindE_assoc) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_bind_alternative_l) apply (wp | simp)+ apply (rule_tac fn="case_sum Inl (Inr \ fst)" in monadic_rewrite_split_fn) apply (simp add: liftME_liftM[symmetric] liftME_def bindE_assoc) apply (rule monadic_rewrite_refl) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: isRight_right_map isRight_case_sum) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_bind_alternative_l[OF lookupIPC_inv]) apply monadic_rewrite_symb_exec_l apply (simp add: lookupExtraCaps_null returnOk_bind liftE_bindE_handle bind_assoc liftE_bindE_assoc decodeInvocation_def Let_def from_bool_0 performInvocation_def liftE_handle liftE_bind) apply monadic_rewrite_symb_exec_r apply (rename_tac "send_ep") apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: getThreadVSpaceRoot_def locateSlot_conv) apply monadic_rewrite_symb_exec_r apply (rename_tac "pdCapCTE") apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply monadic_rewrite_symb_exec_r apply monadic_rewrite_symb_exec_r apply (simp add: isHighestPrio_def') apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_trans, rule monadic_rewrite_pick_alternative_1) apply monadic_rewrite_symb_exec_l (* now committed to fastpath *) apply (rule monadic_rewrite_trans) apply (rule_tac F=True and E=True in monadic_rewrite_weaken_flags) apply simp apply (rule monadic_rewrite_bind_tail) apply (monadic_rewrite_symb_exec_l_known thread) apply (simp add: sendIPC_def bind_assoc) apply (monadic_rewrite_symb_exec_l_known send_ep) apply (rule_tac P="epQueue send_ep \ []" in monadic_rewrite_gen_asm) apply (simp add: isRecvEP_endpoint_case list_case_helper bind_assoc) apply (rule monadic_rewrite_bind_tail) apply (elim conjE) apply (rule monadic_rewrite_bind_tail, rename_tac dest_st) apply (rule_tac P="\gr. dest_st = BlockedOnReceive (capEPPtr (fst (theRight rv))) gr" in monadic_rewrite_gen_asm) apply monadic_rewrite_symb_exec_l_drop apply (rule monadic_rewrite_bind) apply clarsimp apply (rule_tac msgInfo=msgInfo in doIPCTransfer_simple_rewrite) apply (rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_bind) apply (rule_tac destPrio=destPrio and curDom=curDom and destDom=destDom and thread=thread in possibleSwitchTo_rewrite) apply (rule monadic_rewrite_bind) apply (rule monadic_rewrite_trans) apply (rule setupCallerCap_rewrite) apply (rule monadic_rewrite_bind_head) apply (rule setThreadState_rewrite_simple, simp) apply (rule monadic_rewrite_trans) apply (monadic_rewrite_symb_exec_l_known BlockedOnReply) apply simp apply (rule monadic_rewrite_refl) apply wpsimp apply (rule monadic_rewrite_trans) apply (rule monadic_rewrite_bind_head) apply (rule_tac t="hd (epQueue send_ep)" in schedule_rewrite_ct_not_runnable') apply (simp add: bind_assoc) apply (rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_bind) apply (rule switchToThread_rewrite) apply (rule monadic_rewrite_bind) apply (rule activateThread_simple_rewrite) apply (rule monadic_rewrite_refl) apply wp apply (wp setCurThread_ct_in_state) apply (simp only: st_tcb_at'_def[symmetric]) apply (wp, clarsimp simp: cur_tcb'_def ct_in_state'_def) apply (simp add: getThreadCallerSlot_def getThreadReplySlot_def locateSlot_conv ct_in_state'_def cur_tcb'_def) apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply (wp fastpathBestSwitchCandidate_lift[where f="cteInsert c w w'" for c w w']) apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply (wp fastpathBestSwitchCandidate_lift[where f="threadSet f t" for f t]) apply simp apply ((wp assert_inv threadSet_pred_tcb_at_state cteInsert_obj_at'_not_queued | wps)+)[1] apply (simp add: setSchedulerAction_def) apply wp[1] apply (simp cong: if_cong HOL.conj_cong add: if_bool_simps) apply (simp_all only:)[5] apply ((wp setThreadState_oa_queued[of _ "\a _ _. \ a"] setThreadState_obj_at_unchanged asUser_obj_at_unchanged mapM_x_wp' sts_st_tcb_at'_cases setThreadState_no_sch_change setEndpoint_obj_at_tcb' fastpathBestSwitchCandidate_lift[where f="setThreadState f t" for f t] setThreadState_oa_queued fastpathBestSwitchCandidate_lift[where f="asUser t f" for f t] fastpathBestSwitchCandidate_lift[where f="setEndpoint a b" for a b] lookupBitmapPriority_lift setThreadState_runnable_bitmap_inv getEndpoint_obj_at' | simp add: setMessageInfo_def | wp (once) hoare_vcg_disj_lift)+) apply (simp add: setThreadState_runnable_simp getThreadCallerSlot_def getThreadReplySlot_def locateSlot_conv bind_assoc) apply (rule_tac P="\v. obj_at' (%tcb. tcbIPCBuffer tcb = v) (hd (epQueue send_ep))" in monadic_rewrite_exists_v) apply (rename_tac ipcBuffer) apply (rule_tac P="\v. obj_at' (\tcb. tcbState tcb = v) (hd (epQueue send_ep))" in monadic_rewrite_exists_v) apply (rename_tac destState) apply (simp add: ARM_H.switchToThread_def bind_assoc) (* retrieving state or thread registers is not thread_action_isolatable, translate into return with suitable precondition *) apply (rule monadic_rewrite_trans[OF _ monadic_rewrite_transverse]) apply (rule_tac v=destState in monadic_rewrite_getThreadState | rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp mapM_x_wp' getObject_inv | wpc | simp | wp (once) hoare_drop_imps)+ apply (rule_tac v=destState in monadic_rewrite_getThreadState | rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp mapM_x_wp' getObject_inv | wpc | simp | wp (once) hoare_drop_imps)+ apply (rule_tac P="inj (case_bool thread (hd (epQueue send_ep)))" in monadic_rewrite_gen_asm) apply (rule monadic_rewrite_trans[OF _ monadic_rewrite_transverse]) apply (rule monadic_rewrite_weaken_flags[where F=False and E=True], simp) apply (rule isolate_thread_actions_rewrite_bind fastpath_isolate_rewrites fastpath_isolatables bool.simps setRegister_simple setVMRoot_isolatable[THEN thread_actions_isolatableD] setVMRoot_isolatable doMachineOp_isolatable[THEN thread_actions_isolatableD] doMachineOp_isolatable kernelExitAssertions_isolatable[THEN thread_actions_isolatableD] kernelExitAssertions_isolatable zipWithM_setRegister_simple thread_actions_isolatable_bind | assumption | wp assert_inv)+ apply (rule_tac P="\s. ksSchedulerAction s = ResumeCurrentThread \ tcb_at' thread s" and F=True and E=False in monadic_rewrite_weaken_flags) apply simp apply (rule monadic_rewrite_isolate_final) apply (simp add: isRight_case_sum cong: list.case_cong) apply (clarsimp simp: fun_eq_iff if_flip cong: if_cong) apply (drule obj_at_ko_at', clarsimp) apply (frule get_tcb_state_regs_ko_at') apply (clarsimp simp: zip_map2 zip_same_conv_map foldl_map foldl_fun_upd foldr_copy_register_tsrs isRight_case_sum cong: if_cong) apply (simp add: upto_enum_def fromEnum_def enum_register toEnum_def msgRegisters_unfold cong: if_cong) apply (clarsimp split: if_split) apply (rule ext) apply (simp add: badgeRegister_def msgInfoRegister_def ARM.badgeRegister_def ARM.msgInfoRegister_def split: if_split) apply simp apply (wp | simp cong: if_cong bool.case_cong | rule getCTE_wp' gts_wp' threadGet_wp getEndpoint_wp)+ apply (rule validE_cases_valid) apply (simp add: isRight_def getSlotCap_def) apply (wp getCTE_wp') apply (rule resolveAddressBits_points_somewhere) apply (simp cong: if_cong bool.case_cong) apply wp apply simp apply (wp user_getreg_wp threadGet_wp)+ apply clarsimp apply (subgoal_tac "ksCurThread s \ ksIdleThread s") prefer 2 apply (fastforce simp: ct_in_state'_def dest: ct_running_not_idle' elim: pred_tcb'_weakenE) apply (clarsimp simp: ct_in_state'_def pred_tcb_at') apply (frule cte_wp_at_valid_objs_valid_cap', clarsimp+) apply (clarsimp simp: isCap_simps valid_cap'_def maskCapRights_def) apply (frule ko_at_valid_ep', clarsimp) apply (frule sym_refs_ko_atD'[where 'a=endpoint], clarsimp) apply (clarsimp simp: valid_ep'_def isRecvEP_endpoint_case neq_Nil_conv tcbVTableSlot_def cte_level_bits_def cte_at_tcb_at_16' length_msgRegisters size_msgRegisters_def order_less_imp_le ep_q_refs_of'_def st_tcb_at_refs_of_rev' cong: if_cong) apply (rename_tac blockedThread ys tcba tcbb) apply (frule invs_mdb') apply (thin_tac "Ball S P" for S P)+ supply imp_disjL[simp del] apply (subst imp_disjL[symmetric]) (* clean up broken up disj implication and excessive references to same tcbs *) apply normalise_obj_at' apply (clarsimp simp: invs'_def valid_state'_def) apply (fold imp_disjL, intro allI impI) apply (subgoal_tac "ksCurThread s \ blockedThread") prefer 2 apply normalise_obj_at' apply clarsimp apply (frule_tac t="blockedThread" in valid_queues_not_runnable_not_queued, assumption) subgoal by (fastforce simp: st_tcb_at'_def elim: obj_at'_weakenE) apply (subgoal_tac "fastpathBestSwitchCandidate blockedThread s") prefer 2 apply (rule_tac ttcb=tcbb and ctcb=tcb in fastpathBestSwitchCandidateI) apply (solves \simp only: disj_ac\) apply simp+ apply (clarsimp simp: st_tcb_at'_def obj_at'_def objBits_simps projectKOs valid_mdb'_def valid_mdb_ctes_def inj_case_bool split: bool.split)+ done lemma capability_case_Null_ReplyCap: "(case cap of NullCap \ f | ReplyCap t b cg \ g t b cg | _ \ h) = (if isReplyCap cap then g (capTCBPtr cap) (capReplyMaster cap) (capReplyCanGrant cap) else if isNullCap cap then f else h)" by (simp add: isCap_simps split: capability.split split del: if_split) lemma injection_handler_catch: "catch (injection_handler f x) y = catch x (y o f)" apply (simp add: injection_handler_def catch_def handleE'_def bind_assoc) apply (rule bind_cong[OF refl]) apply (simp add: throwError_bind split: sum.split) done lemma doReplyTransfer_simple: "monadic_rewrite True False (obj_at' (\tcb. tcbFault tcb = None) receiver) (doReplyTransfer sender receiver slot grant) (do state \ getThreadState receiver; assert (isReply state); cte \ getCTE slot; mdbnode \ return $ cteMDBNode cte; assert (mdbPrev mdbnode \ 0 \ mdbNext mdbnode = 0); parentCTE \ getCTE (mdbPrev mdbnode); assert (isReplyCap (cteCap parentCTE) \ capReplyMaster (cteCap parentCTE)); doIPCTransfer sender Nothing 0 grant receiver; cteDeleteOne slot; setThreadState Running receiver; possibleSwitchTo receiver od)" apply (simp add: doReplyTransfer_def liftM_def nullPointer_def getSlotCap_def) apply (rule monadic_rewrite_bind_tail)+ apply (monadic_rewrite_symb_exec_l_known None, simp) apply (rule monadic_rewrite_refl) apply (wpsimp wp: threadGet_const gts_wp' getCTE_wp' simp: o_def)+ done lemma receiveIPC_simple_rewrite: "monadic_rewrite True False ((\_. isEndpointCap ep_cap \ \ isSendEP ep) and (ko_at' ep (capEPPtr ep_cap) and (\s. \ntfnptr. bound_tcb_at' ((=) (Some ntfnptr)) thread s \ obj_at' (Not \ isActive) ntfnptr s))) (receiveIPC thread ep_cap True) (do setThreadState (BlockedOnReceive (capEPPtr ep_cap) (capEPCanGrant ep_cap)) thread; setEndpoint (capEPPtr ep_cap) (RecvEP (case ep of RecvEP q \ (q @ [thread]) | _ \ [thread])) od)" supply empty_fail_getEndpoint[wp] apply (rule monadic_rewrite_gen_asm) apply (simp add: receiveIPC_def) apply (monadic_rewrite_symb_exec_l_known ep) apply monadic_rewrite_symb_exec_l+ apply (monadic_rewrite_l monadic_rewrite_if_l_False) apply (rule monadic_rewrite_is_refl) apply (cases ep; simp add: isSendEP_def) apply (wpsimp wp: getNotification_wp gbn_wp' getEndpoint_wp simp: getBoundNotification_def)+ apply (clarsimp simp: obj_at'_def projectKOs pred_tcb_at'_def) done lemma empty_fail_isFinalCapability: "empty_fail (isFinalCapability cte)" by (simp add: isFinalCapability_def Let_def empty_fail_cond split: if_split) lemma cteDeleteOne_replycap_rewrite: "monadic_rewrite True False (cte_wp_at' (\cte. isReplyCap (cteCap cte)) slot) (cteDeleteOne slot) (emptySlot slot NullCap)" supply isFinalCapability_inv[wp] empty_fail_isFinalCapability[wp] (* FIXME *) apply (simp add: cteDeleteOne_def) apply (rule monadic_rewrite_symb_exec_l) apply (rule_tac P="cteCap cte \ NullCap \ isReplyCap (cteCap cte) \ \ isEndpointCap (cteCap cte) \ \ isNotificationCap (cteCap cte)" in monadic_rewrite_gen_asm) apply (simp add: finaliseCapTrue_standin_def capRemovable_def) apply monadic_rewrite_symb_exec_l apply (rule monadic_rewrite_refl) apply (wpsimp wp: getCTE_wp')+ apply (clarsimp simp: cte_wp_at_ctes_of isCap_simps) done lemma cteDeleteOne_nullcap_rewrite: "monadic_rewrite True False (cte_wp_at' (\cte. cteCap cte = NullCap) slot) (cteDeleteOne slot) (return ())" apply (simp add: cteDeleteOne_def unless_def when_def) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp wp: getCTE_wp'\) apply (monadic_rewrite_symb_exec_l, rule monadic_rewrite_refl) apply (wpsimp wp: getCTE_wp' simp: cte_wp_at_ctes_of)+ done lemma deleteCallerCap_nullcap_rewrite: "monadic_rewrite True False (cte_wp_at' (\cte. cteCap cte = NullCap) (thread + 2 ^ cte_level_bits * tcbCallerSlot)) (deleteCallerCap thread) (return ())" apply (simp add: deleteCallerCap_def getThreadCallerSlot_def locateSlot_conv getSlotCap_def) apply (monadic_rewrite_l cteDeleteOne_nullcap_rewrite \wpsimp wp: getCTE_wp\) apply (monadic_rewrite_symb_exec_l+, rule monadic_rewrite_refl) apply (wpsimp simp: cte_wp_at_ctes_of)+ done lemma emptySlot_cnode_caps: "\\s. P (only_cnode_caps (ctes_of s)) \ cte_wp_at' (\cte. \ isCNodeCap (cteCap cte)) slot s\ emptySlot slot NullCap \\rv s. P (only_cnode_caps (ctes_of s))\" apply (simp add: only_cnode_caps_def map_option_comp2 o_assoc[symmetric] cteCaps_of_def[symmetric]) apply (wp emptySlot_cteCaps_of) apply (clarsimp simp: cteCaps_of_def cte_wp_at_ctes_of elim!: rsubst[where P=P] del: ext intro!: ext split: if_split) done lemma asUser_obj_at_ep[wp]: "\obj_at' P p\ asUser t m \\rv. obj_at' (P :: endpoint \ bool) p\" apply (simp add: asUser_def split_def) apply (wp hoare_drop_imps | simp)+ done lemma setCTE_obj_at_ep[wp]: "\obj_at' (P :: endpoint \ bool) p\ setCTE ptr cte \\rv. obj_at' P p\" unfolding setCTE_def apply (rule obj_at_setObject2) apply (clarsimp simp: updateObject_cte typeError_def in_monad split: Structures_H.kernel_object.split_asm if_split_asm) done lemma setCTE_obj_at_ntfn[wp]: "\obj_at' (P :: Structures_H.notification \ bool) p\ setCTE ptr cte \\rv. obj_at' P p\" unfolding setCTE_def apply (rule obj_at_setObject2) apply (clarsimp simp: updateObject_cte typeError_def in_monad split: Structures_H.kernel_object.split_asm if_split_asm) done crunch obj_at_ep[wp]: emptySlot "obj_at' (P :: endpoint \ bool) p" crunches emptySlot, asUser for gsCNodes[wp]: "\s. P (gsCNodes s)" (wp: crunch_wps) crunch tcbContext[wp]: possibleSwitchTo "obj_at' (\tcb. P ( (atcbContextGet o tcbArch) tcb)) t" (wp: crunch_wps simp_del: comp_apply) crunch only_cnode_caps[wp]: doFaultTransfer "\s. P (only_cnode_caps (ctes_of s))" (wp: crunch_wps simp: crunch_simps) lemma tcbSchedDequeue_rewrite_not_queued: "monadic_rewrite True False (tcb_at' t and obj_at' (Not \ tcbQueued) t) (tcbSchedDequeue t) (return ())" apply (simp add: tcbSchedDequeue_def when_def) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wp threadGet_const\) apply (monadic_rewrite_symb_exec_l, rule monadic_rewrite_refl) apply wp+ apply clarsimp done lemma schedule_known_rewrite: "monadic_rewrite True False (\s. ksSchedulerAction s = SwitchToThread t \ tcb_at' t s \ obj_at' (Not \ tcbQueued) t s \ ksCurThread s = t' \ st_tcb_at' (Not \ runnable') t' s \ (ksCurThread s \ ksIdleThread s) \ fastpathBestSwitchCandidate t s) (schedule) (do Arch.switchToThread t; setCurThread t; setSchedulerAction ResumeCurrentThread od)" supply subst_all[simp del] if_split[split del] apply (simp add: schedule_def) apply (simp only: Thread_H.switchToThread_def) (* switching to t *) apply (monadic_rewrite_l sched_act_SwitchToThread_rewrite[where t=t]) (* not wasRunnable, skip enqueue *) apply (simp add: when_def) apply (monadic_rewrite_l monadic_rewrite_if_l_False) (* fastpath: \ (fastfail \ \ highest) *) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp simp: isHighestPrio_def' wp: hoare_vcg_imp_lift hoare_vcg_disj_lift threadGet_wp'' scheduleSwitchThreadFastfail_False_wp\) (* fastpath: no scheduleChooseNewThread *) apply (monadic_rewrite_l monadic_rewrite_if_l_False \wpsimp simp: isHighestPrio_def' wp: hoare_vcg_imp_lift hoare_vcg_disj_lift threadGet_wp'' scheduleSwitchThreadFastfail_False_wp\) apply (simp add: bind_assoc) apply (monadic_rewrite_l tcbSchedDequeue_rewrite_not_queued \wpsimp wp: Arch_switchToThread_obj_at_pre\) (* remove no-ops *) apply simp apply (repeat 9 \rule monadic_rewrite_symb_exec_l\) (* until switchToThread *) apply (rule monadic_rewrite_refl) apply (wpsimp simp: isHighestPrio_def')+ apply (clarsimp simp: ct_in_state'_def not_pred_tcb_at'_strengthen fastpathBestSwitchCandidate_def) apply normalise_obj_at' done lemma tcb_at_cte_at_offset: "\ tcb_at' t s; 2 ^ cte_level_bits * off \ dom tcb_cte_cases \ \ cte_at' (t + 2 ^ cte_level_bits * off) s" apply (clarsimp simp: obj_at'_def projectKOs objBits_simps) apply (erule(2) cte_wp_at_tcbI') apply fastforce apply simp done lemma emptySlot_cte_wp_at_cteCap: "\\s. (p = p' \ P NullCap) \ (p \ p' \ cte_wp_at' (\cte. P (cteCap cte)) p s)\ emptySlot p' irqopt \\rv s. cte_wp_at' (\cte. P (cteCap cte)) p s\" apply (simp add: tree_cte_cteCap_eq[unfolded o_def]) apply (wp emptySlot_cteCaps_of) apply (clarsimp split: if_split) done lemma setEndpoint_getCTE_pivot[unfolded K_bind_def]: "do setEndpoint p val; v <- getCTE slot; f v od = do v <- getCTE slot; setEndpoint p val; f v od" apply (simp add: getCTE_assert_opt setEndpoint_def setObject_modify_assert fun_eq_iff bind_assoc) apply (simp add: exec_gets assert_def assert_opt_def exec_modify update_ep_map_to_ctes split: if_split option.split) done lemma setEndpoint_setCTE_pivot[unfolded K_bind_def]: "do setEndpoint p val; setCTE slot cte; f od = do setCTE slot cte; setEndpoint p val; f od" supply if_split[split del] apply (rule monadic_rewrite_to_eq) apply simp apply (rule monadic_rewrite_guard_imp) apply (rule monadic_rewrite_trans, rule_tac f="ep_at' p" in monadic_rewrite_add_gets) apply (rule monadic_rewrite_transverse, rule monadic_rewrite_add_gets, rule monadic_rewrite_bind_tail) apply (rename_tac epat) apply (rule monadic_rewrite_transverse) apply (rule monadic_rewrite_bind_tail) apply (simp add: setEndpoint_def setObject_modify_assert bind_assoc) apply (rule_tac rv=epat in monadic_rewrite_gets_known) apply (wp setCTE_typ_at'[where T="koType TYPE(endpoint)", unfolded typ_at_to_obj_at'] | simp)+ apply (simp add: setCTE_assert_modify bind_assoc) apply (rule monadic_rewrite_trans, rule monadic_rewrite_add_gets, rule monadic_rewrite_bind_tail)+ apply (rename_tac cteat tcbat) apply (rule monadic_rewrite_trans, rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_trans) apply (rule_tac rv=cteat in monadic_rewrite_gets_known) apply (rule_tac rv=tcbat in monadic_rewrite_gets_known) apply (wp setEndpoint_typ_at'[where T="koType TYPE(tcb)", unfolded typ_at_to_obj_at'] setEndpoint_typ_at'[where T="koType TYPE(cte)", unfolded typ_at_to_obj_at'] | simp)+ apply (rule_tac P="\s. epat = ep_at' p s \ cteat = real_cte_at' slot s \ tcbat = (tcb_at' (slot && ~~ mask 9) and (%y. slot && mask 9 : dom tcb_cte_cases)) s" in monadic_rewrite_pre_imp_eq) apply (simp add: setEndpoint_def setObject_modify_assert bind_assoc exec_gets assert_def exec_modify split: if_split) apply (auto split: if_split simp: obj_at'_def projectKOs objBits_defs del: ext intro!: arg_cong[where f=f] ext kernel_state.fold_congs)[1] apply wp+ apply (simp add: objBits_defs) done lemma setEndpoint_updateMDB_pivot[unfolded K_bind_def]: "do setEndpoint p val; updateMDB slot mf; f od = do updateMDB slot mf; setEndpoint p val; f od" by (clarsimp simp: updateMDB_def bind_assoc setEndpoint_getCTE_pivot setEndpoint_setCTE_pivot split: if_split) lemma setEndpoint_updateCap_pivot[unfolded K_bind_def]: "do setEndpoint p val; updateCap slot mf; f od = do updateCap slot mf; setEndpoint p val; f od" by (clarsimp simp: updateCap_def bind_assoc setEndpoint_getCTE_pivot setEndpoint_setCTE_pivot) lemma modify_setEndpoint_pivot[unfolded K_bind_def]: "\ \ksf s. ksPSpace_update ksf (sf s) = sf (ksPSpace_update ksf s) \ \ (do modify sf; setEndpoint p val; f od) = (do setEndpoint p val; modify sf; f od)" apply (subgoal_tac "\s. ep_at' p (sf s) = ep_at' p s") apply (simp add: setEndpoint_def setObject_modify_assert bind_assoc fun_eq_iff exec_gets exec_modify assert_def split: if_split) apply atomize apply clarsimp apply (drule_tac x="\_. ksPSpace s" in spec) apply (drule_tac x="s" in spec) apply (drule_tac f="ksPSpace" in arg_cong) apply simp apply (metis obj_at'_pspaceI) done lemma setEndpoint_clearUntypedFreeIndex_pivot[unfolded K_bind_def]: "do setEndpoint p val; v <- clearUntypedFreeIndex slot; f od = do v <- clearUntypedFreeIndex slot; setEndpoint p val; f od" supply option.case_cong_weak[cong del] by (simp add: clearUntypedFreeIndex_def bind_assoc getSlotCap_def setEndpoint_getCTE_pivot updateTrackedFreeIndex_def modify_setEndpoint_pivot split: capability.split | rule bind_cong[OF refl] allI impI bind_apply_cong[OF refl])+ lemma emptySlot_setEndpoint_pivot[unfolded K_bind_def]: "(do emptySlot slot NullCap; setEndpoint p val; f od) = (do setEndpoint p val; emptySlot slot NullCap; f od)" apply (rule ext) apply (simp add: emptySlot_def bind_assoc setEndpoint_getCTE_pivot setEndpoint_updateCap_pivot setEndpoint_updateMDB_pivot case_Null_If Retype_H.postCapDeletion_def setEndpoint_clearUntypedFreeIndex_pivot split: if_split | rule bind_apply_cong[OF refl])+ done lemma set_getCTE[unfolded K_bind_def]: "do setCTE p cte; v <- getCTE p; f v od = do setCTE p cte; f cte od" apply (simp add: getCTE_assert_opt bind_assoc) apply (rule monadic_rewrite_to_eq) apply (rule monadic_rewrite_bind_tail) apply (monadic_rewrite_symb_exec_l) apply (monadic_rewrite_symb_exec_l_known cte, rule monadic_rewrite_refl) apply (wpsimp simp: assert_opt_def wp: gets_wp)+ done lemma set_setCTE[unfolded K_bind_def]: "do setCTE p val; setCTE p val' od = setCTE p val'" supply if_split[split del] apply simp apply (rule monadic_rewrite_to_eq) apply (rule monadic_rewrite_guard_imp) apply (rule monadic_rewrite_trans, rule_tac f="real_cte_at' p" in monadic_rewrite_add_gets) apply (rule monadic_rewrite_transverse, rule monadic_rewrite_add_gets, rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_trans, rule_tac f="tcb_at' (p && ~~ mask 9) and K (p && mask 9 \ dom tcb_cte_cases)" in monadic_rewrite_add_gets) apply (rule monadic_rewrite_transverse, rule monadic_rewrite_add_gets, rule monadic_rewrite_bind_tail) apply (rename_tac cteat tcbat) apply (rule monadic_rewrite_trans) apply (rule monadic_rewrite_bind_tail) apply (simp add: setCTE_assert_modify) apply (rule monadic_rewrite_trans, rule_tac rv=cteat in monadic_rewrite_gets_known) apply (rule_tac rv=tcbat in monadic_rewrite_gets_known) apply (wp setCTE_typ_at'[where T="koType TYPE(tcb)", unfolded typ_at_to_obj_at'] setCTE_typ_at'[where T="koType TYPE(cte)", unfolded typ_at_to_obj_at'] | simp)+ apply (simp add: setCTE_assert_modify bind_assoc) apply (rule monadic_rewrite_bind_tail)+ apply (rule_tac P="c = cteat \ t = tcbat \ (tcbat \ (\ getF setF. tcb_cte_cases (p && mask 9) = Some (getF, setF) \ (\ f g tcb. setF f (setF g tcb) = setF (f o g) tcb)))" in monadic_rewrite_gen_asm) apply (rule monadic_rewrite_is_refl[OF ext]) apply (simp add: exec_modify split: if_split) apply (auto simp: simpler_modify_def projectKO_opt_tcb objBits_defs del: ext intro!: kernel_state.fold_congs ext split: if_split)[1] apply wp+ apply (clarsimp simp: objBits_defs intro!: all_tcbI) apply (auto simp: tcb_cte_cases_def split: if_split_asm) done lemma setCTE_updateCapMDB: "p \ 0 \ setCTE p cte = do updateCap p (cteCap cte); updateMDB p (const (cteMDBNode cte)) od" supply if_split[split del] apply (simp add: updateCap_def updateMDB_def bind_assoc set_getCTE cte_overwrite set_setCTE) apply (simp add: getCTE_assert_opt setCTE_assert_modify bind_assoc) apply (rule ext, simp add: exec_gets assert_opt_def exec_modify split: if_split option.split) apply (cut_tac P=\ and p=p and s=x in cte_wp_at_ctes_of) apply (cases cte) apply (simp add: cte_wp_at_obj_cases') apply (auto simp: mask_out_sub_mask) done lemma clearUntypedFreeIndex_simple_rewrite: "monadic_rewrite True False (cte_wp_at' (Not o isUntypedCap o cteCap) slot) (clearUntypedFreeIndex slot) (return ())" apply (simp add: clearUntypedFreeIndex_def getSlotCap_def) apply (rule monadic_rewrite_name_pre) apply (clarsimp simp: cte_wp_at_ctes_of) apply (monadic_rewrite_symb_exec_l_known cte) apply (simp split: capability.split, strengthen monadic_rewrite_refl) apply (wpsimp wp: getCTE_wp' simp: cte_wp_at_ctes_of)+ done lemma emptySlot_replymaster_rewrite[OF refl]: "mdbn = cteMDBNode cte \ monadic_rewrite True False ((\_. mdbNext mdbn = 0 \ mdbPrev mdbn \ 0) and ((\_. cteCap cte \ NullCap) and (cte_wp_at' ((=) cte) slot and cte_wp_at' (\cte. isReplyCap (cteCap cte)) slot and cte_wp_at' (\cte. isReplyCap (cteCap cte) \ capReplyMaster (cteCap cte)) (mdbPrev mdbn) and (\s. reply_masters_rvk_fb (ctes_of s)) and (\s. no_0 (ctes_of s))))) (emptySlot slot NullCap) (do updateMDB (mdbPrev mdbn) (mdbNext_update (K 0) o mdbFirstBadged_update (K True) o mdbRevocable_update (K True)); setCTE slot makeObject od)" supply if_split[split del] apply (rule monadic_rewrite_gen_asm)+ apply (rule monadic_rewrite_guard_imp) apply (rule_tac P="slot \ 0" in monadic_rewrite_gen_asm) apply (clarsimp simp: emptySlot_def setCTE_updateCapMDB) apply (monadic_rewrite_l clearUntypedFreeIndex_simple_rewrite, simp) apply (monadic_rewrite_symb_exec_l_known cte) apply (simp add: updateMDB_def Let_def bind_assoc makeObject_cte case_Null_If) apply (rule monadic_rewrite_bind_tail) apply (rule monadic_rewrite_bind) apply (rule_tac P="mdbFirstBadged (cteMDBNode ctea) \ mdbRevocable (cteMDBNode ctea)" in monadic_rewrite_gen_asm) apply (rule monadic_rewrite_is_refl) apply (case_tac ctea, rename_tac mdbnode, case_tac mdbnode) apply simp apply (simp add: Retype_H.postCapDeletion_def) apply (rule monadic_rewrite_refl) apply (solves wp | wp getCTE_wp')+ apply (clarsimp simp: cte_wp_at_ctes_of reply_masters_rvk_fb_def) apply (fastforce simp: isCap_simps) done lemma all_prio_not_inQ_not_tcbQueued: "\ obj_at' (\a. (\d p. \ inQ d p a)) t s \ \ obj_at' (\a. \ tcbQueued a) t s" apply (clarsimp simp: obj_at'_def inQ_def) done crunches setThreadState, emptySlot, asUser for ntfn_obj_at[wp]: "obj_at' (P::(Structures_H.notification \ bool)) ntfnptr" (wp: obj_at_setObject2 crunch_wps simp: crunch_simps updateObject_default_def in_monad) lemma st_tcb_at_is_Reply_imp_not_tcbQueued: "\s t.\ invs' s; st_tcb_at' isReply t s\ \ obj_at' (\a. \ tcbQueued a) t s" apply (clarsimp simp: invs'_def valid_state'_def valid_queues_def st_tcb_at'_def valid_queues_no_bitmap_def) apply (rule all_prio_not_inQ_not_tcbQueued) apply (clarsimp simp: obj_at'_def) apply (erule_tac x="d" in allE) apply (erule_tac x="p" in allE) apply (erule conjE) apply (erule_tac x="t" in ballE) apply (clarsimp simp: obj_at'_def runnable'_def isReply_def) apply (case_tac "tcbState obj") apply ((clarsimp simp: inQ_def)+)[8] apply (clarsimp simp: valid_queues'_def obj_at'_def) done lemma valid_objs_ntfn_at_tcbBoundNotification: "ko_at' tcb t s \ valid_objs' s \ tcbBoundNotification tcb \ None \ ntfn_at' (the (tcbBoundNotification tcb)) s" apply (drule(1) ko_at_valid_objs', simp add: projectKOs) apply (simp add: valid_obj'_def valid_tcb'_def valid_bound_ntfn'_def) apply clarsimp done crunch bound_tcb_at'_Q[wp]: setThreadState "\s. Q (bound_tcb_at' P t s)" (wp: threadSet_pred_tcb_no_state crunch_wps simp: unless_def) lemmas emptySlot_pred_tcb_at'_Q[wp] = lift_neg_pred_tcb_at'[OF emptySlot_typ_at' emptySlot_pred_tcb_at'] lemma emptySlot_tcb_at'[wp]: "\\s. Q (tcb_at' t s)\ emptySlot a b \\_ s. Q (tcb_at' t s)\" by (simp add: tcb_at_typ_at', wp) lemmas cnode_caps_gsCNodes_lift = hoare_lift_Pf2[where P="\gs s. cnode_caps_gsCNodes (f s) gs" and f=gsCNodes for f] hoare_lift_Pf2[where P="\gs s. Q s \ cnode_caps_gsCNodes (f s) gs" and f=gsCNodes for f Q] lemma resolveAddressBitsFn_eq_name_slot: "monadic_rewrite F E (\s. (isCNodeCap cap \ cte_wp_at' (\cte. cteCap cte = cap) (slot s) s) \ valid_objs' s \ cnode_caps_gsCNodes' s) (resolveAddressBits cap capptr bits) (gets (resolveAddressBitsFn cap capptr bits o only_cnode_caps o ctes_of))" apply (rule monadic_rewrite_guard_imp, rule resolveAddressBitsFn_eq) apply auto done crunch bound_tcb_at'_Q[wp]: asUser "\s. Q (bound_tcb_at' P t s)" (simp: crunch_simps wp: threadSet_pred_tcb_no_state crunch_wps) lemma asUser_tcb_at'_Q[wp]: "\\s. Q (tcb_at' t s)\ asUser a b \\_ s. Q (tcb_at' t s)\" by (simp add: tcb_at_typ_at', wp) lemma active_ntfn_check_wp: "\\s. Q (\ntfnptr. bound_tcb_at' ((=) (Some ntfnptr)) thread s \ \ obj_at' (Not o isActive) ntfnptr s) s \ do bound_ntfn \ getBoundNotification thread; case bound_ntfn of None \ return False | Some ntfnptr \ liftM EndpointDecls_H.isActive $ getNotification ntfnptr od \Q\" apply (rule hoare_pre) apply (wp getNotification_wp gbn_wp' | wpc)+ apply (auto simp: pred_tcb_at'_def obj_at'_def projectKOs) done lemma tcbSchedEnqueue_tcbIPCBuffer: "\obj_at' (\tcb. P (tcbIPCBuffer tcb)) t\ tcbSchedEnqueue t' \\_. obj_at' (\tcb. P (tcbIPCBuffer tcb)) t\" apply (simp add: tcbSchedEnqueue_def unless_when) apply (wp threadSet_obj_at' hoare_drop_imps threadGet_wp |simp split: if_split)+ done crunch obj_at'_tcbIPCBuffer[wp]: rescheduleRequired "obj_at' (\tcb. P (tcbIPCBuffer tcb)) t" (wp: crunch_wps tcbSchedEnqueue_tcbIPCBuffer simp: rescheduleRequired_def) context notes if_cong[cong] begin crunch obj_at'_tcbIPCBuffer[wp]: setThreadState "obj_at' (\tcb. P (tcbIPCBuffer tcb)) t" (wp: crunch_wps threadSet_obj_at'_really_strongest) crunch obj_at'_tcbIPCBuffer[wp]: handleFault "obj_at' (\tcb. P (tcbIPCBuffer tcb)) t" (wp: crunch_wps constOnFailure_wp tcbSchedEnqueue_tcbIPCBuffer threadSet_obj_at'_really_strongest simp: zipWithM_x_mapM) end crunch obj_at'_tcbIPCBuffer[wp]: emptySlot "obj_at' (\tcb. P (tcbIPCBuffer tcb)) t" (wp: crunch_wps) (* FIXME move *) crunches getBoundNotification for (no_fail) no_fail[intro!, wp, simp] lemma fastpath_callKernel_SysReplyRecv_corres: "monadic_rewrite True False (invs' and ct_in_state' ((=) Running) and (\s. ksSchedulerAction s = ResumeCurrentThread) and cnode_caps_gsCNodes') (callKernel (SyscallEvent SysReplyRecv)) (fastpaths SysReplyRecv)" including no_pre supply if_cong[cong] option.case_cong[cong] supply if_split[split del] supply user_getreg_inv[wp] (* FIXME *) apply (rule monadic_rewrite_introduce_alternative[OF callKernel_def[simplified atomize_eq]]) apply (rule monadic_rewrite_guard_imp) apply (simp add: handleEvent_def handleReply_def handleRecv_def liftE_bindE_handle liftE_handle bind_assoc getMessageInfo_def liftE_bind) apply (simp add: catch_liftE_bindE unlessE_throw_catch_If unifyFailure_catch_If catch_liftE getMessageInfo_def alternative_bind fastpaths_def getThreadCallerSlot_def locateSlot_conv capability_case_Null_ReplyCap getThreadCSpaceRoot_def cong: if_cong) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply monadic_rewrite_symb_exec_r apply (rename_tac msgInfo) apply monadic_rewrite_symb_exec_r apply monadic_rewrite_symb_exec_r apply (rename_tac tcbFault) apply (rule monadic_rewrite_alternative_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: lookupCap_def liftME_def lookupCapAndSlot_def lookupSlotForThread_def bindE_assoc split_def getThreadCSpaceRoot_def locateSlot_conv liftE_bindE bindE_bind_linearise capFaultOnFailure_def rethrowFailure_injection injection_handler_catch bind_bindE_assoc getThreadCallerSlot_def bind_assoc getSlotCap_def case_bool_If isRight_def[where x="Inr v" for v] isRight_def[where x="Inl v" for v] cong: if_cong) apply monadic_rewrite_symb_exec_r apply (rename_tac "cTableCTE") apply (rule monadic_rewrite_transverse, monadic_rewrite_l resolveAddressBitsFn_eq wpsimp, rule monadic_rewrite_refl) apply monadic_rewrite_symb_exec_r apply (rename_tac "rab_ret") apply (rule_tac P="isRight rab_ret" in monadic_rewrite_cases[rotated]) apply (case_tac rab_ret, simp_all add: isRight_def)[1] apply (rule monadic_rewrite_alternative_l) apply clarsimp apply (simp add: isRight_case_sum liftE_bind isRight_def[where x="Inr v" for v]) apply monadic_rewrite_symb_exec_r apply (rename_tac ep_cap) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (monadic_rewrite_symb_exec \rule monadic_rewrite_symb_exec_r_nE[OF _ _ _ active_ntfn_check_wp, unfolded bind_assoc fun_app_def]\ \wpsimp simp: getBoundNotification_def wp: threadGet_wp\) apply (rename_tac ep) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply (rename_tac ep) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_bind_alternative_l, wp) apply (rule monadic_rewrite_bind_tail) apply (rename_tac replyCTE) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: bind_assoc) apply (rule monadic_rewrite_bind_alternative_l, wp assert_inv) apply (rule monadic_rewrite_assert) apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (simp add: getThreadVSpaceRoot_def locateSlot_conv) apply monadic_rewrite_symb_exec_r apply (rename_tac vTableCTE) apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply monadic_rewrite_symb_exec_r apply (simp add: isHighestPrio_def') apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply monadic_rewrite_symb_exec_r apply (rule monadic_rewrite_if_r[rotated]) apply (rule monadic_rewrite_alternative_l) apply (rule monadic_rewrite_trans, rule monadic_rewrite_pick_alternative_1) (* now committed to fastpath *) apply (rule_tac P="\v. obj_at' (%tcb. tcbIPCBuffer tcb = v) (capTCBPtr (cteCap replyCTE))" in monadic_rewrite_exists_v) apply (rename_tac ipcBuffer) apply (simp add: ARM_H.switchToThread_def bind_assoc) apply (rule monadic_rewrite_trans[OF _ monadic_rewrite_transverse]) apply (rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp mapM_x_wp' getObject_inv | wpc | simp add: | wp (once) hoare_drop_imps )+ apply (rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp setCTE_obj_at'_tcbIPCBuffer assert_inv mapM_x_wp' getObject_inv | wpc | simp | wp (once) hoare_drop_imps )+ apply (rule monadic_rewrite_trans) apply (rule monadic_rewrite_trans) apply (rule monadic_rewrite_bind_head) apply (rule monadic_rewrite_trans) apply (rule doReplyTransfer_simple) apply simp apply (((rule monadic_rewrite_weaken_flags', (rule_tac msgInfo=msgInfo in doIPCTransfer_simple_rewrite | rule_tac destPrio=callerPrio and curDom=curDom and destDom=callerDom and thread=thread in possibleSwitchTo_rewrite)) | rule cteDeleteOne_replycap_rewrite | rule monadic_rewrite_bind monadic_rewrite_refl | wp assert_inv mapM_x_wp' setThreadState_obj_at_unchanged asUser_obj_at_unchanged hoare_strengthen_post[OF _ obj_at_conj'[simplified atomize_conjL], rotated] lookupBitmapPriority_lift setThreadState_runnable_bitmap_inv | simp add: setMessageInfo_def setThreadState_runnable_simp | wp (once) hoare_vcg_disj_lift)+)[1] apply (simp add: setMessageInfo_def) apply (rule monadic_rewrite_bind_tail) apply (rename_tac unblocked) apply (monadic_rewrite_symb_exec_l_known thread) apply (monadic_rewrite_symb_exec_l_known cptr) apply (rule monadic_rewrite_bind) apply (rule monadic_rewrite_catch[OF _ monadic_rewrite_refl True_E_E]) apply monadic_rewrite_symb_exec_l apply (rename_tac cTableCTE2, rule_tac P="cteCap cTableCTE2 = cteCap cTableCTE" in monadic_rewrite_gen_asm) apply simp apply (rule monadic_rewrite_trans, rule monadic_rewrite_bindE[OF _ monadic_rewrite_refl]) apply (rule_tac slot="\s. ksCurThread s + 2 ^ cte_level_bits * tcbCTableSlot" in resolveAddressBitsFn_eq_name_slot) apply wp apply (rule monadic_rewrite_trans) apply (rule_tac rv=rab_ret in monadic_rewrite_gets_known[where m="Nondet_Monad.lift f" for f, folded bindE_def]) apply (simp add: Nondet_Monad.lift_def isRight_case_sum) apply monadic_rewrite_symb_exec_l apply (rename_tac ep_cap2) apply (rule_tac P="cteCap ep_cap2 = cteCap ep_cap" in monadic_rewrite_gen_asm) apply (simp add: cap_case_EndpointCap_NotificationCap) apply (rule monadic_rewrite_liftE) apply (rule monadic_rewrite_trans) apply (rule monadic_rewrite_bind) apply (rule deleteCallerCap_nullcap_rewrite) apply (rule_tac ep=ep in receiveIPC_simple_rewrite) apply (wp, simp) apply (rule monadic_rewrite_bind_head) apply (rule monadic_rewrite_weaken_flags[where E=True and F=True], simp) apply (rule setThreadState_rewrite_simple) apply clarsimp apply (wp getCTE_known_cap)+ apply (rule monadic_rewrite_bind) apply (rule_tac t="capTCBPtr (cteCap replyCTE)" and t'=thread in schedule_known_rewrite) apply (rule monadic_rewrite_weaken_flags[where E=True and F=True], simp) apply (rule monadic_rewrite_bind) apply (rule activateThread_simple_rewrite) apply (rule monadic_rewrite_refl) apply wp apply wp apply (simp add: ct_in_state'_def, simp add: ct_in_state'_def[symmetric]) apply ((wp setCurThread_ct_in_state[folded st_tcb_at'_def] Arch_switchToThread_pred_tcb')+)[2] apply (simp add: catch_liftE) apply ((wpsimp wp: user_getreg_rv setEndpoint_obj_at_tcb' threadSet_pred_tcb_at_state[unfolded if_bool_eq_conj] fastpathBestSwitchCandidate_lift[where f="setEndpoint a b" for a b] fastpathBestSwitchCandidate_lift[where f="threadSet f t" for f t] | wps)+)[3] apply (simp cong: rev_conj_cong) apply (wpsimp wp: seThreadState_tcbContext[simplified comp_apply] setThreadState_oa_queued user_getreg_rv setThreadState_no_sch_change setThreadState_obj_at_unchanged sts_st_tcb_at'_cases sts_bound_tcb_at' fastpathBestSwitchCandidate_lift[where f="setThreadState s t" for s t] hoare_weak_lift_imp hoare_vcg_all_lift hoare_vcg_imp_lift hoare_weak_lift_imp cnode_caps_gsCNodes_lift hoare_vcg_ex_lift | wps)+ apply (strengthen imp_consequent[where Q="tcb_at' t s" for t s]) apply ((wp setThreadState_oa_queued user_getreg_rv setThreadState_no_sch_change setThreadState_obj_at_unchanged sts_st_tcb_at'_cases sts_bound_tcb_at' emptySlot_obj_at'_not_queued emptySlot_obj_at_ep emptySlot_tcbContext[simplified comp_apply] emptySlot_cte_wp_at_cteCap emptySlot_cnode_caps user_getreg_inv asUser_typ_ats asUser_obj_at_not_queued asUser_obj_at' mapM_x_wp' hoare_weak_lift_imp hoare_vcg_all_lift hoare_vcg_imp_lift hoare_weak_lift_imp cnode_caps_gsCNodes_lift hoare_vcg_ex_lift fastpathBestSwitchCandidate_lift[where f="emptySlot a b" for a b] | simp del: comp_apply | clarsimp simp: obj_at'_weakenE[OF _ TrueI] | wps)+) apply (wpsimp wp: fastpathBestSwitchCandidate_lift[where f="asUser a b" for a b])+ apply (clarsimp cong: conj_cong) apply ((wp user_getreg_inv asUser_typ_ats asUser_obj_at_not_queued asUser_obj_at' mapM_x_wp' hoare_weak_lift_imp hoare_vcg_all_lift hoare_vcg_imp_lift hoare_weak_lift_imp cnode_caps_gsCNodes_lift hoare_vcg_ex_lift | clarsimp simp: obj_at'_weakenE[OF _ TrueI] | solves \ wp fastpathBestSwitchCandidate_lift[where f="asUser a b" for a b] \)+) apply (clarsimp | wp getCTE_wp' gts_imp')+ apply (simp add: ARM_H.switchToThread_def bind_assoc) apply (rule monadic_rewrite_trans[OF _ monadic_rewrite_transverse]) apply (rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp mapM_x_wp' handleFault_obj_at'_tcbIPCBuffer getObject_inv | wpc | simp | wp (once) hoare_drop_imps )+ apply (rule monadic_rewrite_bind monadic_rewrite_refl)+ apply (wp setCTE_obj_at'_tcbIPCBuffer assert_inv mapM_x_wp' getObject_inv | wpc | simp | wp (once) hoare_drop_imps )+ apply (simp add: bind_assoc catch_liftE receiveIPC_def Let_def liftM_def setThreadState_runnable_simp) apply monadic_rewrite_symb_exec_l apply (rule monadic_rewrite_assert) apply (rule_tac P="inj (case_bool thread (capTCBPtr (cteCap replyCTE)))" in monadic_rewrite_gen_asm) apply (rule monadic_rewrite_trans[OF _ monadic_rewrite_transverse]) apply (rule monadic_rewrite_weaken_flags[where F=False and E=True], simp) apply (rule isolate_thread_actions_rewrite_bind fastpath_isolate_rewrites fastpath_isolatables bool.simps setRegister_simple zipWithM_setRegister_simple thread_actions_isolatable_bind thread_actions_isolatableD[OF setCTE_isolatable] setCTE_isolatable setVMRoot_isolatable[THEN thread_actions_isolatableD] setVMRoot_isolatable doMachineOp_isolatable[THEN thread_actions_isolatableD] doMachineOp_isolatable kernelExitAssertions_isolatable[THEN thread_actions_isolatableD] kernelExitAssertions_isolatable | assumption | wp assert_inv)+ apply (simp only: ) apply (rule_tac P="(\s. ksSchedulerAction s = ResumeCurrentThread) and tcb_at' thread and (cte_wp_at' (\cte. isReplyCap (cteCap cte)) (thread + 2 ^ cte_level_bits * tcbCallerSlot) and (\s. \x. tcb_at' (case_bool thread (capTCBPtr (cteCap replyCTE)) x) s) and valid_mdb')" and F=True and E=False in monadic_rewrite_weaken_flags) apply (rule monadic_rewrite_isolate_final2) apply simp apply monadic_rewrite_symb_exec_l apply (rename_tac callerCTE) apply (rule monadic_rewrite_assert) apply monadic_rewrite_symb_exec_l apply (rule monadic_rewrite_assert) apply (simp add: emptySlot_setEndpoint_pivot) apply (rule monadic_rewrite_bind) apply (rule monadic_rewrite_is_refl) apply (clarsimp simp: isSendEP_def split: Structures_H.endpoint.split) apply (monadic_rewrite_symb_exec_r_known callerCTE) apply (rule monadic_rewrite_trans, rule monadic_rewrite_bind_head, rule_tac cte=callerCTE in emptySlot_replymaster_rewrite) apply (simp add: bind_assoc o_def) apply (rule monadic_rewrite_refl) apply (simp add: cte_wp_at_ctes_of pred_conj_def) apply (clarsimp | wp getCTE_ctes_wp)+ apply (clarsimp simp: zip_map2 zip_same_conv_map foldl_map foldl_fun_upd foldr_copy_register_tsrs isRight_case_sum cong: if_cong) apply (clarsimp simp: fun_eq_iff if_flip cong: if_cong) apply (drule obj_at_ko_at', clarsimp) apply (frule get_tcb_state_regs_ko_at') apply (clarsimp simp: zip_map2 zip_same_conv_map foldl_map foldl_fun_upd foldr_copy_register_tsrs isRight_case_sum cong: if_cong) apply (simp add: upto_enum_def fromEnum_def enum_register toEnum_def msgRegisters_unfold cong: if_cong) apply (clarsimp split: if_split) apply (rule ext) apply (simp add: badgeRegister_def msgInfoRegister_def ARM.msgInfoRegister_def ARM.badgeRegister_def cong: if_cong split: if_split) apply simp apply (clarsimp simp: cte_wp_at_ctes_of isCap_simps map_to_ctes_partial_overwrite) apply (simp add: valid_mdb'_def valid_mdb_ctes_def) apply simp apply (simp cong: if_cong bool.case_cong | rule getCTE_wp' gts_wp' threadGet_wp getEndpoint_wp gets_wp user_getreg_wp gets_the_wp gct_wp getNotification_wp return_wp liftM_wp gbn_wp' | (simp only: curDomain_def, wp)[1])+ apply clarsimp apply (subgoal_tac "ksCurThread s \ ksIdleThread s") prefer 2 apply (fastforce simp: ct_in_state'_def dest: ct_running_not_idle' elim: pred_tcb'_weakenE) apply (clarsimp simp: ct_in_state'_def pred_tcb_at') apply (subst tcb_at_cte_at_offset, erule obj_at'_weakenE[OF _ TrueI], simp add: tcb_cte_cases_def cte_level_bits_def tcbSlots) apply (clarsimp simp: valid_objs_ntfn_at_tcbBoundNotification invs_valid_objs' if_apply_def2) apply (rule conjI[rotated]) apply (fastforce elim: cte_wp_at_weakenE') apply (clarsimp simp: isRight_def) apply (frule cte_wp_at_valid_objs_valid_cap', clarsimp+) apply (frule resolveAddressBitsFn_real_cte_at', (clarsimp | erule cte_wp_at_weakenE')+) apply (frule real_cte_at', clarsimp) apply (frule cte_wp_at_valid_objs_valid_cap', clarsimp, clarsimp simp: isCap_simps, simp add: valid_cap_simps') apply (clarsimp simp: maskCapRights_def isCap_simps) apply (frule_tac p="p' + 2 ^ cte_level_bits * tcbCallerSlot" for p' in cte_wp_at_valid_objs_valid_cap', clarsimp+) apply (clarsimp simp: valid_cap_simps') apply (subst tcb_at_cte_at_offset, assumption, simp add: tcb_cte_cases_def cte_level_bits_def tcbSlots) apply (clarsimp simp: inj_case_bool cte_wp_at_ctes_of length_msgRegisters order_less_imp_le tcb_at_invs' invs_mdb' split: bool.split) apply (subst imp_disjL[symmetric], intro allI impI) apply (clarsimp simp: inj_case_bool cte_wp_at_ctes_of length_msgRegisters size_msgRegisters_def order_less_imp_le tcb_at_invs' invs_mdb' split: bool.split) apply (subgoal_tac "fastpathBestSwitchCandidate v0a s") prefer 2 apply normalise_obj_at' apply (rule_tac ttcb=tcba and ctcb=tcb in fastpathBestSwitchCandidateI) apply (erule disjE, blast, blast) apply simp+ apply (clarsimp simp: obj_at_tcbs_of tcbSlots cte_level_bits_def) apply (frule(1) st_tcb_at_is_Reply_imp_not_tcbQueued) apply (auto simp: obj_at_tcbs_of tcbSlots cte_level_bits_def) done end lemma cnode_caps_gsCNodes_from_sr: "\ valid_objs s; (s, s') \ state_relation \ \ cnode_caps_gsCNodes' s'" apply (clarsimp simp: cnode_caps_gsCNodes_def only_cnode_caps_def o_def ran_map_option) apply (safe, simp_all) apply (clarsimp elim!: ranE) apply (frule(1) pspace_relation_cte_wp_atI[rotated]) apply clarsimp apply (clarsimp simp: is_cap_simps) apply (frule(1) cte_wp_at_valid_objs_valid_cap) apply (clarsimp simp: valid_cap_simps cap_table_at_gsCNodes_eq) done end