6340 lines
309 KiB
Plaintext
6340 lines
309 KiB
Plaintext
|
|
(*
|
|
* Copyright 2014, General Dynamics C4 Systems
|
|
*
|
|
* This software may be distributed and modified according to the terms of
|
|
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
|
* See "LICENSE_GPLv2.txt" for details.
|
|
*
|
|
* @TAG(GD_GPL)
|
|
*)
|
|
|
|
theory Fastpath_C
|
|
imports
|
|
SyscallArgs_C
|
|
Delete_C
|
|
Syscall_C
|
|
"../refine/RAB_FN"
|
|
"../../lib/clib/MonadicRewrite_C"
|
|
begin
|
|
|
|
context begin interpretation Arch . (*FIXME: arch_split*)
|
|
|
|
definition
|
|
"fastpaths sysc \<equiv> case sysc of
|
|
SysCall \<Rightarrow> doE
|
|
curThread \<leftarrow> liftE $ getCurThread;
|
|
mi \<leftarrow> liftE $ getMessageInfo curThread;
|
|
cptr \<leftarrow> liftE $ asUser curThread $ getRegister capRegister;
|
|
|
|
fault \<leftarrow> liftE $ threadGet tcbFault curThread;
|
|
pickFastpath \<leftarrow> liftE $ alternative (return True) (return False);
|
|
unlessE (fault = None \<and> msgExtraCaps mi = 0
|
|
\<and> msgLength mi \<le> scast n_msgRegisters \<and> pickFastpath)
|
|
$ throwError ();
|
|
|
|
ctab \<leftarrow> liftE $ getThreadCSpaceRoot curThread >>= getCTE;
|
|
epCap \<leftarrow> unifyFailure (doE t \<leftarrow> resolveAddressBits (cteCap ctab) cptr (size cptr);
|
|
liftE (getSlotCap (fst t)) odE);
|
|
unlessE (isEndpointCap epCap \<and> capEPCanSend epCap)
|
|
$ throwError ();
|
|
ep \<leftarrow> liftE $ getEndpoint (capEPPtr epCap);
|
|
unlessE (isRecvEP ep) $ throwError ();
|
|
dest \<leftarrow> returnOk $ hd $ epQueue ep;
|
|
newVTable \<leftarrow> liftE $ getThreadVSpaceRoot dest >>= getCTE;
|
|
unlessE (isValidVTableRoot $ cteCap newVTable) $ throwError ();
|
|
pd \<leftarrow> returnOk $ capPDBasePtr $ capCap $ cteCap newVTable;
|
|
curPrio \<leftarrow> liftE $ threadGet tcbPriority curThread;
|
|
destPrio \<leftarrow> liftE $ threadGet tcbPriority dest;
|
|
destFault \<leftarrow>
|
|
unlessE (destPrio \<ge> curPrio) $ throwError ();
|
|
unlessE (capEPCanGrant epCap) $ throwError ();
|
|
asidMap \<leftarrow> liftE $ gets $ armKSASIDMap o ksArchState;
|
|
unlessE (\<exists>v. {hwasid. (hwasid, pd) \<in> ran asidMap} = {v})
|
|
$ throwError ();
|
|
curDom \<leftarrow> liftE $ curDomain;
|
|
destDom \<leftarrow> liftE $ threadGet tcbDomain dest;
|
|
unlessE (destDom = curDom) $ throwError ();
|
|
|
|
liftE $ do
|
|
setEndpoint (capEPPtr epCap)
|
|
(case tl (epQueue ep) of [] \<Rightarrow> IdleEP | _ \<Rightarrow> RecvEP (tl (epQueue ep)));
|
|
threadSet (tcbState_update (\<lambda>_. BlockedOnReply)) curThread;
|
|
replySlot \<leftarrow> getThreadReplySlot curThread;
|
|
callerSlot \<leftarrow> getThreadCallerSlot dest;
|
|
replySlotCTE \<leftarrow> getCTE replySlot;
|
|
assert (mdbNext (cteMDBNode replySlotCTE) = 0
|
|
\<and> isReplyCap (cteCap replySlotCTE)
|
|
\<and> capReplyMaster (cteCap replySlotCTE)
|
|
\<and> mdbFirstBadged (cteMDBNode replySlotCTE)
|
|
\<and> mdbRevocable (cteMDBNode replySlotCTE));
|
|
cteInsert (ReplyCap curThread False) replySlot callerSlot;
|
|
|
|
forM_x (take (unat (msgLength mi)) ARM_H.msgRegisters)
|
|
(\<lambda>r. do v \<leftarrow> asUser curThread (getRegister r);
|
|
asUser dest (setRegister r v) od);
|
|
setThreadState Running dest;
|
|
Arch.switchToThread dest;
|
|
setCurThread dest;
|
|
|
|
asUser dest $ zipWithM_x setRegister
|
|
[ARM_H.badgeRegister, ARM_H.msgInfoRegister]
|
|
[capEPBadge epCap, wordFromMessageInfo (mi\<lparr> msgCapsUnwrapped := 0 \<rparr>)]
|
|
od
|
|
|
|
odE <catch> (\<lambda>_. callKernel (SyscallEvent sysc))
|
|
| SysReplyRecv \<Rightarrow> doE
|
|
curThread \<leftarrow> liftE $ getCurThread;
|
|
mi \<leftarrow> liftE $ getMessageInfo curThread;
|
|
cptr \<leftarrow> liftE $ asUser curThread $ getRegister capRegister;
|
|
|
|
fault \<leftarrow> liftE $ threadGet tcbFault curThread;
|
|
pickFastpath \<leftarrow> liftE $ alternative (return True) (return False);
|
|
unlessE (fault = None \<and> msgExtraCaps mi = 0
|
|
\<and> msgLength mi \<le> scast n_msgRegisters \<and> pickFastpath)
|
|
$ throwError ();
|
|
|
|
ctab \<leftarrow> liftE $ getThreadCSpaceRoot curThread >>= getCTE;
|
|
epCap \<leftarrow> unifyFailure (doE t \<leftarrow> resolveAddressBits (cteCap ctab) cptr (size cptr);
|
|
liftE (getSlotCap (fst t)) odE);
|
|
|
|
unlessE (isEndpointCap epCap \<and> capEPCanReceive epCap)
|
|
$ throwError ();
|
|
|
|
bound_ntfn \<leftarrow> liftE $ getBoundNotification curThread;
|
|
active_ntfn \<leftarrow> liftE $ case bound_ntfn of None \<Rightarrow> return False
|
|
| Some ntfnptr \<Rightarrow> liftM isActive $ getNotification ntfnptr;
|
|
unlessE (\<not> active_ntfn) $ throwError ();
|
|
|
|
ep \<leftarrow> liftE $ getEndpoint (capEPPtr epCap);
|
|
unlessE (\<not> isSendEP ep) $ throwError ();
|
|
|
|
callerSlot \<leftarrow> liftE $ getThreadCallerSlot curThread;
|
|
callerCTE \<leftarrow> liftE $ getCTE callerSlot;
|
|
callerCap \<leftarrow> returnOk $ cteCap callerCTE;
|
|
unlessE (isReplyCap callerCap \<and> \<not> capReplyMaster callerCap)
|
|
$ throwError ();
|
|
|
|
caller \<leftarrow> returnOk $ capTCBPtr callerCap;
|
|
callerFault \<leftarrow> liftE $ threadGet tcbFault caller;
|
|
unlessE (callerFault = None) $ throwError ();
|
|
newVTable \<leftarrow> liftE $ getThreadVSpaceRoot caller >>= getCTE;
|
|
unlessE (isValidVTableRoot $ cteCap newVTable) $ throwError ();
|
|
pd \<leftarrow> returnOk $ capPDBasePtr $ capCap $ cteCap newVTable;
|
|
curPrio \<leftarrow> liftE $ threadGet tcbPriority curThread;
|
|
callerPrio \<leftarrow> liftE $ threadGet tcbPriority caller;
|
|
unlessE (callerPrio \<ge> curPrio) $ throwError ();
|
|
asidMap \<leftarrow> liftE $ gets $ armKSASIDMap o ksArchState;
|
|
unlessE (\<exists>v. {hwasid. (hwasid, pd) \<in> ran asidMap} = {v})
|
|
$ throwError ();
|
|
curDom \<leftarrow> liftE $ curDomain;
|
|
callerDom \<leftarrow> liftE $ threadGet tcbDomain caller;
|
|
unlessE (callerDom = curDom) $ throwError ();
|
|
|
|
liftE $ do
|
|
threadSet (tcbState_update (\<lambda>_. BlockedOnReceive (capEPPtr epCap))) curThread;
|
|
setEndpoint (capEPPtr epCap)
|
|
(case ep of IdleEP \<Rightarrow> RecvEP [curThread] | RecvEP ts \<Rightarrow> RecvEP (ts @ [curThread]));
|
|
mdbPrev \<leftarrow> liftM (mdbPrev o cteMDBNode) $ getCTE callerSlot;
|
|
assert (mdbPrev \<noteq> 0);
|
|
updateMDB mdbPrev (mdbNext_update (K 0) o mdbFirstBadged_update (K True)
|
|
o mdbRevocable_update (K True));
|
|
setCTE callerSlot makeObject;
|
|
|
|
forM_x (take (unat (msgLength mi)) ARM_H.msgRegisters)
|
|
(\<lambda>r. do v \<leftarrow> asUser curThread (getRegister r);
|
|
asUser caller (setRegister r v) od);
|
|
setThreadState Running caller;
|
|
Arch.switchToThread caller;
|
|
setCurThread caller;
|
|
|
|
asUser caller $ zipWithM_x setRegister
|
|
[ARM_H.badgeRegister, ARM_H.msgInfoRegister]
|
|
[0, wordFromMessageInfo (mi\<lparr> msgCapsUnwrapped := 0 \<rparr>)]
|
|
od
|
|
|
|
odE <catch> (\<lambda>_. callKernel (SyscallEvent sysc))
|
|
|
|
| _ \<Rightarrow> callKernel (SyscallEvent sysc)"
|
|
|
|
|
|
lemma setCTE_obj_at'_queued:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. P (tcbQueued tcb)) t\<rbrace> setCTE p v \<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. P (tcbQueued tcb)) t\<rbrace>"
|
|
unfolding setCTE_def
|
|
by (rule setObject_cte_obj_at_tcb', simp+)
|
|
|
|
crunch obj_at'_queued: cteInsert "obj_at' (\<lambda>tcb. P (tcbQueued tcb)) t"
|
|
(wp: setCTE_obj_at'_queued crunch_wps)
|
|
|
|
crunch obj_at'_not_queued: emptySlot "obj_at' (\<lambda>a. \<not> tcbQueued a) p"
|
|
(wp: setCTE_obj_at'_queued)
|
|
|
|
lemma getEndpoint_obj_at':
|
|
"\<lbrace>obj_at' P ptr\<rbrace> getEndpoint ptr \<lbrace>\<lambda>rv s. P rv\<rbrace>"
|
|
apply (wp getEndpoint_wp)
|
|
apply (clarsimp simp: obj_at'_def projectKOs)
|
|
done
|
|
|
|
lemma setEndpoint_obj_at_tcb':
|
|
"\<lbrace>obj_at' (P :: tcb \<Rightarrow> bool) p\<rbrace> setEndpoint p' val \<lbrace>\<lambda>rv. obj_at' P p\<rbrace>"
|
|
apply (simp add: setEndpoint_def)
|
|
apply (rule obj_at_setObject2)
|
|
apply (clarsimp simp: updateObject_default_def in_monad)
|
|
done
|
|
|
|
lemma tcbSchedEnqueue_obj_at_unchangedT:
|
|
assumes y: "\<And>f. \<forall>tcb. P (tcbQueued_update f tcb) = P tcb"
|
|
shows "\<lbrace>obj_at' P t\<rbrace> tcbSchedEnqueue t' \<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: tcbSchedEnqueue_def unless_def)
|
|
apply (wp | simp add: y)+
|
|
done
|
|
|
|
(* FIXME: Move to Schedule_R.thy. Make Arch_switchToThread_obj_at a specialisation of this *)
|
|
lemma Arch_switchToThread_obj_at_pre:
|
|
"\<lbrace>obj_at' P t\<rbrace>
|
|
Arch.switchToThread t
|
|
\<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: ARM_H.switchToThread_def storeWordUser_def)
|
|
apply (wp doMachineOp_obj_at setVMRoot_obj_at hoare_drop_imps)
|
|
done
|
|
|
|
lemma rescheduleRequired_obj_at_unchangedT:
|
|
assumes y: "\<And>f. \<forall>tcb. P (tcbQueued_update f tcb) = P tcb"
|
|
shows "\<lbrace>obj_at' P t\<rbrace> rescheduleRequired \<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: rescheduleRequired_def)
|
|
apply (wp tcbSchedEnqueue_obj_at_unchangedT[OF y] | wpc)+
|
|
apply simp
|
|
done
|
|
|
|
lemma setThreadState_obj_at_unchangedT:
|
|
assumes x: "\<And>f. \<forall>tcb. P (tcbState_update f tcb) = P tcb"
|
|
assumes y: "\<And>f. \<forall>tcb. P (tcbQueued_update f tcb) = P tcb"
|
|
shows "\<lbrace>obj_at' P t\<rbrace> setThreadState t' ts \<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: setThreadState_def)
|
|
apply (wp rescheduleRequired_obj_at_unchangedT[OF y], simp)
|
|
apply (wp threadSet_obj_at'_strongish)
|
|
apply (clarsimp simp: obj_at'_def projectKOs x cong: if_cong)
|
|
done
|
|
|
|
lemma setBoundNotification_obj_at_unchangedT:
|
|
assumes x: "\<And>f. \<forall>tcb. P (tcbBoundNotification_update f tcb) = P tcb"
|
|
shows "\<lbrace>obj_at' P t\<rbrace> setBoundNotification t' ts \<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: setBoundNotification_def)
|
|
apply (wp threadSet_obj_at'_strongish)
|
|
apply (clarsimp simp: obj_at'_def projectKOs x cong: if_cong)
|
|
done
|
|
|
|
lemmas setThreadState_obj_at_unchanged
|
|
= setThreadState_obj_at_unchangedT[OF all_tcbI all_tcbI]
|
|
|
|
lemmas setBoundNotification_obj_at_unchanged
|
|
= setBoundNotification_obj_at_unchangedT[OF all_tcbI]
|
|
|
|
lemma tcbSchedEnqueue_tcbContext[wp]:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. P (tcbContext tcb)) t\<rbrace>
|
|
tcbSchedEnqueue t'
|
|
\<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. P (tcbContext tcb)) t\<rbrace>"
|
|
apply (rule tcbSchedEnqueue_obj_at_unchangedT[OF all_tcbI])
|
|
apply simp
|
|
done
|
|
|
|
lemma setNotification_tcb:
|
|
"\<lbrace>obj_at' (\<lambda>tcb::tcb. P tcb) t\<rbrace>
|
|
setNotification ntfn e
|
|
\<lbrace>\<lambda>_. obj_at' P t\<rbrace>"
|
|
apply (simp add: setNotification_def)
|
|
apply (rule obj_at_setObject2)
|
|
apply (clarsimp simp: updateObject_default_def in_monad)
|
|
done
|
|
|
|
lemma setCTE_tcbContext:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. P (tcbContext tcb)) t\<rbrace>
|
|
setCTE slot cte
|
|
\<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. P (tcbContext tcb)) t\<rbrace>"
|
|
apply (simp add: setCTE_def)
|
|
apply (rule setObject_cte_obj_at_tcb', simp_all)
|
|
done
|
|
|
|
|
|
|
|
crunch tcbContext[wp]: deleteCallerCap "obj_at' (\<lambda>tcb. P (tcbContext tcb)) t"
|
|
(wp: setEndpoint_obj_at_tcb' setThreadState_obj_at_unchanged
|
|
setNotification_tcb crunch_wps setBoundNotification_obj_at_unchanged
|
|
simp: crunch_simps unless_def)
|
|
|
|
crunch ksArch[wp]: asUser "\<lambda>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: split_if)
|
|
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)
|
|
|
|
end
|
|
|
|
context kernel_m begin
|
|
|
|
lemma ccorres_disj_division:
|
|
"\<lbrakk> P \<or> Q; P \<Longrightarrow> ccorres_underlying sr G r xf ar axf R S hs a c;
|
|
Q \<Longrightarrow> ccorres_underlying sr G r xf ar axf T U hs a c \<rbrakk>
|
|
\<Longrightarrow> ccorres_underlying sr G r xf ar axf
|
|
(\<lambda>s. (P \<longrightarrow> R s) \<and> (Q \<longrightarrow> T s)) {s. (P \<longrightarrow> s \<in> S) \<and> (Q \<longrightarrow> s \<in> U)}
|
|
hs a c"
|
|
apply (erule disjE, simp_all)
|
|
apply (auto elim!: ccorres_guard_imp)
|
|
done
|
|
|
|
lemma disj_division_bool: "b \<or> \<not> b" by simp
|
|
|
|
lemmas ccorres_case_bools2 = ccorres_disj_division [OF disj_division_bool]
|
|
|
|
lemma capMasterCap_NullCap_eq:
|
|
"(capMasterCap c = NullCap) = (c = NullCap)"
|
|
by (auto dest!: capMasterCap_eqDs)
|
|
|
|
lemma getCTE_h_val_ccorres_split:
|
|
assumes var: "\<And>s f s'. var (var_update f s) = f (var s)
|
|
\<and> ((s', var_update f s) \<in> rf_sr) = ((s', s) \<in> rf_sr)"
|
|
and "\<And>rv' t t'. ceqv \<Gamma> var rv' t t' g (g' rv')"
|
|
and "\<And>rv rv'. \<lbrakk> ccap_relation (cteCap rv) rv'; P rv \<rbrakk>
|
|
\<Longrightarrow> ccorres r xf (Q rv) (Q' rv rv') hs (f rv) (g' rv')"
|
|
shows
|
|
"ccorres r xf (\<lambda>s. \<forall>cte. ctes_of s slot = Some cte \<longrightarrow> P cte \<and> Q cte s)
|
|
{s. (\<forall>cte cap. ccap_relation (cteCap cte) cap \<and> P cte
|
|
\<longrightarrow> var_update (\<lambda>_. cap) s \<in> Q' cte cap)
|
|
\<and> slot' = cte_Ptr slot} hs
|
|
(getCTE slot >>= (\<lambda>rv. f rv))
|
|
((Basic (\<lambda>s. var_update (\<lambda>_. h_val (hrs_mem (t_hrs_' (globals s))) (cap_Ptr &(slot' \<rightarrow>[''cap_C'']))) s));; g)"
|
|
(is "ccorres r xf ?G ?G' hs ?f ?g")
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_pre_getCTE)
|
|
apply (rule_tac A="cte_wp_at' (op = rv and P) slot and Q rv" and A'="?G'" in ccorres_guard_imp2)
|
|
apply (rule_tac P="P rv" in ccorres_gen_asm)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'=var in ccorres_abstract)
|
|
apply (rule assms)
|
|
apply (rule ccorres_gen_asm2, erule(1) assms)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg, clarsimp simp: var)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of var)
|
|
apply (erule(1) cmap_relationE1[OF cmap_relation_cte])
|
|
apply (clarsimp simp: typ_heap_simps' dest!: ccte_relation_ccap_relation)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
done
|
|
|
|
lemma cap_'_cap_'_update_var_props:
|
|
"cap_' (cap_'_update f s) = f (cap_' s) \<and>
|
|
((s', cap_'_update f s) \<in> rf_sr) = ((s', s) \<in> rf_sr)"
|
|
by simp
|
|
|
|
lemmas getCTE_cap_h_val_ccorres_split
|
|
= getCTE_h_val_ccorres_split[where var_update=cap_'_update and P=\<top>,
|
|
OF cap_'_cap_'_update_var_props]
|
|
|
|
lemma getCTE_ccorres_helper:
|
|
"\<lbrakk> \<And>\<sigma> cte cte'. \<Gamma> \<turnstile> {s. (\<sigma>, s) \<in> rf_sr \<and> P \<sigma> \<and> s \<in> P' \<and> ctes_of \<sigma> slot = Some cte
|
|
\<and> cslift s (cte_Ptr slot) = Some cte'
|
|
\<and> ccte_relation cte cte'}
|
|
f {s. (\<sigma>, s) \<in> rf_sr \<and> r cte (xf s)} \<rbrakk> \<Longrightarrow>
|
|
ccorres r xf P P' hs (getCTE slot) f"
|
|
apply atomize
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_add_return2)
|
|
apply (rule ccorres_pre_getCTE)
|
|
apply (rule_tac P="cte_wp_at' (op = x) slot and P"
|
|
in ccorres_from_vcg[where P'=P'])
|
|
apply (erule allEI)
|
|
apply (drule_tac x="the (ctes_of \<sigma> slot)" in spec)
|
|
apply (erule HoarePartial.conseq)
|
|
apply (clarsimp simp: return_def cte_wp_at_ctes_of)
|
|
apply (erule(1) cmap_relationE1[OF cmap_relation_cte])
|
|
apply simp
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
done
|
|
|
|
lemma acc_CNodeCap_repr:
|
|
"isCNodeCap cap
|
|
\<Longrightarrow> cap = CNodeCap (capCNodePtr cap) (capCNodeBits cap)
|
|
(capCNodeGuard cap) (capCNodeGuardSize cap)"
|
|
by (clarsimp simp: isCap_simps)
|
|
|
|
lemma valid_cnode_cap_cte_at':
|
|
"\<lbrakk> s \<turnstile>' c; isCNodeCap c; ptr = capCNodePtr c; v < 2 ^ capCNodeBits c \<rbrakk>
|
|
\<Longrightarrow> cte_at' (ptr + v * 0x10) 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
|
|
|
|
lemma ccorres_abstract_all:
|
|
"\<lbrakk>\<And>rv' t t'. ceqv Gamm xf' rv' t t' d (d' rv');
|
|
\<And>rv'. ccorres_underlying sr Gamm r xf arrel axf (G rv') (G' rv') hs a (d' rv')\<rbrakk>
|
|
\<Longrightarrow> ccorres_underlying sr Gamm r xf arrel axf (\<lambda>s. \<forall>rv'. G rv' s) {s. s \<in> G' (xf' s)} hs a d"
|
|
apply (erule ccorres_abstract)
|
|
apply (rule ccorres_guard_imp2)
|
|
apply assumption
|
|
apply simp
|
|
done
|
|
|
|
lemma of_int_sint_scast [simp]:
|
|
"of_int (sint (x :: 'a::len word)) = (scast x :: 'b::len word)"
|
|
by (metis scast_def word_of_int)
|
|
|
|
lemma stateAssert_bind_out_of_if:
|
|
"If P f (stateAssert Q xs >>= g) = stateAssert (\<lambda>s. \<not> P \<longrightarrow> Q s) [] >>= (\<lambda>_. If P f (g ()))"
|
|
"If P (stateAssert Q xs >>= g) f = stateAssert (\<lambda>s. P \<longrightarrow> Q s) [] >>= (\<lambda>_. If P (g ()) f)"
|
|
by (simp_all add: fun_eq_iff stateAssert_def exec_get split: split_if)
|
|
|
|
lemma isCNodeCap_capUntypedPtr_capCNodePtr:
|
|
"isCNodeCap c \<Longrightarrow> capUntypedPtr c = capCNodePtr c"
|
|
by (clarsimp simp: isCap_simps)
|
|
|
|
lemma of_bl_from_bool:
|
|
"of_bl [x] = from_bool x"
|
|
by (cases x, simp_all)
|
|
|
|
lemma lookup_fp_ccorres':
|
|
assumes bits: "bits = size cptr"
|
|
shows
|
|
"ccorres (\<lambda>mcp ccp. ccap_relation (case mcp of Inl v => NullCap | Inr v => v) ccp)
|
|
ret__struct_cap_C_'
|
|
(valid_cap' cap and valid_objs')
|
|
(UNIV \<inter> {s. ccap_relation cap (cap_' s)} \<inter> {s. cptr_' s = cptr}) []
|
|
(cutMon (op = s) (doE t \<leftarrow> resolveAddressBits cap cptr bits;
|
|
liftE (getSlotCap (fst t))
|
|
odE))
|
|
(Call lookup_fp_'proc)"
|
|
apply (cinit' lift: cptr_')
|
|
apply (rule ccorres_rhs_assoc2)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'=ret__int_' in ccorres_abstract, ceqv)
|
|
apply (rule_tac P="rv' = from_bool (isCNodeCap cap)" in ccorres_gen_asm2)
|
|
apply (simp add: from_bool_0 del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp add: resolveAddressBits.simps split_def del: Collect_const
|
|
split del: split_if)
|
|
apply (rule ccorres_drop_cutMon)
|
|
apply (rule ccorres_from_vcg_split_throws[where P=\<top> and P'=UNIV])
|
|
apply vcg
|
|
apply (rule conseqPre, vcg)
|
|
apply (clarsimp simp: throwError_def return_def isRight_def isLeft_def
|
|
ccap_relation_NullCap_iff)
|
|
apply (clarsimp simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule_tac P="valid_cap' cap and valid_objs'"
|
|
and P'="UNIV \<inter> {s. ccap_relation cap (cap_' s) \<and> isCNodeCap cap}
|
|
\<inter> {s. bits_' s = 32 - of_nat bits \<and> bits \<le> 32 \<and> bits \<noteq> 0}"
|
|
in ccorres_inst)
|
|
apply (thin_tac "isCNodeCap cap")
|
|
defer
|
|
apply vcg
|
|
apply (rule conseqPre, vcg)
|
|
apply clarsimp
|
|
apply (clarsimp simp: word_size cap_get_tag_isCap bits
|
|
of_bl_from_bool from_bool_0)
|
|
proof (induct cap cptr bits arbitrary: s
|
|
rule: resolveAddressBits.induct)
|
|
case (1 acap acptr abits as)
|
|
|
|
have sub_mask_neq_0_eq:
|
|
"\<And>v :: word32. v && 0x1F \<noteq> 0 \<Longrightarrow> 0x20 - (0x20 - (v && 0x1F) && mask 5) = v && 0x1F"
|
|
apply (subst word_le_mask_eq)
|
|
apply (simp only: mask_def)
|
|
apply (rule word_le_minus_mono, simp_all add: word_le_sub1 word_sub_le_iff)[1]
|
|
apply (rule order_trans, rule word_and_le1, simp)
|
|
apply (simp add: word_bits_def)
|
|
apply simp
|
|
done
|
|
|
|
have valid_cnode_bits_0:
|
|
"\<And>s acap. \<lbrakk> isCNodeCap acap; s \<turnstile>' acap \<rbrakk> \<Longrightarrow> capCNodeBits acap \<noteq> 0"
|
|
by (clarsimp simp: isCap_simps valid_cap'_def)
|
|
|
|
have cap_get_tag_update_1:
|
|
"\<And>f cap. cap_get_tag (cap_C.words_C_update (\<lambda>w. Arrays.update w (Suc 0) (f w)) cap) = cap_get_tag cap"
|
|
by (simp add: cap_get_tag_def)
|
|
|
|
show ?case
|
|
apply (cinitlift cap_' bits_')
|
|
apply (rename_tac cbits ccap)
|
|
apply (elim conjE)
|
|
apply (rule_tac F="capCNodePtr_CL (cap_cnode_cap_lift ccap)
|
|
= capCNodePtr acap
|
|
\<and> capCNodeGuardSize acap < 32
|
|
\<and> capCNodeBits acap < 32
|
|
\<and> capCNodeGuard_CL (cap_cnode_cap_lift ccap)
|
|
= capCNodeGuard acap
|
|
\<and> unat (capCNodeGuardSize_CL (cap_cnode_cap_lift ccap))
|
|
= capCNodeGuardSize acap
|
|
\<and> unat (capCNodeRadix_CL (cap_cnode_cap_lift ccap))
|
|
= capCNodeBits acap
|
|
\<and> unat (0x20 - capCNodeRadix_CL (cap_cnode_cap_lift ccap))
|
|
= 32 - capCNodeBits acap
|
|
\<and> unat ((0x20 :: word32) - of_nat abits) = 32 - abits
|
|
\<and> unat (capCNodeGuardSize_CL (cap_cnode_cap_lift ccap)
|
|
+ capCNodeRadix_CL (cap_cnode_cap_lift ccap))
|
|
= capCNodeGuardSize acap + capCNodeBits acap"
|
|
in Corres_UL_C.ccorres_req)
|
|
apply (clarsimp simp: cap_get_tag_isCap[symmetric])
|
|
apply (clarsimp simp: cap_lift_cnode_cap cap_to_H_simps valid_cap'_def
|
|
capAligned_def cap_cnode_cap_lift_def objBits_simps
|
|
word_mod_2p_is_mask[where n=5, simplified]
|
|
elim!: ccap_relationE)
|
|
apply (simp add: unat_sub[unfolded word_le_nat_alt]
|
|
unat_of_nat32 word_bits_def)
|
|
apply (subst unat_plus_simple[symmetric], subst no_olen_add_nat)
|
|
apply (rule order_le_less_trans, rule add_le_mono)
|
|
apply (rule word_le_nat_alt[THEN iffD1], rule word_and_le1)+
|
|
apply simp
|
|
apply (rule ccorres_guard_imp2)
|
|
apply csymbr+
|
|
apply (rule ccorres_Guard_Seq, csymbr)
|
|
apply (simp add: resolveAddressBits.simps bindE_assoc extra_sle_sless_unfolds
|
|
Collect_True
|
|
split del: split_if del: Collect_const cong: call_ignore_cong)
|
|
apply (simp add: cutMon_walk_bindE del: Collect_const
|
|
split del: split_if cong: call_ignore_cong)
|
|
apply (rule ccorres_drop_cutMon_bindE, rule ccorres_assertE)
|
|
apply (rule ccorres_cutMon)
|
|
apply csymbr
|
|
apply (simp add: locateSlot_conv liftE_bindE cutMon_walk_bind)
|
|
apply (rule ccorres_drop_cutMon_bind, rule ccorres_stateAssert)
|
|
|
|
apply (rule_tac P="abits < capCNodeBits acap + capCNodeGuardSize acap"
|
|
in ccorres_case_bools2)
|
|
apply (rule ccorres_drop_cutMon)
|
|
apply csymbr+
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'=ret__int_' in ccorres_abstract_all, ceqv)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (rule ccorres_from_vcg_split_throws[where P=\<top> and P'=UNIV])
|
|
apply vcg
|
|
apply (rule conseqPre, vcg)
|
|
apply (clarsimp simp: unlessE_def split: split_if)
|
|
apply (simp add: throwError_def return_def cap_tag_defs
|
|
isRight_def isLeft_def
|
|
ccap_relation_NullCap_iff
|
|
in_bindE)
|
|
apply auto[1]
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply csymbr+
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_array_assertion_cnode_ctes ccorres_move_c_guard_cte
|
|
| csymbr)+
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply ccorres_remove_UNIV_guard
|
|
apply csymbr+
|
|
apply (rule ccorres_cond_false_seq)
|
|
apply (simp add: ccorres_expand_while_iff_Seq[symmetric]
|
|
whileAnno_def cong: call_ignore_cong)
|
|
apply (rule ccorres_cond_false)
|
|
apply (rule ccorres_cond_true_seq)
|
|
apply (rule ccorres_from_vcg_split_throws[where P=\<top> and P'=UNIV])
|
|
apply vcg
|
|
apply (rule conseqPre, vcg)
|
|
apply (clarsimp simp: unlessE_def split: split_if cong: call_ignore_cong)
|
|
apply (simp add: throwError_def return_def cap_tag_defs isRight_def
|
|
isLeft_def ccap_relation_NullCap_iff)
|
|
apply fastforce
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg, clarsimp)
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg, clarsimp)
|
|
|
|
apply (rule ccorres_cutMon)
|
|
apply (simp add: cutMon_walk_bindE unlessE_whenE
|
|
del: Collect_const
|
|
split del: split_if cong: call_ignore_cong)
|
|
apply (rule ccorres_drop_cutMon_bindE)
|
|
apply csymbr+
|
|
apply (rule ccorres_rhs_assoc2)
|
|
apply (rule_tac r'=dc and xf'=xfdc in ccorres_splitE[OF _ ceqv_refl])
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply csymbr
|
|
apply (simp add: unat_sub word_le_nat_alt if_1_0_0 shiftl_shiftr3 word_size
|
|
del: Collect_const)
|
|
apply (rule ccorres_Cond_rhs)
|
|
apply (rule ccorres_from_vcg_throws[where P=\<top> and P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: whenE_def throwError_def return_def
|
|
ccap_relation_NullCap_iff isRight_def isLeft_def)
|
|
apply (simp add: whenE_def)
|
|
apply (rule ccorres_returnOk_skip)
|
|
apply simp
|
|
apply (rule ccorres_cond_false)
|
|
apply (rule_tac P="valid_cap' acap" in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: valid_cap'_def isCap_simps if_1_0_0)
|
|
apply (simp add: unat_eq_0[symmetric] whenE_def returnOk_def return_def)
|
|
apply (rule ccorres_cutMon)
|
|
apply (simp add: liftE_bindE locateSlot_conv
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule_tac P="abits = capCNodeBits acap + capCNodeGuardSize acap"
|
|
in ccorres_case_bools2)
|
|
apply (rule ccorres_drop_cutMon)
|
|
apply (simp del: Collect_const)
|
|
apply (simp add: liftE_def getSlotCap_def del: Collect_const)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply csymbr+
|
|
apply (simp)
|
|
apply (rule ccorres_move_array_assertion_cnode_ctes
|
|
ccorres_move_c_guard_cte
|
|
ccorres_rhs_assoc | csymbr)+
|
|
apply (rule getCTE_cap_h_val_ccorres_split)
|
|
apply ceqv
|
|
apply (rename_tac "getCTE_cap")
|
|
apply (csymbr | rule ccorres_Guard_Seq)+
|
|
apply (rule ccorres_cond_false_seq)
|
|
apply (simp add: ccorres_expand_while_iff_Seq[symmetric]
|
|
whileAnno_def del: Collect_const)
|
|
apply (rule ccorres_cond_false)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply (rule ccorres_cond_false_seq)
|
|
apply (simp del: Collect_const)
|
|
apply (rule_tac P'="{s. cap_' s = getCTE_cap}"
|
|
in ccorres_from_vcg_throws[where P=\<top>])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: word_sle_def return_def returnOk_def
|
|
isRight_def)
|
|
apply (simp add: bind_bindE_assoc
|
|
del: Collect_const cong: call_ignore_cong if_cong)
|
|
apply (simp add: liftE_bindE "1.prems" unlessE_def
|
|
cutMon_walk_bind cnode_cap_case_if
|
|
del: Collect_const cong: if_cong call_ignore_cong)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply csymbr+
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_drop_cutMon_bind)
|
|
apply (rule ccorres_getSlotCap_cte_at)
|
|
apply (rule ccorres_move_c_guard_cte
|
|
ccorres_move_array_assertion_cnode_ctes
|
|
| csymbr)+
|
|
apply ctac
|
|
apply (csymbr | rule ccorres_Guard_Seq)+
|
|
apply (rule ccorres_cond_true_seq)
|
|
apply (rule ccorres_rhs_assoc | csymbr)+
|
|
apply (simp add: ccorres_expand_while_iff_Seq[symmetric]
|
|
whileAnno_def if_to_top_of_bindE bindE_assoc
|
|
split_def
|
|
cong: if_cong call_ignore_cong)
|
|
apply (rule ccorres_cutMon)
|
|
apply (simp add: cutMon_walk_if cong: call_ignore_cong)
|
|
apply (rule_tac Q'="\<lambda>s. ret__int_' s = from_bool (isCNodeCap rv)"
|
|
in ccorres_cond_both'[where Q=\<top>])
|
|
apply (clarsimp simp: from_bool_0)
|
|
apply (rule ccorres_rhs_assoc)+
|
|
apply (rule_tac P="ccorres r xf Gd Gd' hs a" for r xf Gd Gd' hs a in rsubst)
|
|
apply (rule "1.hyps",
|
|
(rule refl in_returns in_bind[THEN iffD2, OF exI, OF exI, OF conjI]
|
|
acc_CNodeCap_repr
|
|
| assumption
|
|
| clarsimp simp: unlessE_whenE locateSlot_conv
|
|
"1.prems"
|
|
| clarsimp simp: whenE_def[where P=False])+)[1]
|
|
apply (simp add: whileAnno_def extra_sle_sless_unfolds)
|
|
apply (rule ccorres_drop_cutMon)
|
|
apply (simp add: liftE_def getSlotCap_def)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply (rule ccorres_pre_getCTE)
|
|
apply (rule ccorres_cond_false_seq)
|
|
apply (rule_tac P="\<lambda>s. cteCap rva = rv" and P'="{s. cap_' s = cap}"
|
|
in ccorres_from_vcg_throws)
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: return_def returnOk_def word_sle_def isRight_def)
|
|
apply simp
|
|
apply (wp getSlotCap_wp)
|
|
apply (simp add: if_1_0_0)
|
|
apply vcg
|
|
apply (wp whenE_throwError_wp)
|
|
apply (simp add: ccHoarePost_def del: Collect_const)
|
|
apply vcg
|
|
apply (clarsimp simp: Collect_const_mem if_1_0_0 of_bl_from_bool
|
|
split del: split_if cong: if_cong)
|
|
apply (clarsimp simp: cap_get_tag_isCap
|
|
option.split[where P="\<lambda>x. x"]
|
|
isCNodeCap_capUntypedPtr_capCNodePtr
|
|
)
|
|
apply (clarsimp simp: word_less_nat_alt word_le_nat_alt linorder_not_less
|
|
cong: conj_cong)
|
|
apply (clarsimp simp: word_less_nat_alt word_le_nat_alt linorder_not_less
|
|
cong: rev_conj_cong)
|
|
apply (subgoal_tac "\<not> isZombie acap \<and> \<not> isThreadCap acap")
|
|
prefer 2
|
|
apply (clarsimp simp: isCap_simps)
|
|
apply (simp add: imp_conjL)
|
|
apply (simp only: all_simps[symmetric] imp_conjL cong: imp_cong,
|
|
simp only: all_simps, simp)
|
|
apply (simp add: unat_shiftr_le_bound)
|
|
apply (frule(1) valid_cnode_bits_0, clarsimp)
|
|
apply (intro conjI impI)
|
|
apply (simp add: size_of_def)
|
|
apply (erule (1) valid_cnode_cap_cte_at')
|
|
apply simp
|
|
apply (rule shiftr_less_t2n')
|
|
apply simp
|
|
apply simp
|
|
apply (simp add:size_of_def)
|
|
apply (erule (1) valid_cnode_cap_cte_at')
|
|
apply simp
|
|
apply (rule shiftr_less_t2n')
|
|
apply simp
|
|
apply simp
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (clarsimp dest!: ctes_of_valid')
|
|
apply (simp add: cte_level_bits_def size_of_def field_simps)
|
|
apply (simp add: shiftl_shiftr3 word_size)
|
|
apply (simp add: word_bw_assocs mask_and_mask min.absorb2)
|
|
apply (simp_all add: unat_sub word_le_nat_alt unat_eq_0[symmetric])
|
|
apply (simp_all add: unat_plus_if' if_P)
|
|
apply (clarsimp simp: rightsFromWord_and shiftr_over_and_dist
|
|
size_of_def cte_level_bits_def field_simps shiftl_shiftl
|
|
shiftl_shiftr3 word_size)+
|
|
apply (clarsimp simp: unat_gt_0 from_bool_0 trans [OF eq_commute from_bool_eq_if])
|
|
apply (intro conjI impI, simp_all)[1]
|
|
apply (rule word_unat.Rep_inject[THEN iffD1], subst unat_plus_if')
|
|
apply (simp add: unat_plus_if' unat_of_nat32 word_bits_def)
|
|
apply (clarsimp simp: rightsFromWord_and shiftr_over_and_dist
|
|
size_of_def cte_level_bits_def field_simps shiftl_shiftl
|
|
shiftl_shiftr3 word_size)+
|
|
apply (clarsimp simp: unat_gt_0 from_bool_0 trans [OF eq_commute from_bool_eq_if])
|
|
|
|
apply (intro conjI impI, simp_all)[1]
|
|
apply (rule word_unat.Rep_inject[THEN iffD1], simp add: unat_of_nat32 word_bits_def)
|
|
done
|
|
qed
|
|
|
|
lemmas lookup_fp_ccorres
|
|
= lookup_fp_ccorres'[OF refl, THEN ccorres_use_cutMon]
|
|
|
|
lemma ccap_relation_case_sum_Null_endpoint:
|
|
"ccap_relation (case x of Inl v => NullCap | Inr v => v) ccap
|
|
\<Longrightarrow> (cap_get_tag ccap = scast cap_endpoint_cap)
|
|
= (isRight x \<and> isEndpointCap (theRight x))"
|
|
by (clarsimp simp: cap_get_tag_isCap isRight_def isCap_simps
|
|
split: sum.split_asm)
|
|
|
|
lemma empty_fail_isRunnable:
|
|
"empty_fail (isRunnable t)"
|
|
by (simp add: isRunnable_def isBlocked_def)
|
|
|
|
lemma findPDForASID_pd_at_asid_noex:
|
|
"\<lbrace>pd_at_asid' pd asid\<rbrace> findPDForASID asid \<lbrace>\<lambda>rv s. rv = pd\<rbrace>,\<lbrace>\<bottom>\<bottom>\<rbrace>"
|
|
apply (simp add: findPDForASID_def
|
|
liftME_def bindE_assoc
|
|
cong: option.case_cong)
|
|
apply (rule seqE, rule assertE_sp)+
|
|
apply (rule seqE, rule liftE_wp, rule gets_sp)
|
|
apply (rule hoare_pre)
|
|
apply (rule seqE[rotated])
|
|
apply wpc
|
|
apply wp[1]
|
|
apply (rule seqE[rotated])
|
|
apply (rule seqE[rotated])
|
|
apply (rule returnOk_wp)
|
|
apply (simp add:checkPDAt_def)
|
|
apply wp[1]
|
|
apply (rule assertE_wp)
|
|
apply wpc
|
|
apply wp[1]
|
|
apply (rule liftE_wp)
|
|
apply (rule getASID_wp)
|
|
apply (clarsimp simp: pd_at_asid'_def obj_at'_def projectKOs
|
|
inv_ASIDPool)
|
|
done
|
|
|
|
lemma ccorres_catch_bindE_symb_exec_l:
|
|
"\<lbrakk> \<And>s. \<lbrace>op = s\<rbrace> f \<lbrace>\<lambda>rv. op = s\<rbrace>; empty_fail f;
|
|
\<And>rv. ccorres_underlying sr G r xf ar axf (Q rv) (Q' rv) hs (catch (g rv) h >>= j) c;
|
|
\<And>ex. ccorres_underlying sr G r xf ar axf (R ex) (R' ex) hs (h ex >>= j) c;
|
|
\<lbrace>P\<rbrace> f \<lbrace>Q\<rbrace>,\<lbrace>R\<rbrace> \<rbrakk>
|
|
\<Longrightarrow>
|
|
ccorres_underlying sr G r xf ar axf P {s. (\<forall>rv. s \<in> Q' rv) \<and> (\<forall>ex. s \<in> R' ex)} hs
|
|
(catch (f >>=E g) h >>= j) c"
|
|
apply (simp add: catch_def bindE_def bind_assoc lift_def)
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_symb_exec_l[where G=P])
|
|
apply wpc
|
|
apply (simp add: throwError_bind)
|
|
apply assumption+
|
|
apply (clarsimp simp: valid_def validE_def split_def split: sum.split_asm)
|
|
apply assumption
|
|
apply clarsimp
|
|
done
|
|
|
|
lemmas ccorres_catch_symb_exec_l
|
|
= ccorres_catch_bindE_symb_exec_l[where g=returnOk,
|
|
simplified bindE_returnOk returnOk_catch_bind]
|
|
|
|
|
|
lemma ccorres_alt_rdonly_bind:
|
|
"\<lbrakk> ccorres_underlying sr Gamm r xf arrel axf A A' hs
|
|
(f >>= (\<lambda>x. alternative (g x) h)) c;
|
|
\<And>s. \<lbrace>op = s\<rbrace> f \<lbrace>\<lambda>rv. op = s\<rbrace>; empty_fail f \<rbrakk>
|
|
\<Longrightarrow> ccorres_underlying sr Gamm r xf arrel axf A A' hs
|
|
(alternative (f >>= (\<lambda>x. g x)) h) c"
|
|
apply (rule ccorresI')
|
|
apply (erule(3) ccorresE)
|
|
defer
|
|
apply assumption
|
|
apply (subst alternative_left_readonly_bind, assumption)
|
|
apply (rule notI, drule(1) empty_failD)
|
|
apply (simp add: alternative_def bind_def)
|
|
apply fastforce
|
|
apply (subgoal_tac "\<forall>x \<in> fst (f s). snd x = s")
|
|
apply (simp add: bind_def alternative_def image_image split_def
|
|
cong: image_cong)
|
|
apply clarsimp
|
|
apply (drule use_valid, assumption, simp+)
|
|
done
|
|
|
|
definition
|
|
"pd_has_hwasid pd =
|
|
(\<lambda>s. \<exists>v. asid_map_pd_to_hwasids (armKSASIDMap (ksArchState s)) pd = {v})"
|
|
|
|
lemma ccap_relation_pd_helper:
|
|
"\<lbrakk> ccap_relation cap cap'; cap_get_tag cap' = scast cap_page_directory_cap \<rbrakk>
|
|
\<Longrightarrow> capPDBasePtr_CL (cap_page_directory_cap_lift cap') = capPDBasePtr (capCap cap)"
|
|
by (clarsimp simp: cap_lift_page_directory_cap cap_to_H_simps
|
|
cap_page_directory_cap_lift
|
|
elim!: ccap_relationE)
|
|
|
|
lemma stored_hw_asid_get_ccorres_split':
|
|
assumes ptr: "ptr = CTypesDefs.ptr_add pd 0xFF0"
|
|
assumes ceqv: "\<And>rv' t t'. ceqv Gamm stored_hw_asid___struct_pde_C_' rv' t t' c (c' rv')"
|
|
and ccorres: "\<And>shw_asid. pde_get_tag shw_asid = scast pde_pde_invalid \<Longrightarrow>
|
|
ccorres_underlying rf_sr Gamm r xf ar axf
|
|
(Q shw_asid) (R shw_asid) hs
|
|
a (c' shw_asid)"
|
|
shows "ccorres_underlying rf_sr Gamm r xf ar axf
|
|
(\<lambda>s. page_directory_at' (ptr_val pd) s \<and> valid_pde_mappings' s
|
|
\<and> (\<forall>shw_asid. asid_map_pd_to_hwasids (armKSASIDMap (ksArchState s)) (ptr_val pd)
|
|
= set_option (pde_stored_asid shw_asid) \<and> pde_get_tag shw_asid = scast pde_pde_invalid
|
|
\<longrightarrow> P shw_asid \<and> Q shw_asid s))
|
|
{s. \<forall>stored_hw_asid. P stored_hw_asid \<and> pde_get_tag stored_hw_asid = scast pde_pde_invalid
|
|
\<and> (cslift s \<circ>\<^sub>m pd_pointer_to_asid_slot) (ptr_val pd) = Some stored_hw_asid
|
|
\<longrightarrow> s \<lparr> stored_hw_asid___struct_pde_C_' := stored_hw_asid \<rparr>
|
|
\<in> R stored_hw_asid} hs
|
|
a (Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t ptr\<rbrace>
|
|
(\<acute>stored_hw_asid___struct_pde_C :==
|
|
h_val (hrs_mem \<acute>t_hrs) ptr);; c)"
|
|
unfolding ptr
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_Guard_Seq)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule ccorres_abstract_all[OF ceqv])
|
|
apply (rule_tac A="\<lambda>s. asid_map_pd_to_hwasids (armKSASIDMap (ksArchState s)) (ptr_val pd)
|
|
= set_option (pde_stored_asid rv') \<and> pde_get_tag rv' = scast pde_pde_invalid
|
|
\<longrightarrow> P rv' \<and> Q rv' s"
|
|
and A'="{s. P rv' \<longrightarrow> s \<in> R rv'}
|
|
\<inter> {s. (cslift s \<circ>\<^sub>m pd_pointer_to_asid_slot) (ptr_val pd)
|
|
= Some rv' \<and> pde_get_tag rv' = scast pde_pde_invalid}"
|
|
in ccorres_guard_imp2)
|
|
apply (rule_tac P="pde_get_tag rv' = scast pde_pde_invalid" in ccorres_gen_asm)
|
|
apply (erule ccorres)
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def
|
|
carch_state_relation_def
|
|
map_comp_Some_iff)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg)
|
|
apply clarsimp
|
|
apply clarsimp
|
|
apply (frule_tac x=pd_asid_slot in page_directory_pde_atI')
|
|
apply (simp add: pd_asid_slot_def pageBits_def)
|
|
apply (cases pd)
|
|
apply (simp add: typ_at_to_obj_at_arches)
|
|
apply (drule obj_at_ko_at')
|
|
apply (clarsimp simp: pd_asid_slot_def)
|
|
apply (erule cmap_relationE1[OF rf_sr_cpde_relation], erule ko_at_projectKO_opt)
|
|
apply (frule(1) valid_pde_mappings_ko_atD')
|
|
apply (clarsimp simp: typ_heap_simps' map_comp_Some_iff
|
|
valid_pde_mapping'_def)
|
|
apply (clarsimp simp: pd_pointer_to_asid_slot_def page_directory_at'_def
|
|
add_mask_eq pdBits_def pageBits_def word_bits_def
|
|
valid_pde_mapping_offset'_def pd_asid_slot_def)
|
|
apply (simp add: cpde_relation_def Let_def pde_lift_def
|
|
split: split_if_asm)
|
|
done
|
|
|
|
lemma ptr_add_0xFF0:
|
|
"pde_Ptr (pd + 0x3FC0) = CTypesDefs.ptr_add (pde_Ptr pd) 0xFF0"
|
|
by simp
|
|
|
|
lemmas stored_hw_asid_get_ccorres_split
|
|
= stored_hw_asid_get_ccorres_split'[OF refl]
|
|
stored_hw_asid_get_ccorres_split'[OF ptr_add_0xFF0]
|
|
|
|
lemma doMachineOp_pd_at_asid':
|
|
"\<lbrace>\<lambda>s. P (pd_at_asid' pd asid s)\<rbrace> doMachineOp oper \<lbrace>\<lambda>rv s. P (pd_at_asid' pd asid s)\<rbrace>"
|
|
apply (simp add: doMachineOp_def split_def)
|
|
apply wp
|
|
apply (clarsimp simp: pd_at_asid'_def)
|
|
done
|
|
|
|
lemma doMachineOp_page_directory_at_P':
|
|
"\<lbrace>\<lambda>s. P (page_directory_at' pd s)\<rbrace> doMachineOp oper \<lbrace>\<lambda>rv s. P (page_directory_at' pd s)\<rbrace>"
|
|
apply (simp add: doMachineOp_def split_def)
|
|
apply wp
|
|
apply (clarsimp simp: pd_at_asid'_def)
|
|
done
|
|
|
|
lemma pde_stored_asid_Some:
|
|
"(pde_stored_asid pde = Some v)
|
|
= (pde_get_tag pde = scast pde_pde_invalid
|
|
\<and> to_bool (stored_asid_valid_CL (pde_pde_invalid_lift pde))
|
|
\<and> v = ucast (stored_hw_asid_CL (pde_pde_invalid_lift pde)))"
|
|
by (auto simp add: pde_stored_asid_def split: split_if)
|
|
|
|
lemma pointerInUserData_c_guard':
|
|
"\<lbrakk> pointerInUserData ptr s; no_0_obj' s; is_aligned ptr 2 \<rbrakk>
|
|
\<Longrightarrow> c_guard (Ptr ptr :: word32 ptr)"
|
|
apply (simp add: pointerInUserData_def)
|
|
apply (simp add: c_guard_def ptr_aligned_def)
|
|
apply (rule conjI)
|
|
apply (simp add: is_aligned_def)
|
|
apply (simp add: c_null_guard_def)
|
|
apply (subst intvl_aligned_bottom_eq[where n=2 and bits=2], simp_all)
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma heap_relation_user_word_at_cross_over:
|
|
"\<lbrakk> user_word_at x p s; cmap_relation (heap_to_page_data (ksPSpace s)
|
|
(underlying_memory (ksMachineState s))) (cslift s') Ptr cuser_data_relation;
|
|
p' = Ptr p \<rbrakk>
|
|
\<Longrightarrow> c_guard p' \<and> hrs_htd (t_hrs_' (globals s')) \<Turnstile>\<^sub>t p'
|
|
\<and> h_val (hrs_mem (t_hrs_' (globals s'))) p' = x"
|
|
apply (erule cmap_relationE1)
|
|
apply (clarsimp simp: heap_to_page_data_def Let_def
|
|
user_word_at_def pointerInUserData_def
|
|
typ_at_to_obj_at'[where 'a=user_data, simplified])
|
|
apply (drule obj_at_ko_at', clarsimp)
|
|
apply (rule conjI, rule exI, erule ko_at_projectKO_opt)
|
|
apply (rule refl)
|
|
apply (thin_tac "heap_to_page_data a b c = d" for a b c d)
|
|
apply (cut_tac x=p and w="~~ mask pageBits" in word_plus_and_or_coroll2)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: user_word_at_def pointerInUserData_def)
|
|
apply (simp add: c_guard_def c_null_guard_def ptr_aligned_def)
|
|
apply (drule lift_t_g)
|
|
apply (clarsimp simp: )
|
|
apply (simp add: align_of_def user_data_C_size_of user_data_C_align_of
|
|
size_of_def user_data_C_typ_name)
|
|
apply (fold is_aligned_def[where n=2, simplified], simp)
|
|
apply (erule contra_subsetD[rotated])
|
|
apply (rule order_trans[rotated])
|
|
apply (rule_tac x="p && mask pageBits" and y=4 in intvl_sub_offset)
|
|
apply (cut_tac y=p and a="mask pageBits && (~~ mask 2)" in word_and_le1)
|
|
apply (subst(asm) word_bw_assocs[symmetric], subst(asm) aligned_neg_mask,
|
|
erule is_aligned_andI1)
|
|
apply (simp add: word_le_nat_alt mask_def pageBits_def)
|
|
apply simp
|
|
apply (clarsimp simp: cuser_data_relation_def user_word_at_def)
|
|
apply (frule_tac f="[''words_C'']" in h_t_valid_field[OF h_t_valid_clift],
|
|
simp+)
|
|
apply (drule_tac n="uint (p && mask pageBits >> 2)" in h_t_valid_Array_element)
|
|
apply simp
|
|
apply (simp add: shiftr_over_and_dist mask_def pageBits_def uint_and)
|
|
apply (insert int_and_leR [where a="uint (p >> 2)" and b=1023], clarsimp)[1]
|
|
apply (simp add: field_lvalue_def
|
|
field_lookup_offset_eq[OF trans, OF _ arg_cong[where f=Some, symmetric], OF _ prod.collapse]
|
|
word32_shift_by_2 shiftr_shiftl1 is_aligned_neg_mask_eq is_aligned_andI1)
|
|
apply (drule_tac x="ucast (p >> 2)" in spec)
|
|
apply (simp add: byte_to_word_heap_def Let_def ucast_ucast_mask)
|
|
apply (fold shiftl_t2n[where n=2, simplified, simplified mult.commute mult.left_commute])
|
|
apply (simp add: aligned_shiftr_mask_shiftl pageBits_def)
|
|
apply (rule trans[rotated], rule_tac hp="hrs_mem (t_hrs_' (globals s'))"
|
|
and x="Ptr &(Ptr (p && ~~ mask 12) \<rightarrow> [''words_C''])"
|
|
in access_in_array)
|
|
apply (rule trans)
|
|
apply (erule typ_heap_simps)
|
|
apply simp+
|
|
apply (rule order_less_le_trans, rule unat_lt2p)
|
|
apply simp
|
|
apply (fastforce simp add: typ_info_word)
|
|
apply simp
|
|
apply (rule_tac f="h_val hp" for hp in arg_cong)
|
|
apply simp
|
|
apply (simp add: field_lvalue_def)
|
|
apply (simp add: ucast_nat_def ucast_ucast_mask)
|
|
apply (fold shiftl_t2n[where n=2, simplified, simplified mult.commute mult.left_commute])
|
|
apply (simp add: aligned_shiftr_mask_shiftl)
|
|
done
|
|
|
|
lemma pointerInUserData_h_t_valid2:
|
|
"\<lbrakk> pointerInUserData ptr s; cmap_relation (heap_to_page_data (ksPSpace s)
|
|
(underlying_memory (ksMachineState s))) (cslift s') Ptr cuser_data_relation;
|
|
is_aligned ptr 2 \<rbrakk>
|
|
\<Longrightarrow> hrs_htd (t_hrs_' (globals s')) \<Turnstile>\<^sub>t (Ptr ptr :: word32 ptr)"
|
|
apply (frule_tac p=ptr in
|
|
heap_relation_user_word_at_cross_over[rotated, OF _ refl])
|
|
apply (simp add: user_word_at_def)
|
|
apply simp
|
|
done
|
|
|
|
lemma dmo_clearExMonitor_setCurThread_swap:
|
|
"(do _ \<leftarrow> doMachineOp ARM.clearExMonitor;
|
|
setCurThread thread
|
|
od)
|
|
= (do _ \<leftarrow> 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 add: select_f_oblivious)
|
|
done
|
|
|
|
lemma ccorres_bind_assoc_rev:
|
|
"ccorres_underlying sr E r xf arrel axf G G' hs ((a1 >>= a2) >>= a3) c
|
|
\<Longrightarrow> ccorres_underlying sr E r xf arrel axf G G' hs
|
|
(do x \<leftarrow> a1; y \<leftarrow> a2 x; a3 y od) c"
|
|
by (simp add: bind_assoc)
|
|
|
|
lemma monadic_rewrite_gets_l:
|
|
"(\<And>x. monadic_rewrite F E (P x) (g x) m)
|
|
\<Longrightarrow> monadic_rewrite F E (\<lambda>s. P (f s) s) (gets f >>= (\<lambda>x. g x)) m"
|
|
by (auto simp add: monadic_rewrite_def exec_gets)
|
|
|
|
lemma pd_at_asid_inj':
|
|
"pd_at_asid' pd asid s \<Longrightarrow> pd_at_asid' pd' asid s \<Longrightarrow> pd' = pd"
|
|
by (clarsimp simp: pd_at_asid'_def obj_at'_def)
|
|
|
|
lemma armv_contextSwitch_HWASID_fp_rewrite:
|
|
"monadic_rewrite True False
|
|
(pd_has_hwasid pd and pd_at_asid' pd asid and
|
|
(\<lambda>s. asid_map_pd_to_hwasids (armKSASIDMap (ksArchState s)) pd
|
|
= set_option (pde_stored_asid v)))
|
|
(armv_contextSwitch pd asid)
|
|
(doMachineOp (armv_contextSwitch_HWASID pd (the (pde_stored_asid v))))"
|
|
apply (simp add: getHWASID_def armv_contextSwitch_def
|
|
bind_assoc loadHWASID_def
|
|
findPDForASIDAssert_def
|
|
checkPDAt_def checkPDUniqueToASID_def
|
|
checkPDASIDMapMembership_def
|
|
stateAssert_def2[folded assert_def])
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_gets_l)
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply (wp | simp)+
|
|
apply (simp add: empty_fail_findPDForASID empty_fail_catch)
|
|
apply (rule monadic_rewrite_assert monadic_rewrite_gets_l)+
|
|
apply (rule_tac P="x asid \<noteq> None \<and> fst (the (x asid)) = the (pde_stored_asid v)"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (simp only: case_option_If2 simp_thms if_True if_False
|
|
split_def, simp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp findPDForASID_pd_at_wp | simp only: const_def)+
|
|
apply (clarsimp simp: pd_has_hwasid_def cte_level_bits_def
|
|
field_simps cte_wp_at_ctes_of
|
|
word_0_sle_from_less
|
|
isCap_simps invs_valid_pspace'
|
|
simp del: Collect_const rf_sr_upd_safe)
|
|
apply (drule(1) pd_at_asid_inj')
|
|
apply (clarsimp simp: singleton_eq_o2s singleton_eq_o2s[THEN trans[OF eq_commute]])
|
|
apply (cases "pde_stored_asid v", simp_all)
|
|
apply (clarsimp simp: asid_map_pd_to_hwasids_def set_eq_subset
|
|
elim!: ranE)
|
|
apply (case_tac "x = asid")
|
|
apply clarsimp
|
|
apply (erule notE, rule_tac a=x in ranI)
|
|
apply simp
|
|
done
|
|
|
|
lemma switchToThread_fp_ccorres:
|
|
"ccorres dc xfdc (pspace_aligned' and pspace_distinct' and valid_objs' and no_0_obj'
|
|
and valid_pde_mappings' and valid_arch_state'
|
|
and tcb_at' thread
|
|
and cte_wp_at' (\<lambda>cte. isValidVTableRoot (cteCap cte)
|
|
\<and> capPDBasePtr (capCap (cteCap cte)) = pd)
|
|
(thread + tcbVTableSlot * 0x10)
|
|
and pd_has_hwasid pd
|
|
and (\<lambda>s. asid_map_pd_to_hwasids (armKSASIDMap (ksArchState s)) pd
|
|
= set_option (pde_stored_asid v)))
|
|
(UNIV \<inter> {s. thread_' s = tcb_ptr_to_ctcb_ptr thread}
|
|
\<inter> {s. cap_pd_' s = pde_Ptr pd}
|
|
\<inter> {s. stored_hw_asid___struct_pde_C_' s = v}) []
|
|
(Arch.switchToThread thread
|
|
>>= (\<lambda>_. setCurThread thread))
|
|
(Call switchToThread_fp_'proc)"
|
|
apply (cinit' lift: thread_' cap_pd_' stored_hw_asid___struct_pde_C_')
|
|
apply (simp add: ARM_H.switchToThread_def bind_assoc
|
|
setVMRoot_def cap_case_isPageDirectoryCap
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (simp add: getThreadVSpaceRoot_def locateSlot_conv getSlotCap_def
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (simp only: )
|
|
apply (rule ccorres_symb_exec_r, rule_tac xf'="hw_asid_'" in ccorres_abstract,
|
|
ceqv, rename_tac "hw_asid")
|
|
apply (rule ccorres_getCTE, rename_tac cte)
|
|
apply (rule_tac P="isValidVTableRoot (cteCap cte)
|
|
\<and> capPDBasePtr (capCap (cteCap cte)) = pd" in ccorres_gen_asm)
|
|
apply (erule conjE, drule isValidVTableRootD)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_catch_bindE_symb_exec_l,
|
|
rule findPDForASID_inv,
|
|
rule empty_fail_findPDForASID)
|
|
apply (rename_tac "pd_found")
|
|
apply (rule_tac P="pd_found \<noteq> pd"
|
|
in ccorres_case_bools2)
|
|
apply (simp add: bindE_assoc catch_liftE_bindE bind_assoc
|
|
checkPDNotInASIDMap_def
|
|
checkPDASIDMapMembership_def
|
|
catch_throwError)
|
|
apply (rule ccorres_stateAssert)
|
|
apply (rule ccorres_False[where P'=UNIV])
|
|
apply (simp add: catch_liftE bind_assoc
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule monadic_rewrite_ccorres_assemble[rotated])
|
|
apply (rule monadic_rewrite_bind_head)
|
|
apply (rule_tac pd=pd and v=v
|
|
in armv_contextSwitch_HWASID_fp_rewrite)
|
|
apply (ctac(no_vcg) add: armv_contextSwitch_HWASID_ccorres)
|
|
apply (simp add: storeWordUser_def bind_assoc case_option_If2
|
|
split_def
|
|
del: Collect_const)
|
|
apply (rule ccorres_symb_exec_l[OF _ gets_inv _ empty_fail_gets])
|
|
apply (rename_tac "gf")
|
|
apply (rule ccorres_pre_threadGet)
|
|
apply (rule ccorres_stateAssert)
|
|
apply (rule_tac P="pointerInUserData gf and no_0_obj'
|
|
and K (is_aligned gf 2)
|
|
and (\<lambda>s. gf = armKSGlobalsFrame (ksArchState s))
|
|
and valid_arch_state'"
|
|
in ccorres_cross_over_guard)
|
|
apply (rule ccorres_Guard_Seq)
|
|
apply (rule ccorres_Guard_Seq)
|
|
apply (rule ccorres_move_c_guard_tcb)
|
|
apply (ctac add: storeWord_ccorres'[unfolded fun_app_def])
|
|
apply (simp only: dmo_clearExMonitor_setCurThread_swap
|
|
dc_def[symmetric])
|
|
apply (rule ccorres_split_nothrow_novcg_dc)
|
|
apply (rule ccorres_from_vcg[where P=\<top> and P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp del: rf_sr_upd_safe)
|
|
apply (clarsimp simp: setCurThread_def simpler_modify_def
|
|
rf_sr_def cstate_relation_def Let_def
|
|
carch_state_relation_def cmachine_state_relation_def)
|
|
apply (ctac add: clearExMonitor_fp_ccorres)
|
|
apply wp
|
|
apply (simp add: guard_is_UNIV_def)
|
|
apply wp
|
|
apply vcg
|
|
apply wp
|
|
apply (simp add: obj_at'_weakenE[OF _ TrueI])
|
|
apply (wp hoare_drop_imps)[1]
|
|
apply (simp add: bind_assoc checkPDNotInASIDMap_def
|
|
checkPDASIDMapMembership_def)
|
|
apply (rule ccorres_stateAssert)
|
|
apply (rule ccorres_False[where P'=UNIV])
|
|
apply simp
|
|
apply (wp findPDForASID_pd_at_wp)[1]
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg, clarsimp)
|
|
apply (clarsimp simp: pd_has_hwasid_def cte_level_bits_def
|
|
field_simps cte_wp_at_ctes_of
|
|
pd_at_asid'_def word_0_sle_from_less
|
|
isCap_simps invs_valid_pspace'
|
|
simp del: Collect_const rf_sr_upd_safe)
|
|
apply (frule_tac P="\<lambda>Sf. Sf x = S'" for x S'
|
|
in subst[OF meta_eq_to_obj_eq, OF asid_map_pd_to_hwasids_def])
|
|
apply (clarsimp simp: isCap_simps dest!: isValidVTableRootD)
|
|
apply (rule context_conjI)
|
|
apply (drule singleton_eqD[OF sym])
|
|
apply clarsimp
|
|
apply (fastforce simp: ran_def)
|
|
apply (frule ctes_of_valid', clarsimp, clarsimp simp: valid_cap'_def)
|
|
apply (cut_tac s=s in is_aligned_globals_2_strg[rule_format])
|
|
apply auto[1]
|
|
apply (intro conjI impI)
|
|
apply simp
|
|
apply (clarsimp simp: singleton_eq_o2s projectKOs obj_at'_def)
|
|
apply (clarsimp simp: singleton_eq_o2s projectKOs obj_at'_def
|
|
pde_stored_asid_def split: split_if_asm)
|
|
apply (clarsimp simp: singleton_eq_o2s pde_stored_asid_def
|
|
split: if_splits)
|
|
apply (clarsimp simp del: rf_sr_upd_safe
|
|
dest!: isValidVTableRootD
|
|
simp: cap_get_tag_isCap_ArchObject2 pde_stored_asid_Some
|
|
rf_sr_asid_map_pd_to_hwasids option_set_singleton_eq
|
|
map_comp_Some_iff)
|
|
apply (clarsimp simp: typ_heap_simps' ctcb_relation_def
|
|
trans[OF eq_commute option_set_singleton_eq]
|
|
pde_stored_asid_Some
|
|
simp del: rf_sr_upd_safe)
|
|
apply (clarsimp simp: pde_stored_asid_def typ_heap_simps'
|
|
pointerInUserData_h_t_valid2
|
|
simp del: rf_sr_upd_safe)
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def carch_state_relation_def
|
|
carch_globals_def pointerInUserData_c_guard'
|
|
pointerInUserData_h_t_valid2 cpspace_relation_def
|
|
c_guard_abs_word32_armKSGlobalsFrame)
|
|
done
|
|
|
|
lemma thread_state_ptr_set_tsType_np_spec:
|
|
defines "ptr s \<equiv> cparent \<^bsup>s\<^esup>ts_ptr [''tcbState_C''] :: tcb_C ptr"
|
|
shows
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ptr s
|
|
\<and> (tsType_' s = scast ThreadState_Running \<or> tsType_' s = scast ThreadState_Restart
|
|
\<or> tsType_' s = scast ThreadState_BlockedOnReply)\<rbrace>
|
|
Call thread_state_ptr_set_tsType_np_'proc
|
|
{t. (\<exists>thread_state.
|
|
tsType_CL (thread_state_lift thread_state) = tsType_' s \<and>
|
|
tcbQueued_CL (thread_state_lift thread_state)
|
|
= tcbQueued_CL (thread_state_lift (tcbState_C (the (cslift s (ptr s))))) \<and>
|
|
cslift t = cslift s(ptr s \<mapsto> the (cslift s (ptr s))\<lparr>tcbState_C := thread_state\<rparr>))
|
|
\<and> types_proofs.cslift_all_but_tcb_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: ptr_def)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff)
|
|
apply (frule h_t_valid_c_guard_cparent[OF h_t_valid_clift], simp+,
|
|
simp add: typ_uinfo_t_def)
|
|
apply (frule clift_subtype, simp+)
|
|
apply (clarsimp simp: typ_heap_simps' word_sle_def word_sless_def)
|
|
apply (subst parent_update_child, erule typ_heap_simps', simp+)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (rule exI, rule conjI[OF _ conjI [OF _ refl]])
|
|
apply (simp_all add: thread_state_lift_def)
|
|
apply (auto simp: "StrictC'_thread_state_defs")
|
|
done
|
|
|
|
lemma thread_state_ptr_mset_blockingObject_tsType_spec:
|
|
defines "ptr s \<equiv> cparent \<^bsup>s\<^esup>ts_ptr [''tcbState_C''] :: tcb_C ptr"
|
|
shows
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ptr s \<and> is_aligned (ep_ref_' s) 4
|
|
\<and> tsType_' s && mask 4 = tsType_' s\<rbrace>
|
|
Call thread_state_ptr_mset_blockingObject_tsType_'proc
|
|
{t. (\<exists>thread_state.
|
|
tsType_CL (thread_state_lift thread_state) = tsType_' s
|
|
\<and> blockingObject_CL (thread_state_lift thread_state) = ep_ref_' s
|
|
\<and> tcbQueued_CL (thread_state_lift thread_state)
|
|
= tcbQueued_CL (thread_state_lift (tcbState_C (the (cslift s (ptr s)))))
|
|
\<and> cslift t = cslift s(ptr s \<mapsto> the (cslift s (ptr s))\<lparr>tcbState_C := thread_state\<rparr>))
|
|
\<and> types_proofs.cslift_all_but_tcb_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: ptr_def)
|
|
apply (frule h_t_valid_c_guard_cparent, simp+)
|
|
apply (simp add: typ_uinfo_t_def)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff)
|
|
apply (frule clift_subtype, simp+)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (subst parent_update_child, erule typ_heap_simps', simp+)
|
|
apply (clarsimp simp: typ_heap_simps' word_sless_def word_sle_def)
|
|
apply (rule exI, intro conjI[rotated], rule refl)
|
|
apply (simp_all add: thread_state_lift_def word_ao_dist
|
|
is_aligned_mask mask_def mask_eq_0_eq_x,
|
|
simp_all add: mask_eq_x_eq_0)
|
|
done
|
|
|
|
lemma mdb_node_ptr_mset_mdbNext_mdbRevocable_mdbFirstBadged_spec:
|
|
defines "ptr s \<equiv> cparent \<^bsup>s\<^esup>node_ptr [''cteMDBNode_C''] :: cte_C ptr"
|
|
shows
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ptr s \<and> is_aligned (mdbNext___unsigned_long_' s) 4
|
|
\<and> mdbRevocable___unsigned_long_' s && mask 1 = mdbRevocable___unsigned_long_' s
|
|
\<and> mdbFirstBadged___unsigned_long_' s && mask 1 = mdbFirstBadged___unsigned_long_' s\<rbrace>
|
|
Call mdb_node_ptr_mset_mdbNext_mdbRevocable_mdbFirstBadged_'proc
|
|
{t. (\<exists>mdb_node.
|
|
mdb_node_lift mdb_node = mdb_node_lift (cteMDBNode_C (the (cslift s (ptr s))))
|
|
\<lparr> mdbNext_CL := mdbNext___unsigned_long_' s, mdbRevocable_CL := mdbRevocable___unsigned_long_' s,
|
|
mdbFirstBadged_CL := mdbFirstBadged___unsigned_long_' s \<rparr>
|
|
\<and> cslift t = cslift s(ptr s \<mapsto> the (cslift s (ptr s)) \<lparr> cteMDBNode_C := mdb_node \<rparr>))
|
|
\<and> types_proofs.cslift_all_but_cte_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: ptr_def)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff)
|
|
apply (frule h_t_valid_c_guard_cparent[OF h_t_valid_clift], simp+,
|
|
simp add: typ_uinfo_t_def)
|
|
apply (frule clift_subtype, simp+)
|
|
apply (clarsimp simp: typ_heap_simps' word_sle_def word_sless_def)
|
|
apply (subst parent_update_child, erule typ_heap_simps', simp+)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (rule exI, rule conjI[OF _ refl])
|
|
apply (simp add: mdb_node_lift_def word_ao_dist shiftr_over_or_dist ucast_id)
|
|
apply (fold limited_and_def)
|
|
apply (simp add: limited_and_simps)
|
|
done
|
|
|
|
|
|
lemma mdb_node_ptr_set_mdbPrev_np_spec:
|
|
defines "ptr s \<equiv> cparent \<^bsup>s\<^esup>node_ptr [''cteMDBNode_C''] :: cte_C ptr"
|
|
shows
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ptr s \<and> is_aligned (mdbPrev___unsigned_long_' s) 4\<rbrace>
|
|
Call mdb_node_ptr_set_mdbPrev_np_'proc
|
|
{t. (\<exists>mdb_node.
|
|
mdb_node_lift mdb_node = mdb_node_lift (cteMDBNode_C (the (cslift s (ptr s))))
|
|
\<lparr> mdbPrev_CL := mdbPrev___unsigned_long_' s \<rparr>
|
|
\<and> cslift t = cslift s(ptr s \<mapsto> the (cslift s (ptr s)) \<lparr> cteMDBNode_C := mdb_node \<rparr>))
|
|
\<and> types_proofs.cslift_all_but_cte_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: ptr_def)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff)
|
|
apply (frule h_t_valid_c_guard_cparent[OF h_t_valid_clift], simp+,
|
|
simp add: typ_uinfo_t_def)
|
|
apply (frule clift_subtype, simp+)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (subst parent_update_child, erule typ_heap_simps', simp+)
|
|
apply (clarsimp simp: typ_heap_simps' word_sle_def word_sless_def)
|
|
apply (rule exI, rule conjI [OF _ refl])
|
|
apply (simp add: mdb_node_lift_def limited_and_simps)
|
|
done
|
|
|
|
lemma cap_reply_cap_ptr_new_np_spec2:
|
|
defines "ptr s \<equiv> cparent \<^bsup>s\<^esup>cap_ptr [''cap_C''] :: cte_C ptr"
|
|
shows
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ptr s \<and> is_aligned (capTCBPtr___unsigned_long_' s) 8
|
|
\<and> capReplyMaster___unsigned_long_' s && 1 = capReplyMaster___unsigned_long_' s\<rbrace>
|
|
Call cap_reply_cap_ptr_new_np_'proc
|
|
{t. (\<exists>cap.
|
|
cap_lift cap = Some (Cap_reply_cap \<lparr> capReplyMaster_CL = capReplyMaster___unsigned_long_' s,
|
|
capTCBPtr_CL = capTCBPtr___unsigned_long_' s \<rparr>)
|
|
\<and> cslift t = cslift s(ptr s \<mapsto> the (cslift s (ptr s)) \<lparr> cte_C.cap_C := cap \<rparr>))
|
|
\<and> types_proofs.cslift_all_but_cte_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: ptr_def)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff word_sle_def)
|
|
apply (frule h_t_valid_c_guard_cparent[OF h_t_valid_clift],
|
|
simp+, simp add: typ_uinfo_t_def)
|
|
apply (frule clift_subtype, simp+)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (subst parent_update_child, erule typ_heap_simps', simp+)
|
|
apply (clarsimp simp: typ_heap_simps' word_sless_def word_sle_def)
|
|
apply (rule exI, rule conjI [OF _ refl])
|
|
apply (fold limited_and_def)
|
|
apply (simp add: cap_get_tag_def mask_def cap_tag_defs
|
|
word_ao_dist limited_and_simps
|
|
cap_lift_reply_cap shiftr_over_or_dist)
|
|
done
|
|
|
|
lemma endpoint_ptr_mset_epQueue_tail_state_spec:
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ep_ptr_' s \<and> is_aligned (epQueue_tail_' s) 4
|
|
\<and> state_' s && mask 2 = state_' s\<rbrace>
|
|
Call endpoint_ptr_mset_epQueue_tail_state_'proc
|
|
{t. (\<exists>endpoint.
|
|
endpoint_lift endpoint = endpoint_lift (the (cslift s (ep_ptr_' s)))
|
|
\<lparr> endpoint_CL.state_CL := state_' s, epQueue_tail_CL := epQueue_tail_' s \<rparr>
|
|
\<and> cslift t = cslift s(ep_ptr_' s \<mapsto> endpoint))
|
|
\<and> types_proofs.cslift_all_but_endpoint_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff typ_heap_simps'
|
|
word_sle_def word_sless_def)
|
|
apply (rule exI, rule conjI[OF _ refl])
|
|
apply (simp add: endpoint_lift_def word_ao_dist
|
|
mask_def)
|
|
apply (fold limited_and_def)
|
|
apply (simp add: limited_and_simps)
|
|
done
|
|
|
|
lemma endpoint_ptr_set_epQueue_head_np_spec:
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. hrs_htd \<^bsup>s\<^esup>t_hrs \<Turnstile>\<^sub>t ep_ptr_' s \<and> is_aligned (epQueue_head_' s) 4\<rbrace>
|
|
Call endpoint_ptr_set_epQueue_head_np_'proc
|
|
{t. (\<exists>endpoint.
|
|
endpoint_lift endpoint = endpoint_lift (the (cslift s (ep_ptr_' s)))
|
|
\<lparr> epQueue_head_CL := epQueue_head_' s \<rparr>
|
|
\<and> cslift t = cslift s(ep_ptr_' s \<mapsto> endpoint))
|
|
\<and> types_proofs.cslift_all_but_endpoint_C t s
|
|
\<and> hrs_htd (t_hrs_' (globals t)) = hrs_htd (t_hrs_' (globals s))}"
|
|
apply (intro allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: h_t_valid_clift_Some_iff typ_heap_simps'
|
|
word_sless_def word_sle_def)
|
|
apply (rule exI, rule conjI[OF _ refl])
|
|
apply (simp add: endpoint_lift_def word_ao_dist
|
|
mask_def)
|
|
apply (simp add: limited_and_simps)
|
|
done
|
|
|
|
lemmas empty_fail_user_getreg = empty_fail_asUser[OF empty_fail_getRegister]
|
|
|
|
lemma empty_fail_getCurThread[iff]:
|
|
"empty_fail getCurThread" by (simp add: getCurThread_def)
|
|
|
|
lemma ccorres_call_hSkip':
|
|
assumes cul: "ccorres_underlying sr \<Gamma> r xf' r xf' P (i ` P') [SKIP] a (Call f)"
|
|
and gsr: "\<And>a b x s t. (x, t) \<in> sr \<Longrightarrow> (x, g a b (clean s t)) \<in> sr"
|
|
and csr: "\<And>x s t. (x, t) \<in> sr \<Longrightarrow> (x, clean s t) \<in> sr"
|
|
and res: "\<And>a s t rv. r rv (xf' t) \<Longrightarrow> r rv (xf (g a t (clean s t)))"
|
|
and ares: "\<And>s t rv. r rv (xf' t) \<Longrightarrow> r rv (xf (clean s t))"
|
|
and ist: "\<And>x s. (x, s) \<in> sr \<Longrightarrow> (x, i s) \<in> sr"
|
|
shows "ccorres_underlying sr \<Gamma> r xf r xf P P' [SKIP] a (call i f clean (\<lambda>x y. Basic (g x y)))"
|
|
apply (rule ccorresI')
|
|
apply (erule exec_handlers.cases, simp_all)[1]
|
|
apply clarsimp
|
|
apply (erule exec_call_Normal_elim, simp_all)[1]
|
|
apply (clarsimp elim!: exec_Normal_elim_cases)
|
|
apply (rule ccorresE[OF cul ist], assumption+, simp+)
|
|
apply (rule EHAbrupt)
|
|
apply (erule(1) exec.Call)
|
|
apply (rule EHOther, rule exec.Skip, simp)
|
|
apply clarsimp
|
|
apply (erule exec_handlers.cases, simp_all)[1]
|
|
apply (clarsimp elim!: exec_Normal_elim_cases)
|
|
apply (clarsimp elim!: exec_Normal_elim_cases)
|
|
apply (erule rev_bexI)
|
|
apply (simp add: unif_rrel_simps csr ares)
|
|
apply clarsimp
|
|
apply (erule exec_call_Normal_elim, simp_all)[1]
|
|
apply (clarsimp elim!: exec_Normal_elim_cases)
|
|
apply (rule ccorresE[OF cul ist], assumption+, simp+)
|
|
apply (rule EHOther, erule(1) exec.Call)
|
|
apply simp
|
|
apply (simp add: unif_rrel_simps)
|
|
apply (erule rev_bexI)
|
|
apply (simp add: gsr res)
|
|
apply (rule ccorresE[OF cul ist], assumption+, simp+)
|
|
apply (rule EHOther, erule(1) exec.Call)
|
|
apply simp
|
|
apply simp
|
|
apply (rule ccorresE[OF cul ist], assumption+, simp+)
|
|
apply (rule EHOther, erule(1) exec.Call)
|
|
apply simp
|
|
apply simp
|
|
apply (rule ccorresE[OF cul ist], assumption+, simp+)
|
|
apply (rule EHOther, erule exec.CallUndefined)
|
|
apply simp
|
|
apply simp
|
|
done
|
|
|
|
(* The naming convention here is that xf', xfr, and xfru are the terms we instantiate *)
|
|
lemma ccorres_call_hSkip:
|
|
assumes cul: "ccorres_underlying rf_sr \<Gamma> r xfdc r xfdc A C' [SKIP] a (Call f)"
|
|
and ggl: "\<And>x y s. globals (g x y s) = globals s"
|
|
and igl: "\<And>s. globals (i s) = globals s"
|
|
shows "ccorres_underlying rf_sr \<Gamma> r xfdc r xfdc
|
|
A {s. i s \<in> C'} [SKIP] a (call i f (\<lambda>s t. s\<lparr>globals := globals t\<rparr>) (\<lambda>x y. Basic (g x y)))"
|
|
using cul
|
|
unfolding rf_sr_def
|
|
apply -
|
|
apply (rule ccorres_call_hSkip')
|
|
apply (erule ccorres_guard_imp)
|
|
apply simp
|
|
apply clarsimp
|
|
apply (simp_all add: ggl xfdc_def)
|
|
apply (clarsimp simp: igl)
|
|
done
|
|
|
|
lemma bind_case_sum_rethrow:
|
|
"rethrowFailure fl f >>= case_sum e g
|
|
= f >>= case_sum (e \<circ> 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
|
|
|
|
lemma ccorres_alt_rdonly_liftE_bindE:
|
|
"\<lbrakk> ccorres_underlying sr Gamm r xf arrel axf A A' hs
|
|
(f >>= (\<lambda>x. alternative (g x) h)) c;
|
|
\<And>s. \<lbrace>op = s\<rbrace> f \<lbrace>\<lambda>rv. op = s\<rbrace>; empty_fail f \<rbrakk>
|
|
\<Longrightarrow> ccorres_underlying sr Gamm r xf arrel axf A A' hs
|
|
(alternative (liftE f >>=E (\<lambda>x. g x)) h) c"
|
|
by (simp add: liftE_bindE ccorres_alt_rdonly_bind)
|
|
|
|
lemma ccorres_pre_getCTE2:
|
|
"(\<And>rv. ccorresG rf_sr \<Gamma> r xf (P rv) (P' rv) hs (f rv) c) \<Longrightarrow>
|
|
ccorresG rf_sr \<Gamma> r xf (\<lambda>s. \<forall>cte. ctes_of s p = Some cte \<longrightarrow> P cte s)
|
|
{s. \<forall>cte cte'. cslift s (cte_Ptr p) = Some cte' \<and> ccte_relation cte cte'
|
|
\<longrightarrow> s \<in> P' cte} hs
|
|
(getCTE p >>= (\<lambda>rv. f rv)) c"
|
|
apply (rule ccorres_guard_imp2, erule ccorres_pre_getCTE)
|
|
apply (clarsimp simp: map_comp_Some_iff ccte_relation_def
|
|
c_valid_cte_def cl_valid_cte_def
|
|
c_valid_cap_def)
|
|
done
|
|
|
|
declare empty_fail_assertE[iff]
|
|
|
|
declare empty_fail_resolveAddressBits[iff]
|
|
|
|
lemma ccap_relation_ep_helpers:
|
|
"\<lbrakk> ccap_relation cap cap'; cap_get_tag cap' = scast cap_endpoint_cap \<rbrakk>
|
|
\<Longrightarrow> capCanSend_CL (cap_endpoint_cap_lift cap') = from_bool (capEPCanSend cap)
|
|
\<and> capCanReceive_CL (cap_endpoint_cap_lift cap') = from_bool (capEPCanReceive cap)
|
|
\<and> capEPPtr_CL (cap_endpoint_cap_lift cap') = capEPPtr cap
|
|
\<and> capEPBadge_CL (cap_endpoint_cap_lift cap') = capEPBadge cap
|
|
\<and> capCanGrant_CL (cap_endpoint_cap_lift cap') = from_bool (capEPCanGrant cap)"
|
|
by (clarsimp simp: cap_lift_endpoint_cap cap_to_H_simps
|
|
cap_endpoint_cap_lift_def word_size
|
|
from_bool_to_bool_and_1
|
|
elim!: ccap_relationE)
|
|
|
|
lemma lookupExtraCaps_null:
|
|
"msgExtraCaps info = 0 \<Longrightarrow>
|
|
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 fastpath_mi_check:
|
|
"((mi && mask 9) + 3) && ~~ mask 3 = 0
|
|
= (msgExtraCaps (messageInfoFromWord mi) = 0
|
|
\<and> msgLength (messageInfoFromWord mi) \<le> scast n_msgRegisters
|
|
\<and> length_CL (seL4_MessageInfo_lift (seL4_MessageInfo_C (FCP (K mi))))
|
|
\<le> scast n_msgRegisters)"
|
|
(is "?P = (?Q \<and> ?R \<and> ?S)")
|
|
proof -
|
|
have le_Q: "?P = (?Q \<and> ?S)"
|
|
apply (simp add: mask_def messageInfoFromWord_def Let_def
|
|
msgExtraCapBits_def msgLengthBits_def
|
|
seL4_MessageInfo_lift_def fcp_beta n_msgRegisters_def)
|
|
apply word_bitwise
|
|
apply blast
|
|
done
|
|
have Q_R: "?S \<Longrightarrow> ?R"
|
|
apply (clarsimp simp: messageInfoFromWord_def Let_def msgLengthBits_def
|
|
msgExtraCapBits_def mask_def n_msgRegisters_def
|
|
seL4_MessageInfo_lift_def fcp_beta)
|
|
apply (subst if_not_P, simp_all)
|
|
apply (simp add: msgMaxLength_def linorder_not_less)
|
|
apply (erule order_trans, simp)
|
|
done
|
|
from le_Q Q_R show ?thesis
|
|
by blast
|
|
qed
|
|
|
|
lemma messageInfoFromWord_raw_spec:
|
|
"\<forall>s. \<Gamma>\<turnstile> {s} Call messageInfoFromWord_raw_'proc
|
|
\<lbrace>\<acute>ret__struct_seL4_MessageInfo_C
|
|
= (seL4_MessageInfo_C (FCP (K \<^bsup>s\<^esup>w)))\<rbrace>"
|
|
apply vcg
|
|
apply (clarsimp simp: word_sless_def word_sle_def)
|
|
apply (case_tac v)
|
|
apply (simp add: cart_eq fcp_beta)
|
|
done
|
|
|
|
lemma mi_check_messageInfo_raw:
|
|
"length_CL (seL4_MessageInfo_lift (seL4_MessageInfo_C (FCP (K mi))))
|
|
\<le> scast n_msgRegisters
|
|
\<Longrightarrow> seL4_MessageInfo_lift (seL4_MessageInfo_C (FCP (K mi)))
|
|
= mi_from_H (messageInfoFromWord mi)"
|
|
apply (simp add: messageInfoFromWord_def Let_def mi_from_H_def
|
|
seL4_MessageInfo_lift_def fcp_beta msgLengthBits_def msgExtraCapBits_def
|
|
msgMaxExtraCaps_def shiftL_nat)
|
|
apply (subst if_not_P)
|
|
apply (simp add: linorder_not_less msgMaxLength_def n_msgRegisters_def)
|
|
apply (erule order_trans, simp)
|
|
apply simp
|
|
apply (thin_tac "P" for P)
|
|
apply word_bitwise
|
|
done
|
|
|
|
lemma fastpath_mi_check_spec:
|
|
"\<forall>s. \<Gamma> \<turnstile> \<lbrace>s. True\<rbrace> Call fastpath_mi_check_'proc
|
|
\<lbrace>(\<acute>ret__int = 0) = (msgExtraCaps (messageInfoFromWord \<^bsup>s\<^esup>msgInfo) = 0
|
|
\<and> msgLength (messageInfoFromWord \<^bsup>s\<^esup>msgInfo) \<le> scast n_msgRegisters
|
|
\<and> seL4_MessageInfo_lift (seL4_MessageInfo_C (FCP (K \<^bsup>s\<^esup>msgInfo)))
|
|
= mi_from_H (messageInfoFromWord \<^bsup>s\<^esup>msgInfo))\<rbrace>"
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: seL4_MsgLengthBits_def seL4_MsgExtraCapBits_def
|
|
word_sle_def if_1_0_0)
|
|
apply (cut_tac mi="msgInfo_' s" in fastpath_mi_check)
|
|
apply (simp add: mask_def)
|
|
apply (auto intro: mi_check_messageInfo_raw[unfolded K_def])
|
|
done
|
|
|
|
lemma isValidVTableRoot_fp_lemma:
|
|
"(index (cap_C.words_C ccap) 0 && 0x1F = 0x10 || scast cap_page_directory_cap)
|
|
= isValidVTableRoot_C ccap"
|
|
apply (simp add: isValidVTableRoot_C_def ARM_H.isValidVTableRoot_def
|
|
cap_case_isPageDirectoryCap if_bool_simps)
|
|
apply (subst split_word_eq_on_mask[where m="mask 4"])
|
|
apply (simp add: mask_def word_bw_assocs word_ao_dist cap_page_directory_cap_def)
|
|
apply (subgoal_tac "cap_get_tag ccap = scast cap_page_directory_cap
|
|
\<Longrightarrow> (index (cap_C.words_C ccap) 0 && 0x10 = 0x10) = to_bool (capPDIsMapped_CL (cap_page_directory_cap_lift ccap))")
|
|
apply (clarsimp simp add: cap_get_tag_eq_x mask_def
|
|
cap_page_directory_cap_def split: split_if)
|
|
apply (rule conj_cong[OF refl])
|
|
apply clarsimp
|
|
apply (clarsimp simp: cap_lift_page_directory_cap
|
|
cap_to_H_simps
|
|
to_bool_def bool_mask[folded word_neq_0_conv]
|
|
cap_page_directory_cap_lift_def
|
|
elim!: ccap_relationE split: split_if)
|
|
apply (thin_tac "P" for P)
|
|
apply word_bitwise
|
|
done
|
|
|
|
lemma isValidVTableRoot_fp_spec:
|
|
"\<forall>s. \<Gamma> \<turnstile> {s} Call isValidVTableRoot_fp_'proc
|
|
{t. ret__unsigned_long_' t = from_bool (isValidVTableRoot_C (pd_cap_' s))}"
|
|
apply vcg
|
|
apply (clarsimp simp: word_sle_def word_sless_def isValidVTableRoot_fp_lemma)
|
|
apply (simp add: from_bool_def split: split_if)
|
|
done
|
|
|
|
lemma isRecvEP_endpoint_case:
|
|
"isRecvEP ep \<Longrightarrow> case_endpoint f g h ep = f (epQueue ep)"
|
|
by (clarsimp simp: isRecvEP_def split: endpoint.split_asm)
|
|
|
|
lemma ccorres_cond_both_seq:
|
|
"\<lbrakk> \<forall>s s'. (s, s') \<in> sr \<and> R s \<longrightarrow> P s = (s' \<in> P');
|
|
ccorres_underlying sr \<Gamma> r xf arrel axf Pt Rt hs a (c ;; d);
|
|
ccorres_underlying sr \<Gamma> r xf arrel axf Pf Rf hs a (c' ;; d) \<rbrakk>
|
|
\<Longrightarrow> ccorres_underlying sr \<Gamma> r xf arrel axf
|
|
(R and (\<lambda>s. P s \<longrightarrow> Pt s) and (\<lambda>s. \<not> P s \<longrightarrow> Pf s))
|
|
{s. (s \<in> P' \<longrightarrow> s \<in> Rt) \<and> (s \<notin> P' \<longrightarrow> s \<in> Rf)}
|
|
hs a (Cond P' c c' ;; d)"
|
|
apply (subst ccorres_seq_cond_raise)
|
|
apply (rule ccorres_guard_imp2, rule ccorres_cond_both, assumption+)
|
|
apply auto
|
|
done
|
|
|
|
lemma copyMRs_simple:
|
|
"msglen \<le> of_nat (length ARM_H.msgRegisters) \<longrightarrow>
|
|
copyMRs sender sbuf receiver rbuf msglen
|
|
= forM_x (take (unat msglen) ARM_H.msgRegisters)
|
|
(\<lambda>r. do v \<leftarrow> asUser sender (getRegister r);
|
|
asUser receiver (setRegister r v) od)
|
|
>>= (\<lambda>rv. return msglen)"
|
|
apply (clarsimp simp: copyMRs_def mapM_discarded)
|
|
apply (rule bind_cong[OF refl])
|
|
apply (simp add: length_msgRegisters n_msgRegisters_def min_def
|
|
word_le_nat_alt
|
|
split: option.split)
|
|
apply (simp add: upto_enum_def mapM_Nil)
|
|
done
|
|
|
|
lemma unifyFailure_catch_If:
|
|
"catch (unifyFailure f >>=E g) h
|
|
= f >>= (\<lambda>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
|
|
|
|
end
|
|
|
|
abbreviation "tcb_Ptr_Ptr \<equiv> (Ptr :: word32 \<Rightarrow> tcb_C ptr ptr)"
|
|
|
|
abbreviation(input)
|
|
"ptr_basic_update ptrfun vfun
|
|
\<equiv> Basic (\<lambda>s. globals_update (t_hrs_'_update (hrs_mem_update
|
|
(heap_update (ptrfun s) (vfun s)))) s)"
|
|
|
|
context kernel_m begin
|
|
|
|
lemma fastpath_dequeue_ccorres:
|
|
"dest1 = dest2 \<and> dest2 = tcb_ptr_to_ctcb_ptr dest \<and> ep_ptr1 = ep_Ptr ep_ptr \<Longrightarrow>
|
|
ccorres dc xfdc
|
|
(ko_at' (RecvEP (dest # xs)) ep_ptr and invs')
|
|
{s. dest2 = tcb_ptr_to_ctcb_ptr dest
|
|
\<and> dest1 = tcb_ptr_to_ctcb_ptr dest
|
|
\<and> ep_ptr1 = ep_Ptr ep_ptr} hs
|
|
(setEndpoint ep_ptr (case xs of [] \<Rightarrow> IdleEP | _ \<Rightarrow> RecvEP xs))
|
|
(Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t dest1\<rbrace>
|
|
(CALL endpoint_ptr_set_epQueue_head_np(ep_ptr1,ptr_val (h_val (hrs_mem \<acute>t_hrs) (tcb_Ptr_Ptr &(dest2\<rightarrow>[''tcbEPNext_C''])))));;
|
|
Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t dest1\<rbrace>
|
|
(IF h_val (hrs_mem \<acute>t_hrs) (tcb_Ptr_Ptr &(dest1\<rightarrow>[''tcbEPNext_C''])) \<noteq> tcb_Ptr 0 THEN
|
|
Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t h_val (hrs_mem \<acute>t_hrs) (tcb_Ptr_Ptr &(dest1\<rightarrow>[''tcbEPNext_C'']))\<rbrace>
|
|
(Guard C_Guard {s. s \<Turnstile>\<^sub>c dest1} (
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &(h_val (hrs_mem (t_hrs_' (globals s)))
|
|
(tcb_Ptr_Ptr &(dest1\<rightarrow>[''tcbEPNext_C'']))\<rightarrow>[''tcbEPPrev_C''])) (\<lambda>_. NULL))))
|
|
ELSE
|
|
CALL endpoint_ptr_mset_epQueue_tail_state(ep_ptr1,scast 0,scast EPState_Idle)
|
|
FI))"
|
|
unfolding setEndpoint_def
|
|
apply (rule setObject_ccorres_helper[rotated])
|
|
apply simp
|
|
apply (simp add: objBits_simps)
|
|
apply (rule conseqPre, vcg)
|
|
apply clarsimp
|
|
apply (drule(1) ko_at_obj_congD')
|
|
apply (frule ko_at_valid_ep', clarsimp)
|
|
apply (rule cmap_relationE1[OF cmap_relation_ep], assumption,
|
|
erule ko_at_projectKO_opt)
|
|
apply (clarsimp simp: typ_heap_simps' valid_ep'_def
|
|
isRecvEP_endpoint_case neq_Nil_conv)
|
|
apply (drule(1) obj_at_cslift_tcb)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (case_tac "xs")
|
|
apply (clarsimp simp: cendpoint_relation_def Let_def
|
|
isRecvEP_endpoint_case
|
|
tcb_queue_relation'_def
|
|
typ_heap_simps' endpoint_state_defs)
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def update_ep_map_tos)
|
|
apply (erule(1) cpspace_relation_ep_update_ep2)
|
|
apply (simp add: cendpoint_relation_def endpoint_state_defs)
|
|
apply simp
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
h_t_valid_clift_Some_iff update_ep_map_tos)
|
|
apply (clarsimp simp: neq_Nil_conv cendpoint_relation_def Let_def
|
|
isRecvEP_endpoint_case tcb_queue_relation'_def
|
|
typ_heap_simps' endpoint_state_defs)
|
|
apply (clarsimp simp: is_aligned_weaken[OF is_aligned_tcb_ptr_to_ctcb_ptr]
|
|
tcb_at_not_NULL)
|
|
apply (drule(1) obj_at_cslift_tcb)+
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def update_ep_map_tos
|
|
update_tcb_map_tos typ_heap_simps')
|
|
apply (rule conjI, erule ctcb_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_queue_ptrs_def
|
|
split: split_if)
|
|
apply (rule conjI)
|
|
apply (rule cpspace_relation_ep_update_ep, assumption+)
|
|
apply (simp add: Let_def cendpoint_relation_def EPState_Recv_def)
|
|
apply (simp add: tcb_queue_relation'_def tcb_queue_update_other)
|
|
apply (simp add: isRecvEP_def)
|
|
apply (erule iffD1 [OF cmap_relation_cong, OF refl refl, rotated -1])
|
|
apply simp
|
|
apply (rule cnotification_relation_ep_queue [OF invs_sym'], assumption+)
|
|
apply (simp add: isRecvEP_def)
|
|
apply simp
|
|
apply (erule (1) map_to_ko_atI')
|
|
apply (simp add: carch_state_relation_def typ_heap_simps'
|
|
cmachine_state_relation_def h_t_valid_clift_Some_iff
|
|
update_ep_map_tos)
|
|
apply (erule cready_queues_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_ep_ptrs_def split: split_if)
|
|
done
|
|
|
|
lemma tcb_NextPrev_C_update_swap:
|
|
"tcbEPPrev_C_update f (tcbEPNext_C_update g tcb)
|
|
= tcbEPNext_C_update g (tcbEPPrev_C_update f tcb)"
|
|
by simp
|
|
|
|
lemma st_tcb_at_not_in_ep_queue:
|
|
"\<lbrakk> st_tcb_at' P t s; ko_at' ep epptr s; sym_refs (state_refs_of' s);
|
|
ep \<noteq> IdleEP; \<And>ts. P ts \<Longrightarrow> tcb_st_refs_of' ts = {} \<rbrakk>
|
|
\<Longrightarrow> t \<notin> 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:
|
|
"\<lbrakk> st_tcb_at' P t s; ko_at' ntfn ntfnptr s; sym_refs (state_refs_of' s); ntfnObj ntfn = WaitingNtfn xs;
|
|
\<And>ts. P ts \<Longrightarrow> (ntfnptr, TCBSignal) \<notin> tcb_st_refs_of' ts \<rbrakk>
|
|
\<Longrightarrow> t \<notin> 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 cntfn_relation_double_fun_upd:
|
|
"\<lbrakk> cnotification_relation mp ntfn ntfn'
|
|
= cnotification_relation (mp(a := b)) ntfn ntfn';
|
|
cnotification_relation (mp(a := b)) ntfn ntfn'
|
|
= cnotification_relation (mp(a := b, c := d)) ntfn ntfn' \<rbrakk>
|
|
\<Longrightarrow> cnotification_relation mp ntfn ntfn'
|
|
= cnotification_relation (mp(a := b, c := d)) ntfn ntfn'"
|
|
by simp
|
|
|
|
lemma sym_refs_upd_ko_atD':
|
|
"\<lbrakk> ko_at' ko p s; sym_refs ((state_refs_of' s) (p' := S)); p \<noteq> p' \<rbrakk>
|
|
\<Longrightarrow> \<forall>(x, tp) \<in> refs_of' (injectKO ko). (x = p' \<and> (p, symreftype tp) \<in> S)
|
|
\<or> (x \<noteq> p' \<and> ko_wp_at' (\<lambda>ko. (p, symreftype tp) \<in> refs_of' ko)x s)"
|
|
apply (clarsimp del: disjCI)
|
|
apply (drule ko_at_state_refs_ofD')
|
|
apply (drule_tac y=a and tp=b and x=p in sym_refsD[rotated])
|
|
apply simp
|
|
apply (case_tac "a = p'")
|
|
apply simp
|
|
apply simp
|
|
apply (erule state_refs_of'_elemD)
|
|
done
|
|
|
|
lemma sym_refs_upd_sD:
|
|
"\<lbrakk> 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 \<rbrakk>
|
|
\<Longrightarrow> \<exists>s'. sym_refs (state_refs_of' s')
|
|
\<and> (\<forall>p' (ko' :: endpoint). ko_at' ko' p' s \<and> injectKO ko' \<noteq> injectKO ko
|
|
\<longrightarrow> ko_at' ko' p' s')
|
|
\<and> (\<forall>p' (ko' :: Structures_H.notification). ko_at' ko' p' s \<and> injectKO ko' \<noteq> injectKO ko
|
|
\<longrightarrow> ko_at' ko' p' s')
|
|
\<and> (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: split_if)
|
|
apply (clarsimp simp: project_inject objBits_def)
|
|
apply auto
|
|
done
|
|
|
|
lemma sym_refs_upd_tcb_sD:
|
|
"\<lbrakk> sym_refs ((state_refs_of' s) (p := {r \<in> state_refs_of' s p. snd r = TCBBound})); valid_pspace' s;
|
|
ko_at' (tcb :: tcb) p s \<rbrakk>
|
|
\<Longrightarrow> \<exists>s'. sym_refs (state_refs_of' s')
|
|
\<and> (\<forall>p' (ko' :: endpoint).
|
|
ko_at' ko' p' s \<longrightarrow> ko_at' ko' p' s')
|
|
\<and> (\<forall>p' (ko' :: Structures_H.notification).
|
|
ko_at' ko' p' s \<longrightarrow> ko_at' ko' p' s')
|
|
\<and> (st_tcb_at' (op = Running) p s')"
|
|
apply (drule(2) sym_refs_upd_sD[where koEx="makeObject\<lparr>tcbState := Running, tcbBoundNotification := tcbBoundNotification tcb\<rparr>"])
|
|
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 fastpath_enqueue_ccorres:
|
|
"\<lbrakk> epptr' = ep_Ptr epptr \<rbrakk> \<Longrightarrow>
|
|
ccorres dc xfdc
|
|
(ko_at' ep epptr and (\<lambda>s. thread = ksCurThread s)
|
|
and (\<lambda>s. sym_refs ((state_refs_of' s) (thread := {r \<in> state_refs_of' s thread. snd r = TCBBound})))
|
|
and K (\<not> isSendEP ep) and valid_pspace' and cur_tcb')
|
|
UNIV hs
|
|
(setEndpoint epptr (case ep of IdleEP \<Rightarrow> RecvEP [thread] | RecvEP ts \<Rightarrow> RecvEP (ts @ [thread])))
|
|
(\<acute>ret__unsigned :== CALL endpoint_ptr_get_epQueue_tail(epptr');;
|
|
\<acute>endpointTail :== tcb_Ptr \<acute>ret__unsigned;;
|
|
IF \<acute>endpointTail = tcb_Ptr 0 THEN
|
|
(Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t \<acute>ksCurThread\<rbrace>
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &((ksCurThread_' (globals s))\<rightarrow>[''tcbEPPrev_C''])) (\<lambda>_. NULL)));;
|
|
(Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t \<acute>ksCurThread\<rbrace>
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &((ksCurThread_' (globals s))\<rightarrow>[''tcbEPNext_C''])) (\<lambda>_. NULL)));;
|
|
(CALL endpoint_ptr_set_epQueue_head_np(epptr',ucast (ptr_val \<acute>ksCurThread)));;
|
|
(CALL endpoint_ptr_mset_epQueue_tail_state(epptr',ucast (ptr_val \<acute>ksCurThread),
|
|
scast EPState_Recv))
|
|
ELSE
|
|
Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t \<acute>endpointTail\<rbrace>
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &((endpointTail_' s)\<rightarrow>[''tcbEPNext_C'']))
|
|
(ksCurThread_' o globals));;
|
|
(Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t \<acute>ksCurThread\<rbrace>
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &((ksCurThread_' (globals s))\<rightarrow>[''tcbEPPrev_C'']))
|
|
endpointTail_'));;
|
|
(Guard C_Guard \<lbrace>hrs_htd \<acute>t_hrs \<Turnstile>\<^sub>t \<acute>ksCurThread\<rbrace>
|
|
(ptr_basic_update (\<lambda>s. tcb_Ptr_Ptr &((ksCurThread_' (globals s))\<rightarrow>[''tcbEPNext_C'']))
|
|
(\<lambda>_. NULL)));;
|
|
(CALL endpoint_ptr_mset_epQueue_tail_state(epptr',ucast (ptr_val \<acute>ksCurThread),
|
|
scast EPState_Recv))
|
|
FI)"
|
|
unfolding setEndpoint_def
|
|
apply clarsimp
|
|
apply (rule setObject_ccorres_helper[rotated])
|
|
apply simp
|
|
apply (simp add: objBits_simps)
|
|
apply (rule conseqPre, vcg)
|
|
apply clarsimp
|
|
apply (drule(1) ko_at_obj_congD')
|
|
apply (frule ko_at_valid_ep', clarsimp)
|
|
apply (rule cmap_relationE1[OF cmap_relation_ep], assumption,
|
|
erule ko_at_projectKO_opt)
|
|
apply (simp add: cur_tcb'_def)
|
|
apply (drule(1) obj_at_cslift_tcb)
|
|
apply (clarsimp simp: typ_heap_simps' valid_ep'_def rf_sr_ksCurThread)
|
|
apply (cases ep,
|
|
simp_all add: isSendEP_def cendpoint_relation_def Let_def
|
|
tcb_queue_relation'_def)
|
|
apply (rename_tac list)
|
|
apply (clarsimp simp: NULL_ptr_val[symmetric] tcb_queue_relation_last_not_NULL
|
|
ct_in_state'_def
|
|
dest!: trans [OF sym [OF ptr_val_def] arg_cong[where f=ptr_val]])
|
|
apply (frule obj_at_cslift_tcb[rotated], erule(1) bspec[OF _ last_in_set])
|
|
apply clarsimp
|
|
apply (drule(2) sym_refs_upd_tcb_sD)
|
|
apply clarsimp
|
|
apply (frule st_tcb_at_not_in_ep_queue,
|
|
fastforce, simp+)
|
|
apply (subgoal_tac "ksCurThread \<sigma> \<noteq> last list")
|
|
prefer 2
|
|
apply clarsimp
|
|
apply (clarsimp simp: typ_heap_simps' EPState_Recv_def mask_def
|
|
is_aligned_weaken[OF is_aligned_tcb_ptr_to_ctcb_ptr])
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def update_ep_map_tos
|
|
typ_heap_simps')
|
|
apply (rule conjI, erule ctcb_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_queue_ptrs_def
|
|
split: split_if)
|
|
apply (rule conjI)
|
|
apply (rule_tac S="tcb_ptr_to_ctcb_ptr ` set (ksCurThread \<sigma> # list)"
|
|
in cpspace_relation_ep_update_an_ep,
|
|
assumption+)
|
|
apply (simp add: cendpoint_relation_def Let_def EPState_Recv_def
|
|
tcb_queue_relation'_def)
|
|
apply (drule_tac qend="tcb_ptr_to_ctcb_ptr (last list)"
|
|
and qend'="tcb_ptr_to_ctcb_ptr (ksCurThread \<sigma>)"
|
|
and tn_update="tcbEPNext_C_update"
|
|
and tp_update="tcbEPPrev_C_update"
|
|
in tcb_queue_relation_append,
|
|
clarsimp+, simp_all)[1]
|
|
apply (rule sym, erule init_append_last)
|
|
apply (fastforce simp: tcb_at_not_NULL)
|
|
apply (clarsimp simp add: tcb_at_not_NULL[OF obj_at'_weakenE[OF _ TrueI]])
|
|
apply clarsimp+
|
|
apply (subst st_tcb_at_not_in_ep_queue, assumption, blast, clarsimp+)
|
|
apply (drule(1) ep_ep_disjoint[rotated -1, where epptr=epptr],
|
|
blast, blast,
|
|
simp_all add: Int_commute endpoint_not_idle_cases image_image)[1]
|
|
apply (erule iffD1 [OF cmap_relation_cong, OF refl refl, rotated -1])
|
|
apply simp
|
|
apply (rule cntfn_relation_double_fun_upd)
|
|
apply (rule cnotification_relation_ep_queue, assumption+)
|
|
apply fastforce
|
|
apply (simp add: isRecvEP_def)
|
|
apply simp
|
|
apply (fastforce dest!: map_to_ko_atI)
|
|
|
|
apply (rule cnotification_relation_q_cong)
|
|
apply (clarsimp split: split_if)
|
|
apply (clarsimp simp: restrict_map_def ntfn_q_refs_of'_def
|
|
split: split_if Structures_H.notification.split_asm Structures_H.ntfn.split_asm)
|
|
apply (erule notE[rotated], erule_tac ntfnptr=p and ntfn=a in st_tcb_at_not_in_ntfn_queue,
|
|
auto dest!: map_to_ko_atI)[1]
|
|
apply (simp add: carch_state_relation_def typ_heap_simps' update_ep_map_tos
|
|
cmachine_state_relation_def h_t_valid_clift_Some_iff)
|
|
apply (erule cready_queues_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_ep_ptrs_def split: split_if)
|
|
apply (clarsimp simp: typ_heap_simps' EPState_Recv_def mask_def
|
|
is_aligned_weaken[OF is_aligned_tcb_ptr_to_ctcb_ptr])
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def)
|
|
apply (drule(2) sym_refs_upd_tcb_sD)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def update_ep_map_tos
|
|
typ_heap_simps' ct_in_state'_def)
|
|
apply (rule conjI, erule ctcb_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_queue_ptrs_def
|
|
split: split_if)
|
|
apply (rule conjI)
|
|
apply (rule_tac S="{tcb_ptr_to_ctcb_ptr (ksCurThread \<sigma>)}"
|
|
in cpspace_relation_ep_update_an_ep, assumption+)
|
|
apply (simp add: cendpoint_relation_def Let_def EPState_Recv_def
|
|
tcb_queue_relation'_def)
|
|
apply clarsimp+
|
|
apply (erule notE[rotated], erule st_tcb_at_not_in_ep_queue,
|
|
auto)[1]
|
|
apply (erule iffD1 [OF cmap_relation_cong, OF refl refl, rotated -1])
|
|
apply simp
|
|
apply (rule cnotification_relation_q_cong)
|
|
apply (clarsimp split: split_if)
|
|
apply (clarsimp simp: restrict_map_def ntfn_q_refs_of'_def
|
|
split: split_if Structures_H.notification.split_asm Structures_H.ntfn.split_asm)
|
|
apply (erule notE[rotated], rule_tac ntfnptr=p and ntfn=a in st_tcb_at_not_in_ntfn_queue,
|
|
assumption+, auto dest!: map_to_ko_atI)[1]
|
|
apply (simp add: carch_state_relation_def typ_heap_simps' update_ep_map_tos
|
|
cmachine_state_relation_def h_t_valid_clift_Some_iff)
|
|
apply (erule cready_queues_relation_null_queue_ptrs)
|
|
apply (rule ext, simp add: tcb_null_ep_ptrs_def split: split_if)
|
|
done
|
|
|
|
|
|
lemma ccorres_updateCap [corres]:
|
|
fixes ptr :: "cstate \<Rightarrow> cte_C ptr" and val :: "cstate \<Rightarrow> cap_C"
|
|
shows "ccorres dc xfdc \<top>
|
|
({s. ccap_relation cap (val s)} \<inter> {s. ptr s = Ptr dest}) hs
|
|
(updateCap dest cap)
|
|
(Basic
|
|
(\<lambda>s. globals_update
|
|
(t_hrs_'_update
|
|
(hrs_mem_update (heap_update (Ptr &(ptr s\<rightarrow>[''cap_C''])) (val s)))) s))"
|
|
unfolding updateCap_def
|
|
apply (cinitlift ptr)
|
|
apply (erule ssubst)
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_pre_getCTE)
|
|
apply (rule_tac P = "\<lambda>s. ctes_of s dest = Some rva" in ccorres_from_vcg [where P' = "{s. ccap_relation cap (val s)}"])
|
|
apply (rule allI)
|
|
apply (rule conseqPre)
|
|
apply vcg
|
|
apply clarsimp
|
|
apply (rule fst_setCTE [OF ctes_of_cte_at], assumption)
|
|
apply (erule bexI [rotated])
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (frule (1) rf_sr_ctes_of_clift)
|
|
apply (clarsimp simp add: rf_sr_def cstate_relation_def typ_heap_simps
|
|
Let_def cpspace_relation_def)
|
|
apply (rule conjI)
|
|
apply (erule (3) cpspace_cte_relation_upd_capI)
|
|
apply (erule_tac t = s' in ssubst)
|
|
apply (simp add: heap_to_page_data_def)
|
|
apply (rule conjI)
|
|
apply (erule (1) setCTE_tcb_case)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
cvariable_array_map_const_add_map_option[where f="tcb_no_ctes_proj"]
|
|
typ_heap_simps h_t_valid_clift_Some_iff)
|
|
apply clarsimp
|
|
done
|
|
|
|
|
|
lemma setCTE_rf_sr:
|
|
"\<lbrakk> (\<sigma>, s) \<in> rf_sr; ctes_of \<sigma> ptr = Some cte'';
|
|
cslift s' = ((cslift s)(cte_Ptr ptr \<mapsto> cte'));
|
|
ccte_relation cte cte';
|
|
types_proofs.cslift_all_but_cte_C s' s;
|
|
hrs_htd (t_hrs_' (globals s')) = hrs_htd (t_hrs_' (globals s));
|
|
(globals s')\<lparr> t_hrs_' := undefined \<rparr>
|
|
= (globals s)\<lparr> t_hrs_' := undefined \<rparr> \<rbrakk>
|
|
|
|
\<Longrightarrow>
|
|
\<exists>x\<in>fst (setCTE ptr cte \<sigma>).
|
|
(snd x, s') \<in> rf_sr"
|
|
apply (rule fst_setCTE[OF ctes_of_cte_at], assumption)
|
|
apply (erule rev_bexI)
|
|
apply (subgoal_tac "\<exists>hrs. globals s' = globals s
|
|
\<lparr> t_hrs_' := hrs \<rparr>")
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def
|
|
typ_heap_simps' cpspace_relation_def)
|
|
apply (rule conjI)
|
|
apply (erule(2) cmap_relation_updI, simp)
|
|
apply (erule_tac t = s'a in ssubst)
|
|
apply (simp add: heap_to_page_data_def)
|
|
apply (rule conjI)
|
|
apply (erule(1) setCTE_tcb_case)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
cvariable_array_map_const_add_map_option[where f="tcb_no_ctes_proj"]
|
|
typ_heap_simps' h_t_valid_clift_Some_iff)
|
|
apply (cases "globals s", cases "globals s'")
|
|
apply simp
|
|
done
|
|
|
|
lemma getCTE_setCTE_rf_sr:
|
|
"\<lbrakk> (\<sigma>, s) \<in> rf_sr; ctes_of \<sigma> ptr = Some cte;
|
|
cslift s' = ((cslift s)(cte_Ptr ptr \<mapsto> cte'));
|
|
ccte_relation (f cte) cte';
|
|
types_proofs.cslift_all_but_cte_C s' s;
|
|
hrs_htd (t_hrs_' (globals s')) = hrs_htd (t_hrs_' (globals s));
|
|
(globals s')\<lparr> t_hrs_' := undefined \<rparr>
|
|
= (globals s)\<lparr> t_hrs_' := undefined \<rparr> \<rbrakk>
|
|
|
|
\<Longrightarrow>
|
|
\<exists>x\<in>fst ((do cte \<leftarrow> getCTE ptr;
|
|
setCTE ptr (f cte)
|
|
od)
|
|
\<sigma>).
|
|
(snd x, s') \<in> rf_sr"
|
|
apply (drule setCTE_rf_sr, assumption+)
|
|
apply (clarsimp simp: Bex_def in_bind_split in_getCTE2 cte_wp_at_ctes_of)
|
|
done
|
|
|
|
lemma ccte_relation_eq_ccap_relation:
|
|
notes option.case_cong_weak [cong]
|
|
shows
|
|
"ccte_relation cte ccte
|
|
= (ccap_relation (cteCap cte) (cte_C.cap_C ccte)
|
|
\<and> mdb_node_to_H (mdb_node_lift (cteMDBNode_C ccte))
|
|
= (cteMDBNode cte))"
|
|
apply (simp add: ccte_relation_def option_map_Some_eq2 cte_lift_def
|
|
ccap_relation_def)
|
|
apply (simp add: cte_to_H_def split: option.split)
|
|
apply (cases cte, clarsimp simp: c_valid_cte_def conj_comms)
|
|
done
|
|
|
|
lemma cap_reply_cap_ptr_new_np_updateCap_ccorres:
|
|
"ccorres dc xfdc
|
|
(cte_at' ptr and tcb_at' thread)
|
|
(UNIV \<inter> {s. cap_ptr_' s = cap_Ptr &(cte_Ptr ptr \<rightarrow> [''cap_C''])}
|
|
\<inter> {s. capTCBPtr___unsigned_long_' s = ptr_val (tcb_ptr_to_ctcb_ptr thread)}
|
|
\<inter> {s. capReplyMaster___unsigned_long_' s = from_bool m}) []
|
|
(updateCap ptr (ReplyCap thread m))
|
|
(Call cap_reply_cap_ptr_new_np_'proc)"
|
|
apply (rule ccorres_from_vcg, rule allI)
|
|
apply (rule conseqPre, vcg)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of word_sle_def)
|
|
apply (rule cmap_relationE1[OF cmap_relation_cte], assumption+)
|
|
apply (clarsimp simp: updateCap_def split_def typ_heap_simps'
|
|
word_sless_def word_sle_def)
|
|
apply (erule(1) getCTE_setCTE_rf_sr, simp_all add: typ_heap_simps')
|
|
apply (clarsimp simp: ccte_relation_eq_ccap_relation
|
|
ccap_relation_def c_valid_cap_def)
|
|
apply (frule is_aligned_tcb_ptr_to_ctcb_ptr)
|
|
apply (rule ssubst[OF cap_lift_reply_cap])
|
|
apply (simp add: cap_get_tag_def cap_reply_cap_def
|
|
mask_def word_ao_dist
|
|
limited_and_simps
|
|
limited_and_simps1[OF lshift_limited_and, OF limited_and_from_bool])
|
|
apply (simp add: cap_to_H_simps word_ao_dist cl_valid_cap_def
|
|
limited_and_simps cap_reply_cap_def
|
|
limited_and_simps1[OF lshift_limited_and, OF limited_and_from_bool]
|
|
shiftr_over_or_dist word_bw_assocs)
|
|
done
|
|
|
|
lemma fastpath_copy_mrs_ccorres:
|
|
notes min_simps [simp del]
|
|
shows
|
|
"ccorres dc xfdc (\<top> and (\<lambda>_. ln <= length ARM_H.msgRegisters))
|
|
(UNIV \<inter> {s. unat (length___unsigned_long_' s) = ln}
|
|
\<inter> {s. src_' s = tcb_ptr_to_ctcb_ptr src}
|
|
\<inter> {s. dest_' s = tcb_ptr_to_ctcb_ptr dest}) []
|
|
(forM_x (take ln ARM_H.msgRegisters)
|
|
(\<lambda>r. do v \<leftarrow> asUser src (getRegister r);
|
|
asUser dest (setRegister r v) od))
|
|
(Call fastpath_copy_mrs_'proc)"
|
|
apply (rule ccorres_gen_asm)
|
|
apply (cinit' lift: length___unsigned_long_' src_' dest_' simp: word_sle_def word_sless_def)
|
|
apply (unfold whileAnno_def)
|
|
apply (rule ccorres_rel_imp)
|
|
apply (rule_tac F="K \<top>" in ccorres_mapM_x_while)
|
|
apply clarsimp
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule ccorres_rhs_assoc)+
|
|
apply (rule_tac xf'="i_'" in ccorres_abstract, ceqv)
|
|
apply (rule ccorres_Guard_Seq)+
|
|
apply csymbr
|
|
apply (ctac(no_vcg))
|
|
apply ctac
|
|
apply wp
|
|
apply (clarsimp simp: rf_sr_ksCurThread)
|
|
apply (simp add: msgRegisters_ccorres[symmetric] length_msgRegisters)
|
|
apply (simp add: n_msgRegisters_def msgRegisters_unfold)
|
|
apply (drule(1) order_less_le_trans)
|
|
apply (clarsimp simp: "StrictC'_register_defs" msgRegistersC_def fupdate_def
|
|
| drule nat_less_cases' | erule disjE)+
|
|
apply (simp add: min.absorb2)
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (simp)
|
|
apply (simp add: length_msgRegisters n_msgRegisters_def
|
|
word_bits_def hoare_TrueI)+
|
|
done
|
|
|
|
lemma switchToThread_ksCurThread:
|
|
"\<lbrace>\<lambda>s. P t\<rbrace> switchToThread t \<lbrace>\<lambda>rv s. P (ksCurThread s)\<rbrace>"
|
|
apply (simp add: switchToThread_def setCurThread_def)
|
|
apply (wp | simp)+
|
|
done
|
|
|
|
lemma updateCap_cte_wp_at_cteMDBNode:
|
|
"\<lbrace>cte_wp_at' (\<lambda>cte. P (cteMDBNode cte)) p\<rbrace>
|
|
updateCap ptr cap
|
|
\<lbrace>\<lambda>rv. cte_wp_at' (\<lambda>cte. P (cteMDBNode cte)) p\<rbrace>"
|
|
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 \<Longrightarrow> cte_wp_at' P p s = P cte"
|
|
by (clarsimp simp: cte_wp_at_ctes_of)
|
|
|
|
lemma user_getreg_wp:
|
|
"\<lbrace>\<lambda>s. tcb_at' t s \<and> (\<forall>rv. obj_at' (\<lambda>tcb. tcbContext tcb r = rv) t s \<longrightarrow> Q rv s)\<rbrace>
|
|
asUser t (getRegister r) \<lbrace>Q\<rbrace>"
|
|
apply (rule_tac Q="\<lambda>rv s. \<exists>rv'. rv' = rv \<and> 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 cap_page_directory_cap_get_capPDBasePtr_spec2:
|
|
"\<forall>s. \<Gamma>\<turnstile> \<lbrace>s. True\<rbrace>
|
|
Call cap_page_directory_cap_get_capPDBasePtr_'proc
|
|
\<lbrace>cap_get_tag \<^bsup>s\<^esup>cap = scast cap_page_directory_cap
|
|
\<longrightarrow> \<acute>ret__unsigned = capPDBasePtr_CL (cap_page_directory_cap_lift \<^bsup>s\<^esup>cap)\<rbrace>"
|
|
apply (hoare_rule HoarePartial.ProcNoRec1)
|
|
apply vcg
|
|
apply (clarsimp simp: word_sle_def word_sless_def
|
|
cap_page_directory_cap_lift_def
|
|
cap_lift_page_directory_cap)
|
|
done
|
|
|
|
lemma ccorres_flip_Guard2:
|
|
assumes cc: "ccorres_underlying sr \<Gamma> r xf arrel axf A C hs a (Guard F S (Guard F1 S1 c) ;; d)"
|
|
shows "ccorres_underlying sr \<Gamma> r xf arrel axf A C hs a (Guard F1 S1 (Guard F S c) ;; d)"
|
|
apply (rule ccorres_name_pre_C)
|
|
using cc
|
|
apply (case_tac "s \<in> (S1 \<inter> S)")
|
|
apply (clarsimp simp: ccorres_underlying_def)
|
|
apply (erule exec_handlers.cases;
|
|
fastforce elim!: exec_Normal_elim_cases intro: exec_handlers.intros exec.Guard exec.Seq)
|
|
apply (clarsimp simp: ccorres_underlying_def)
|
|
apply (case_tac "s \<in> S")
|
|
apply (fastforce intro: exec.Guard exec.GuardFault exec_handlers.intros exec.Seq)
|
|
apply (fastforce intro: exec.Guard exec.GuardFault exec_handlers.intros exec.Seq)
|
|
done
|
|
|
|
lemma ccorres_abstract_ksCurThread:
|
|
assumes ceqv: "\<And>rv' t t'. ceqv \<Gamma> (\<lambda>s. ksCurThread_' (globals s)) rv' t t' d (d' rv')"
|
|
and cc: "\<And>ct. ccorres_underlying rf_sr \<Gamma> r xf arrel axf (G ct) (G' ct) hs a (d' (tcb_ptr_to_ctcb_ptr ct))"
|
|
shows "ccorres_underlying rf_sr \<Gamma> r xf arrel axf (\<lambda>s. G (ksCurThread s) s)
|
|
{s. s \<in> G' (ctcb_ptr_to_tcb_ptr (ksCurThread_' (globals s)))} hs a d"
|
|
apply (rule ccorres_guard_imp)
|
|
prefer 2
|
|
apply assumption
|
|
apply (rule ccorres_abstract[OF ceqv, where G'="\<lambda>ct. \<lbrace>ct = \<acute>ksCurThread\<rbrace> \<inter> G' (ctcb_ptr_to_tcb_ptr ct)"])
|
|
apply (subgoal_tac "\<exists>t. rv' = tcb_ptr_to_ctcb_ptr t")
|
|
apply clarsimp
|
|
apply (rule ccorres_guard_imp2)
|
|
apply (rule cc)
|
|
apply (clarsimp simp: rf_sr_ksCurThread)
|
|
apply (metis tcb_ptr_to_tcb_ptr)
|
|
apply simp
|
|
done
|
|
|
|
lemmas cte_C_numeral_fold = cte_C_size[THEN meta_eq_to_obj_eq,
|
|
THEN arg_cong[where f="of_nat :: _ \<Rightarrow> word32"], simplified, symmetric]
|
|
|
|
lemmas ccorres_move_c_guard_tcb_ctes2
|
|
= ccorres_move_c_guard_tcb_ctes[unfolded cte_C_numeral_fold]
|
|
|
|
lemma setUntypedCapAsFull_replyCap[simp]:
|
|
"setUntypedCapAsFull cap (ReplyCap curThread False) slot = return ()"
|
|
by (clarsimp simp:setUntypedCapAsFull_def isCap_simps)
|
|
|
|
end
|
|
|
|
context begin interpretation Arch . (*FIXME: arch_split*)
|
|
|
|
lemma getObject_return:
|
|
fixes v :: "'a :: pspace_storable" shows
|
|
"\<lbrakk> \<And>a b c d. (loadObject a b c d :: 'a kernel) = loadObject_default a b c d;
|
|
ko_at' v p s; (1 :: word32) < 2 ^ objBits v \<rbrakk> \<Longrightarrow> getObject p s = return v s"
|
|
apply (clarsimp simp: getObject_def split_def exec_gets
|
|
obj_at'_def projectKOs lookupAround2_known1
|
|
assert_opt_def loadObject_default_def)
|
|
apply (simp add: projectKO_def alignCheck_assert)
|
|
apply (simp add: project_inject objBits_def)
|
|
apply (frule(2) in_magnitude_check[where s'=s])
|
|
apply (simp add: magnitudeCheck_assert in_monad)
|
|
done
|
|
|
|
end
|
|
|
|
context kernel_m begin
|
|
|
|
lemma obj_at_bound_tcb_grandD:
|
|
"\<lbrakk> obj_at' P t s; valid_objs' s; no_0_obj' s; (s, s') \<in> rf_sr \<rbrakk>
|
|
\<Longrightarrow> \<exists>tcb tcb' ntfn ntfn'. ko_at' tcb t s \<and> P tcb
|
|
\<and> cslift s' (tcb_ptr_to_ctcb_ptr t) = Some tcb'
|
|
\<and> ctcb_relation tcb tcb'
|
|
\<and> ((tcbBoundNotification_C tcb' = NULL) = (tcbBoundNotification tcb = None))
|
|
\<and> (tcbBoundNotification tcb \<noteq> None \<longrightarrow> ko_at' ntfn (the (tcbBoundNotification tcb)) s)
|
|
\<and> (tcbBoundNotification tcb \<noteq> None \<longrightarrow> cslift s' (tcbBoundNotification_C tcb') = Some ntfn')
|
|
\<and> (tcbBoundNotification tcb \<noteq> None \<longrightarrow> cnotification_relation (cslift s') ntfn ntfn')"
|
|
apply (clarsimp simp: pred_tcb_at'_def)
|
|
apply (drule(1) obj_at_cslift_tcb, clarsimp)
|
|
apply (rule exI, rule conjI, assumption)
|
|
apply (clarsimp simp: ctcb_relation_def
|
|
option_to_ptr_def option_to_0_def)
|
|
apply (simp add: return_def split: option.split_asm)
|
|
apply (drule_tac s="ntfn_Ptr x"for x in sym)
|
|
apply (drule(1) ko_at_valid_objs', clarsimp simp: projectKOs)
|
|
apply (clarsimp simp: projectKOs valid_obj'_def valid_tcb'_def)
|
|
apply (drule obj_at_ko_at', clarsimp)
|
|
apply (rule conjI, clarsimp)
|
|
apply (rule cmap_relationE1[OF cmap_relation_ntfn], assumption, erule ko_at_projectKO_opt)
|
|
apply auto
|
|
done
|
|
|
|
lemma cnotification_relation_isActive:
|
|
"cnotification_relation tcbs ntfn ntfn'
|
|
\<Longrightarrow> (notification_CL.state_CL (notification_lift ntfn') = scast NtfnState_Active)
|
|
= EndpointDecls_H.isActive ntfn"
|
|
apply (clarsimp simp: cnotification_relation_def Let_def)
|
|
apply (cases ntfn, simp)
|
|
apply (rename_tac ntfna ooeuoue)
|
|
apply (case_tac ntfna, simp_all add: notification_state_defs isActive_def)
|
|
done
|
|
|
|
lemma option_case_liftM_getNotification_wp:
|
|
"\<lbrace>\<lambda>s. \<forall>rv. (case x of None \<Rightarrow> rv = v | Some p \<Rightarrow> obj_at' (\<lambda>ntfn. f ntfn = rv) p s)
|
|
\<longrightarrow> Q rv s\<rbrace> case x of None \<Rightarrow> return v | Some ptr \<Rightarrow> liftM f $ getNotification ptr \<lbrace> Q \<rbrace>"
|
|
apply (rule hoare_pre, wpc, wp getNotification_wp)
|
|
apply (auto simp: obj_at'_def)
|
|
done
|
|
|
|
lemma threadSet_st_tcb_at_state:
|
|
"\<lbrace>\<lambda>s. tcb_at' t s \<longrightarrow> (if p = t
|
|
then obj_at' (\<lambda>tcb. P (tcbState (f tcb))) t s
|
|
else st_tcb_at' P p s)\<rbrace>
|
|
threadSet f t \<lbrace>\<lambda>_. st_tcb_at' P p\<rbrace>"
|
|
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 fastpath_call_ccorres:
|
|
notes hoare_TrueI[simp]
|
|
shows "ccorres dc xfdc
|
|
(\<lambda>s. invs' s \<and> ct_in_state' (op = Running) s
|
|
\<and> obj_at' (\<lambda>tcb. tcbContext tcb ARM_H.capRegister = cptr
|
|
\<and> tcbContext tcb ARM_H.msgInfoRegister = msginfo)
|
|
(ksCurThread s) s)
|
|
(UNIV \<inter> {s. cptr_' s = cptr} \<inter> {s. msgInfo_' s = msginfo}) []
|
|
(fastpaths SysCall) (Call fastpath_call_'proc)"
|
|
proof -
|
|
have [simp]: "scast Kernel_C.tcbCaller = tcbCallerSlot"
|
|
by (simp add:Kernel_C.tcbCaller_def tcbCallerSlot_def)
|
|
have [simp]: "scast Kernel_C.tcbVTable = tcbVTableSlot"
|
|
by (simp add:Kernel_C.tcbVTable_def tcbVTableSlot_def)
|
|
|
|
have tcbs_of_cte_wp_at_vtable:
|
|
"\<And>s tcb ptr. tcbs_of s ptr = Some tcb \<Longrightarrow>
|
|
cte_wp_at' \<top> (ptr + 0x10 * tcbVTableSlot) s"
|
|
apply (clarsimp simp:tcbs_of_def cte_at'_obj_at'
|
|
split:if_splits)
|
|
apply (drule_tac x = "0x10 * tcbVTableSlot" in bspec)
|
|
apply (simp add:tcb_cte_cases_def tcbVTableSlot_def)
|
|
apply simp
|
|
done
|
|
|
|
have tcbs_of_cte_wp_at_caller:
|
|
"\<And>s tcb ptr. tcbs_of s ptr = Some tcb \<Longrightarrow>
|
|
cte_wp_at' \<top> (ptr + 0x10 * tcbCallerSlot) s"
|
|
apply (clarsimp simp:tcbs_of_def cte_at'_obj_at'
|
|
split:if_splits)
|
|
apply (drule_tac x = "0x10 * tcbCallerSlot" in bspec)
|
|
apply (simp add:tcb_cte_cases_def tcbCallerSlot_def)
|
|
apply simp
|
|
done
|
|
|
|
have tcbs_of_aligned':
|
|
"\<And>s ptr tcb. \<lbrakk>tcbs_of s ptr = Some tcb;pspace_aligned' s\<rbrakk> \<Longrightarrow> is_aligned ptr 9"
|
|
apply (clarsimp simp:tcbs_of_def obj_at'_def split:if_splits)
|
|
apply (drule pspace_alignedD')
|
|
apply simp+
|
|
apply (simp add:projectKO_opt_tcb objBitsKO_def
|
|
split: Structures_H.kernel_object.splits)
|
|
done
|
|
|
|
show ?thesis
|
|
using [[goals_limit = 3]]
|
|
apply (cinit lift: cptr_' msgInfo_')
|
|
apply (simp add: catch_liftE_bindE unlessE_throw_catch_If
|
|
unifyFailure_catch_If catch_liftE
|
|
getMessageInfo_def alternative_bind
|
|
cong: if_cong call_ignore_cong del: Collect_const)
|
|
apply (rule ccorres_pre_getCurThread)
|
|
apply (rename_tac curThread)
|
|
apply (rule ccorres_symb_exec_l3[OF _ user_getreg_inv' _ empty_fail_user_getreg])+
|
|
apply (rename_tac msginfo' cptr')
|
|
apply (rule_tac P="msginfo' = msginfo \<and> cptr' = cptr" in ccorres_gen_asm)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (simp only: )
|
|
apply (csymbr, csymbr)
|
|
apply (rule_tac r'="\<lambda>ft ft'. (ft' = scast fault_null_fault) = (ft = None)"
|
|
and xf'="fault_type_'" in ccorres_split_nothrow)
|
|
apply (rule_tac P="cur_tcb' and (\<lambda>s. curThread = ksCurThread s)"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cur_tcb'_def rf_sr_ksCurThread)
|
|
apply (drule(1) obj_at_cslift_tcb, clarsimp)
|
|
apply (clarsimp simp: typ_heap_simps' ctcb_relation_def cfault_rel_def)
|
|
apply (rule rev_bexI, erule threadGet_eq)
|
|
apply (clarsimp simp: fault_lift_def Let_def split: split_if_asm)
|
|
apply ceqv
|
|
apply csymbr
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (rule ccorres_alternative2)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (rule ccorres_alternative1)
|
|
apply (rule ccorres_if_lhs[rotated])
|
|
apply (rule ccorres_inst[where P=\<top> and P'=UNIV])
|
|
apply simp
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (elim conjE)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (simp add: getThreadCSpaceRoot_def locateSlot_conv
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_pre_getCTE2)
|
|
apply (rule ccorres_move_array_assertion_tcb_ctes
|
|
ccorres_move_c_guard_tcb_ctes2
|
|
ccorres_move_const_guard
|
|
ccorres_rhs_assoc)+
|
|
apply (simp only: )
|
|
apply (ctac add: lookup_fp_ccorres)
|
|
apply (rename_tac luRet ep_cap)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rule ccorres_move_array_assertion_tcb_ctes
|
|
| simp del: Collect_const cong: call_ignore_cong)+
|
|
apply (csymbr, csymbr)
|
|
apply (simp add: ccap_relation_case_sum_Null_endpoint
|
|
of_bl_from_bool from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp add: from_bool_0 if_1_0_0 cong: if_cong)
|
|
apply (rule ccorres_cond_true_seq)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (rule ccorres_rhs_assoc)+
|
|
apply csymbr+
|
|
apply (simp add: if_1_0_0 isRight_case_sum
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (elim conjE)
|
|
apply (frule(1) cap_get_tag_isCap[THEN iffD2])
|
|
apply (simp add: ccap_relation_ep_helpers from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (csymbr, csymbr)
|
|
apply (simp add: ccap_relation_ep_helpers
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_rhs_assoc2, rule ccorres_rhs_assoc2)
|
|
apply (rule_tac xf'="\<lambda>s. (dest_' s, ret__unsigned_' s)"
|
|
and r'="\<lambda>ep v. snd v = scast EPState_Recv = isRecvEP ep
|
|
\<and> (isRecvEP ep \<longrightarrow> epQueue ep \<noteq> []
|
|
\<and> fst v = tcb_ptr_to_ctcb_ptr (hd (epQueue ep)))"
|
|
in ccorres_split_nothrow)
|
|
apply (rule ccorres_add_return2)
|
|
apply (rule ccorres_pre_getEndpoint, rename_tac ep)
|
|
apply (rule_tac P="ko_at' ep (capEPPtr (theRight luRet)) and valid_objs'"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: return_def)
|
|
apply (erule cmap_relationE1[OF cmap_relation_ep], erule ko_at_projectKO_opt)
|
|
apply (frule(1) ko_at_valid_ep')
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (simp add: cendpoint_relation_def Let_def isRecvEP_def
|
|
endpoint_state_defs valid_ep'_def
|
|
split: endpoint.split_asm)
|
|
apply (clarsimp simp: tcb_queue_relation'_def neq_Nil_conv)
|
|
apply (rule ceqv_tuple2)
|
|
apply ceqv
|
|
apply ceqv
|
|
apply (rename_tac send_ep send_ep_c)
|
|
apply (rule_tac P="ko_at' send_ep (capEPPtr (theRight luRet))
|
|
and valid_objs'" in ccorres_cross_over_guard)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: getThreadVSpaceRoot_def locateSlot_conv
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_c_guard_tcb_ctes2
|
|
ccorres_move_array_assertion_tcb_ctes
|
|
ccorres_move_const_guard)+
|
|
apply (rule_tac var="newVTable_'" and var_update="newVTable_'_update"
|
|
in getCTE_h_val_ccorres_split[where P=\<top>])
|
|
apply simp
|
|
apply ceqv
|
|
apply (rename_tac pd_cap pd_cap_c)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'=ret__unsigned_' in ccorres_abstract, ceqv)
|
|
apply (rename_tac pd_cap_c_ptr_maybe)
|
|
apply csymbr+
|
|
apply (simp add: isValidVTableRoot_conv from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (drule isValidVTableRootD)
|
|
apply (rule_tac P="pd_cap_c_ptr_maybe = capUntypedPtr (cteCap pd_cap)"
|
|
in ccorres_gen_asm2)
|
|
apply (simp add: ccap_relation_pd_helper ptr_add_assertion_positive
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_array_assertion_pd
|
|
| (rule ccorres_flip_Guard ccorres_flip_Guard2,
|
|
rule ccorres_move_array_assertion_pd))+
|
|
apply (rule stored_hw_asid_get_ccorres_split[where P=\<top>], ceqv)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rename_tac ksCurThread_x)
|
|
apply (rule ccorres_move_c_guard_tcb ccorres_move_const_guard)+
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rename_tac curPrio destPrio)
|
|
apply (rule ccorres_seq_cond_raise[THEN iffD2])
|
|
apply (rule_tac R="obj_at' (op = curPrio \<circ> tcbPriority) curThread
|
|
and obj_at' (op = destPrio \<circ> tcbPriority)
|
|
(hd (epQueue send_ep))
|
|
and (\<lambda>s. ksCurThread s = curThread)
|
|
and (\<lambda>s. ksCurThread s = ksCurThread_x)"
|
|
in ccorres_cond2')
|
|
apply clarsimp
|
|
apply (drule(1) obj_at_cslift_tcb)+
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_ksCurThread)
|
|
apply (simp add: ctcb_relation_unat_tcbPriority_C
|
|
word_less_nat_alt linorder_not_le)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply csymbr+
|
|
apply (simp add: if_1_0_0 ccap_relation_ep_helpers from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: ccap_relation_pd_helper cap_get_tag_isCap_ArchObject2
|
|
del: Collect_const WordSetup.ptr_add_def cong: call_ignore_cong)
|
|
apply csymbr
|
|
apply (rule ccorres_symb_exec_l3[OF _ gets_inv _ empty_fail_gets])
|
|
apply (rename_tac asidMap)
|
|
apply (rule_tac P="asid_map_pd_to_hwasids asidMap (capPDBasePtr (capCap ((cteCap pd_cap))))
|
|
= set_option (pde_stored_asid shw_asid)" in ccorres_gen_asm)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp add: pde_stored_asid_def asid_map_pd_to_hwasids_def)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: pde_stored_asid_def asid_map_pd_to_hwasids_def
|
|
to_bool_def
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_c_guard_tcb ccorres_move_const_guard)+
|
|
apply (rule ccorres_symb_exec_l3[OF _ curDomain_inv _])
|
|
prefer 3
|
|
apply (simp only: curDomain_def, rule empty_fail_gets)
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rename_tac curDom destDom)
|
|
|
|
apply (rule ccorres_seq_cond_raise[THEN iffD2])
|
|
apply (rule_tac R="obj_at' (op = destDom \<circ> tcbDomain)
|
|
(hd (epQueue send_ep))
|
|
and (\<lambda>s. ksCurDomain s = curDom)"
|
|
in ccorres_cond2')
|
|
apply clarsimp
|
|
apply (drule(1) obj_at_cslift_tcb)+
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_ksCurDomain)
|
|
apply (drule ctcb_relation_tcbDomain[symmetric])
|
|
apply (clarsimp simp: up_ucast_inj_eq[symmetric] maxDom_def)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
|
|
apply (rule ccorres_rhs_assoc2)
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (simp only: ucast_id tl_drop_1 One_nat_def)
|
|
apply (rule fastpath_dequeue_ccorres)
|
|
apply simp
|
|
apply ceqv
|
|
apply csymbr
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (rule_tac P="cur_tcb' and (\<lambda>s. ksCurThread s = curThread)"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cur_tcb'_def rf_sr_ksCurThread)
|
|
apply (drule(1) obj_at_cslift_tcb)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (rule rev_bexI, erule threadSet_eq)
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def typ_heap_simps'
|
|
update_tcb_map_tos map_to_tcbs_upd)
|
|
apply (subst map_to_ctes_upd_tcb_no_ctes, assumption)
|
|
apply (rule ball_tcb_cte_casesI, simp_all)[1]
|
|
apply (simp add: cep_relations_drop_fun_upd)
|
|
apply (erule cmap_relation_updI, erule ko_at_projectKO_opt)
|
|
apply (simp add: ctcb_relation_def cthread_state_relation_def)
|
|
apply simp
|
|
apply (rule conjI, erule cready_queues_relation_not_queue_ptrs)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
h_t_valid_clift_Some_iff map_comp_update projectKO_opt_tcb
|
|
cvariable_relation_upd_const ko_at_projectKO_opt)
|
|
apply ceqv
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rule ccorres_move_c_guard_tcb_ctes
|
|
ccorres_move_array_assertion_tcb_ctes
|
|
ccorres_move_const_guard)+
|
|
apply (simp add: getThreadReplySlot_def getThreadCallerSlot_def
|
|
locateSlot_conv
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'="replySlot_'" in ccorres_abstract, ceqv)
|
|
apply (rename_tac replySlot,
|
|
rule_tac P="replySlot = cte_Ptr (curThread
|
|
+ (tcbReplySlot << cte_level_bits))"
|
|
in ccorres_gen_asm2)
|
|
apply (rule ccorres_move_const_guard
|
|
ccorres_move_array_assertion_tcb_ctes
|
|
ccorres_move_c_guard_tcb_ctes)+
|
|
apply csymbr
|
|
apply (simp add: cteInsert_def bind_assoc dc_def[symmetric]
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_pre_getCTE2 ccorres_assert2)+
|
|
apply (rename_tac curThreadReplyCTE curThreadReplyCTE2
|
|
destCallerCTE)
|
|
apply (rule_tac P="curThreadReplyCTE2 = curThreadReplyCTE"
|
|
in ccorres_gen_asm)
|
|
apply (rule ccorres_move_c_guard_tcb_ctes2)
|
|
apply (ctac add: cap_reply_cap_ptr_new_np_updateCap_ccorres)
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (rule_tac P="cte_wp_at' (\<lambda>cte. cteMDBNode cte = nullMDBNode)
|
|
(hd (epQueue send_ep)
|
|
+ (tcbCallerSlot << cte_level_bits))
|
|
and cte_wp_at' (op = curThreadReplyCTE) (curThread
|
|
+ (tcbReplySlot << cte_level_bits))
|
|
and tcb_at' curThread and (no_0 o ctes_of)
|
|
and tcb_at' (hd (epQueue send_ep))"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of size_of_def
|
|
tcb_cnode_index_defs tcbCallerSlot_def
|
|
tcbReplySlot_def cte_level_bits_def
|
|
valid_mdb'_def valid_mdb_ctes_def)
|
|
apply (subst aligned_add_aligned, erule tcb_aligned',
|
|
simp add: is_aligned_def, simp add: word_bits_def, simp)
|
|
apply (rule_tac x="hd (epQueue send_ep) + v" for v
|
|
in cmap_relationE1[OF cmap_relation_cte], assumption+)
|
|
apply (clarsimp simp: typ_heap_simps' updateMDB_def Let_def)
|
|
apply (subst if_not_P)
|
|
apply clarsimp
|
|
apply (simp add: split_def)
|
|
apply (rule getCTE_setCTE_rf_sr, simp_all)[1]
|
|
apply (case_tac destCallerCTE, case_tac curThreadReplyCTE,
|
|
case_tac "cteMDBNode curThreadReplyCTE")
|
|
apply (clarsimp simp add: ccte_relation_eq_ccap_relation)
|
|
apply (clarsimp simp: nullMDBNode_def)
|
|
apply ceqv
|
|
apply (rule ccorres_move_c_guard_cte)
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (rule_tac P="cte_at' (hd (epQueue send_ep)
|
|
+ (tcbCallerSlot << cte_level_bits))
|
|
and cte_wp_at' (op = curThreadReplyCTE) (curThread
|
|
+ (tcbReplySlot << cte_level_bits))
|
|
and tcb_at' (hd (epQueue send_ep))
|
|
and (no_0 o ctes_of)"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of size_of_def
|
|
tcb_cnode_index_defs tcbCallerSlot_def
|
|
tcbReplySlot_def cte_level_bits_def)
|
|
apply (subst aligned_add_aligned, erule tcb_aligned',
|
|
simp add: is_aligned_def, simp add: word_bits_def, simp)
|
|
apply (rule_tac x="curThread + 0x20" in cmap_relationE1[OF cmap_relation_cte],
|
|
assumption+)
|
|
apply (clarsimp simp: typ_heap_simps' updateMDB_def Let_def)
|
|
apply (subst if_not_P)
|
|
apply clarsimp
|
|
apply (simp add: split_def)
|
|
apply (rule getCTE_setCTE_rf_sr, simp_all)[1]
|
|
apply (simp add: ccte_relation_eq_ccap_relation)
|
|
apply (case_tac curThreadReplyCTE,
|
|
case_tac "cteMDBNode curThreadReplyCTE",
|
|
simp)
|
|
apply ceqv
|
|
apply (simp add: updateMDB_def
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_split_nothrow_dc)
|
|
apply simp
|
|
apply (ctac add: fastpath_copy_mrs_ccorres[unfolded forM_x_def])
|
|
apply (rule ccorres_move_c_guard_tcb)
|
|
apply (rule_tac r'=dc and xf'=xfdc in ccorres_split_nothrow)
|
|
apply (simp add: setThreadState_runnable_simp)
|
|
apply (rule_tac P=\<top> in threadSet_ccorres_lemma2, vcg)
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_def
|
|
cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def typ_heap_simps'
|
|
update_tcb_map_tos map_to_tcbs_upd)
|
|
apply (subst map_to_ctes_upd_tcb_no_ctes, assumption)
|
|
apply (rule ball_tcb_cte_casesI, simp_all)[1]
|
|
apply (simp add: cep_relations_drop_fun_upd)
|
|
apply (erule cmap_relation_updI, erule ko_at_projectKO_opt)
|
|
apply (simp add: ctcb_relation_def cthread_state_relation_def)
|
|
apply simp
|
|
apply (rule conjI, erule cready_queues_relation_not_queue_ptrs)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
h_t_valid_clift_Some_iff map_comp_update projectKO_opt_tcb
|
|
cvariable_relation_upd_const ko_at_projectKO_opt)
|
|
apply ceqv
|
|
apply (simp only: bind_assoc[symmetric])
|
|
apply (rule ccorres_split_nothrow_novcg_dc)
|
|
apply simp
|
|
apply (rule ccorres_call,
|
|
rule_tac v=shw_asid and pd="capUntypedPtr (cteCap pd_cap)"
|
|
in switchToThread_fp_ccorres,
|
|
simp+)[1]
|
|
apply (rule_tac P="\<lambda>s. ksCurThread s = hd (epQueue send_ep)"
|
|
in ccorres_cross_over_guard)
|
|
apply csymbr
|
|
apply csymbr
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (fold dc_def)[1]
|
|
apply (rule fastpath_restore_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (simp add: setCurThread_def)
|
|
apply wp
|
|
apply (rule_tac P=\<top> in hoare_triv, simp)
|
|
apply (simp add: imp_conjL rf_sr_ksCurThread del: all_imp_to_ex)
|
|
apply (clarsimp simp: ccap_relation_ep_helpers guard_is_UNIV_def
|
|
mi_from_H_def)
|
|
apply (simp add: pd_has_hwasid_def)
|
|
apply (wp sts_ct_in_state_neq' sts_valid_objs')
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=thread_state_ptr_set_tsType_np_modifies)
|
|
apply (simp add: pred_conj_def)
|
|
apply (rule mapM_x_wp'[OF hoare_weaken_pre])
|
|
apply wp
|
|
apply clarsimp
|
|
apply simp
|
|
apply (vcg exspec=fastpath_copy_mrs_modifies)
|
|
apply (simp add: valid_tcb_state'_def)
|
|
apply wp
|
|
apply (wp updateMDB_weak_cte_wp_at)
|
|
apply simp
|
|
apply (vcg exspec=mdb_node_ptr_mset_mdbNext_mdbRevocable_mdbFirstBadged_modifies)
|
|
apply (simp add: o_def)
|
|
apply (wp | simp
|
|
| wp_once updateMDB_weak_cte_wp_at
|
|
| wp_once updateMDB_cte_wp_at_other)+
|
|
apply (vcg exspec=mdb_node_ptr_set_mdbPrev_np_modifies)
|
|
apply (wp updateCap_cte_wp_at_cteMDBNode
|
|
updateCap_cte_wp_at_cases
|
|
updateCap_no_0 | simp)+
|
|
apply (vcg exspec=cap_reply_cap_ptr_new_np_modifies)
|
|
apply (simp add: word_sle_def)
|
|
apply vcg
|
|
apply (rule conseqPre, vcg, clarsimp)
|
|
apply (simp add: cte_level_bits_def field_simps shiftl_t2n
|
|
ctes_of_Some_cte_wp_at
|
|
del: all_imp_to_ex)
|
|
apply (wp hoare_vcg_all_lift threadSet_ctes_of
|
|
hoare_vcg_imp_lift threadSet_valid_objs'
|
|
threadSet_st_tcb_at_state threadSet_cte_wp_at'
|
|
threadSet_cur
|
|
| simp add: cur_tcb'_def[symmetric])+
|
|
apply (vcg exspec=thread_state_ptr_set_tsType_np_modifies)
|
|
apply (simp only: imp_conv_disj[symmetric])
|
|
apply simp
|
|
apply (simp add: valid_tcb'_def tcb_cte_cases_def
|
|
valid_tcb_state'_def)
|
|
apply (wp hoare_vcg_all_lift hoare_vcg_imp_lift
|
|
set_ep_valid_objs'
|
|
setObject_no_0_obj'[where 'a=endpoint, folded setEndpoint_def])
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=endpoint_ptr_mset_epQueue_tail_state_modifies
|
|
exspec=endpoint_ptr_set_epQueue_head_np_modifies)
|
|
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply simp
|
|
apply wp[1]
|
|
|
|
apply simp
|
|
apply wp[1]
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=cap_page_directory_cap_get_capPDBasePtr_spec2)
|
|
apply (rule conseqPre,
|
|
vcg exspec=cap_page_directory_cap_get_capPDBasePtr_spec2,
|
|
clarsimp)
|
|
apply simp
|
|
apply (rule getEndpoint_wp)
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=endpoint_ptr_get_epQueue_head_modifies
|
|
exspec=endpoint_ptr_get_state_modifies)
|
|
apply (simp add: if_1_0_0 getSlotCap_def)
|
|
apply (rule valid_isRight_theRight_split)
|
|
apply simp
|
|
apply (wp getCTE_wp')
|
|
apply (rule validE_R_abstract_rv)
|
|
apply wp
|
|
apply (simp add: if_1_0_0 del: Collect_const)
|
|
apply (vcg exspec=lookup_fp_modifies)
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply simp
|
|
apply (rule user_getreg_wp)
|
|
apply simp
|
|
apply (rule user_getreg_wp)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: obj_at_tcbs_of ct_in_state'_def st_tcb_at_tcbs_of
|
|
invs_cur' invs_valid_objs' ctes_of_valid'
|
|
word_sle_def
|
|
tcb_ptr_to_ctcb_ptr_mask[OF tcb_at_invs'])
|
|
apply (frule cte_wp_at_valid_objs_valid_cap', clarsimp)
|
|
apply (clarsimp simp: isCap_simps valid_cap'_def maskCapRights_def)
|
|
apply (clarsimp simp add:obj_at'_def projectKO_eq)
|
|
apply (frule invs_valid_objs')
|
|
apply (erule valid_objsE')
|
|
apply simp
|
|
apply (clarsimp simp:projectKO_opt_ep split:Structures_H.kernel_object.splits)
|
|
apply (clarsimp simp:isRecvEP_def valid_obj'_def valid_ep'_def
|
|
split:Structures_H.endpoint.split_asm)
|
|
apply (erule not_NilE)
|
|
apply (drule_tac x = x in bspec)
|
|
apply fastforce
|
|
apply (clarsimp simp:obj_at_tcbs_of)
|
|
apply (frule_tac ptr2 = x in tcbs_of_aligned')
|
|
apply (simp add:invs_pspace_aligned')
|
|
apply (frule_tac ptr2 = x in tcbs_of_cte_wp_at_vtable)
|
|
apply (clarsimp simp:size_of_def field_simps word_sless_def word_sle_def
|
|
dest!:ptr_val_tcb_ptr_mask2[unfolded mask_def, simplified])
|
|
apply (frule_tac p="x + offs" for offs in ctes_of_valid', clarsimp)
|
|
apply (clarsimp simp: isCap_simps valid_cap'_def invs_valid_pde_mappings'
|
|
dest!: isValidVTableRootD)
|
|
apply (clarsimp simp: invs_sym' tcbCallerSlot_def
|
|
tcbVTableSlot_def tcbReplySlot_def
|
|
conj_comms tcb_cnode_index_defs field_simps
|
|
obj_at_tcbs_of)
|
|
apply (clarsimp simp: cte_level_bits_def isValidVTableRoot_def
|
|
ARM_H.isValidVTableRoot_def cte_wp_at_ctes_of
|
|
capAligned_def objBits_simps)
|
|
apply (simp cong: conj_cong)
|
|
apply (frule invs_mdb', clarsimp simp: valid_mdb'_def valid_mdb_ctes_def)
|
|
apply (case_tac xb, clarsimp, drule(1) nullcapsD')
|
|
apply (clarsimp simp: pde_stored_asid_def to_bool_def
|
|
length_msgRegisters word_le_nat_alt[symmetric])
|
|
apply (frule tcb_aligned'[OF obj_at_tcbs_of[THEN iffD2], OF exI, simplified])
|
|
apply clarsimp
|
|
apply (safe del: notI)[1]
|
|
apply (rule not_sym, clarsimp)
|
|
apply (drule aligned_sub_aligned[where x="x + 0x10" and y=x for x])
|
|
apply (erule tcbs_of_aligned')
|
|
apply (simp add:invs_pspace_aligned')
|
|
apply simp
|
|
apply (simp add:is_aligned_def dvd_def)
|
|
apply (clarsimp simp:tcbs_of_def obj_at'_def projectKO_opt_tcb
|
|
split:if_splits Structures_H.kernel_object.splits)
|
|
apply (drule pspace_distinctD')
|
|
apply (simp add:invs_pspace_distinct')
|
|
apply (simp add:objBits_simps)
|
|
apply (clarsimp simp: obj_at_tcbs_of split: list.split)
|
|
apply (erule_tac x = v0 in valid_objsE'[OF invs_valid_objs',rotated])
|
|
apply (clarsimp simp: valid_obj'_def valid_ep'_def isRecvEP_def neq_Nil_conv size_of_def
|
|
split: Structures_H.endpoint.split_asm
|
|
cong: list.case_cong)
|
|
apply (simp add:obj_at_tcbs_of)
|
|
apply simp
|
|
apply (clarsimp simp: syscall_from_H_def[split_simps syscall.split]
|
|
word_sle_def word_sless_def rf_sr_ksCurThread
|
|
ptr_val_tcb_ptr_mask' size_of_def cte_level_bits_def
|
|
tcb_cnode_index_defs tcbCTableSlot_def tcbVTableSlot_def
|
|
tcbReplySlot_def tcbCallerSlot_def
|
|
simp del: Collect_const split del: split_if)
|
|
apply (drule(1) obj_at_cslift_tcb)
|
|
apply (clarsimp simp: ccte_relation_eq_ccap_relation of_bl_from_bool from_bool_0
|
|
if_1_0_0 ccap_relation_case_sum_Null_endpoint
|
|
isRight_case_sum typ_heap_simps')
|
|
apply (frule(1) cap_get_tag_isCap[THEN iffD2])
|
|
apply (clarsimp simp: typ_heap_simps' ccap_relation_ep_helpers)
|
|
apply (erule cmap_relationE1[OF cmap_relation_ep],
|
|
erule ko_at_projectKO_opt)
|
|
apply (frule(1) ko_at_valid_ep')
|
|
apply (clarsimp simp: cendpoint_relation_def Let_def
|
|
isRecvEP_endpoint_case neq_Nil_conv
|
|
tcb_queue_relation'_def valid_ep'_def
|
|
mi_from_H_def)
|
|
apply (clarsimp simp: ccap_relation_ep_helpers from_bool_0
|
|
isValidVTableRoot_conv
|
|
ptr_add_assertion_positive
|
|
pdBits_def pageBits_def
|
|
cap_get_tag_isCap_ArchObject2
|
|
ccap_relation_pd_helper)
|
|
apply (clarsimp simp: isCap_simps dest!: isValidVTableRootD)
|
|
done
|
|
qed
|
|
|
|
lemma isMasterReplyCap_fp_conv:
|
|
"ccap_relation cap cap' \<Longrightarrow>
|
|
(index (cap_C.words_C cap') 0 && 0x1F = scast cap_reply_cap)
|
|
= (isReplyCap cap \<and> \<not> capReplyMaster cap)"
|
|
apply (rule trans)
|
|
apply (rule_tac m="mask 4" in split_word_eq_on_mask)
|
|
apply (simp add: cap_get_tag_isCap[symmetric])
|
|
apply (rule conj_cong)
|
|
apply (simp add: mask_def word_bw_assocs cap_get_tag_eq_x
|
|
cap_reply_cap_def split: split_if)
|
|
apply (clarsimp simp: cap_lift_reply_cap cap_to_H_simps
|
|
isCap_simps
|
|
elim!: ccap_relationE)
|
|
apply (simp add: mask_def cap_reply_cap_def word_bw_assocs
|
|
to_bool_def)
|
|
apply (thin_tac "P" for P)
|
|
apply (rule iffI)
|
|
apply (drule_tac f="\<lambda>v. v >> 4" in arg_cong)
|
|
apply (simp add: shiftr_over_and_dist)
|
|
apply (drule_tac f="\<lambda>v. v << 4" in arg_cong)
|
|
apply (simp add: shiftl_over_and_dist shiftr_shiftl1 mask_def
|
|
word_bw_assocs)
|
|
done
|
|
|
|
lemma ccap_relation_reply_helper:
|
|
"\<lbrakk> ccap_relation cap cap'; isReplyCap cap \<rbrakk>
|
|
\<Longrightarrow> cap_reply_cap_CL.capTCBPtr_CL (cap_reply_cap_lift cap')
|
|
= ptr_val (tcb_ptr_to_ctcb_ptr (capTCBPtr cap))"
|
|
by (clarsimp simp: cap_get_tag_isCap[symmetric]
|
|
cap_lift_reply_cap cap_to_H_simps
|
|
cap_reply_cap_lift_def
|
|
elim!: ccap_relationE)
|
|
|
|
lemma valid_ep_typ_at_lift':
|
|
"\<lbrakk> \<And>p. \<lbrace>typ_at' TCBT p\<rbrace> f \<lbrace>\<lambda>rv. typ_at' TCBT p\<rbrace> \<rbrakk>
|
|
\<Longrightarrow> \<lbrace>\<lambda>s. valid_ep' ep s\<rbrace> f \<lbrace>\<lambda>rv s. valid_ep' ep s\<rbrace>"
|
|
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:
|
|
"\<lbrace>valid_tcb_state' st and valid_objs'\<rbrace>
|
|
threadSet (tcbState_update (\<lambda>_. st)) t
|
|
\<lbrace>\<lambda>rv. valid_objs'\<rbrace>"
|
|
apply (wp threadSet_valid_objs')
|
|
apply (clarsimp simp: valid_tcb'_def tcb_cte_cases_def)
|
|
done
|
|
|
|
lemmas array_assertion_abs_tcb_ctes_add
|
|
= array_assertion_abs_tcb_ctes_add[where
|
|
tcb="\<lambda>s. Ptr (tcb' s)" for tcb', simplified]
|
|
|
|
lemmas ccorres_move_array_assertion_tcb_ctes [corres_pre]
|
|
= ccorres_move_array_assertions [OF array_assertion_abs_tcb_ctes(1)[where
|
|
tcb="\<lambda>s. Ptr (tcb' s)" for tcb', simplified]]
|
|
ccorres_move_array_assertions [OF array_assertion_abs_tcb_ctes(2)]
|
|
ccorres_move_Guard_Seq[OF array_assertion_abs_tcb_ctes_add]
|
|
ccorres_move_Guard[OF array_assertion_abs_tcb_ctes_add]
|
|
|
|
lemmas ccorres_move_c_guard_tcb_ctes3
|
|
= ccorres_move_c_guards [OF c_guard_abs_tcb_ctes[where
|
|
tcb="\<lambda>s. Ptr (tcb' s)" for tcb', simplified],
|
|
unfolded cte_C_numeral_fold]
|
|
|
|
lemma fastpath_reply_cap_check_ccorres:
|
|
"ccorres (\<lambda>rv rv'. \<forall>cap. ccap_relation cap ccap
|
|
\<longrightarrow> rv' = from_bool (isReplyCap cap \<and> \<not> capReplyMaster cap)) ret__int_'
|
|
\<top> ({s. cap_' s = ccap}) []
|
|
(return ()) (Call fastpath_reply_cap_check_'proc)"
|
|
apply (rule ccorres_from_vcg)
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: extra_sle_sless_unfolds isMasterReplyCap_fp_conv
|
|
from_bool_def return_def)
|
|
apply (simp split: bool.split split_if)
|
|
done
|
|
|
|
lemma fastpath_reply_recv_ccorres:
|
|
notes hoare_TrueI[simp]
|
|
shows "ccorres dc xfdc
|
|
(\<lambda>s. invs' s \<and> ct_in_state' (op = Running) s
|
|
\<and> obj_at' (\<lambda>tcb. tcbContext tcb capRegister = cptr
|
|
\<and> tcbContext tcb msgInfoRegister = msginfo)
|
|
(ksCurThread s) s)
|
|
(UNIV \<inter> {s. cptr_' s = cptr} \<inter> {s. msgInfo_' s = msginfo}) []
|
|
(fastpaths SysReplyRecv) (Call fastpath_reply_recv_'proc)"
|
|
proof -
|
|
have [simp]: "Kernel_C.tcbCaller = scast tcbCallerSlot"
|
|
by (simp add:Kernel_C.tcbCaller_def tcbCallerSlot_def)
|
|
have [simp]: "Kernel_C.tcbVTable = scast tcbVTableSlot"
|
|
by (simp add:Kernel_C.tcbVTable_def tcbVTableSlot_def)
|
|
|
|
have tcbs_of_cte_wp_at_vtable:
|
|
"\<And>s tcb ptr. tcbs_of s ptr = Some tcb \<Longrightarrow>
|
|
cte_wp_at' \<top> (ptr + 0x10 * tcbVTableSlot) s"
|
|
apply (clarsimp simp:tcbs_of_def cte_at'_obj_at'
|
|
split:if_splits)
|
|
apply (drule_tac x = "0x10 * tcbVTableSlot" in bspec)
|
|
apply (simp add:tcb_cte_cases_def tcbVTableSlot_def)
|
|
apply simp
|
|
done
|
|
|
|
have tcbs_of_cte_wp_at_caller:
|
|
"\<And>s tcb ptr. tcbs_of s ptr = Some tcb \<Longrightarrow>
|
|
cte_wp_at' \<top> (ptr + 0x10 * tcbCallerSlot) s"
|
|
apply (clarsimp simp:tcbs_of_def cte_at'_obj_at'
|
|
split:if_splits)
|
|
apply (drule_tac x = "0x10 * tcbCallerSlot" in bspec)
|
|
apply (simp add:tcb_cte_cases_def tcbCallerSlot_def)
|
|
apply simp
|
|
done
|
|
|
|
have tcbs_of_aligned':
|
|
"\<And>s ptr tcb. \<lbrakk>tcbs_of s ptr = Some tcb;pspace_aligned' s\<rbrakk> \<Longrightarrow> is_aligned ptr 9"
|
|
apply (clarsimp simp:tcbs_of_def obj_at'_def split:if_splits)
|
|
apply (drule pspace_alignedD')
|
|
apply simp+
|
|
apply (simp add:projectKO_opt_tcb objBitsKO_def
|
|
split: Structures_H.kernel_object.splits)
|
|
done
|
|
|
|
show ?thesis
|
|
using [[goals_limit = 1]]
|
|
apply (cinit lift: cptr_' msgInfo_')
|
|
apply (simp add: catch_liftE_bindE unlessE_throw_catch_If
|
|
unifyFailure_catch_If catch_liftE
|
|
getMessageInfo_def alternative_bind
|
|
cong: if_cong call_ignore_cong del: Collect_const)
|
|
apply (rule ccorres_pre_getCurThread)
|
|
apply (rename_tac curThread)
|
|
apply (rule ccorres_symb_exec_l3[OF _ user_getreg_inv' _ empty_fail_user_getreg])+
|
|
apply (rename_tac msginfo' cptr')
|
|
apply (rule_tac P="msginfo' = msginfo \<and> cptr' = cptr" in ccorres_gen_asm)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (simp only:)
|
|
apply (csymbr, csymbr)
|
|
apply (rule_tac r'="\<lambda>ft ft'. (ft' = scast fault_null_fault) = (ft = None)"
|
|
and xf'="fault_type_'" in ccorres_split_nothrow)
|
|
apply (rule_tac P="cur_tcb' and (\<lambda>s. curThread = ksCurThread s)"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cur_tcb'_def rf_sr_ksCurThread)
|
|
apply (drule(1) obj_at_cslift_tcb, clarsimp)
|
|
apply (clarsimp simp: typ_heap_simps' ctcb_relation_def cfault_rel_def)
|
|
apply (rule rev_bexI, erule threadGet_eq)
|
|
apply (clarsimp simp: fault_lift_def Let_def split: split_if_asm)
|
|
apply ceqv
|
|
apply csymbr
|
|
apply (simp only:)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (rule ccorres_alternative2)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (rule ccorres_alternative1)
|
|
apply (rule ccorres_if_lhs[rotated])
|
|
apply (rule ccorres_inst[where P=\<top> and P'=UNIV])
|
|
apply simp
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (elim conjE)
|
|
apply (simp add: getThreadCSpaceRoot_def locateSlot_conv
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_pre_getCTE2)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rule ccorres_move_array_assertion_tcb_ctes
|
|
ccorres_move_c_guard_tcb_ctes3
|
|
ccorres_move_const_guard
|
|
ccorres_rhs_assoc)+
|
|
apply (ctac add: lookup_fp_ccorres)
|
|
apply (rename_tac luRet ep_cap)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rule ccorres_move_array_assertion_tcb_ctes
|
|
| simp del: Collect_const cong: call_ignore_cong)+
|
|
apply (csymbr, csymbr)
|
|
apply (simp add: ccap_relation_case_sum_Null_endpoint
|
|
of_bl_from_bool from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp add: if_1_0_0 cong: if_cong)
|
|
apply (rule ccorres_cond_true_seq)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (rule ccorres_rhs_assoc)+
|
|
apply csymbr+
|
|
apply (simp add: if_1_0_0 isRight_case_sum
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (elim conjE)
|
|
apply (frule(1) cap_get_tag_isCap[THEN iffD2])
|
|
apply (simp add: ccap_relation_ep_helpers from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_pre_getBoundNotification)
|
|
apply (rule ccorres_rhs_assoc2)
|
|
apply (rule_tac xf'=ret__int_' and r'="\<lambda>rv rv'. rv' = from_bool rv"
|
|
in ccorres_split_nothrow)
|
|
apply (rule_tac P="bound_tcb_at' (op = bound_ntfn) curThread
|
|
and valid_objs' and no_0_obj'
|
|
and (\<lambda>s. curThread = ksCurThread s)" in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: rf_sr_ksCurThread pred_tcb_at'_def)
|
|
apply (drule(3) obj_at_bound_tcb_grandD, clarsimp simp: typ_heap_simps if_1_0_0 return_def)
|
|
apply (simp add: in_liftM Bex_def getNotification_def getObject_return objBits_simps
|
|
return_def cnotification_relation_isActive
|
|
trans [OF eq_commute from_bool_eq_if])
|
|
apply ceqv
|
|
apply (simp only: from_bool_0)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (rule ccorres_split_throws)
|
|
apply simp
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (csymbr, csymbr)
|
|
apply (simp add: ccap_relation_ep_helpers
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule_tac xf'="ret__unsigned_'"
|
|
and r'="\<lambda>ep v. (v = scast EPState_Send) = isSendEP ep"
|
|
in ccorres_split_nothrow)
|
|
apply (rule ccorres_add_return2)
|
|
apply (rule ccorres_pre_getEndpoint, rename_tac ep)
|
|
apply (rule_tac P="ko_at' ep (capEPPtr (theRight luRet)) and valid_objs'"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: return_def)
|
|
apply (erule cmap_relationE1[OF cmap_relation_ep], erule ko_at_projectKO_opt)
|
|
apply (clarsimp simp: typ_heap_simps')
|
|
apply (simp add: cendpoint_relation_def Let_def isSendEP_def
|
|
endpoint_state_defs
|
|
split: endpoint.split_asm)
|
|
apply ceqv
|
|
apply (rename_tac send_ep send_ep_is_send)
|
|
apply (rule_tac P="ko_at' send_ep (capEPPtr (theRight luRet))
|
|
and valid_objs'" in ccorres_cross_over_guard)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp del: Collect_const not_None_eq)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: getThreadVSpaceRoot_def locateSlot_conv
|
|
getThreadCallerSlot_def
|
|
del: Collect_const cong: if_cong call_ignore_cong)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rename_tac ksCurThread_y)
|
|
apply (rule ccorres_move_const_guard
|
|
ccorres_move_c_guard_tcb_ctes2
|
|
ccorres_move_array_assertion_tcb_ctes)+
|
|
apply (rule_tac xf'="ksCurThread_' \<circ> globals"
|
|
and val="tcb_ptr_to_ctcb_ptr curThread"
|
|
in ccorres_abstract_known)
|
|
apply (rule Seq_weak_ceqv, rule Basic_ceqv)
|
|
apply (rule rewrite_xfI, clarsimp simp only: o_def)
|
|
apply (rule refl)
|
|
apply csymbr
|
|
apply (rule ccorres_move_c_guard_cte)
|
|
apply (rule_tac var="callerCap_'" and var_update="callerCap_'_update"
|
|
in getCTE_h_val_ccorres_split[where P=\<top>])
|
|
apply simp
|
|
apply ceqv
|
|
apply (rename_tac caller_cap caller_cap_c)
|
|
apply (rule_tac P="\<lambda>_. capAligned (cteCap caller_cap)"
|
|
in ccorres_cross_over_guard)
|
|
apply (rule ccorres_add_return, ctac add: fastpath_reply_cap_check_ccorres)
|
|
apply (drule spec, drule_tac P="ccap_relation cp caller_cap_c" for cp in mp, assumption)
|
|
apply (simp add: from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp cong: conj_cong)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (csymbr, csymbr)
|
|
apply (rule_tac r'="\<lambda>ft ft'. (ft' = scast fault_null_fault) = (ft = None)"
|
|
and xf'="fault_type_'" in ccorres_split_nothrow)
|
|
apply (rule threadGet_vcg_corres)
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: obj_at_tcbs_of)
|
|
apply (clarsimp simp: typ_heap_simps' ctcb_relation_def cfault_rel_def
|
|
ccap_relation_reply_helper)
|
|
apply (clarsimp simp: fault_lift_def Let_def split: split_if_asm)
|
|
apply ceqv
|
|
apply (simp del: Collect_const not_None_eq cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp del: Collect_const not_None_eq)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_c_guard_tcb_ctes3 ccorres_move_const_guards
|
|
ccorres_move_array_assertion_tcb_ctes)+
|
|
apply (rule_tac var="newVTable_'" and var_update="newVTable_'_update"
|
|
in getCTE_h_val_ccorres_split[where P=\<top>])
|
|
apply simp
|
|
apply ceqv
|
|
apply (rename_tac pd_cap pd_cap_c)
|
|
apply (rule ccorres_symb_exec_r)
|
|
apply (rule_tac xf'=ret__unsigned_' in ccorres_abstract, ceqv)
|
|
apply (rename_tac pd_cap_c_ptr_maybe)
|
|
apply csymbr+
|
|
apply (simp add: isValidVTableRoot_conv from_bool_0
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (drule isValidVTableRootD)
|
|
apply (rule_tac P="pd_cap_c_ptr_maybe = capUntypedPtr (cteCap pd_cap)"
|
|
in ccorres_gen_asm2)
|
|
apply (simp add: ccap_relation_pd_helper cap_get_tag_isCap_ArchObject2
|
|
ccap_relation_reply_helper
|
|
ptr_add_assertion_positive
|
|
del: Collect_const WordSetup.ptr_add_def cong: call_ignore_cong)
|
|
apply (rule ccorres_move_array_assertion_pd
|
|
| (rule ccorres_flip_Guard ccorres_flip_Guard2,
|
|
rule ccorres_move_array_assertion_pd))+
|
|
apply (rule stored_hw_asid_get_ccorres_split[where P=\<top>], ceqv)
|
|
apply (rule ccorres_abstract_ksCurThread, ceqv)
|
|
apply (rename_tac ksCurThread_x)
|
|
apply (rule_tac P="ksCurThread_y = ksCurThread_x" in ccorres_gen_asm)
|
|
apply (rule ccorres_move_c_guard_tcb
|
|
ccorres_move_const_guard)+
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rename_tac curPrio destPrio)
|
|
apply (rule ccorres_seq_cond_raise[THEN iffD2])
|
|
apply (rule_tac R="obj_at' (op = curPrio \<circ> tcbPriority) curThread
|
|
and obj_at' (op = destPrio \<circ> tcbPriority)
|
|
(capTCBPtr (cteCap caller_cap))
|
|
and (\<lambda>s. ksCurThread s = curThread)
|
|
and (\<lambda>s. ksCurThread s = ksCurThread_x)"
|
|
in ccorres_cond2')
|
|
apply clarsimp
|
|
apply (drule(1) obj_at_cslift_tcb)+
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_ksCurThread)
|
|
apply (simp add: ctcb_relation_unat_tcbPriority_C
|
|
word_less_nat_alt linorder_not_le)
|
|
apply simp
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply csymbr+
|
|
apply (rule ccorres_symb_exec_l3[OF _ gets_inv _ empty_fail_gets])
|
|
apply (rename_tac asidMap)
|
|
apply (rule_tac P="asid_map_pd_to_hwasids asidMap (capPDBasePtr (capCap ((cteCap pd_cap))))
|
|
= set_option (pde_stored_asid shw_asid)" in ccorres_gen_asm)
|
|
apply (simp del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_Cond_rhs_Seq)
|
|
apply (simp add: pde_stored_asid_def asid_map_pd_to_hwasids_def)
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: pde_stored_asid_def asid_map_pd_to_hwasids_def
|
|
to_bool_def
|
|
del: Collect_const cong: call_ignore_cong)
|
|
|
|
apply (rule ccorres_move_c_guard_tcb ccorres_move_const_guard)+
|
|
apply (rule ccorres_symb_exec_l3[OF _ curDomain_inv _])
|
|
prefer 3
|
|
apply (simp only: curDomain_def, rule empty_fail_gets)
|
|
apply (rule ccorres_symb_exec_l3[OF _ threadGet_inv _ empty_fail_threadGet])
|
|
apply (rename_tac curDom destDom)
|
|
|
|
apply (rule ccorres_seq_cond_raise[THEN iffD2])
|
|
apply (rule_tac R="obj_at' (op = destDom \<circ> tcbDomain)
|
|
(capTCBPtr (cteCap caller_cap))
|
|
and (\<lambda>s. ksCurDomain s = curDom)"
|
|
in ccorres_cond2')
|
|
apply clarsimp
|
|
apply (drule(1) obj_at_cslift_tcb)+
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_ksCurDomain)
|
|
apply (drule ctcb_relation_tcbDomain[symmetric])
|
|
apply (clarsimp simp: up_ucast_inj_eq[symmetric] maxDom_def)
|
|
|
|
apply simp
|
|
|
|
apply (rule ccorres_split_throws)
|
|
apply (fold dc_def)[1]
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (rule slowpath_ccorres, simp+)
|
|
apply (vcg exspec=slowpath_noreturn_spec)
|
|
apply (simp add: pde_stored_asid_def asid_map_pd_to_hwasids_def
|
|
to_bool_def
|
|
del: Collect_const cong: call_ignore_cong)
|
|
apply simp
|
|
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (rule_tac P="capAligned (theRight luRet)" in ccorres_gen_asm)
|
|
apply (rule_tac P=\<top> and P'="\<lambda>s. ksCurThread s = curThread"
|
|
in threadSet_ccorres_lemma3)
|
|
apply vcg
|
|
apply (clarsimp simp: rf_sr_ksCurThread typ_heap_simps'
|
|
h_t_valid_clift_Some_iff)
|
|
apply (clarsimp simp: capAligned_def isCap_simps objBits_simps
|
|
"StrictC'_thread_state_defs" mask_def)
|
|
apply (clarsimp simp: rf_sr_def cstate_relation_def Let_def
|
|
typ_heap_simps')
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def typ_heap_simps'
|
|
update_tcb_map_tos map_to_tcbs_upd)
|
|
apply (subst map_to_ctes_upd_tcb_no_ctes, assumption)
|
|
apply (rule ball_tcb_cte_casesI, simp_all)[1]
|
|
apply (simp add: cep_relations_drop_fun_upd)
|
|
apply (erule cmap_relation_updI, erule ko_at_projectKO_opt)
|
|
apply (simp add: ctcb_relation_def cthread_state_relation_def
|
|
"StrictC'_thread_state_defs" from_bool_0
|
|
to_bool_def if_1_0_0)
|
|
apply simp
|
|
apply (rule conjI, erule cready_queues_relation_not_queue_ptrs)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
h_t_valid_clift_Some_iff map_comp_update projectKO_opt_tcb
|
|
cvariable_relation_upd_const ko_at_projectKO_opt)
|
|
apply ceqv
|
|
apply (rule ccorres_rhs_assoc2, rule ccorres_rhs_assoc2)
|
|
apply (rule_tac xf'=xfdc and r'=dc in ccorres_split_nothrow)
|
|
apply (rule fastpath_enqueue_ccorres[unfolded o_def,simplified])
|
|
apply simp
|
|
apply ceqv
|
|
apply (simp add: liftM_def del: Collect_const cong: call_ignore_cong)
|
|
apply (rule ccorres_move_c_guard_tcb_ctes3)
|
|
apply (rule_tac r'="\<lambda>rv rv'. rv' = mdbPrev (cteMDBNode rv)"
|
|
and xf'=ret__unsigned_' in ccorres_split_nothrow)
|
|
apply (rule_tac P="tcb_at' curThread
|
|
and K (curThread = ksCurThread_x)
|
|
and (\<lambda>s. ksCurThread s = ksCurThread_x)"
|
|
in getCTE_ccorres_helper[where P'=UNIV])
|
|
apply (rule conseqPre, vcg)
|
|
apply (clarsimp simp: typ_heap_simps' cte_level_bits_def
|
|
tcbCallerSlot_def size_of_def
|
|
tcb_cnode_index_defs tcb_ptr_to_ctcb_ptr_mask)
|
|
apply (clarsimp simp: ccte_relation_def option_map_Some_eq2)
|
|
apply ceqv
|
|
apply (rule ccorres_assert)
|
|
apply (rename_tac mdbPrev_cte mdbPrev_cte_c)
|
|
apply (rule ccorres_split_nothrow_dc)
|
|
apply (simp add: updateMDB_def Let_def
|
|
del: Collect_const cong: if_cong)
|
|
apply (rule_tac P="cte_wp_at' (op = mdbPrev_cte)
|
|
(curThread + (tcbCallerSlot << cte_level_bits))
|
|
and valid_mdb'"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (drule(2) valid_mdb_ctes_of_prev[rotated])
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (rule cmap_relationE1[OF cmap_relation_cte], assumption+)
|
|
apply (clarsimp simp: typ_heap_simps' split_def)
|
|
apply (rule getCTE_setCTE_rf_sr, simp_all)[1]
|
|
apply (clarsimp simp: ccte_relation_def option_map_Some_eq2
|
|
cte_to_H_def mdb_node_to_H_def
|
|
c_valid_cte_def)
|
|
apply (rule ccorres_rhs_assoc2, rule ccorres_rhs_assoc2,
|
|
rule ccorres_rhs_assoc2)
|
|
apply (rule ccorres_split_nothrow_dc)
|
|
apply (rule_tac P="cte_at' (curThread + (tcbCallerSlot << cte_level_bits))
|
|
and tcb_at' curThread
|
|
and K (curThread = ksCurThread_x)"
|
|
in ccorres_from_vcg[where P'=UNIV])
|
|
apply (rule allI, rule conseqPre, vcg)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (rule cmap_relationE1[OF cmap_relation_cte], assumption+)
|
|
apply (clarsimp simp: typ_heap_simps' split_def tcbCallerSlot_def
|
|
tcb_cnode_index_defs tcb_ptr_to_ctcb_ptr_mask
|
|
cte_level_bits_def size_of_def)
|
|
apply (rule setCTE_rf_sr, simp_all add: typ_heap_simps')[1]
|
|
apply (clarsimp simp: ccte_relation_eq_ccap_relation makeObject_cte
|
|
mdb_node_to_H_def nullMDBNode_def
|
|
ccap_relation_NullCap_iff)
|
|
apply csymbr
|
|
apply (ctac add: fastpath_copy_mrs_ccorres[unfolded forM_x_def])
|
|
apply (rule_tac r'=dc and xf'=xfdc in ccorres_split_nothrow)
|
|
apply (simp add: setThreadState_runnable_simp)
|
|
apply (rule_tac P=\<top> in threadSet_ccorres_lemma2, vcg)
|
|
apply (clarsimp simp: typ_heap_simps' rf_sr_def
|
|
cstate_relation_def Let_def)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: cpspace_relation_def typ_heap_simps'
|
|
update_tcb_map_tos map_to_tcbs_upd)
|
|
apply (subst map_to_ctes_upd_tcb_no_ctes, assumption)
|
|
apply (rule ball_tcb_cte_casesI, simp_all)[1]
|
|
apply (simp add: cep_relations_drop_fun_upd)
|
|
apply (erule cmap_relation_updI, erule ko_at_projectKO_opt)
|
|
apply (simp add: ctcb_relation_def cthread_state_relation_def)
|
|
apply simp
|
|
apply (rule conjI, erule cready_queues_relation_not_queue_ptrs)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (rule ext, simp split: split_if)
|
|
apply (simp add: carch_state_relation_def cmachine_state_relation_def
|
|
h_t_valid_clift_Some_iff map_comp_update projectKO_opt_tcb
|
|
cvariable_relation_upd_const ko_at_projectKO_opt)
|
|
apply ceqv
|
|
apply (simp only: bind_assoc[symmetric])
|
|
apply (rule ccorres_split_nothrow_novcg_dc)
|
|
apply (rule ccorres_call,
|
|
rule_tac v=shw_asid and pd="capUntypedPtr (cteCap pd_cap)"
|
|
in switchToThread_fp_ccorres,
|
|
simp+)[1]
|
|
apply (rule_tac P="\<lambda>s. ksCurThread s = capTCBPtr (cteCap caller_cap)"
|
|
in ccorres_cross_over_guard)
|
|
apply csymbr
|
|
apply csymbr
|
|
apply (rule ccorres_call_hSkip)
|
|
apply (fold dc_def)[1]
|
|
apply (rule fastpath_restore_ccorres)
|
|
apply simp
|
|
apply simp
|
|
apply (simp add: setCurThread_def)
|
|
apply wp
|
|
apply (rule_tac P=\<top> in hoare_triv, simp)
|
|
apply (simp add: imp_conjL rf_sr_ksCurThread del: all_imp_to_ex)
|
|
apply (clarsimp simp: ccap_relation_ep_helpers guard_is_UNIV_def
|
|
mi_from_H_def)
|
|
apply (simp add: pd_has_hwasid_def)
|
|
apply (wp sts_ct_in_state_neq' sts_valid_objs')
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=thread_state_ptr_set_tsType_np_modifies)
|
|
apply simp
|
|
apply (rule mapM_x_wp'[OF hoare_weaken_pre], wp)
|
|
apply clarsimp
|
|
apply simp
|
|
apply (vcg exspec=fastpath_copy_mrs_modifies)
|
|
apply (simp add: valid_tcb_state'_def)
|
|
apply wp
|
|
apply (wp setCTE_cte_wp_at_other)
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply (simp add: o_def)
|
|
apply (wp | simp
|
|
| wp_once updateMDB_weak_cte_wp_at
|
|
| wp_once updateMDB_cte_wp_at_other)+
|
|
apply (vcg exspec=mdb_node_ptr_mset_mdbNext_mdbRevocable_mdbFirstBadged_modifies)
|
|
apply simp
|
|
apply (wp getCTE_wp')
|
|
apply simp
|
|
apply vcg
|
|
apply (simp add: shiftl_t2n)
|
|
apply (wp hoare_drop_imps setEndpoint_valid_mdb' set_ep_valid_objs'
|
|
setObject_no_0_obj'[where 'a=endpoint, folded setEndpoint_def])
|
|
apply simp
|
|
apply (vcg exspec=endpoint_ptr_mset_epQueue_tail_state_modifies
|
|
exspec=endpoint_ptr_set_epQueue_head_np_modifies
|
|
exspec=endpoint_ptr_get_epQueue_tail_modifies)
|
|
apply (simp add: valid_pspace'_def pred_conj_def conj_comms
|
|
valid_mdb'_def)
|
|
apply (wp threadSet_cur threadSet_tcbState_valid_objs
|
|
threadSet_state_refs_of' threadSet_ctes_of
|
|
valid_ep_typ_at_lift' threadSet_cte_wp_at'
|
|
| simp)+
|
|
apply (vcg exspec=thread_state_ptr_mset_blockingObject_tsType_modifies)
|
|
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply simp
|
|
apply wp[1]
|
|
|
|
apply simp
|
|
apply wp
|
|
apply (simp cong: if_cong)
|
|
apply (rule threadGet_wp)
|
|
apply (simp cong: if_cong)
|
|
apply (rule threadGet_wp)
|
|
apply (simp add: syscall_from_H_def del: Collect_const)
|
|
apply (vcg exspec=cap_page_directory_cap_get_capPDBasePtr_spec2)
|
|
apply (rule conseqPre,
|
|
vcg exspec=cap_page_directory_cap_get_capPDBasePtr_spec2,
|
|
clarsimp)
|
|
apply (simp add:ccap_relation_reply_helper cong:if_cong)
|
|
apply (rule threadGet_wp)
|
|
apply (simp add: syscall_from_H_def ccap_relation_reply_helper)
|
|
apply (vcg exspec=fault_get_faultType_modifies)
|
|
apply simp
|
|
apply wp
|
|
apply simp
|
|
apply (vcg exspec=fastpath_reply_cap_check_modifies)
|
|
apply simp
|
|
apply (rule getEndpoint_wp)
|
|
apply (simp add: syscall_from_H_def ccap_relation_reply_helper)
|
|
apply (vcg exspec=endpoint_ptr_get_state_modifies)
|
|
apply simp
|
|
apply (wp option_case_liftM_getNotification_wp[unfolded fun_app_def])
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply (simp add: if_1_0_0 getSlotCap_def)
|
|
apply (rule valid_isRight_theRight_split)
|
|
apply (wp getCTE_wp')
|
|
apply (rule validE_R_abstract_rv)
|
|
apply wp
|
|
apply (simp del: Collect_const)
|
|
apply (vcg exspec=lookup_fp_modifies)
|
|
apply simp
|
|
apply (rule threadGet_wp)
|
|
apply (simp del: Collect_const)
|
|
apply vcg
|
|
apply simp
|
|
apply (rule user_getreg_wp)
|
|
apply simp
|
|
apply (rule user_getreg_wp)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: ct_in_state'_def obj_at_tcbs_of word_sle_def)
|
|
apply (frule tcbs_of_aligned')
|
|
apply (simp add:invs_pspace_aligned')
|
|
apply (frule tcbs_of_cte_wp_at_caller)
|
|
apply (clarsimp simp:size_of_def field_simps
|
|
dest!:ptr_val_tcb_ptr_mask2[unfolded mask_def])
|
|
apply (frule st_tcb_at_state_refs_ofD')
|
|
apply (clarsimp simp: obj_at_tcbs_of ct_in_state'_def st_tcb_at_tcbs_of
|
|
invs_cur' invs_valid_objs' ctes_of_valid'
|
|
fun_upd_def[symmetric] fun_upd_idem pred_tcb_at'_def invs_no_0_obj')
|
|
apply (frule cte_wp_at_valid_objs_valid_cap', clarsimp)
|
|
apply (clarsimp simp: isCap_simps valid_cap'_def[split_simps capability.split]
|
|
maskCapRights_def cte_wp_at_ctes_of cte_level_bits_def)
|
|
apply (frule_tac p = a in ctes_of_valid',clarsimp)
|
|
apply (simp add:valid_cap_simps')
|
|
apply (clarsimp simp:cte_level_bits_def)
|
|
apply (frule_tac p="p + tcbCallerSlot * 0x10"for p in ctes_of_valid',clarsimp)
|
|
apply (clarsimp simp: valid_capAligned)
|
|
apply (frule_tac ptr2 = v0a in tcbs_of_cte_wp_at_vtable)
|
|
apply (frule_tac ptr2 = v0a in tcbs_of_aligned')
|
|
apply (simp add:invs_pspace_aligned')
|
|
apply (clarsimp simp:size_of_def field_simps cte_wp_at_ctes_of
|
|
word_sle_def word_sless_def
|
|
dest!:ptr_val_tcb_ptr_mask2[unfolded mask_def])
|
|
apply (clarsimp simp: valid_cap_simps' obj_at_tcbs_of)
|
|
apply (frule_tac p="p + tcbVTableSlot * 0x10" for p in ctes_of_valid', clarsimp)
|
|
apply (clarsimp simp: isCap_simps valid_cap_simps' capAligned_def
|
|
invs_valid_pde_mappings' obj_at_tcbs_of
|
|
dest!: isValidVTableRootD)
|
|
apply (frule invs_mdb')
|
|
apply (clarsimp simp: cte_wp_at_ctes_of tcbSlots cte_level_bits_def
|
|
makeObject_cte isValidVTableRoot_def
|
|
ARM_H.isValidVTableRoot_def
|
|
pde_stored_asid_def to_bool_def
|
|
valid_mdb'_def valid_tcb_state'_def
|
|
word_le_nat_alt[symmetric] length_msgRegisters)
|
|
apply (frule ko_at_valid_ep', clarsimp)
|
|
apply (safe del: notI)[1]
|
|
apply (simp add: isSendEP_def valid_ep'_def tcb_at_invs'
|
|
split: Structures_H.endpoint.split_asm)
|
|
apply (rule subst[OF epQueue.simps(1)],
|
|
erule st_tcb_at_not_in_ep_queue[where P="op = Running", rotated],
|
|
clarsimp+)
|
|
apply (simp add: obj_at_tcbs_of st_tcb_at_tcbs_of)
|
|
apply (drule invs_sym')
|
|
apply (erule_tac P=sym_refs in subst[rotated])
|
|
apply (rule fun_upd_idem[symmetric])
|
|
apply (clarsimp simp: tcb_bound_refs'_def)
|
|
apply (case_tac ntfnptr, simp_all)[1]
|
|
apply (clarsimp simp: set_eq_subset)
|
|
apply (clarsimp simp: field_simps)
|
|
apply (clarsimp simp: syscall_from_H_def[split_simps syscall.split]
|
|
word_sle_def word_sless_def rf_sr_ksCurThread
|
|
ptr_val_tcb_ptr_mask' size_of_def cte_level_bits_def
|
|
tcb_cnode_index_defs tcbSlots
|
|
simp del: Collect_const)
|
|
apply (frule obj_at_bound_tcb_grandD, clarsimp, clarsimp, simp)
|
|
apply (clarsimp simp: typ_heap_simps if_1_0_0)
|
|
apply (clarsimp simp: ccte_relation_eq_ccap_relation
|
|
if_1_0_0 ccap_relation_case_sum_Null_endpoint
|
|
isRight_case_sum typ_heap_simps'
|
|
pdBits_def pageBits_def
|
|
cap_get_tag_isCap mi_from_H_def)
|
|
apply (auto simp: isCap_simps capAligned_def objBits_simps ccap_relation_pd_helper
|
|
cap_get_tag_isCap_ArchObject2
|
|
dest!: ptr_val_tcb_ptr_mask2[unfolded mask_def] isValidVTableRootD)
|
|
done
|
|
qed
|
|
|
|
end
|
|
|
|
datatype tcb_state_regs = TCBStateRegs "thread_state" "MachineTypes.register \<Rightarrow> machine_word"
|
|
|
|
definition
|
|
"tsrContext tsr \<equiv> case tsr of TCBStateRegs ts regs \<Rightarrow> regs"
|
|
|
|
definition
|
|
"tsrState tsr \<equiv> case tsr of TCBStateRegs ts regs \<Rightarrow> ts"
|
|
|
|
lemma accessors_TCBStateRegs[simp]:
|
|
"TCBStateRegs (tsrState v) (tsrContext v) = v"
|
|
by (cases v, simp add: tsrState_def tsrContext_def)
|
|
|
|
lemma tsrContext_simp[simp]:
|
|
"tsrContext (TCBStateRegs st con) = con"
|
|
by (simp add: tsrContext_def)
|
|
|
|
lemma tsrState_simp[simp]:
|
|
"tsrState (TCBStateRegs st con) = st"
|
|
by (simp add: tsrState_def)
|
|
|
|
definition
|
|
get_tcb_state_regs :: "kernel_object option \<Rightarrow> tcb_state_regs"
|
|
where
|
|
"get_tcb_state_regs oko \<equiv> case oko of
|
|
Some (KOTCB tcb) \<Rightarrow> TCBStateRegs (tcbState tcb) (tcbContext tcb)"
|
|
|
|
definition
|
|
put_tcb_state_regs_tcb :: "tcb_state_regs \<Rightarrow> tcb \<Rightarrow> tcb"
|
|
where
|
|
"put_tcb_state_regs_tcb tsr tcb \<equiv> case tsr of
|
|
TCBStateRegs st regs \<Rightarrow> tcb \<lparr> tcbState := st, tcbContext := regs \<rparr>"
|
|
|
|
definition
|
|
put_tcb_state_regs :: "tcb_state_regs \<Rightarrow> kernel_object option \<Rightarrow> kernel_object option"
|
|
where
|
|
"put_tcb_state_regs tsr oko = Some (KOTCB (put_tcb_state_regs_tcb tsr
|
|
(case oko of
|
|
Some (KOTCB tcb) \<Rightarrow> tcb | _ \<Rightarrow> makeObject)))"
|
|
|
|
definition
|
|
"partial_overwrite idx tcbs ps \<equiv>
|
|
\<lambda>x. if x \<in> range idx
|
|
then put_tcb_state_regs (tcbs (inv idx x)) (ps x)
|
|
else ps x"
|
|
|
|
definition
|
|
isolate_thread_actions :: "('x \<Rightarrow> word32) \<Rightarrow> 'a kernel
|
|
\<Rightarrow> (('x \<Rightarrow> tcb_state_regs) \<Rightarrow> ('x \<Rightarrow> tcb_state_regs))
|
|
\<Rightarrow> (scheduler_action \<Rightarrow> scheduler_action)
|
|
\<Rightarrow> 'a kernel"
|
|
where
|
|
"isolate_thread_actions idx m t f \<equiv> do
|
|
s \<leftarrow> gets (ksSchedulerAction_update (\<lambda>_. ResumeCurrentThread)
|
|
o ksPSpace_update (partial_overwrite idx (K undefined)));
|
|
tcbs \<leftarrow> gets (\<lambda>s. get_tcb_state_regs o ksPSpace s o idx);
|
|
sa \<leftarrow> getSchedulerAction;
|
|
(rv, s') \<leftarrow> select_f (m s);
|
|
modify (\<lambda>s. ksPSpace_update (partial_overwrite idx (t tcbs))
|
|
(s' \<lparr> ksSchedulerAction := f sa \<rparr>));
|
|
return rv
|
|
od"
|
|
|
|
lemma put_tcb_state_regs_twice[simp]:
|
|
"put_tcb_state_regs tsr (put_tcb_state_regs tsr' tcb)
|
|
= put_tcb_state_regs tsr tcb"
|
|
apply (simp add: put_tcb_state_regs_def put_tcb_state_regs_tcb_def
|
|
makeObject_tcb
|
|
split: tcb_state_regs.split option.split
|
|
Structures_H.kernel_object.split)
|
|
apply (intro all_tcbI impI allI)
|
|
apply simp
|
|
done
|
|
|
|
lemma partial_overwrite_twice[simp]:
|
|
"partial_overwrite idx f (partial_overwrite idx g ps)
|
|
= partial_overwrite idx f ps"
|
|
by (rule ext, simp add: partial_overwrite_def)
|
|
|
|
lemma get_tcb_state_regs_partial_overwrite[simp]:
|
|
"inj idx \<Longrightarrow>
|
|
get_tcb_state_regs (partial_overwrite idx tcbs f (idx x))
|
|
= tcbs x"
|
|
apply (simp add: partial_overwrite_def)
|
|
apply (simp add: put_tcb_state_regs_def
|
|
get_tcb_state_regs_def
|
|
put_tcb_state_regs_tcb_def
|
|
split: tcb_state_regs.split)
|
|
done
|
|
|
|
lemma isolate_thread_actions_bind:
|
|
"inj idx \<Longrightarrow>
|
|
isolate_thread_actions idx a b c >>=
|
|
(\<lambda>x. isolate_thread_actions idx (d x) e f)
|
|
= isolate_thread_actions idx a id id
|
|
>>= (\<lambda>x. isolate_thread_actions idx (d x) (e o b) (f o c))"
|
|
apply (rule ext)
|
|
apply (clarsimp simp: isolate_thread_actions_def bind_assoc split_def
|
|
bind_select_f_bind[symmetric])
|
|
apply (clarsimp simp: exec_gets getSchedulerAction_def)
|
|
apply (rule select_bind_eq)
|
|
apply (simp add: exec_gets exec_modify o_def)
|
|
apply (rule select_bind_eq)
|
|
apply (simp add: exec_gets exec_modify)
|
|
done
|
|
|
|
context kernel_m begin
|
|
|
|
lemma setObject_modify:
|
|
fixes v :: "'a :: pspace_storable" shows
|
|
"\<lbrakk> obj_at' (P :: 'a \<Rightarrow> bool) p s; updateObject v = updateObject_default v;
|
|
(1 :: word32) < 2 ^ objBits v \<rbrakk>
|
|
\<Longrightarrow> setObject p v s
|
|
= modify (ksPSpace_update (\<lambda>ps. ps (p \<mapsto> injectKO v))) s"
|
|
apply (clarsimp simp: setObject_def split_def exec_gets
|
|
obj_at'_def projectKOs lookupAround2_known1
|
|
assert_opt_def updateObject_default_def
|
|
bind_assoc)
|
|
apply (simp add: projectKO_def alignCheck_assert)
|
|
apply (simp add: project_inject objBits_def)
|
|
apply (clarsimp simp only: objBitsT_koTypeOf[symmetric] koTypeOf_injectKO)
|
|
apply (frule(2) in_magnitude_check[where s'=s])
|
|
apply (simp add: magnitudeCheck_assert in_monad)
|
|
apply (simp add: simpler_modify_def)
|
|
done
|
|
|
|
lemmas getObject_return_tcb
|
|
= getObject_return[OF meta_eq_to_obj_eq, OF loadObject_tcb,
|
|
unfolded objBits_simps, simplified]
|
|
|
|
lemmas setObject_modify_tcb
|
|
= setObject_modify[OF _ meta_eq_to_obj_eq, OF _ updateObject_tcb,
|
|
unfolded objBits_simps, simplified]
|
|
|
|
lemma partial_overwrite_fun_upd:
|
|
"inj idx \<Longrightarrow>
|
|
partial_overwrite idx (tsrs (x := y))
|
|
= (\<lambda>ps. (partial_overwrite idx tsrs ps) (idx x := put_tcb_state_regs y (ps (idx x))))"
|
|
apply (intro ext, simp add: partial_overwrite_def)
|
|
apply (clarsimp split: split_if)
|
|
done
|
|
|
|
lemma get_tcb_state_regs_ko_at':
|
|
"ko_at' ko p s \<Longrightarrow> get_tcb_state_regs (ksPSpace s p)
|
|
= TCBStateRegs (tcbState ko) (tcbContext ko)"
|
|
by (clarsimp simp: obj_at'_def projectKOs get_tcb_state_regs_def)
|
|
|
|
lemma put_tcb_state_regs_ko_at':
|
|
"ko_at' ko p s \<Longrightarrow> put_tcb_state_regs tsr (ksPSpace s p)
|
|
= Some (KOTCB (ko \<lparr> tcbState := tsrState tsr, tcbContext := tsrContext tsr \<rparr>))"
|
|
by (clarsimp simp: obj_at'_def projectKOs put_tcb_state_regs_def
|
|
put_tcb_state_regs_tcb_def
|
|
split: tcb_state_regs.split)
|
|
|
|
lemma partial_overwrite_get_tcb_state_regs:
|
|
"\<lbrakk> \<forall>x. tcb_at' (idx x) s; inj idx \<rbrakk> \<Longrightarrow>
|
|
partial_overwrite idx (\<lambda>x. get_tcb_state_regs (ksPSpace s (idx x)))
|
|
(ksPSpace s) = ksPSpace s"
|
|
apply (rule ext, simp add: partial_overwrite_def
|
|
split: split_if)
|
|
apply clarsimp
|
|
apply (drule_tac x=xa in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs put_tcb_state_regs_def
|
|
get_tcb_state_regs_def put_tcb_state_regs_tcb_def)
|
|
apply (case_tac obj, simp)
|
|
done
|
|
|
|
lemma ksPSpace_update_partial_id:
|
|
"\<lbrakk> \<And>ps x. f ps x = ps (idx x) \<or> f ps x = ksPSpace s (idx x);
|
|
\<forall>x. tcb_at' (idx x) s; inj idx \<rbrakk> \<Longrightarrow>
|
|
ksPSpace_update (\<lambda>ps. partial_overwrite idx (\<lambda>x. get_tcb_state_regs (f ps x)) ps) s
|
|
= s"
|
|
apply (rule trans, rule kernel_state.fold_congs[OF refl refl])
|
|
apply (erule_tac x="ksPSpace s" in meta_allE)
|
|
apply (clarsimp simp: partial_overwrite_get_tcb_state_regs)
|
|
apply (rule refl)
|
|
apply simp
|
|
done
|
|
|
|
lemma isolate_thread_actions_asUser:
|
|
"\<lbrakk> idx t' = t; inj idx; f = (\<lambda>s. ({(v, g s)}, False)) \<rbrakk> \<Longrightarrow>
|
|
monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(asUser t f)
|
|
(isolate_thread_actions idx (return v)
|
|
(\<lambda>tsrs. (tsrs (t' := TCBStateRegs (tsrState (tsrs t'))
|
|
(g (tsrContext (tsrs t'))))))
|
|
id)"
|
|
apply (simp add: asUser_def liftM_def isolate_thread_actions_def split_def
|
|
select_f_returns bind_assoc select_f_singleton_return
|
|
threadGet_def threadSet_def)
|
|
apply (clarsimp simp: monadic_rewrite_def)
|
|
apply (frule_tac x=t' in spec)
|
|
apply (drule obj_at_ko_at', clarsimp)
|
|
apply (simp add: exec_gets getSchedulerAction_def exec_modify
|
|
getObject_return_tcb setObject_modify_tcb o_def
|
|
cong: bind_apply_cong)+
|
|
apply (simp add: partial_overwrite_fun_upd return_def get_tcb_state_regs_ko_at')
|
|
apply (rule kernel_state.fold_congs[OF refl refl])
|
|
apply (clarsimp simp: partial_overwrite_get_tcb_state_regs
|
|
put_tcb_state_regs_ko_at')
|
|
apply (case_tac ko, simp)
|
|
done
|
|
|
|
lemma getRegister_simple:
|
|
"getRegister r = (\<lambda>con. ({(con r, con)}, False))"
|
|
by (simp add: getRegister_def simpler_gets_def)
|
|
|
|
lemma mapM_getRegister_simple:
|
|
"mapM getRegister rs = (\<lambda>con. ({(map con rs, con)}, False))"
|
|
apply (induct rs)
|
|
apply (simp add: mapM_Nil return_def)
|
|
apply (simp add: mapM_Cons getRegister_def simpler_gets_def
|
|
bind_def return_def)
|
|
done
|
|
|
|
lemma setRegister_simple:
|
|
"setRegister r v = (\<lambda>con. ({((), con (r := v))}, False))"
|
|
by (simp add: setRegister_def simpler_modify_def)
|
|
|
|
lemma zipWithM_setRegister_simple:
|
|
"zipWithM_x setRegister rs vs
|
|
= (\<lambda>con. ({((), foldl (\<lambda>con (r, v). con (r := v)) con (zip rs vs))}, False))"
|
|
apply (simp add: zipWithM_x_mapM_x)
|
|
apply (induct ("zip rs vs"))
|
|
apply (simp add: mapM_x_Nil return_def)
|
|
apply (clarsimp simp add: mapM_x_Cons bind_def setRegister_def
|
|
simpler_modify_def fun_upd_def[symmetric])
|
|
done
|
|
|
|
lemma dom_partial_overwrite:
|
|
"\<forall>x. tcb_at' (idx x) s \<Longrightarrow> dom (partial_overwrite idx tsrs (ksPSpace s))
|
|
= dom (ksPSpace s)"
|
|
apply (rule set_eqI)
|
|
apply (clarsimp simp: dom_def partial_overwrite_def put_tcb_state_regs_def
|
|
split: split_if)
|
|
apply (fastforce elim!: obj_atE')
|
|
done
|
|
|
|
lemma map_to_ctes_partial_overwrite:
|
|
"\<forall>x. tcb_at' (idx x) s \<Longrightarrow>
|
|
map_to_ctes (partial_overwrite idx tsrs (ksPSpace s))
|
|
= ctes_of s"
|
|
apply (rule ext)
|
|
apply (frule dom_partial_overwrite[where tsrs=tsrs])
|
|
apply (simp add: map_to_ctes_def partial_overwrite_def
|
|
Let_def)
|
|
apply (case_tac "x \<in> range idx")
|
|
apply (clarsimp simp: put_tcb_state_regs_def)
|
|
apply (drule_tac x=xa in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps
|
|
cong: if_cong)
|
|
apply (simp add: put_tcb_state_regs_def put_tcb_state_regs_tcb_def
|
|
objBits_simps
|
|
cong: if_cong option.case_cong)
|
|
apply (case_tac obj, simp split: tcb_state_regs.split split_if)
|
|
apply simp
|
|
apply (rule if_cong[OF refl])
|
|
apply simp
|
|
apply (case_tac "x && ~~ mask (objBitsKO (KOTCB undefined)) \<in> range idx")
|
|
apply (clarsimp simp: put_tcb_state_regs_def)
|
|
apply (drule_tac x=xa in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps
|
|
cong: if_cong)
|
|
apply (simp add: put_tcb_state_regs_def put_tcb_state_regs_tcb_def
|
|
objBits_simps
|
|
cong: if_cong option.case_cong)
|
|
apply (case_tac obj, simp split: tcb_state_regs.split split_if)
|
|
apply (intro impI allI)
|
|
apply (subgoal_tac "x - idx xa = x && mask 9")
|
|
apply (clarsimp simp: tcb_cte_cases_def split: split_if)
|
|
apply (drule_tac t = "idx xa" in sym)
|
|
apply simp
|
|
apply (simp cong: if_cong)
|
|
done
|
|
|
|
definition
|
|
"thread_actions_isolatable idx f =
|
|
(inj idx \<longrightarrow> monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
f (isolate_thread_actions idx f id id))"
|
|
|
|
lemma getCTE_assert_opt:
|
|
"getCTE p = gets (\<lambda>s. ctes_of s p) >>= assert_opt"
|
|
apply (intro ext)
|
|
apply (simp add: exec_gets assert_opt_def prod_eq_iff
|
|
fail_def return_def
|
|
split: option.split)
|
|
apply (rule conjI)
|
|
apply clarsimp
|
|
apply (rule context_conjI)
|
|
apply (rule ccontr, clarsimp elim!: nonemptyE)
|
|
apply (frule use_valid[OF _ getCTE_sp], rule TrueI)
|
|
apply (frule in_inv_by_hoareD[OF getCTE_inv])
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
apply (simp add: empty_failD[OF empty_fail_getCTE])
|
|
apply clarsimp
|
|
apply (simp add: no_failD[OF no_fail_getCTE, OF ctes_of_cte_at])
|
|
apply (subgoal_tac "cte_wp_at' (op = x2) p x")
|
|
apply (clarsimp simp: cte_wp_at'_def getCTE_def)
|
|
apply (simp add: cte_wp_at_ctes_of)
|
|
done
|
|
|
|
lemma getCTE_isolatable:
|
|
"thread_actions_isolatable idx (getCTE p)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def)
|
|
apply (simp add: isolate_thread_actions_def bind_assoc split_def)
|
|
apply (simp add: getCTE_assert_opt bind_select_f_bind[symmetric]
|
|
bind_assoc select_f_returns)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets getSchedulerAction_def
|
|
map_to_ctes_partial_overwrite)
|
|
apply (simp add: assert_opt_def select_f_returns select_f_asserts
|
|
split: option.split)
|
|
apply (clarsimp simp: exec_modify o_def return_def)
|
|
apply (simp add: ksPSpace_update_partial_id)
|
|
done
|
|
|
|
lemma objBits_2n:
|
|
"(1 :: word32) < 2 ^ objBits obj"
|
|
by (simp add: objBits_def objBitsKO_def archObjSize_def pageBits_def
|
|
split: kernel_object.split arch_kernel_object.split)
|
|
|
|
lemma magnitudeCheck_assert2:
|
|
"\<lbrakk> is_aligned x n; (1 :: word32) < 2 ^ n; ksPSpace s x = Some v \<rbrakk> \<Longrightarrow>
|
|
magnitudeCheck x (snd (lookupAround2 x (ksPSpace (s :: kernel_state)))) n
|
|
= assert (ps_clear x n s)"
|
|
using in_magnitude_check[where x=x and n=n and s=s and s'=s and v="()"]
|
|
by (simp add: magnitudeCheck_assert in_monad)
|
|
|
|
lemma getObject_get_assert:
|
|
assumes deflt: "\<And>a b c d. (loadObject a b c d :: ('a :: pspace_storable) kernel)
|
|
= loadObject_default a b c d"
|
|
shows
|
|
"(getObject p :: ('a :: pspace_storable) kernel)
|
|
= do v \<leftarrow> gets (obj_at' (\<lambda>x :: 'a. True) p);
|
|
assert v;
|
|
gets (the o projectKO_opt o the o swp fun_app p o ksPSpace)
|
|
od"
|
|
apply (rule ext)
|
|
apply (simp add: exec_get getObject_def split_def exec_gets
|
|
deflt loadObject_default_def projectKO_def2
|
|
alignCheck_assert)
|
|
apply (case_tac "ksPSpace x p")
|
|
apply (simp add: obj_at'_def assert_opt_def assert_def
|
|
split: option.split split_if)
|
|
apply (simp add: lookupAround2_known1 assert_opt_def
|
|
obj_at'_def projectKO_def2
|
|
split: option.split)
|
|
apply (clarsimp simp: fail_def fst_return conj_comms project_inject
|
|
objBits_def)
|
|
apply (simp only: assert2[symmetric],
|
|
rule bind_apply_cong[OF refl])
|
|
apply (clarsimp simp: in_monad)
|
|
apply (fold objBits_def)
|
|
apply (simp add: magnitudeCheck_assert2[OF _ objBits_2n])
|
|
apply (rule bind_apply_cong[OF refl])
|
|
apply (clarsimp simp: in_monad return_def simpler_gets_def)
|
|
apply (simp add: iffD2[OF project_inject refl])
|
|
done
|
|
|
|
lemma obj_at_partial_overwrite_If:
|
|
"\<lbrakk> \<forall>x. tcb_at' (idx x) s \<rbrakk>
|
|
\<Longrightarrow> obj_at' P p (ksPSpace_update (partial_overwrite idx f) s)
|
|
= (if p \<in> range idx
|
|
then obj_at' (\<lambda>tcb. P (put_tcb_state_regs_tcb (f (inv idx p)) tcb)) p s
|
|
else obj_at' P p s)"
|
|
apply (frule dom_partial_overwrite[where tsrs=f])
|
|
apply (simp add: obj_at'_def ps_clear_def partial_overwrite_def
|
|
projectKOs split: split_if)
|
|
apply clarsimp
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: put_tcb_state_regs_def objBits_simps)
|
|
done
|
|
|
|
lemma obj_at_partial_overwrite_id1:
|
|
"\<lbrakk> p \<notin> range idx; \<forall>x. tcb_at' (idx x) s \<rbrakk>
|
|
\<Longrightarrow> obj_at' P p (ksPSpace_update (partial_overwrite idx f) s)
|
|
= obj_at' P p s"
|
|
apply (drule dom_partial_overwrite[where tsrs=f])
|
|
apply (simp add: obj_at'_def ps_clear_def partial_overwrite_def
|
|
projectKOs)
|
|
done
|
|
|
|
lemma obj_at_partial_overwrite_id2:
|
|
"\<lbrakk> \<forall>x. tcb_at' (idx x) s; \<And>v tcb. P v \<or> True \<Longrightarrow> injectKO v \<noteq> KOTCB tcb \<rbrakk>
|
|
\<Longrightarrow> obj_at' P p (ksPSpace_update (partial_overwrite idx f) s)
|
|
= obj_at' P p s"
|
|
apply (frule dom_partial_overwrite[where tsrs=f])
|
|
apply (simp add: obj_at'_def ps_clear_def partial_overwrite_def
|
|
projectKOs split: split_if)
|
|
apply clarsimp
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: put_tcb_state_regs_def objBits_simps
|
|
project_inject)
|
|
done
|
|
|
|
lemma getObject_isolatable:
|
|
"\<lbrakk> \<And>a b c d. (loadObject a b c d :: 'a kernel) = loadObject_default a b c d;
|
|
\<And>tcb. projectKO_opt (KOTCB tcb) = (None :: 'a option) \<rbrakk> \<Longrightarrow>
|
|
thread_actions_isolatable idx (getObject p :: ('a :: pspace_storable) kernel)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def)
|
|
apply (simp add: getObject_get_assert split_def
|
|
isolate_thread_actions_def bind_select_f_bind[symmetric]
|
|
bind_assoc select_f_asserts select_f_returns)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets getSchedulerAction_def)
|
|
apply (case_tac "p \<in> range idx")
|
|
apply clarsimp
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs partial_overwrite_def
|
|
put_tcb_state_regs_def)
|
|
apply (simp add: obj_at_partial_overwrite_id1)
|
|
apply (simp add: partial_overwrite_def)
|
|
apply (rule bind_apply_cong[OF refl])
|
|
apply (simp add: exec_modify return_def o_def simpler_gets_def
|
|
ksPSpace_update_partial_id in_monad)
|
|
done
|
|
|
|
lemma gets_isolatable:
|
|
"\<lbrakk> \<And>g h s. \<forall>x. tcb_at' (idx x) s \<Longrightarrow>
|
|
f (ksSchedulerAction_update g
|
|
(ksPSpace_update (partial_overwrite idx (\<lambda>_. undefined)) s)) = f s \<rbrakk> \<Longrightarrow>
|
|
thread_actions_isolatable idx (gets f)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def)
|
|
apply (simp add: isolate_thread_actions_def select_f_returns
|
|
liftM_def bind_assoc)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets
|
|
getSchedulerAction_def exec_modify)
|
|
apply (simp add: simpler_gets_def return_def
|
|
ksPSpace_update_partial_id o_def)
|
|
done
|
|
|
|
lemma modify_isolatable:
|
|
assumes swap:"\<And>tsrs act s. \<forall>x. tcb_at' (idx x) s \<Longrightarrow>
|
|
(ksPSpace_update (partial_overwrite idx tsrs) ((f s)\<lparr> ksSchedulerAction := act \<rparr>))
|
|
= f (ksPSpace_update (partial_overwrite idx tsrs)
|
|
(s \<lparr> ksSchedulerAction := act\<rparr>))"
|
|
shows
|
|
"thread_actions_isolatable idx (modify f)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def)
|
|
apply (simp add: isolate_thread_actions_def select_f_returns
|
|
liftM_def bind_assoc)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets
|
|
getSchedulerAction_def)
|
|
apply (simp add: simpler_modify_def o_def)
|
|
apply (subst swap)
|
|
apply (simp add: obj_at_partial_overwrite_If)
|
|
apply (simp add: ksPSpace_update_partial_id o_def)
|
|
done
|
|
|
|
lemma isolate_thread_actions_wrap_bind:
|
|
"inj idx \<Longrightarrow>
|
|
do x \<leftarrow> isolate_thread_actions idx a b c;
|
|
isolate_thread_actions idx (d x) e f
|
|
od =
|
|
isolate_thread_actions idx
|
|
(do x \<leftarrow> isolate_thread_actions idx a id id;
|
|
isolate_thread_actions idx (d x) id id
|
|
od) (e o b) (f o c)
|
|
"
|
|
apply (rule ext)
|
|
apply (clarsimp simp: isolate_thread_actions_def bind_assoc split_def
|
|
bind_select_f_bind[symmetric] liftM_def
|
|
select_f_returns select_f_selects
|
|
getSchedulerAction_def)
|
|
apply (clarsimp simp: exec_gets getSchedulerAction_def o_def)
|
|
apply (rule select_bind_eq)
|
|
apply (simp add: exec_gets exec_modify o_def)
|
|
apply (rule select_bind_eq)
|
|
apply (simp add: exec_modify)
|
|
done
|
|
|
|
lemma monadic_rewrite_in_isolate_thread_actions:
|
|
"\<lbrakk> inj idx; monadic_rewrite F True P a d \<rbrakk> \<Longrightarrow>
|
|
monadic_rewrite F True (\<lambda>s. P (ksSchedulerAction_update (\<lambda>_. ResumeCurrentThread)
|
|
(ksPSpace_update (partial_overwrite idx (\<lambda>_. undefined)) s)))
|
|
(isolate_thread_actions idx a b c) (isolate_thread_actions idx d b c)"
|
|
apply (clarsimp simp: isolate_thread_actions_def split_def)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule_tac P="\<lambda>_. P s" in monadic_rewrite_bind_head)
|
|
apply (simp add: monadic_rewrite_def select_f_def)
|
|
apply wp
|
|
apply simp
|
|
done
|
|
|
|
lemma thread_actions_isolatable_bind:
|
|
"\<lbrakk> thread_actions_isolatable idx f; \<And>x. thread_actions_isolatable idx (g x);
|
|
\<And>t. \<lbrace>tcb_at' t\<rbrace> f \<lbrace>\<lambda>rv. tcb_at' t\<rbrace> \<rbrakk>
|
|
\<Longrightarrow> thread_actions_isolatable idx (f >>= g)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (erule monadic_rewrite_bind2, assumption)
|
|
apply (rule hoare_vcg_all_lift, assumption)
|
|
apply (subst isolate_thread_actions_wrap_bind, simp)
|
|
apply simp
|
|
apply (rule monadic_rewrite_in_isolate_thread_actions, assumption)
|
|
apply (rule monadic_rewrite_transverse)
|
|
apply (erule monadic_rewrite_bind2, assumption)
|
|
apply (rule hoare_vcg_all_lift, assumption)
|
|
apply (simp add: bind_assoc id_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (simp add: obj_at_partial_overwrite_If)
|
|
done
|
|
|
|
lemma thread_actions_isolatable_return:
|
|
"thread_actions_isolatable idx (return v)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def
|
|
monadic_rewrite_def liftM_def
|
|
isolate_thread_actions_def
|
|
split_def bind_assoc select_f_returns
|
|
exec_gets getSchedulerAction_def)
|
|
apply (simp add: exec_modify return_def o_def
|
|
ksPSpace_update_partial_id)
|
|
done
|
|
|
|
lemma thread_actions_isolatable_fail:
|
|
"thread_actions_isolatable idx fail"
|
|
by (simp add: thread_actions_isolatable_def
|
|
isolate_thread_actions_def select_f_asserts
|
|
liftM_def bind_assoc getSchedulerAction_def
|
|
monadic_rewrite_def exec_gets)
|
|
|
|
lemma thread_actions_isolatable_returns:
|
|
"thread_actions_isolatable idx (return v)"
|
|
"thread_actions_isolatable idx (returnOk v)"
|
|
"thread_actions_isolatable idx (throwError v)"
|
|
by (simp add: returnOk_def throwError_def
|
|
thread_actions_isolatable_return)+
|
|
|
|
lemma thread_actions_isolatable_bindE:
|
|
"\<lbrakk> thread_actions_isolatable idx f; \<And>x. thread_actions_isolatable idx (g x);
|
|
\<And>t. \<lbrace>tcb_at' t\<rbrace> f \<lbrace>\<lambda>rv. tcb_at' t\<rbrace> \<rbrakk>
|
|
\<Longrightarrow> thread_actions_isolatable idx (f >>=E g)"
|
|
apply (simp add: bindE_def)
|
|
apply (erule thread_actions_isolatable_bind)
|
|
apply (simp add: lift_def thread_actions_isolatable_returns
|
|
split: sum.split)
|
|
apply assumption
|
|
done
|
|
|
|
lemma thread_actions_isolatable_catch:
|
|
"\<lbrakk> thread_actions_isolatable idx f; \<And>x. thread_actions_isolatable idx (g x);
|
|
\<And>t. \<lbrace>tcb_at' t\<rbrace> f \<lbrace>\<lambda>rv. tcb_at' t\<rbrace> \<rbrakk>
|
|
\<Longrightarrow> thread_actions_isolatable idx (f <catch> g)"
|
|
apply (simp add: catch_def)
|
|
apply (erule thread_actions_isolatable_bind)
|
|
apply (simp add: thread_actions_isolatable_returns
|
|
split: sum.split)
|
|
apply assumption
|
|
done
|
|
|
|
lemma thread_actions_isolatable_if:
|
|
"\<lbrakk> P \<Longrightarrow> thread_actions_isolatable idx a;
|
|
\<not> P \<Longrightarrow> thread_actions_isolatable idx b \<rbrakk>
|
|
\<Longrightarrow> thread_actions_isolatable idx (if P then a else b)"
|
|
by (cases P, simp_all)
|
|
|
|
lemma select_f_isolatable:
|
|
"thread_actions_isolatable idx (select_f v)"
|
|
apply (clarsimp simp: thread_actions_isolatable_def
|
|
isolate_thread_actions_def
|
|
split_def select_f_selects liftM_def bind_assoc)
|
|
apply (rule monadic_rewrite_imp, rule monadic_rewrite_transverse)
|
|
apply (rule monadic_rewrite_drop_modify monadic_rewrite_bind_tail)+
|
|
apply wp
|
|
apply (simp add: gets_bind_ign getSchedulerAction_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (simp add: ksPSpace_update_partial_id o_def)
|
|
done
|
|
|
|
lemma doMachineOp_isolatable:
|
|
"thread_actions_isolatable idx (doMachineOp m)"
|
|
apply (simp add: doMachineOp_def split_def)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
gets_isolatable thread_actions_isolatable_returns
|
|
modify_isolatable select_f_isolatable)
|
|
apply (simp | wp)+
|
|
done
|
|
|
|
lemma page_directory_at_partial_overwrite:
|
|
"\<forall>x. tcb_at' (idx x) s \<Longrightarrow>
|
|
page_directory_at' p (ksPSpace_update (partial_overwrite idx f) s)
|
|
= page_directory_at' p s"
|
|
by (simp add: page_directory_at'_def typ_at_to_obj_at_arches
|
|
obj_at_partial_overwrite_id2)
|
|
|
|
lemma findPDForASID_isolatable:
|
|
"thread_actions_isolatable idx (findPDForASID asid)"
|
|
apply (simp add: findPDForASID_def liftE_bindE liftME_def bindE_assoc
|
|
case_option_If2 assertE_def liftE_def checkPDAt_def
|
|
stateAssert_def2
|
|
cong: if_cong)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_bindE[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if thread_actions_isolatable_returns
|
|
thread_actions_isolatable_fail
|
|
gets_isolatable getObject_isolatable)
|
|
apply (simp add: projectKO_opt_asidpool page_directory_at_partial_overwrite
|
|
| wp getASID_wp)+
|
|
done
|
|
|
|
lemma getHWASID_isolatable:
|
|
"thread_actions_isolatable idx (getHWASID asid)"
|
|
apply (simp add: getHWASID_def loadHWASID_def
|
|
findFreeHWASID_def
|
|
case_option_If2 findPDForASIDAssert_def
|
|
checkPDAt_def checkPDUniqueToASID_def
|
|
checkPDASIDMapMembership_def
|
|
stateAssert_def2 const_def assert_def
|
|
findFreeHWASID_def
|
|
invalidateASID_def
|
|
invalidateHWASIDEntry_def
|
|
storeHWASID_def
|
|
cong: if_cong)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_bindE[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_catch[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if thread_actions_isolatable_returns
|
|
thread_actions_isolatable_fail
|
|
gets_isolatable modify_isolatable
|
|
findPDForASID_isolatable doMachineOp_isolatable)
|
|
apply (wp hoare_drop_imps
|
|
| simp add: page_directory_at_partial_overwrite)+
|
|
done
|
|
|
|
lemma setVMRoot_isolatable:
|
|
"thread_actions_isolatable idx (setVMRoot t)"
|
|
apply (simp add: setVMRoot_def getThreadVSpaceRoot_def
|
|
locateSlot_conv getSlotCap_def
|
|
cap_case_isPageDirectoryCap if_bool_simps
|
|
whenE_def liftE_def
|
|
checkPDNotInASIDMap_def stateAssert_def2
|
|
checkPDASIDMapMembership_def armv_contextSwitch_def
|
|
cong: if_cong)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_bindE[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_catch[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if thread_actions_isolatable_returns
|
|
thread_actions_isolatable_fail
|
|
gets_isolatable getCTE_isolatable getHWASID_isolatable
|
|
findPDForASID_isolatable doMachineOp_isolatable)
|
|
apply (simp add: projectKO_opt_asidpool
|
|
| wp getASID_wp typ_at_lifts [OF getHWASID_typ_at'])+
|
|
done
|
|
|
|
lemma transferCaps_simple:
|
|
"transferCaps mi [] ep receiver rcvrBuf =
|
|
do
|
|
getReceiveSlots receiver rcvrBuf;
|
|
return (mi\<lparr>msgExtraCaps := 0, msgCapsUnwrapped := 0\<rparr>)
|
|
od"
|
|
apply (cases mi)
|
|
apply (clarsimp simp: transferCaps_def getThreadCSpaceRoot_def locateSlot_conv)
|
|
apply (rule ext bind_apply_cong[OF refl])+
|
|
apply (simp add: upto_enum_def
|
|
split: option.split)
|
|
done
|
|
|
|
lemma transferCaps_simple_rewrite:
|
|
"monadic_rewrite True True ((\<lambda>_. caps = []) and \<top>)
|
|
(transferCaps mi caps ep r rBuf)
|
|
(return (mi \<lparr> msgExtraCaps := 0, msgCapsUnwrapped := 0 \<rparr>))"
|
|
apply (rule monadic_rewrite_gen_asm)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (simp add: transferCaps_simple, rule monadic_rewrite_refl)
|
|
apply (rule monadic_rewrite_symb_exec2, wp empty_fail_getReceiveSlots)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply simp
|
|
done
|
|
|
|
lemma lookupExtraCaps_simple_rewrite:
|
|
"msgExtraCaps mi = 0 \<Longrightarrow>
|
|
(lookupExtraCaps thread rcvBuf mi = returnOk [])"
|
|
by (cases mi, simp add: lookupExtraCaps_def getExtraCPtrs_def
|
|
liftE_bindE upto_enum_step_def mapM_Nil
|
|
split: option.split)
|
|
|
|
lemma doIPCTransfer_simple_rewrite:
|
|
"monadic_rewrite True True
|
|
((\<lambda>_. msgExtraCaps (messageInfoFromWord msgInfo) = 0
|
|
\<and> msgLength (messageInfoFromWord msgInfo)
|
|
\<le> of_nat (length ARM_H.msgRegisters))
|
|
and obj_at' (\<lambda>tcb. tcbFault tcb = None
|
|
\<and> tcbContext tcb msgInfoRegister = msgInfo) sender)
|
|
(doIPCTransfer sender ep badge True rcvr)
|
|
(do rv \<leftarrow> mapM_x (\<lambda>r. do v \<leftarrow> asUser sender (getRegister r);
|
|
asUser rcvr (setRegister r v)
|
|
od)
|
|
(take (unat (msgLength (messageInfoFromWord msgInfo))) ARM_H.msgRegisters);
|
|
y \<leftarrow> setMessageInfo rcvr ((messageInfoFromWord msgInfo) \<lparr>msgCapsUnwrapped := 0\<rparr>);
|
|
asUser rcvr (setRegister ARM_H.badgeRegister badge)
|
|
od)"
|
|
apply (rule monadic_rewrite_gen_asm)
|
|
apply (simp add: doIPCTransfer_def bind_assoc doNormalTransfer_def
|
|
getMessageInfo_def
|
|
cong: option.case_cong)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule_tac P="fault = None" in monadic_rewrite_gen_asm, simp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac x=msgInfo in monadic_rewrite_symb_exec,
|
|
wp empty_fail_user_getreg user_getreg_rv)
|
|
apply (simp add: lookupExtraCaps_simple_rewrite returnOk_catch_bind)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule monadic_rewrite_from_simple, rule copyMRs_simple)
|
|
apply (rule monadic_rewrite_bind_head)
|
|
apply (rule transferCaps_simple_rewrite)
|
|
apply (wp threadGet_const)
|
|
apply (simp add: bind_assoc)
|
|
apply (rule monadic_rewrite_symb_exec2[OF lookupIPC_inv empty_fail_lookupIPCBuffer]
|
|
monadic_rewrite_symb_exec2[OF threadGet_inv empty_fail_threadGet]
|
|
monadic_rewrite_symb_exec2[OF user_getreg_inv' empty_fail_user_getreg]
|
|
monadic_rewrite_bind_head monadic_rewrite_bind_tail
|
|
| wp)+
|
|
apply (case_tac "messageInfoFromWord msgInfo")
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply clarsimp
|
|
apply (auto elim!: obj_at'_weakenE)
|
|
done
|
|
|
|
lemma monadic_rewrite_setSchedulerAction_noop:
|
|
"monadic_rewrite F E (\<lambda>s. ksSchedulerAction s = act) (setSchedulerAction act) (return ())"
|
|
unfolding setSchedulerAction_def
|
|
apply (rule monadic_rewrite_imp, rule monadic_rewrite_modify_noop)
|
|
apply simp
|
|
done
|
|
|
|
lemma rescheduleRequired_simple_rewrite:
|
|
"monadic_rewrite F E
|
|
(sch_act_simple)
|
|
rescheduleRequired
|
|
(setSchedulerAction ChooseNewThread)"
|
|
apply (simp add: rescheduleRequired_def getSchedulerAction_def)
|
|
apply (simp add: monadic_rewrite_def exec_gets sch_act_simple_def)
|
|
apply auto
|
|
done
|
|
|
|
lemma setThreadState_blocked_rewrite:
|
|
"\<not> runnable' st \<Longrightarrow>
|
|
monadic_rewrite True True
|
|
(\<lambda>s. ksCurThread s = t \<and> ksSchedulerAction s \<noteq> ResumeCurrentThread \<and> tcb_at' t s)
|
|
(setThreadState st t)
|
|
(threadSet (tcbState_update (\<lambda>_. st)) t)"
|
|
apply (simp add: setThreadState_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule_tac P="\<not> runnable \<and> curThread = t
|
|
\<and> (action \<noteq> ResumeCurrentThread)"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (simp add: when_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply (rule monadic_rewrite_symb_exec2,
|
|
(wp empty_fail_isRunnable
|
|
| (simp only: getCurThread_def getSchedulerAction_def
|
|
, rule empty_fail_gets))+)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (simp add: conj_comms, wp)
|
|
apply (rule_tac Q="\<lambda>rv s. obj_at' (Not o runnable' o tcbState) t s"
|
|
in hoare_post_imp)
|
|
apply (clarsimp simp: obj_at'_def sch_act_simple_def st_tcb_at'_def)
|
|
apply (wp)
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma setupCallerCap_rewrite:
|
|
"monadic_rewrite True True (\<lambda>s. reply_masters_rvk_fb (ctes_of s))
|
|
(setupCallerCap send rcv)
|
|
(do setThreadState BlockedOnReply send;
|
|
replySlot \<leftarrow> getThreadReplySlot send;
|
|
callerSlot \<leftarrow> getThreadCallerSlot rcv;
|
|
replySlotCTE \<leftarrow> getCTE replySlot;
|
|
assert (mdbNext (cteMDBNode replySlotCTE) = 0
|
|
\<and> isReplyCap (cteCap replySlotCTE)
|
|
\<and> capReplyMaster (cteCap replySlotCTE)
|
|
\<and> mdbFirstBadged (cteMDBNode replySlotCTE)
|
|
\<and> mdbRevocable (cteMDBNode replySlotCTE));
|
|
cteInsert (ReplyCap send False) replySlot callerSlot
|
|
od)"
|
|
apply (simp add: setupCallerCap_def getThreadCallerSlot_def
|
|
getThreadReplySlot_def locateSlot_conv
|
|
getSlotCap_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule monadic_rewrite_assert)+
|
|
apply (rule_tac P="mdbFirstBadged (cteMDBNode masterCTE)
|
|
\<and> mdbRevocable (cteMDBNode masterCTE)"
|
|
in monadic_rewrite_gen_asm)
|
|
apply simp
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec2, (wp | simp)+)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply (rule monadic_rewrite_symb_exec2, wp empty_fail_getCTE)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp getCTE_wp' | simp add: cte_wp_at_ctes_of)+
|
|
apply (clarsimp simp: reply_masters_rvk_fb_def)
|
|
apply fastforce
|
|
done
|
|
|
|
lemma attemptSwitchTo_rewrite:
|
|
"monadic_rewrite True True
|
|
(\<lambda>s. obj_at' (\<lambda>tcb. tcbPriority tcb = curPrio) thread s
|
|
\<and> obj_at' (\<lambda>tcb. tcbPriority tcb = destPrio \<and> tcbDomain tcb = destDom) t s
|
|
\<and> destPrio \<ge> curPrio
|
|
\<and> ksSchedulerAction s = ResumeCurrentThread
|
|
\<and> ksCurThread s = thread
|
|
\<and> ksCurDomain s = curDom
|
|
\<and> destDom = curDom)
|
|
(attemptSwitchTo t) (setSchedulerAction (SwitchToThread t))"
|
|
apply (simp add: attemptSwitchTo_def possibleSwitchTo_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="curPrio \<le> targetPrio \<and> action = ResumeCurrentThread
|
|
\<and> targetDom = curDom"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (simp add: eq_commute le_less[symmetric])
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp threadGet_wp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec2,
|
|
wp empty_fail_threadGet | simp add: getSchedulerAction_def curDomain_def)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply (rule monadic_rewrite_symb_exec2, simp_all add: getCurThread_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (auto simp: obj_at'_def)
|
|
done
|
|
|
|
lemma oblivious_getObject_ksPSpace_default:
|
|
"\<lbrakk> \<forall>s. ksPSpace (f s) = ksPSpace s;
|
|
\<And>a b c ko. (loadObject a b c ko :: 'a kernel) \<equiv> loadObject_default a b c ko \<rbrakk> \<Longrightarrow>
|
|
oblivious f (getObject p :: ('a :: pspace_storable) kernel)"
|
|
apply (simp add: getObject_def split_def loadObject_default_def
|
|
projectKO_def2 alignCheck_assert magnitudeCheck_assert)
|
|
apply (intro oblivious_bind, simp_all)
|
|
done
|
|
|
|
lemmas oblivious_getObject_ksPSpace_tcb[simp]
|
|
= oblivious_getObject_ksPSpace_default[OF _ loadObject_tcb]
|
|
|
|
lemma oblivious_setObject_ksPSpace_tcb[simp]:
|
|
"\<lbrakk> \<forall>s. ksPSpace (f s) = ksPSpace s;
|
|
\<forall>s g. ksPSpace_update g (f s) = f (ksPSpace_update g s) \<rbrakk> \<Longrightarrow>
|
|
oblivious f (setObject p (v :: tcb))"
|
|
apply (simp add: setObject_def split_def updateObject_default_def
|
|
projectKO_def2 alignCheck_assert magnitudeCheck_assert)
|
|
apply (intro oblivious_bind, simp_all)
|
|
done
|
|
|
|
lemma oblivious_getObject_ksPSpace_cte[simp]:
|
|
"\<lbrakk> \<forall>s. ksPSpace (f s) = ksPSpace s \<rbrakk> \<Longrightarrow>
|
|
oblivious f (getObject p :: cte kernel)"
|
|
apply (simp add: getObject_def split_def loadObject_cte
|
|
projectKO_def2 alignCheck_assert magnitudeCheck_assert
|
|
typeError_def unless_when
|
|
cong: Structures_H.kernel_object.case_cong)
|
|
apply (intro oblivious_bind,
|
|
simp_all split: Structures_H.kernel_object.split split_if)
|
|
by (safe intro!: oblivious_bind, simp_all)
|
|
|
|
lemma oblivious_doMachineOp[simp]:
|
|
"\<lbrakk> \<forall>s. ksMachineState (f s) = ksMachineState s;
|
|
\<forall>g s. ksMachineState_update g (f s) = f (ksMachineState_update g s) \<rbrakk>
|
|
\<Longrightarrow> oblivious f (doMachineOp oper)"
|
|
apply (simp add: doMachineOp_def split_def)
|
|
apply (intro oblivious_bind, simp_all)
|
|
done
|
|
|
|
lemmas oblivious_getObject_ksPSpace_asidpool[simp]
|
|
= oblivious_getObject_ksPSpace_default[OF _ loadObject_asidpool]
|
|
|
|
lemma oblivious_setVMRoot_schact:
|
|
"oblivious (ksSchedulerAction_update f) (setVMRoot t)"
|
|
apply (simp add: setVMRoot_def getThreadVSpaceRoot_def locateSlot_conv
|
|
getSlotCap_def getCTE_def armv_contextSwitch_def)
|
|
by (safe intro!: oblivious_bind oblivious_bindE oblivious_catch
|
|
| simp_all add: liftE_def getHWASID_def
|
|
findPDForASID_def liftME_def loadHWASID_def
|
|
findPDForASIDAssert_def checkPDAt_def
|
|
checkPDUniqueToASID_def
|
|
checkPDASIDMapMembership_def
|
|
findFreeHWASID_def invalidateASID_def
|
|
invalidateHWASIDEntry_def storeHWASID_def
|
|
checkPDNotInASIDMap_def armv_contextSwitch_def
|
|
split: capability.split arch_capability.split option.split)+
|
|
|
|
lemma oblivious_switchToThread_schact:
|
|
"oblivious (ksSchedulerAction_update f) (ThreadDecls_H.switchToThread t)"
|
|
apply (simp add: switchToThread_def ARM_H.switchToThread_def bind_assoc
|
|
getCurThread_def setCurThread_def threadGet_def liftM_def
|
|
threadSet_def tcbSchedEnqueue_def unless_when
|
|
getQueue_def setQueue_def storeWordUser_def
|
|
pointerInUserData_def isRunnable_def isBlocked_def
|
|
getThreadState_def tcbSchedDequeue_def bitmap_fun_defs)
|
|
by (safe intro!: oblivious_bind
|
|
| simp_all add: oblivious_setVMRoot_schact)+
|
|
|
|
lemma schedule_rewrite:
|
|
notes hoare_TrueI[simp]
|
|
shows "monadic_rewrite True True
|
|
(\<lambda>s. ksSchedulerAction s = SwitchToThread t \<and> ct_in_state' (op = Running) s)
|
|
(schedule)
|
|
(do curThread \<leftarrow> getCurThread; tcbSchedEnqueue curThread; setSchedulerAction ResumeCurrentThread; switchToThread t od)"
|
|
apply (simp add: schedule_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="action = SwitchToThread t" in monadic_rewrite_gen_asm, simp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="curRunnable \<and> action = SwitchToThread t" in monadic_rewrite_gen_asm, simp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp,simp,wp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec2, wp | simp add: isRunnable_def getSchedulerAction_def)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp)
|
|
apply (simp add: setSchedulerAction_def)
|
|
apply (subst oblivious_modify_swap[symmetric], rule oblivious_switchToThread_schact)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (clarsimp simp: st_tcb_at'_def pred_neg_def o_def obj_at'_def ct_in_state'_def)
|
|
done
|
|
|
|
lemma schedule_rewrite_ct_not_runnable':
|
|
"monadic_rewrite True True
|
|
(\<lambda>s. ksSchedulerAction s = SwitchToThread t \<and> ct_in_state' (Not \<circ> runnable') s)
|
|
(schedule)
|
|
(do setSchedulerAction ResumeCurrentThread; switchToThread t od)"
|
|
apply (simp add: schedule_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="action = SwitchToThread t" in monadic_rewrite_gen_asm, simp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="\<not> curRunnable \<and> action = SwitchToThread t" in monadic_rewrite_gen_asm,simp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp,simp,wp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec2, wp |
|
|
simp add: isRunnable_def getSchedulerAction_def |
|
|
rule hoare_TrueI)+
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp)
|
|
apply (simp add: setSchedulerAction_def)
|
|
apply (subst oblivious_modify_swap[symmetric], rule oblivious_switchToThread_schact)
|
|
apply (rule monadic_rewrite_symb_exec2)
|
|
apply (wp, simp, rule hoare_TrueI)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (clarsimp simp: st_tcb_at'_def pred_neg_def o_def obj_at'_def ct_in_state'_def)
|
|
done
|
|
|
|
lemma activateThread_simple_rewrite:
|
|
"monadic_rewrite True True (ct_in_state' (op = Running))
|
|
(activateThread) (return ())"
|
|
apply (simp add: activateThread_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans, rule monadic_rewrite_bind_tail)+
|
|
apply (rule_tac P="state = Running" in monadic_rewrite_gen_asm)
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply (rule monadic_rewrite_symb_exec2, wp empty_fail_getThreadState)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply (rule monadic_rewrite_symb_exec2,
|
|
simp_all add: getCurThread_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (clarsimp simp: ct_in_state'_def elim!: pred_tcb'_weakenE)
|
|
done
|
|
|
|
end
|
|
|
|
lemma setCTE_obj_at_prio[wp]:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t\<rbrace> setCTE p v \<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t\<rbrace>"
|
|
unfolding setCTE_def
|
|
by (rule setObject_cte_obj_at_tcb', simp+)
|
|
|
|
crunch obj_at_prio[wp]: cteInsert "obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t"
|
|
(wp: crunch_wps)
|
|
|
|
crunch ctes_of[wp]: asUser "\<lambda>s. P (ctes_of s)"
|
|
(wp: crunch_wps)
|
|
|
|
lemma tcbSchedEnqueue_tcbPriority[wp]:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t\<rbrace>
|
|
tcbSchedEnqueue t'
|
|
\<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t\<rbrace>"
|
|
apply (simp add: tcbSchedEnqueue_def unless_def)
|
|
apply (wp | simp cong: if_cong)+
|
|
done
|
|
|
|
crunch obj_at_prio[wp]: cteDeleteOne "obj_at' (\<lambda>tcb. P (tcbPriority tcb)) t"
|
|
(wp: crunch_wps setEndpoint_obj_at_tcb'
|
|
setThreadState_obj_at_unchanged setNotification_tcb setBoundNotification_obj_at_unchanged
|
|
simp: crunch_simps unless_def)
|
|
|
|
context kernel_m begin
|
|
|
|
lemma setThreadState_no_sch_change:
|
|
"\<lbrace>\<lambda>s. P (ksSchedulerAction s) \<and> (runnable' st \<or> t \<noteq> ksCurThread s)\<rbrace>
|
|
setThreadState st t
|
|
\<lbrace>\<lambda>rv s. P (ksSchedulerAction s)\<rbrace>"
|
|
(is "NonDetMonad.valid ?P ?f ?Q")
|
|
apply (simp add: setThreadState_def setSchedulerAction_def)
|
|
apply (wp hoare_pre_cont[where a=rescheduleRequired])
|
|
apply (rule_tac Q="\<lambda>_. ?P and st_tcb_at' (op = st) t" in hoare_post_imp)
|
|
apply (clarsimp split: split_if)
|
|
apply (clarsimp simp: obj_at'_def st_tcb_at'_def projectKOs)
|
|
apply (rule hoare_pre, wp threadSet_pred_tcb_at_state)
|
|
apply simp
|
|
done
|
|
|
|
lemma asUser_obj_at_unchangedT:
|
|
assumes x: "\<forall>tcb con con'. con' \<in> fst (m con)
|
|
\<longrightarrow> P (tcbContext_update (\<lambda>_. snd con') tcb) = P tcb" shows
|
|
"\<lbrace>obj_at' P t\<rbrace> asUser t' m \<lbrace>\<lambda>rv. obj_at' P t\<rbrace>"
|
|
apply (simp add: asUser_def split_def)
|
|
apply (wp threadSet_obj_at' threadGet_wp)
|
|
apply (clarsimp simp: obj_at'_def projectKOs x cong: if_cong)
|
|
done
|
|
|
|
lemmas asUser_obj_at_unchanged
|
|
= asUser_obj_at_unchangedT[OF all_tcbI, rule_format]
|
|
|
|
lemma bind_assoc:
|
|
"do y \<leftarrow> do x \<leftarrow> m; f x od; g y od
|
|
= do x \<leftarrow> m; y \<leftarrow> f x; g y od"
|
|
by (rule bind_assoc)
|
|
|
|
lemma setObject_modify_assert:
|
|
"\<lbrakk> updateObject v = updateObject_default v \<rbrakk>
|
|
\<Longrightarrow> setObject p v = do f \<leftarrow> gets (obj_at' (\<lambda>v'. v = v' \<or> True) p);
|
|
assert f; modify (ksPSpace_update (\<lambda>ps. ps(p \<mapsto> injectKO v))) od"
|
|
using objBits_2n[where obj=v]
|
|
apply (simp add: setObject_def split_def updateObject_default_def
|
|
bind_assoc projectKO_def2 alignCheck_assert)
|
|
apply (rule ext, simp add: exec_gets)
|
|
apply (case_tac "obj_at' (\<lambda>v'. v = v' \<or> True) p x")
|
|
apply (clarsimp simp: obj_at'_def projectKOs lookupAround2_known1
|
|
assert_opt_def)
|
|
apply (clarsimp simp: project_inject)
|
|
apply (simp only: objBits_def objBitsT_koTypeOf[symmetric] koTypeOf_injectKO)
|
|
apply (simp add: magnitudeCheck_assert2 simpler_modify_def)
|
|
apply (clarsimp simp: assert_opt_def assert_def magnitudeCheck_assert2
|
|
split: option.split split_if)
|
|
apply (clarsimp simp: obj_at'_def projectKOs)
|
|
apply (clarsimp simp: project_inject)
|
|
apply (simp only: objBits_def objBitsT_koTypeOf[symmetric]
|
|
koTypeOf_injectKO simp_thms)
|
|
done
|
|
|
|
lemma setEndpoint_isolatable:
|
|
"thread_actions_isolatable idx (setEndpoint p e)"
|
|
apply (simp add: setEndpoint_def setObject_modify_assert
|
|
assert_def)
|
|
apply (case_tac "p \<in> range idx")
|
|
apply (clarsimp simp: thread_actions_isolatable_def
|
|
monadic_rewrite_def fun_eq_iff
|
|
liftM_def isolate_thread_actions_def
|
|
bind_assoc exec_gets getSchedulerAction_def
|
|
bind_select_f_bind[symmetric])
|
|
apply (simp add: obj_at_partial_overwrite_id2)
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs select_f_asserts)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if
|
|
thread_actions_isolatable_return
|
|
thread_actions_isolatable_fail)
|
|
apply (rule gets_isolatable)
|
|
apply (simp add: obj_at_partial_overwrite_id2)
|
|
apply (rule modify_isolatable)
|
|
apply (clarsimp simp: o_def partial_overwrite_def)
|
|
apply (rule kernel_state.fold_congs[OF refl refl])
|
|
apply (clarsimp simp: fun_eq_iff
|
|
split: split_if)
|
|
apply (wp | simp)+
|
|
done
|
|
|
|
lemma setCTE_assert_modify:
|
|
"setCTE p v = do c \<leftarrow> gets (real_cte_at' p);
|
|
t \<leftarrow> gets (tcb_at' (p && ~~ mask 9)
|
|
and K ((p && mask 9) \<in> dom tcb_cte_cases));
|
|
if c then modify (ksPSpace_update (\<lambda>ps. ps(p \<mapsto> KOCTE v)))
|
|
else if t then
|
|
modify (ksPSpace_update
|
|
(\<lambda>ps. ps (p && ~~ mask 9 \<mapsto>
|
|
KOTCB (snd (the (tcb_cte_cases (p && mask 9))) (K v)
|
|
(the (projectKO_opt (the (ps (p && ~~ mask 9)))))))))
|
|
else fail od"
|
|
apply (clarsimp simp: setCTE_def setObject_def split_def
|
|
fun_eq_iff exec_gets)
|
|
apply (case_tac "real_cte_at' p x")
|
|
apply (clarsimp simp: obj_at'_def projectKOs lookupAround2_known1
|
|
assert_opt_def alignCheck_assert objBits_simps
|
|
magnitudeCheck_assert2 updateObject_cte)
|
|
apply (simp add: simpler_modify_def)
|
|
apply (simp split: split_if, intro conjI impI)
|
|
apply (clarsimp simp: obj_at'_def projectKOs)
|
|
apply (subgoal_tac "p \<le> (p && ~~ mask 9) + 2 ^ 9 - 1")
|
|
apply (subgoal_tac "fst (lookupAround2 p (ksPSpace x))
|
|
= Some (p && ~~ mask 9, KOTCB obj)")
|
|
apply (simp add: assert_opt_def)
|
|
apply (subst updateObject_cte_tcb)
|
|
apply (fastforce simp add: subtract_mask)
|
|
apply (simp add: assert_opt_def alignCheck_assert bind_assoc
|
|
magnitudeCheck_assert
|
|
is_aligned_neg_mask2 objBits_def)
|
|
apply (rule ps_clear_lookupAround2, assumption+)
|
|
apply (rule word_and_le2)
|
|
apply (simp add: objBits_simps mask_def field_simps)
|
|
apply (simp add: simpler_modify_def cong: option.case_cong if_cong)
|
|
apply (rule kernel_state.fold_congs[OF refl refl])
|
|
apply (clarsimp simp: projectKO_opt_tcb cong: if_cong)
|
|
apply (clarsimp simp: lookupAround2_char1 word_and_le2)
|
|
apply (rule ccontr, clarsimp)
|
|
apply (erule(2) ps_clearD)
|
|
apply (simp add: objBits_simps mask_def field_simps)
|
|
apply (rule tcb_cte_cases_in_range2)
|
|
apply (simp add: subtract_mask)
|
|
apply simp
|
|
apply (clarsimp simp: assert_opt_def split: option.split)
|
|
apply (rule trans [OF bind_apply_cong[OF _ refl] fun_cong[OF fail_bind]])
|
|
apply (simp add: fail_def prod_eq_iff)
|
|
apply (rule context_conjI)
|
|
apply (rule ccontr, clarsimp elim!: nonemptyE)
|
|
apply (frule(1) updateObject_cte_is_tcb_or_cte[OF _ refl])
|
|
apply (erule disjE)
|
|
apply clarsimp
|
|
apply (frule(1) tcb_cte_cases_aligned_helpers)
|
|
apply (clarsimp simp: domI[where m = cte_cte_cases] field_simps)
|
|
apply (clarsimp simp: lookupAround2_char1 obj_at'_def projectKOs
|
|
objBits_simps)
|
|
apply (clarsimp simp: obj_at'_def lookupAround2_char1
|
|
objBits_simps projectKOs cte_level_bits_def)
|
|
apply (erule empty_failD[OF empty_fail_updateObject_cte])
|
|
done
|
|
|
|
lemma partial_overwrite_fun_upd2:
|
|
"partial_overwrite idx tsrs (f (x := y))
|
|
= (partial_overwrite idx tsrs f)
|
|
(x := if x \<in> range idx then put_tcb_state_regs (tsrs (inv idx x)) y
|
|
else y)"
|
|
by (simp add: fun_eq_iff partial_overwrite_def split: split_if)
|
|
|
|
lemma setCTE_isolatable:
|
|
"thread_actions_isolatable idx (setCTE p v)"
|
|
apply (simp add: setCTE_assert_modify)
|
|
apply (clarsimp simp: thread_actions_isolatable_def
|
|
monadic_rewrite_def fun_eq_iff
|
|
liftM_def exec_gets
|
|
isolate_thread_actions_def
|
|
bind_assoc exec_gets getSchedulerAction_def
|
|
bind_select_f_bind[symmetric]
|
|
obj_at_partial_overwrite_If
|
|
obj_at_partial_overwrite_id2
|
|
cong: if_cong)
|
|
apply (case_tac "p && ~~ mask 9 \<in> range idx \<and> p && mask 9 \<in> dom tcb_cte_cases")
|
|
apply clarsimp
|
|
apply (frule_tac x=x in spec, erule obj_atE')
|
|
apply (subgoal_tac "\<not> real_cte_at' p s")
|
|
apply (clarsimp simp: select_f_returns select_f_asserts split: split_if)
|
|
apply (clarsimp simp: o_def simpler_modify_def partial_overwrite_fun_upd2)
|
|
apply (rule kernel_state.fold_congs[OF refl refl])
|
|
apply (rule ext)
|
|
apply (clarsimp simp: partial_overwrite_get_tcb_state_regs
|
|
split: split_if)
|
|
apply (clarsimp simp: projectKOs get_tcb_state_regs_def
|
|
put_tcb_state_regs_def put_tcb_state_regs_tcb_def
|
|
partial_overwrite_def
|
|
split: tcb_state_regs.split)
|
|
apply (case_tac obj, simp add: projectKO_opt_tcb)
|
|
apply (simp add: tcb_cte_cases_def split: split_if_asm)
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps subtract_mask(2) [symmetric])
|
|
apply (erule notE[rotated], erule (3) tcb_ctes_clear[rotated])
|
|
apply (simp add: select_f_returns select_f_asserts split: split_if)
|
|
apply (intro conjI impI)
|
|
apply (clarsimp simp: simpler_modify_def fun_eq_iff
|
|
partial_overwrite_fun_upd2 o_def
|
|
intro!: kernel_state.fold_congs[OF refl refl])
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps)
|
|
apply (erule notE[rotated], rule tcb_ctes_clear[rotated 2], assumption+)
|
|
apply (fastforce simp add: subtract_mask)
|
|
apply simp
|
|
apply (clarsimp simp: simpler_modify_def
|
|
partial_overwrite_fun_upd2 o_def
|
|
partial_overwrite_get_tcb_state_regs
|
|
intro!: kernel_state.fold_congs[OF refl refl]
|
|
split: split_if)
|
|
apply (simp add: partial_overwrite_def)
|
|
apply (subgoal_tac "p \<notin> range idx")
|
|
apply (clarsimp simp: simpler_modify_def
|
|
partial_overwrite_fun_upd2 o_def
|
|
partial_overwrite_get_tcb_state_regs
|
|
intro!: kernel_state.fold_congs[OF refl refl])
|
|
apply clarsimp
|
|
apply (drule_tac x=x in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs)
|
|
done
|
|
|
|
lemma assert_isolatable:
|
|
"thread_actions_isolatable idx (assert P)"
|
|
by (simp add: assert_def thread_actions_isolatable_if
|
|
thread_actions_isolatable_returns
|
|
thread_actions_isolatable_fail)
|
|
|
|
lemma cteInsert_isolatable:
|
|
"thread_actions_isolatable idx (cteInsert cap src dest)"
|
|
apply (simp add: cteInsert_def updateCap_def updateMDB_def
|
|
Let_def setUntypedCapAsFull_def)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if
|
|
thread_actions_isolatable_returns assert_isolatable
|
|
getCTE_isolatable setCTE_isolatable)
|
|
apply (wp | simp)+
|
|
done
|
|
|
|
lemma isolate_thread_actions_threadSet_tcbState:
|
|
"\<lbrakk> inj idx; idx t' = t \<rbrakk> \<Longrightarrow>
|
|
monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(threadSet (tcbState_update (\<lambda>_. st)) t)
|
|
(isolate_thread_actions idx (return ())
|
|
(\<lambda>tsrs. (tsrs (t' := TCBStateRegs st (tsrContext (tsrs t')))))
|
|
id)"
|
|
apply (simp add: isolate_thread_actions_def bind_assoc split_def
|
|
select_f_returns getSchedulerAction_def)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets threadSet_def
|
|
getObject_get_assert bind_assoc liftM_def
|
|
setObject_modify_assert)
|
|
apply (frule_tac x=t' in spec, drule obj_at_ko_at')
|
|
apply (clarsimp simp: exec_gets simpler_modify_def o_def
|
|
intro!: kernel_state.fold_congs[OF refl refl])
|
|
apply (simp add: partial_overwrite_fun_upd
|
|
partial_overwrite_get_tcb_state_regs)
|
|
apply (clarsimp simp: put_tcb_state_regs_def put_tcb_state_regs_tcb_def
|
|
projectKOs get_tcb_state_regs_def
|
|
elim!: obj_atE')
|
|
apply (case_tac ko)
|
|
apply (simp add: projectKO_opt_tcb)
|
|
done
|
|
|
|
lemma thread_actions_isolatableD:
|
|
"\<lbrakk> thread_actions_isolatable idx f; inj idx \<rbrakk>
|
|
\<Longrightarrow> monadic_rewrite False True (\<lambda>s. (\<forall>x. tcb_at' (idx x) s))
|
|
f (isolate_thread_actions idx f id id)"
|
|
by (clarsimp simp: thread_actions_isolatable_def)
|
|
|
|
lemma tcbSchedDequeue_rewrite:
|
|
"monadic_rewrite True True (obj_at' (Not \<circ> tcbQueued) t) (tcbSchedDequeue t) (return ())"
|
|
apply (simp add: tcbSchedDequeue_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="\<not> queued" in monadic_rewrite_gen_asm)
|
|
apply (simp add: when_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp threadGet_const)
|
|
apply (rule monadic_rewrite_symb_exec2)
|
|
apply wp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (clarsimp)
|
|
done
|
|
|
|
lemma switchToThread_rewrite:
|
|
"monadic_rewrite True True
|
|
(ct_in_state' (Not \<circ> runnable') and cur_tcb' and obj_at' (Not \<circ> tcbQueued) t)
|
|
(switchToThread t)
|
|
(do Arch.switchToThread t; setCurThread t od)"
|
|
apply (simp add: switchToThread_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule tcbSchedDequeue_rewrite)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp Arch_switchToThread_obj_at_pre)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec)
|
|
apply (wp, simp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp)
|
|
apply (clarsimp)
|
|
done
|
|
|
|
lemma threadGet_isolatable:
|
|
assumes v: "\<And>tsr. \<forall>tcb. f (put_tcb_state_regs_tcb tsr tcb) = f tcb"
|
|
shows "thread_actions_isolatable idx (threadGet f t)"
|
|
apply (clarsimp simp: threadGet_def thread_actions_isolatable_def
|
|
isolate_thread_actions_def split_def
|
|
getObject_get_assert liftM_def
|
|
bind_select_f_bind[symmetric]
|
|
select_f_returns select_f_asserts bind_assoc)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets
|
|
getSchedulerAction_def)
|
|
apply (simp add: obj_at_partial_overwrite_If)
|
|
apply (rule bind_apply_cong[OF refl])
|
|
apply (clarsimp simp: exec_gets exec_modify o_def
|
|
ksPSpace_update_partial_id in_monad)
|
|
apply (erule obj_atE')
|
|
apply (clarsimp simp: projectKOs
|
|
partial_overwrite_def put_tcb_state_regs_def
|
|
cong: if_cong)
|
|
apply (simp add: projectKO_opt_tcb v split: split_if)
|
|
done
|
|
|
|
lemma switchToThread_isolatable:
|
|
"thread_actions_isolatable idx (Arch.switchToThread t)"
|
|
apply (simp add: ARM_H.switchToThread_def
|
|
storeWordUser_def stateAssert_def2)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
gets_isolatable setVMRoot_isolatable
|
|
thread_actions_isolatable_if
|
|
doMachineOp_isolatable
|
|
threadGet_isolatable [OF all_tcbI]
|
|
thread_actions_isolatable_returns
|
|
thread_actions_isolatable_fail)
|
|
apply (wp |
|
|
simp add: pointerInUserData_def
|
|
typ_at_to_obj_at_arches
|
|
obj_at_partial_overwrite_id2
|
|
put_tcb_state_regs_tcb_def
|
|
split: tcb_state_regs.split)+
|
|
done
|
|
|
|
lemma setCurThread_isolatable:
|
|
"thread_actions_isolatable idx (setCurThread t)"
|
|
by (simp add: setCurThread_def modify_isolatable)
|
|
|
|
end
|
|
|
|
crunch tcb2[wp]: "Arch.switchToThread" "tcb_at' t"
|
|
(ignore: ARM.clearExMonitor)
|
|
|
|
context kernel_m begin
|
|
|
|
lemma isolate_thread_actions_tcbs_at:
|
|
assumes f: "\<And>x. \<lbrace>tcb_at' (idx x)\<rbrace> f \<lbrace>\<lambda>rv. tcb_at' (idx x)\<rbrace>" shows
|
|
"\<lbrace>\<lambda>s. \<forall>x. tcb_at' (idx x) s\<rbrace>
|
|
isolate_thread_actions idx f f' f'' \<lbrace>\<lambda>p s. \<forall>x. tcb_at' (idx x) s\<rbrace>"
|
|
apply (simp add: isolate_thread_actions_def split_def)
|
|
apply wp
|
|
apply clarsimp
|
|
apply (simp add: obj_at_partial_overwrite_If use_valid[OF _ f])
|
|
done
|
|
|
|
lemma isolate_thread_actions_rewrite_bind:
|
|
"\<lbrakk> inj idx; monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
f (isolate_thread_actions idx f' f'' f''');
|
|
\<And>x. monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(g x)
|
|
(isolate_thread_actions idx (g' x) g'' g''');
|
|
thread_actions_isolatable idx f'; \<And>x. thread_actions_isolatable idx (g' x);
|
|
\<And>x. \<lbrace>tcb_at' (idx x)\<rbrace> f' \<lbrace>\<lambda>rv. tcb_at' (idx x)\<rbrace> \<rbrakk>
|
|
\<Longrightarrow> monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(f >>= g) (isolate_thread_actions idx
|
|
(f' >>= g') (g'' o f'') (g''' o f'''))"
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind, assumption+)
|
|
apply (wp isolate_thread_actions_tcbs_at)
|
|
apply simp
|
|
apply (subst isolate_thread_actions_wrap_bind, assumption)
|
|
apply (rule monadic_rewrite_in_isolate_thread_actions, assumption)
|
|
apply (rule monadic_rewrite_transverse)
|
|
apply (rule monadic_rewrite_bind2)
|
|
apply (erule(1) thread_actions_isolatableD)
|
|
apply (rule thread_actions_isolatableD, assumption+)
|
|
apply (rule hoare_vcg_all_lift, assumption)
|
|
apply (simp add: liftM_def id_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (simp add: obj_at_partial_overwrite_If)
|
|
done
|
|
|
|
definition
|
|
"copy_register_tsrs src dest r tsrs
|
|
= tsrs (dest := TCBStateRegs (tsrState (tsrs dest))
|
|
((tsrContext (tsrs dest)) (r := tsrContext (tsrs src) r)))"
|
|
|
|
lemma tcb_at_KOTCB_upd:
|
|
"tcb_at' (idx x) s \<Longrightarrow>
|
|
tcb_at' p (ksPSpace_update (\<lambda>ps. ps(idx x \<mapsto> KOTCB tcb)) s)
|
|
= tcb_at' p s"
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps
|
|
split: split_if)
|
|
apply (simp add: ps_clear_def)
|
|
done
|
|
|
|
lemma copy_register_isolate:
|
|
"\<lbrakk> inj idx; idx x = src; idx y = dest \<rbrakk> \<Longrightarrow>
|
|
monadic_rewrite False True
|
|
(\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(do v \<leftarrow> asUser src (getRegister r);
|
|
asUser dest (setRegister r v) od)
|
|
(isolate_thread_actions idx (return ())
|
|
(copy_register_tsrs x y r) id)"
|
|
apply (simp add: asUser_def split_def bind_assoc
|
|
getRegister_def setRegister_def
|
|
select_f_returns isolate_thread_actions_def
|
|
getSchedulerAction_def)
|
|
apply (simp add: threadGet_def liftM_def getObject_get_assert
|
|
bind_assoc threadSet_def
|
|
setObject_modify_assert)
|
|
apply (clarsimp simp: monadic_rewrite_def exec_gets
|
|
exec_modify tcb_at_KOTCB_upd)
|
|
apply (clarsimp simp: simpler_modify_def
|
|
intro!: kernel_state.fold_congs[OF refl refl])
|
|
apply (clarsimp simp: copy_register_tsrs_def o_def
|
|
partial_overwrite_fun_upd
|
|
partial_overwrite_get_tcb_state_regs)
|
|
apply (frule_tac x=x in spec, drule_tac x=y in spec)
|
|
apply (clarsimp simp: obj_at'_def projectKOs objBits_simps
|
|
cong: if_cong)
|
|
apply (case_tac obj, case_tac obja)
|
|
apply (simp add: projectKO_opt_tcb put_tcb_state_regs_def
|
|
put_tcb_state_regs_tcb_def get_tcb_state_regs_def
|
|
cong: if_cong)
|
|
apply (auto simp: fun_eq_iff split: split_if)
|
|
done
|
|
|
|
lemma monadic_rewrite_isolate_final2:
|
|
assumes mr: "monadic_rewrite F E Q f g"
|
|
and eqs: "\<And>s tsrs. \<lbrakk> P s; tsrs = get_tcb_state_regs o ksPSpace s o idx \<rbrakk>
|
|
\<Longrightarrow> f' tsrs = g' tsrs"
|
|
"\<And>s. P s \<Longrightarrow> f'' (ksSchedulerAction s) = g'' (ksSchedulerAction s)"
|
|
"\<And>s tsrs sa. R s \<Longrightarrow>
|
|
Q ((ksPSpace_update (partial_overwrite idx tsrs)
|
|
s) (| ksSchedulerAction := sa |))"
|
|
shows
|
|
"monadic_rewrite F E (P and R)
|
|
(isolate_thread_actions idx f f' f'')
|
|
(isolate_thread_actions idx g g' g'')"
|
|
apply (simp add: isolate_thread_actions_def split_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule_tac P="\<lambda> s'. Q s" in monadic_rewrite_bind)
|
|
apply (insert mr)[1]
|
|
apply (simp add: monadic_rewrite_def select_f_def)
|
|
apply auto[1]
|
|
apply (rule_tac P="P and (\<lambda>s. tcbs = get_tcb_state_regs o ksPSpace s o idx
|
|
\<and> sa = ksSchedulerAction s)"
|
|
in monadic_rewrite_refl3)
|
|
apply (clarsimp simp: exec_modify eqs return_def)
|
|
apply wp
|
|
apply (clarsimp simp: o_def eqs)
|
|
done
|
|
|
|
lemmas monadic_rewrite_isolate_final
|
|
= monadic_rewrite_isolate_final2[where R=\<top>, OF monadic_rewrite_refl2, simplified]
|
|
|
|
lemma copy_registers_isolate:
|
|
"\<lbrakk> inj idx; idx x = t; idx y = t' \<rbrakk> \<Longrightarrow>
|
|
monadic_rewrite False True
|
|
(\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(mapM_x (\<lambda>r. do v \<leftarrow> asUser t (getRegister r);
|
|
asUser t' (setRegister r v)
|
|
od)
|
|
regs)
|
|
(isolate_thread_actions idx
|
|
(return ()) (foldr (copy_register_tsrs x y) (rev regs)) id)"
|
|
apply (induct regs)
|
|
apply (simp add: mapM_x_Nil)
|
|
apply (clarsimp simp: monadic_rewrite_def liftM_def bind_assoc
|
|
isolate_thread_actions_def
|
|
split_def exec_gets getSchedulerAction_def
|
|
select_f_returns o_def ksPSpace_update_partial_id)
|
|
apply (simp add: return_def simpler_modify_def)
|
|
apply (simp add: mapM_x_Cons)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule isolate_thread_actions_rewrite_bind, assumption)
|
|
apply (rule copy_register_isolate, assumption+)
|
|
apply (rule thread_actions_isolatable_returns)+
|
|
apply wp
|
|
apply (rule monadic_rewrite_isolate_final[where P=\<top>], simp+)
|
|
done
|
|
|
|
lemma setSchedulerAction_isolate:
|
|
"inj idx \<Longrightarrow>
|
|
monadic_rewrite False True (\<lambda>s. \<forall>x. tcb_at' (idx x) s)
|
|
(setSchedulerAction sa)
|
|
(isolate_thread_actions idx (return ()) id (\<lambda>_. sa))"
|
|
apply (clarsimp simp: monadic_rewrite_def liftM_def bind_assoc
|
|
isolate_thread_actions_def select_f_returns
|
|
exec_gets getSchedulerAction_def o_def
|
|
ksPSpace_update_partial_id setSchedulerAction_def)
|
|
apply (simp add: simpler_modify_def)
|
|
done
|
|
|
|
lemma updateMDB_isolatable:
|
|
"thread_actions_isolatable idx (updateMDB slot f)"
|
|
apply (simp add: updateMDB_def thread_actions_isolatable_return
|
|
split: split_if)
|
|
apply (intro impI thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
getCTE_isolatable setCTE_isolatable,
|
|
(wp | simp)+)
|
|
done
|
|
|
|
lemma emptySlot_isolatable:
|
|
"thread_actions_isolatable idx (emptySlot slot None)"
|
|
apply (simp add: emptySlot_def updateCap_def
|
|
cong: if_cong)
|
|
apply (intro thread_actions_isolatable_bind[OF _ _ hoare_pre(1)]
|
|
thread_actions_isolatable_if
|
|
getCTE_isolatable setCTE_isolatable
|
|
thread_actions_isolatable_return
|
|
updateMDB_isolatable,
|
|
(wp | simp)+)
|
|
done
|
|
|
|
lemmas fastpath_isolatables
|
|
= setEndpoint_isolatable getCTE_isolatable
|
|
assert_isolatable cteInsert_isolatable
|
|
switchToThread_isolatable setCurThread_isolatable
|
|
emptySlot_isolatable updateMDB_isolatable
|
|
thread_actions_isolatable_returns
|
|
|
|
lemmas fastpath_isolate_rewrites
|
|
= isolate_thread_actions_threadSet_tcbState isolate_thread_actions_asUser
|
|
copy_registers_isolate setSchedulerAction_isolate
|
|
fastpath_isolatables[THEN thread_actions_isolatableD]
|
|
|
|
lemma resolveAddressBits_points_somewhere:
|
|
"\<lbrace>\<lambda>s. \<forall>slot. Q slot s\<rbrace> resolveAddressBits cp cptr bits \<lbrace>Q\<rbrace>,-"
|
|
apply (rule_tac Q'="\<lambda>rv s. \<forall>rv. Q rv s" in hoare_post_imp_R)
|
|
apply wp
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma user_getregs_wp:
|
|
"\<lbrace>\<lambda>s. tcb_at' t s \<and> (\<forall>tcb. ko_at' tcb t s \<longrightarrow> Q (map (tcbContext tcb) regs) s)\<rbrace>
|
|
asUser t (mapM getRegister regs) \<lbrace>Q\<rbrace>"
|
|
apply (rule hoare_strengthen_post)
|
|
apply (rule hoare_vcg_conj_lift)
|
|
apply (rule asUser_get_registers)
|
|
apply (rule asUser_inv)
|
|
apply (wp mapM_wp' getRegister_inv)
|
|
apply clarsimp
|
|
apply (drule obj_at_ko_at', clarsimp)
|
|
done
|
|
|
|
lemma foldr_copy_register_tsrs:
|
|
"foldr (copy_register_tsrs x y) rs s
|
|
= (s (y := TCBStateRegs (tsrState (s y))
|
|
(\<lambda>r. if r \<in> 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: split_if)
|
|
done
|
|
|
|
lemmas cteInsert_obj_at'_not_queued = cteInsert_obj_at'_queued[of "\<lambda>a. \<not> a"]
|
|
|
|
lemma fastpath_callKernel_SysCall_corres:
|
|
"monadic_rewrite True False
|
|
(invs' and ct_in_state' (op = Running)
|
|
and (\<lambda>s. ksSchedulerAction s = ResumeCurrentThread))
|
|
(callKernel (SyscallEvent SysCall)) (fastpaths SysCall)"
|
|
apply (rule monadic_rewrite_introduce_alternative)
|
|
apply (simp add: callKernel_def)
|
|
apply (rule monadic_rewrite_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_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rename_tac msgInfo)
|
|
apply (rule monadic_rewrite_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec_r
|
|
[OF threadGet_inv no_fail_threadGet])
|
|
apply (rename_tac tcbFault)
|
|
apply (rule monadic_rewrite_alternative_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_if_rhs[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
|
|
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_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_rdonly_bind_l)
|
|
apply (wp | simp)+
|
|
apply (rule_tac fn="case_sum Inl (Inr \<circ> 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_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (simp add: isRight_right_map isRight_case_sum)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_rdonly_bind_l[OF lookupIPC_inv])
|
|
apply (rule monadic_rewrite_symb_exec_l[OF lookupIPC_inv empty_fail_lookupIPCBuffer])
|
|
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 (rule monadic_rewrite_symb_exec_r [OF getEndpoint_inv no_fail_getEndpoint])
|
|
apply (rename_tac "send_ep")
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (simp add: getThreadVSpaceRoot_def locateSlot_conv)
|
|
apply (rule monadic_rewrite_symb_exec_r [OF getCTE_inv no_fail_getCTE])
|
|
apply (rename_tac "pdCapCTE")
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r [OF threadGet_inv no_fail_threadGet])+
|
|
apply (rename_tac "curPrio" "destPrio")
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (simp add: isRight_case_sum)
|
|
apply (rule monadic_rewrite_symb_exec_r [OF gets_inv non_fail_gets])
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r[OF curDomain_inv],
|
|
simp only: curDomain_def, rule non_fail_gets)
|
|
apply (rename_tac "curDom")
|
|
apply (rule monadic_rewrite_symb_exec_r[OF threadGet_inv no_fail_threadGet])
|
|
apply (rename_tac "destDom")
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_trans,
|
|
rule monadic_rewrite_pick_alternative_1)
|
|
apply (rule monadic_rewrite_symb_exec_l[OF get_mrs_inv' empty_fail_getMRs])
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule_tac F=True and E=True in monadic_rewrite_weaken)
|
|
apply simp
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac x=thread in monadic_rewrite_symb_exec,
|
|
wp empty_fail_getCurThread)
|
|
apply (simp add: sendIPC_def bind_assoc)
|
|
apply (rule_tac x=send_ep in monadic_rewrite_symb_exec,
|
|
wp empty_fail_getEndpoint getEndpoint_obj_at')
|
|
apply (rule_tac P="epQueue send_ep \<noteq> []" 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 (match premises in "isEndpointCap ep" for ep \<Rightarrow>
|
|
\<open>rule monadic_rewrite_symb_exec[where x="BlockedOnReceive (capEPPtr ep)"]\<close>,
|
|
wp empty_fail_getThreadState)
|
|
apply (rule monadic_rewrite_symb_exec2, (wp | simp)+)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule_tac msgInfo=msgInfo in doIPCTransfer_simple_rewrite)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule_tac curPrio=curPrio and destPrio=destPrio
|
|
and curDom=curDom and destDom=destDom and thread=thread
|
|
in attemptSwitchTo_rewrite)
|
|
apply (rule monadic_rewrite_symb_exec2, wp empty_fail_threadGet)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule setupCallerCap_rewrite)
|
|
apply (rule monadic_rewrite_bind_head)
|
|
apply (rule setThreadState_blocked_rewrite, simp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule_tac x=BlockedOnReply in monadic_rewrite_symb_exec,
|
|
wp empty_fail_getThreadState)
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
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 activateThread_simple_rewrite)
|
|
|
|
apply ((wp setCurThread_ct_in_state Arch_switchToThread_pred_tcb'
|
|
| simp only: st_tcb_at'_def[symmetric])+)[1]
|
|
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 (simp add: setSchedulerAction_def)
|
|
apply wp[1]
|
|
apply (simp cong: if_cong conj_cong add: if_bool_simps)
|
|
apply (simp_all only:)[5]
|
|
apply ((wp setThreadState_oa_queued[of _ "\<lambda>a _ _. \<not> 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'
|
|
| simp add: setMessageInfo_def)+)
|
|
apply (simp add: setThreadState_runnable_simp
|
|
getThreadCallerSlot_def getThreadReplySlot_def
|
|
locateSlot_conv bind_assoc)
|
|
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[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
|
|
| assumption
|
|
| wp assert_inv)+
|
|
apply (rule_tac P="\<lambda>s. ksSchedulerAction s = ResumeCurrentThread
|
|
\<and> tcb_at' thread s"
|
|
and F=True and E=False in monadic_rewrite_weaken)
|
|
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 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: split_if)
|
|
apply (rule ext)
|
|
apply (simp add: badgeRegister_def msgInfoRegister_def
|
|
ARM.badgeRegister_def
|
|
ARM.msgInfoRegister_def
|
|
split: split_if)
|
|
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[1]
|
|
apply simp
|
|
apply (wp user_getreg_wp user_getregs_wp
|
|
threadGet_wp)
|
|
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
|
|
n_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 v tcbc)
|
|
apply (frule invs_mdb')
|
|
apply (thin_tac "Ball S P" for S P)+
|
|
apply (clarsimp simp: invs'_def valid_state'_def)
|
|
apply (frule_tac t="blockedThread" in valid_queues_not_runnable_not_queued)
|
|
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)+
|
|
apply (simp(no_asm) add: eq_commute)
|
|
apply (clarsimp simp: sch_act_simple_def)
|
|
done
|
|
|
|
lemmas fastpath_call_ccorres_callKernel
|
|
= monadic_rewrite_ccorres_assemble[OF fastpath_call_ccorres fastpath_callKernel_SysCall_corres]
|
|
|
|
lemma capability_case_Null_ReplyCap:
|
|
"(case cap of NullCap \<Rightarrow> f | ReplyCap t b \<Rightarrow> g t b | _ \<Rightarrow> h)
|
|
= (if isReplyCap cap then g (capTCBPtr cap) (capReplyMaster cap)
|
|
else if isNullCap cap then f else h)"
|
|
by (simp add: isCap_simps split: capability.split)
|
|
|
|
lemma in_getCTE_slot:
|
|
"(\<exists>s. (rv, s) \<in> fst (getCTE slot s)) = (is_aligned slot cte_level_bits)"
|
|
apply (simp add: getCTE_assert_opt exec_gets assert_opt_member)
|
|
apply (rule iffI)
|
|
apply clarsimp
|
|
apply (subgoal_tac "cte_wp_at' (op = rv) slot s")
|
|
apply (simp add: cte_wp_at_cases')
|
|
apply (erule disjE)
|
|
apply simp
|
|
apply clarsimp
|
|
apply (drule(1) tcb_cte_cases_aligned[where cte=rv])
|
|
apply (simp add: objBits_simps cte_level_bits_def)
|
|
apply (simp add: cte_wp_at_ctes_of)
|
|
apply (rule_tac x="undefined \<lparr> ksPSpace := empty (slot \<mapsto> KOCTE rv) \<rparr>" in exI)
|
|
apply (simp add: map_to_ctes_def Let_def objBits_simps cte_level_bits_def)
|
|
done
|
|
|
|
end
|
|
|
|
context begin interpretation Arch . (*FIXME: arch_split*)
|
|
|
|
lemma inj2_assert_opt:
|
|
"(assert_opt v s = assert_opt v' s') = (v = v' \<and> (v' = None \<or> s = s'))"
|
|
by (simp add: assert_opt_def return_def fail_def split: option.split)
|
|
|
|
lemma gets_the_inj:
|
|
"inj gets_the"
|
|
apply (rule injI)
|
|
apply (clarsimp simp: gets_the_def fun_eq_iff exec_gets inj2_assert_opt)
|
|
done
|
|
|
|
lemmas gets_the_eq = inj_eq[OF gets_the_inj]
|
|
|
|
lemma gets_the_eq2:
|
|
"(gets_the f s = gets_the g s') = (f s = g s' \<and> (g s' = None \<or> s = s'))"
|
|
by (simp add: gets_the_def exec_gets inj2_assert_opt)
|
|
|
|
lemma return_gets_the:
|
|
"return x = gets_the (\<lambda>_. Some x)"
|
|
by (simp add: gets_the_def assert_opt_def)
|
|
|
|
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' (\<lambda>tcb. tcbFault tcb = None) receiver)
|
|
(doReplyTransfer sender receiver slot)
|
|
(do state \<leftarrow> getThreadState receiver;
|
|
assert (isReply state);
|
|
cte \<leftarrow> getCTE slot;
|
|
mdbnode \<leftarrow> return $ cteMDBNode cte;
|
|
assert (mdbPrev mdbnode \<noteq> 0 \<and> mdbNext mdbnode = 0);
|
|
parentCTE \<leftarrow> getCTE (mdbPrev mdbnode);
|
|
assert (isReplyCap (cteCap parentCTE) \<and> capReplyMaster (cteCap parentCTE));
|
|
doIPCTransfer sender Nothing 0 True receiver;
|
|
cteDeleteOne slot;
|
|
setThreadState Running receiver;
|
|
attemptSwitchTo receiver
|
|
od )"
|
|
apply (simp add: doReplyTransfer_def liftM_def nullPointer_def
|
|
getSlotCap_def)
|
|
apply (rule monadic_rewrite_bind_tail)+
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_threadGet)
|
|
apply (rule_tac P="rv = None" in monadic_rewrite_gen_asm, simp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp threadGet_const gts_wp' getCTE_wp')
|
|
apply (simp add: o_def)
|
|
done
|
|
|
|
lemma monadic_rewrite_if_known:
|
|
"monadic_rewrite F E ((\<lambda>s. C = X) and \<top>) (if C then f else g) (if X then f else g)"
|
|
apply (rule monadic_rewrite_gen_asm)
|
|
apply (simp split del: split_if)
|
|
apply (rule monadic_rewrite_refl)
|
|
done
|
|
|
|
end
|
|
|
|
context kernel_m begin
|
|
|
|
lemma receiveIPC_simple_rewrite:
|
|
"monadic_rewrite True False
|
|
((\<lambda>_. isEndpointCap ep_cap \<and> \<not> isSendEP ep) and (ko_at' ep (capEPPtr ep_cap) and
|
|
(\<lambda>s. \<forall>ntfnptr. bound_tcb_at' (op = (Some ntfnptr)) thread s \<longrightarrow> obj_at' (Not \<circ> isActive) ntfnptr s)))
|
|
(receiveIPC thread ep_cap True)
|
|
(do
|
|
setThreadState (BlockedOnReceive (capEPPtr ep_cap)) thread;
|
|
setEndpoint (capEPPtr ep_cap) (RecvEP (case ep of RecvEP q \<Rightarrow> (q @ [thread]) | _ \<Rightarrow> [thread]))
|
|
od)"
|
|
apply (rule monadic_rewrite_gen_asm)
|
|
apply (simp add: receiveIPC_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule_tac rv=ep in monadic_rewrite_symb_exec_l_known,
|
|
wp empty_fail_getEndpoint)
|
|
apply (rule monadic_rewrite_symb_exec_l, (wp | simp add: getBoundNotification_def)+)
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply (rule hoare_pre, wpc, wp, simp)
|
|
apply (simp split: option.split)
|
|
apply (rule monadic_rewrite_trans, rule monadic_rewrite_if_known[where X=False], simp)
|
|
apply (rule monadic_rewrite_refl3[where P=\<top>])
|
|
apply (cases ep, simp_all add: isSendEP_def)[1]
|
|
apply (wp getNotification_wp gbn_wp' getEndpoint_wp | wpc)+
|
|
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 split: split_if)
|
|
|
|
lemma cteDeleteOne_replycap_rewrite:
|
|
"monadic_rewrite True False
|
|
(cte_wp_at' (\<lambda>cte. isReplyCap (cteCap cte)) slot)
|
|
(cteDeleteOne slot)
|
|
(emptySlot slot None)"
|
|
apply (simp add: cteDeleteOne_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
apply (rule_tac P="cteCap rv \<noteq> NullCap \<and> isReplyCap (cteCap rv)
|
|
\<and> \<not> isEndpointCap (cteCap rv)
|
|
\<and> \<not> isNotificationCap (cteCap rv)"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (simp add: finaliseCapTrue_standin_def
|
|
capRemovable_def)
|
|
apply (rule monadic_rewrite_symb_exec_l,
|
|
wp isFinalCapability_inv empty_fail_isFinalCapability)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (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' (\<lambda>cte. cteCap cte = NullCap) slot)
|
|
(cteDeleteOne slot)
|
|
(return ())"
|
|
apply (simp add: cteDeleteOne_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
apply (rule_tac P="cteCap rv = NullCap" in monadic_rewrite_gen_asm)
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp getCTE_wp')
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
done
|
|
|
|
lemma deleteCallerCap_nullcap_rewrite:
|
|
"monadic_rewrite True False
|
|
(cte_wp_at' (\<lambda>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 (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
apply (rule monadic_rewrite_assert)
|
|
apply (rule cteDeleteOne_nullcap_rewrite)
|
|
apply (wp getCTE_wp)
|
|
apply (clarsimp simp: cte_wp_at_ctes_of)
|
|
done
|
|
|
|
end
|
|
|
|
lemma emptySlot_cnode_caps:
|
|
"\<lbrace>\<lambda>s. P (only_cnode_caps (ctes_of s)) \<and> cte_wp_at' (\<lambda>cte. \<not> isCNodeCap (cteCap cte)) slot s\<rbrace>
|
|
emptySlot slot None
|
|
\<lbrace>\<lambda>rv s. P (only_cnode_caps (ctes_of s))\<rbrace>"
|
|
apply (simp add: only_cnode_caps_def option_map_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] intro!: ext
|
|
split: split_if)
|
|
done
|
|
|
|
lemma cteDeleteOne_cnode_caps:
|
|
"\<lbrace>\<lambda>s. P (only_cnode_caps (ctes_of s))\<rbrace>
|
|
cteDeleteOne slot
|
|
\<lbrace>\<lambda>rv s. P (only_cnode_caps (ctes_of s))\<rbrace>"
|
|
apply (simp add: only_cnode_caps_def option_map_comp2
|
|
o_assoc[symmetric] cteCaps_of_def[symmetric])
|
|
apply (wp cteDeleteOne_cteCaps_of)
|
|
apply clarsimp
|
|
apply (erule rsubst[where P=P], rule ext)
|
|
apply (clarsimp simp: cteCaps_of_def cte_wp_at_ctes_of isCap_simps)
|
|
apply (rule_tac x="cteCap cte" in exI)
|
|
apply (clarsimp simp: finaliseCap_def finaliseCapTrue_standin_def isCap_simps)
|
|
done
|
|
|
|
lemma asUser_obj_at_ep[wp]:
|
|
"\<lbrace>obj_at' P p\<rbrace> asUser t m \<lbrace>\<lambda>rv. obj_at' (P :: endpoint \<Rightarrow> bool) p\<rbrace>"
|
|
apply (simp add: asUser_def split_def)
|
|
apply (wp hoare_drop_imps | simp)+
|
|
done
|
|
|
|
lemma setCTE_obj_at_ep[wp]:
|
|
"\<lbrace>obj_at' (P :: endpoint \<Rightarrow> bool) p\<rbrace> setCTE ptr cte \<lbrace>\<lambda>rv. obj_at' P p\<rbrace>"
|
|
unfolding setCTE_def
|
|
apply (rule obj_at_setObject2)
|
|
apply (clarsimp simp: updateObject_cte typeError_def in_monad
|
|
split: Structures_H.kernel_object.split_asm
|
|
split_if_asm)
|
|
done
|
|
|
|
lemma setCTE_obj_at_ntfn[wp]:
|
|
"\<lbrace>obj_at' (P :: Structures_H.notification \<Rightarrow> bool) p\<rbrace> setCTE ptr cte \<lbrace>\<lambda>rv. obj_at' P p\<rbrace>"
|
|
unfolding setCTE_def
|
|
apply (rule obj_at_setObject2)
|
|
apply (clarsimp simp: updateObject_cte typeError_def in_monad
|
|
split: Structures_H.kernel_object.split_asm
|
|
split_if_asm)
|
|
done
|
|
|
|
crunch obj_at_ep[wp]: emptySlot "obj_at' (P :: endpoint \<Rightarrow> bool) p"
|
|
|
|
crunch nosch[wp]: emptySlot "\<lambda>s. P (ksSchedulerAction s)"
|
|
|
|
crunch gsCNodes[wp]: emptySlot, asUser "\<lambda>s. P (gsCNodes s)"
|
|
(wp: crunch_wps)
|
|
|
|
crunch ctes_of[wp]: attemptSwitchTo "\<lambda>s. P (ctes_of s)"
|
|
(wp: crunch_wps)
|
|
|
|
crunch cte_wp_at'[wp]: attemptSwitchTo "cte_wp_at' P p"
|
|
|
|
crunch tcbContext[wp]: attemptSwitchTo "obj_at' (\<lambda>tcb. P (tcbContext tcb)) t"
|
|
(wp: crunch_wps)
|
|
|
|
crunch only_cnode_caps[wp]: doFaultTransfer "\<lambda>s. P (only_cnode_caps (ctes_of s))"
|
|
(wp: crunch_wps simp: crunch_simps)
|
|
|
|
context kernel_m begin
|
|
|
|
lemma tcbSchedDequeue_rewrite_not_queued: "monadic_rewrite True False (tcb_at' t and obj_at' (Not \<circ> tcbQueued) t) (tcbSchedDequeue t) (return ())"
|
|
apply (simp add: tcbSchedDequeue_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="\<not> queued" in monadic_rewrite_gen_asm)
|
|
apply (simp add: when_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp threadGet_const)
|
|
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply wp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp)
|
|
apply (clarsimp simp: o_def obj_at'_def)
|
|
done
|
|
|
|
lemma schedule_known_rewrite:
|
|
"monadic_rewrite True False
|
|
(\<lambda>s. ksSchedulerAction s = SwitchToThread t
|
|
\<and> tcb_at' t s
|
|
\<and> obj_at' (Not \<circ> tcbQueued) t s
|
|
\<and> ksCurThread s = t'
|
|
\<and> st_tcb_at' (Not \<circ> runnable') t' s)
|
|
(schedule)
|
|
(do Arch.switchToThread t;
|
|
setCurThread t;
|
|
setSchedulerAction ResumeCurrentThread od)"
|
|
apply (simp add: schedule_def)
|
|
apply (simp only: switchToThread_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="action = SwitchToThread t" in monadic_rewrite_gen_asm,simp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac P="\<not> curRunnable \<and> action = SwitchToThread t" in monadic_rewrite_gen_asm, simp)
|
|
apply (simp add: bind_assoc)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule tcbSchedDequeue_rewrite_not_queued)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp Arch_switchToThread_obj_at_pre, simp, wp)
|
|
apply (rule monadic_rewrite_trans)
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply (wp)
|
|
apply simp
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply wp
|
|
apply (simp add: getSchedulerAction_def)
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply (wp)
|
|
apply (simp add: isRunnable_def)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec_l)
|
|
apply (wp, simp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (clarsimp simp: st_tcb_at'_def o_def obj_at'_def)
|
|
done
|
|
|
|
lemma setThreadState_schact_set:
|
|
"monadic_rewrite True False
|
|
(\<lambda>s. ksSchedulerAction s \<noteq> ResumeCurrentThread)
|
|
(setThreadState st t)
|
|
(threadSet (tcbState_update (\<lambda>_. st)) t)"
|
|
apply (simp add: setThreadState_def)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (subst bind_return[symmetric], rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_isRunnable)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCurThread)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp)
|
|
apply (simp add: getSchedulerAction_def)
|
|
apply (rename_tac sa)
|
|
apply (rule_tac P="sa \<noteq> ResumeCurrentThread" in monadic_rewrite_gen_asm)
|
|
apply (simp add: when_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp | simp)+
|
|
done
|
|
|
|
lemma tcb_at_cte_at_offset:
|
|
"\<lbrakk> tcb_at' t s; 2 ^ cte_level_bits * off \<in> dom tcb_cte_cases \<rbrakk>
|
|
\<Longrightarrow> 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 attemptSwitchTo_rewrite2:
|
|
"monadic_rewrite True True
|
|
(\<lambda>s. obj_at' (\<lambda>tcb. tcbPriority tcb = curPrio) ct s
|
|
\<and> obj_at' (\<lambda>tcb. tcbPriority tcb = destPrio \<and> tcbDomain tcb = destDom) t s
|
|
\<and> curPrio \<le> destPrio \<and> ct = ksCurThread s
|
|
\<and> ksSchedulerAction s = ResumeCurrentThread
|
|
\<and> curDom = ksCurDomain s \<and> destDom = curDom)
|
|
(attemptSwitchTo t) (setSchedulerAction (SwitchToThread t))"
|
|
apply (rule monadic_rewrite_imp,
|
|
rule attemptSwitchTo_rewrite[where thread=ct and curPrio=curPrio and destPrio=destPrio
|
|
and curDom=curDom and destDom=destDom])
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma emptySlot_cte_wp_at_cteCap:
|
|
"\<lbrace>\<lambda>s. (p = p' \<longrightarrow> P NullCap) \<and> (p \<noteq> p' \<longrightarrow> cte_wp_at' (\<lambda>cte. P (cteCap cte)) p s)\<rbrace>
|
|
emptySlot p' irqopt
|
|
\<lbrace>\<lambda>rv s. cte_wp_at' (\<lambda>cte. P (cteCap cte)) p s\<rbrace>"
|
|
apply (simp add: tree_cte_cteCap_eq[unfolded o_def])
|
|
apply (wp emptySlot_cteCaps_of)
|
|
apply (clarsimp split: split_if)
|
|
done
|
|
|
|
lemma real_cte_at_tcbs_of_neq:
|
|
"[| real_cte_at' p s; tcbs_of s t = Some tcb;
|
|
2 ^ cte_level_bits * offs : dom tcb_cte_cases |]
|
|
==> p ~= t + 2 ^ cte_level_bits * offs"
|
|
apply (clarsimp simp: tcbs_of_def obj_at'_def projectKOs objBits_simps
|
|
split: split_if_asm)
|
|
apply (erule notE[rotated], erule(2) tcb_ctes_clear[rotated])
|
|
apply fastforce
|
|
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_tos
|
|
split: split_if 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"
|
|
apply (rule monadic_rewrite_to_eq)
|
|
apply simp
|
|
apply (rule monadic_rewrite_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="\<lambda>s. epat = ep_at' p s \<and> cteat = real_cte_at' slot s
|
|
\<and> tcbat = (tcb_at' (slot && ~~ mask 9) and (%y. slot && mask 9 : dom tcb_cte_cases)) s"
|
|
in monadic_rewrite_refl3)
|
|
apply (simp add: setEndpoint_def setObject_modify_assert bind_assoc
|
|
exec_gets assert_def exec_modify
|
|
split: split_if)
|
|
apply (auto split: split_if simp: obj_at'_def projectKOs
|
|
intro!: arg_cong[where f=f] ext kernel_state.fold_congs)[1]
|
|
apply wp
|
|
apply simp
|
|
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: split_if)
|
|
|
|
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 emptySlot_setEndpoint_pivot[unfolded K_bind_def]:
|
|
"(do emptySlot slot None; setEndpoint p val; f od) =
|
|
(do setEndpoint p val; emptySlot slot None; f od)"
|
|
apply (rule ext)
|
|
apply (simp add: emptySlot_def bind_assoc
|
|
setEndpoint_getCTE_pivot
|
|
setEndpoint_updateCap_pivot
|
|
setEndpoint_updateMDB_pivot
|
|
split: split_if
|
|
| 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
|
|
apply (rule monadic_rewrite_to_eq)
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (simp add: getCTE_assert_opt bind_assoc)
|
|
apply (rule monadic_rewrite_trans,
|
|
rule_tac rv="Some cte" in monadic_rewrite_gets_known)
|
|
apply (simp add: assert_opt_def)
|
|
apply (rule monadic_rewrite_refl)
|
|
apply wp
|
|
apply simp
|
|
done
|
|
|
|
lemma set_setCTE[unfolded K_bind_def]:
|
|
"do setCTE p val; setCTE p val' od = setCTE p val'"
|
|
apply simp
|
|
apply (rule monadic_rewrite_to_eq)
|
|
apply (rule monadic_rewrite_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 \<in> 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 \<and> t = tcbat
|
|
\<and> (tcbat \<longrightarrow>
|
|
(\<exists> getF setF. tcb_cte_cases (p && mask 9) = Some (getF, setF)
|
|
\<and> (\<forall> f g tcb. setF f (setF g tcb) = setF (f o g) tcb)))"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (rule monadic_rewrite_refl2)
|
|
apply (simp add: exec_modify split: split_if)
|
|
apply (auto simp: simpler_modify_def projectKO_opt_tcb
|
|
intro!: kernel_state.fold_congs ext
|
|
split: split_if)[1]
|
|
apply wp
|
|
apply (clarsimp intro!: all_tcbI)
|
|
apply (auto simp: tcb_cte_cases_def split: split_if_asm)
|
|
done
|
|
|
|
lemma setCTE_updateCapMDB:
|
|
"p \<noteq> 0 \<Longrightarrow>
|
|
setCTE p cte = do updateCap p (cteCap cte); updateMDB p (const (cteMDBNode cte)) od"
|
|
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: split_if option.split)
|
|
apply (cut_tac P=\<top> 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 emptySlot_replymaster_rewrite[OF refl]:
|
|
"mdbn = cteMDBNode cte \<Longrightarrow>
|
|
monadic_rewrite True False
|
|
((\<lambda>_. mdbNext mdbn = 0 \<and> mdbPrev mdbn \<noteq> 0)
|
|
and ((\<lambda>_. cteCap cte \<noteq> NullCap)
|
|
and (cte_wp_at' (op = cte) slot
|
|
and cte_wp_at' (\<lambda>cte. isReplyCap (cteCap cte) \<and> capReplyMaster (cteCap cte))
|
|
(mdbPrev mdbn)
|
|
and (\<lambda>s. reply_masters_rvk_fb (ctes_of s))
|
|
and (\<lambda>s. no_0 (ctes_of s)))))
|
|
(emptySlot slot None)
|
|
(do updateMDB (mdbPrev mdbn) (mdbNext_update (K 0) o mdbFirstBadged_update (K True)
|
|
o mdbRevocable_update (K True));
|
|
setCTE slot makeObject
|
|
od)"
|
|
apply (rule monadic_rewrite_gen_asm)+
|
|
apply (rule monadic_rewrite_imp)
|
|
apply (rule_tac P="slot \<noteq> 0" in monadic_rewrite_gen_asm)
|
|
apply (clarsimp simp: emptySlot_def setCTE_updateCapMDB)
|
|
apply (rule_tac rv=cte in monadic_rewrite_symb_exec_l_known, wp empty_fail_getCTE)
|
|
apply (simp add: updateMDB_def Let_def bind_assoc makeObject_cte)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule_tac P="mdbFirstBadged (cteMDBNode ctea) \<and> mdbRevocable (cteMDBNode ctea)"
|
|
in monadic_rewrite_gen_asm)
|
|
apply (rule monadic_rewrite_refl2)
|
|
apply (case_tac ctea, rename_tac mdbnode, case_tac mdbnode)
|
|
apply simp
|
|
apply (rule monadic_rewrite_refl)
|
|
apply (wp getCTE_wp')
|
|
apply (clarsimp simp: cte_wp_at_ctes_of reply_masters_rvk_fb_def)
|
|
apply fastforce
|
|
done
|
|
|
|
(* FIXME: Move *)
|
|
lemma asUser_obj_at_not_queued[wp]:
|
|
"\<lbrace>obj_at' (\<lambda>tcb. \<not> tcbQueued tcb) p\<rbrace> asUser t m \<lbrace>\<lambda>rv. obj_at' (\<lambda>tcb. \<not> tcbQueued tcb) p\<rbrace>"
|
|
apply (simp add: asUser_def split_def)
|
|
apply (wp hoare_drop_imps | simp)+
|
|
done
|
|
|
|
lemma all_prio_not_inQ_not_tcbQueued: "\<lbrakk> obj_at' (\<lambda>a. (\<forall>d p. \<not> inQ d p a)) t s \<rbrakk> \<Longrightarrow> obj_at' (\<lambda>a. \<not> tcbQueued a) t s"
|
|
apply (clarsimp simp: obj_at'_def inQ_def)
|
|
done
|
|
|
|
crunch ntfn_obj_at[wp]: setThreadState, emptySlot, asUser "obj_at' (P::(Structures_H.notification \<Rightarrow> bool)) ntfnptr"
|
|
(ignore: getObject setObject wp: obj_at_setObject2 crunch_wps
|
|
simp: crunch_simps updateObject_default_def in_monad)
|
|
|
|
lemma st_tcb_at_is_Reply_imp_not_tcbQueued: "\<And>s t.\<lbrakk> invs' s; st_tcb_at' isReply t s\<rbrakk> \<Longrightarrow> obj_at' (\<lambda>a. \<not> 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 \<Longrightarrow> valid_objs' s \<Longrightarrow> tcbBoundNotification tcb \<noteq> None
|
|
\<Longrightarrow> 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 "\<lambda>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]:
|
|
"\<lbrace>\<lambda>s. Q (tcb_at' t s)\<rbrace> emptySlot a b \<lbrace>\<lambda>_ s. Q (tcb_at' t s)\<rbrace>"
|
|
by (simp add: tcb_at_typ_at', wp)
|
|
|
|
lemmas cnode_caps_gsCNodes_lift
|
|
= hoare_lift_Pf2[where P="\<lambda>gs s. cnode_caps_gsCNodes (f s) gs" and f=gsCNodes for f]
|
|
hoare_lift_Pf2[where P="\<lambda>gs s. Q s \<longrightarrow> cnode_caps_gsCNodes (f s) gs" and f=gsCNodes for f Q]
|
|
|
|
lemma monadic_rewrite_option_cases:
|
|
"\<lbrakk> v = None \<Longrightarrow> monadic_rewrite F E Q a b; \<And>x. v = Some x \<Longrightarrow> monadic_rewrite F E (R x) a b \<rbrakk>
|
|
\<Longrightarrow> monadic_rewrite F E (\<lambda>s. (v = None \<longrightarrow> Q s) \<and> (\<forall>x. v = Some x \<longrightarrow> R x s)) a b"
|
|
by (cases v, simp_all)
|
|
|
|
lemma resolveAddressBitsFn_eq_name_slot:
|
|
"monadic_rewrite F E (\<lambda>s. (isCNodeCap cap \<longrightarrow> cte_wp_at' (\<lambda>cte. cteCap cte = cap) (slot s) s)
|
|
\<and> valid_objs' s \<and> cnode_caps_gsCNodes' s)
|
|
(resolveAddressBits cap capptr bits)
|
|
(gets (resolveAddressBitsFn cap capptr bits o only_cnode_caps o ctes_of))"
|
|
apply (rule monadic_rewrite_imp, rule resolveAddressBitsFn_eq)
|
|
apply auto
|
|
done
|
|
|
|
crunch bound_tcb_at'_Q[wp]: asUser "\<lambda>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]:
|
|
"\<lbrace>\<lambda>s. Q (tcb_at' t s)\<rbrace> asUser a b \<lbrace>\<lambda>_ s. Q (tcb_at' t s)\<rbrace>"
|
|
by (simp add: tcb_at_typ_at', wp)
|
|
|
|
lemma active_ntfn_check_wp:
|
|
"\<lbrace>\<lambda>s. Q (\<exists>ntfnptr. bound_tcb_at' (op = (Some ntfnptr)) thread s
|
|
\<and> \<not> obj_at' (Not o isActive) ntfnptr s) s \<rbrace> do bound_ntfn \<leftarrow> getBoundNotification thread;
|
|
case bound_ntfn of None \<Rightarrow> return False
|
|
| Some ntfnptr \<Rightarrow> liftM EndpointDecls_H.isActive $ getNotification ntfnptr
|
|
od \<lbrace>Q\<rbrace>"
|
|
apply (rule hoare_pre)
|
|
apply (wp getNotification_wp gbn_wp' | wpc)+
|
|
apply (auto simp: pred_tcb_at'_def obj_at'_def projectKOs)
|
|
done
|
|
|
|
lemma fastpath_callKernel_SysReplyRecv_corres:
|
|
"monadic_rewrite True False
|
|
(invs' and ct_in_state' (op = Running) and (\<lambda>s. ksSchedulerAction s = ResumeCurrentThread)
|
|
and cnode_caps_gsCNodes')
|
|
(callKernel (SyscallEvent SysReplyRecv)) (fastpaths SysReplyRecv)"
|
|
apply (rule monadic_rewrite_introduce_alternative)
|
|
apply (simp add: callKernel_def)
|
|
apply (rule monadic_rewrite_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_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac msgInfo)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac cptr)
|
|
apply (rule monadic_rewrite_symb_exec_r[OF threadGet_inv no_fail_threadGet])
|
|
apply (rename_tac tcbFault)
|
|
apply (rule monadic_rewrite_alternative_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_if_rhs[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 o_def
|
|
isRight_def[where x="Inr v" for v]
|
|
isRight_def[where x="Inl v" for v]
|
|
cong: if_cong)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac "cTableCTE")
|
|
|
|
apply (rule monadic_rewrite_transverse,
|
|
rule monadic_rewrite_bind_head,
|
|
rule resolveAddressBitsFn_eq)
|
|
apply (rule monadic_rewrite_symb_exec_r, (wp | simp)+)
|
|
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 (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac ep_cap)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r[OF _ _ _ active_ntfn_check_wp, unfolded bind_assoc fun_app_def])
|
|
apply (rule hoare_pre, (wp | wpc | simp)+)[1]
|
|
apply (unfold getBoundNotification_def)[1]
|
|
apply (wp threadGet_wp)
|
|
apply (rename_tac ep)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac ep)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_rdonly_bind_l, wp)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rename_tac replyCTE)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (simp add: bind_assoc)
|
|
apply (rule monadic_rewrite_rdonly_bind_l, wp assert_inv)
|
|
apply (rule monadic_rewrite_assert)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac callerFault)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (simp add: getThreadVSpaceRoot_def locateSlot_conv)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rename_tac vTableCTE)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)+
|
|
apply (rename_tac curPrio callerPrio)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r, wp)
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_symb_exec_r[OF curDomain_inv],
|
|
simp only: curDomain_def, rule non_fail_gets)
|
|
apply (rename_tac "curDom")
|
|
apply (rule monadic_rewrite_symb_exec_r[OF threadGet_inv no_fail_threadGet])
|
|
apply (rename_tac "callerDom")
|
|
apply (rule monadic_rewrite_if_rhs[rotated])
|
|
apply (rule monadic_rewrite_alternative_l)
|
|
apply (rule monadic_rewrite_trans,
|
|
rule monadic_rewrite_pick_alternative_1)
|
|
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_weaken2,
|
|
(rule_tac msgInfo=msgInfo in doIPCTransfer_simple_rewrite
|
|
| rule_tac curPrio=curPrio and destPrio=callerPrio
|
|
and curDom=curDom and destDom=callerDom
|
|
and ct=thread in attemptSwitchTo_rewrite2))
|
|
| 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]
|
|
| simp add: setMessageInfo_def setThreadState_runnable_simp)+)[1]
|
|
apply (simp add: setMessageInfo_def)
|
|
apply (rule monadic_rewrite_bind_tail)
|
|
apply (rule_tac rv=thread in monadic_rewrite_symb_exec_l_known,
|
|
wp empty_fail_getCurThread)
|
|
apply (rule_tac rv=cptr in monadic_rewrite_symb_exec_l_known,
|
|
wp empty_fail_asUser empty_fail_getRegister)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule monadic_rewrite_catch[OF _ monadic_rewrite_refl True_E_E])
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
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="\<lambda>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="NonDetMonad.lift f"
|
|
for f, folded bindE_def])
|
|
apply (simp add: NonDetMonad.lift_def isRight_case_sum)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
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 setThreadState_schact_set)
|
|
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[where E=True and F=True], simp)
|
|
apply (rule activateThread_simple_rewrite)
|
|
apply wp
|
|
apply (simp add: ct_in_state'_def)
|
|
apply (wp setCurThread_ct_in_state[folded st_tcb_at'_def]
|
|
Arch_switchToThread_pred_tcb')[2]
|
|
apply (simp add: catch_liftE)
|
|
apply (wp setEndpoint_obj_at_tcb' threadSet_pred_tcb_at_state[unfolded if_bool_eq_conj])
|
|
apply (simp cong: rev_conj_cong)
|
|
apply (strengthen imp_consequent[where Q="tcb_at' t s" for t s])
|
|
apply (unfold setSchedulerAction_def)[3]
|
|
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_cte_wp_at_cteCap
|
|
emptySlot_cnode_caps
|
|
user_getreg_inv asUser_typ_ats
|
|
asUser_obj_at_not_queued asUser_obj_at' mapM_x_wp'
|
|
static_imp_wp hoare_vcg_all_lift hoare_vcg_imp_lift
|
|
static_imp_wp cnode_caps_gsCNodes_lift
|
|
hoare_vcg_ex_lift
|
|
| simp
|
|
| clarsimp simp: obj_at'_weakenE[OF _ TrueI])+)
|
|
apply (wp getCTE_wp' gts_imp')
|
|
apply (simp add: bind_assoc catch_liftE
|
|
receiveIPC_def Let_def liftM_def
|
|
setThreadState_runnable_simp)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getThreadState)
|
|
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[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
|
|
| assumption
|
|
| wp assert_inv)+
|
|
apply (simp only: )
|
|
apply (rule_tac P="(\<lambda>s. ksSchedulerAction s = ResumeCurrentThread)
|
|
and tcb_at' thread
|
|
and (cte_wp_at' (\<lambda>cte. isReplyCap (cteCap cte))
|
|
(thread + 2 ^ cte_level_bits * tcbCallerSlot)
|
|
and (\<lambda>s. \<forall>x. tcb_at' (case_bool thread (capTCBPtr (cteCap replyCTE)) x) s)
|
|
and valid_mdb')"
|
|
and F=True and E=False in monadic_rewrite_weaken)
|
|
apply (rule monadic_rewrite_isolate_final2)
|
|
apply simp
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
apply (rename_tac callerCTE)
|
|
apply (rule monadic_rewrite_assert)
|
|
apply (rule monadic_rewrite_symb_exec_l, wp empty_fail_getCTE)
|
|
apply (rule monadic_rewrite_assert)
|
|
apply (simp add: emptySlot_setEndpoint_pivot)
|
|
apply (rule monadic_rewrite_bind)
|
|
apply (rule monadic_rewrite_refl2)
|
|
apply (clarsimp simp: isSendEP_def split: Structures_H.endpoint.split)
|
|
apply (rule_tac Q="\<lambda>rv. (\<lambda>_. rv = callerCTE) and Q'" for Q'
|
|
in monadic_rewrite_symb_exec_r, wp)
|
|
apply (rule monadic_rewrite_gen_asm, simp)
|
|
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 (wp getCTE_ctes_wp)
|
|
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 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: split_if)
|
|
apply (rule ext)
|
|
apply (simp add: badgeRegister_def msgInfoRegister_def
|
|
ARM.msgInfoRegister_def
|
|
ARM.badgeRegister_def
|
|
split: split_if)
|
|
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 user_getregs_wp
|
|
gets_the_wp gct_wp getNotification_wp
|
|
return_wp liftM_wp gbn_wp'
|
|
| (simp only: curDomain_def, wp)[1])+
|
|
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
|
|
n_msgRegisters_def order_less_imp_le
|
|
tcb_at_invs' invs_mdb'
|
|
split: bool.split)
|
|
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
|
|
|
|
lemmas fastpath_reply_recv_ccorres_callKernel
|
|
= monadic_rewrite_ccorres_assemble[OF fastpath_reply_recv_ccorres fastpath_callKernel_SysReplyRecv_corres]
|
|
|
|
lemma cnode_caps_gsCNodes_from_sr:
|
|
"valid_objs s \<Longrightarrow> (s, s') \<in> state_relation
|
|
\<Longrightarrow> 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
|
|
|
|
end
|