lh-l4v/proof/refine/RISCV64/Invariants_H.thy

304 lines
14 KiB
Plaintext
Raw Normal View History

2019-06-06 22:52:56 +00:00
(*
* Copyright 2019, Data61, CSIRO
*
* 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(DATA61_GPL)
*)
theory Invariants_H
imports
LevityCatch
"AInvs.Deterministic_AI"
"AInvs.AInvs"
"Lib.AddUpdSimps"
begin
context Arch begin
lemmas haskell_crunch_def [crunch_def] =
deriveCap_def finaliseCap_def
hasCancelSendRights_def sameRegionAs_def isPhysicalCap_def
sameObjectAs_def updateCapData_def maskCapRights_def
createObject_def capUntypedPtr_def capUntypedSize_def
performInvocation_def decodeInvocation_def
context begin global_naming global
requalify_facts
Retype_H.deriveCap_def Retype_H.finaliseCap_def
Retype_H.hasCancelSendRights_def Retype_H.sameRegionAs_def Retype_H.isPhysicalCap_def
Retype_H.sameObjectAs_def Retype_H.updateCapData_def Retype_H.maskCapRights_def
Retype_H.createObject_def Retype_H.capUntypedPtr_def Retype_H.capUntypedSize_def
Retype_H.performInvocation_def Retype_H.decodeInvocation_def
end
end
\<comment> \<open>---------------------------------------------------------------------------\<close>
section "Invariants on Executable Spec"
(* FIXME RISCV: move up, use everywhere *)
abbreviation ptr_range :: "obj_ref \<Rightarrow> nat \<Rightarrow> machine_word set" where
"ptr_range p n \<equiv> {p .. p + mask n}"
context begin interpretation Arch .
definition ps_clear :: "obj_ref \<Rightarrow> nat \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ps_clear p n s \<equiv> (ptr_range p n - {p}) \<inter> dom (ksPSpace s) = {}"
definition pspace_no_overlap' :: "obj_ref \<Rightarrow> nat \<Rightarrow> kernel_state \<Rightarrow> bool" where
"pspace_no_overlap' ptr bits \<equiv>
\<lambda>s. \<forall>x ko. ksPSpace s x = Some ko \<longrightarrow>
(ptr_range x (objBitsKO ko)) \<inter> {ptr .. (ptr && ~~ mask bits) + mask bits} = {}"
definition ko_wp_at' :: "(kernel_object \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ko_wp_at' P p s \<equiv> \<exists>ko. ksPSpace s p = Some ko \<and> is_aligned p (objBitsKO ko) \<and> P ko \<and>
ps_clear p (objBitsKO ko) s"
definition obj_at' :: "('a::pspace_storable \<Rightarrow> bool) \<Rightarrow> machine_word \<Rightarrow> kernel_state \<Rightarrow> bool" where
obj_at'_real_def:
"obj_at' P p s \<equiv> ko_wp_at' (\<lambda>ko. \<exists>obj. projectKO_opt ko = Some obj \<and> P obj) p s"
definition typ_at' :: "kernel_object_type \<Rightarrow> machine_word \<Rightarrow> kernel_state \<Rightarrow> bool" where
"typ_at' T \<equiv> ko_wp_at' (\<lambda>ko. koTypeOf ko = T)"
abbreviation ep_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ep_at' \<equiv> obj_at' ((\<lambda>x. True) :: endpoint \<Rightarrow> bool)"
abbreviation ntfn_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ntfn_at' \<equiv> obj_at' ((\<lambda>x. True) :: notification \<Rightarrow> bool)"
abbreviation tcb_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"tcb_at' \<equiv> obj_at' ((\<lambda>x. True) :: tcb \<Rightarrow> bool)"
abbreviation real_cte_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"real_cte_at' \<equiv> obj_at' ((\<lambda>x. True) :: cte \<Rightarrow> bool)"
abbreviation ko_at' :: "'a::pspace_storable \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ko_at' v \<equiv> obj_at' (\<lambda>k. k = v)"
abbreviation pte_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"pte_at' \<equiv> typ_at' (ArchT PTET)"
end
record itcb' =
itcbState :: thread_state
itcbFaultHandler :: cptr
itcbIPCBuffer :: vptr
itcbBoundNotification :: "machine_word option"
itcbPriority :: priority
itcbFault :: "fault option"
itcbTimeSlice :: nat
itcbMCP :: priority
definition tcb_to_itcb' :: "tcb \<Rightarrow> itcb'" where
"tcb_to_itcb' tcb \<equiv> \<lparr> itcbState = tcbState tcb,
itcbFaultHandler = tcbFaultHandler tcb,
itcbIPCBuffer = tcbIPCBuffer tcb,
itcbBoundNotification = tcbBoundNotification tcb,
itcbPriority = tcbPriority tcb,
itcbFault = tcbFault tcb,
itcbTimeSlice = tcbTimeSlice tcb,
itcbMCP = tcbMCP tcb\<rparr>"
lemma itcb_simps[simp]:
"itcbState (tcb_to_itcb' tcb) = tcbState tcb"
"itcbFaultHandler (tcb_to_itcb' tcb) = tcbFaultHandler tcb"
"itcbIPCBuffer (tcb_to_itcb' tcb) = tcbIPCBuffer tcb"
"itcbBoundNotification (tcb_to_itcb' tcb) = tcbBoundNotification tcb"
"itcbPriority (tcb_to_itcb' tcb) = tcbPriority tcb"
"itcbFault (tcb_to_itcb' tcb) = tcbFault tcb"
"itcbTimeSlice (tcb_to_itcb' tcb) = tcbTimeSlice tcb"
"itcbMCP (tcb_to_itcb' tcb) = tcbMCP tcb"
by (auto simp: tcb_to_itcb'_def)
definition pred_tcb_at' :: "(itcb' \<Rightarrow> 'a) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> machine_word \<Rightarrow> kernel_state \<Rightarrow> bool"
where
"pred_tcb_at' proj test \<equiv> obj_at' (\<lambda>ko. test (proj (tcb_to_itcb' ko)))"
abbreviation st_tcb_at' :: "(thread_state \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"st_tcb_at' \<equiv> pred_tcb_at' itcbState"
abbreviation bound_tcb_at' :: "(obj_ref option \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"bound_tcb_at' \<equiv> pred_tcb_at' itcbBoundNotification"
abbreviation mcpriority_tcb_at' :: "(priority \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"mcpriority_tcb_at' \<equiv> pred_tcb_at' itcbMCP"
lemma st_tcb_at'_def:
"st_tcb_at' test \<equiv> obj_at' (test \<circ> tcbState)"
by (simp add: pred_tcb_at'_def o_def)
text \<open> cte with property at \<close>
definition cte_wp_at' :: "(cte \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"cte_wp_at' P p s \<equiv> \<exists>cte::cte. fst (getObject p s) = {(cte,s)} \<and> P cte"
abbreviation cte_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"cte_at' \<equiv> cte_wp_at' \<top>"
definition tcb_cte_cases :: "machine_word \<rightharpoonup> ((tcb \<Rightarrow> cte) \<times> ((cte \<Rightarrow> cte) \<Rightarrow> tcb \<Rightarrow> tcb))" where
"tcb_cte_cases \<equiv> [ 0 << cteSizeBits \<mapsto> (tcbCTable, tcbCTable_update),
1 << cteSizeBits \<mapsto> (tcbVTable, tcbVTable_update),
2 << cteSizeBits \<mapsto> (tcbReply, tcbReply_update),
3 << cteSizeBits \<mapsto> (tcbCaller, tcbCaller_update),
4 << cteSizeBits \<mapsto> (tcbIPCBufferFrame, tcbIPCBufferFrame_update) ]"
definition max_ipc_words :: machine_word where
"max_ipc_words \<equiv> capTransferDataSize + msgMaxLength + msgMaxExtraCaps + 2"
definition tcb_st_refs_of' :: "thread_state \<Rightarrow> (obj_ref \<times> reftype) set" where
"tcb_st_refs_of' st \<equiv> case st of
(BlockedOnReceive x _) => {(x, TCBBlockedRecv)}
| (BlockedOnSend x _ _ _ _) => {(x, TCBBlockedSend)}
| (BlockedOnNotification x) => {(x, TCBSignal)}
| _ => {}"
definition ep_q_refs_of' :: "endpoint \<Rightarrow> (obj_ref \<times> reftype) set" where
"ep_q_refs_of' ep \<equiv> case ep of
IdleEP => {}
| (RecvEP q) => set q \<times> {EPRecv}
| (SendEP q) => set q \<times> {EPSend}"
definition ntfn_q_refs_of' :: "Structures_H.ntfn \<Rightarrow> (obj_ref \<times> reftype) set" where
"ntfn_q_refs_of' ntfn \<equiv> case ntfn of
IdleNtfn => {}
| (WaitingNtfn q) => set q \<times> {NTFNSignal}
| (ActiveNtfn b) => {}"
definition ntfn_bound_refs' :: "obj_ref option \<Rightarrow> (obj_ref \<times> reftype) set" where
"ntfn_bound_refs' t \<equiv> set_option t \<times> {NTFNBound}"
definition tcb_bound_refs' :: "obj_ref option \<Rightarrow> (obj_ref \<times> reftype) set" where
"tcb_bound_refs' a \<equiv> set_option a \<times> {TCBBound}"
definition refs_of' :: "kernel_object \<Rightarrow> (obj_ref \<times> reftype) set" where
"refs_of' ko \<equiv> case ko of
(KOTCB tcb) => tcb_st_refs_of' (tcbState tcb) \<union> tcb_bound_refs' (tcbBoundNotification tcb)
| (KOEndpoint ep) => ep_q_refs_of' ep
| (KONotification ntfn) => ntfn_q_refs_of' (ntfnObj ntfn) \<union> ntfn_bound_refs' (ntfnBoundTCB ntfn)
| _ => {}"
definition state_refs_of' :: "kernel_state \<Rightarrow> obj_ref \<Rightarrow> (obj_ref \<times> reftype) set" where
"state_refs_of' s \<equiv> \<lambda>x.
case ksPSpace s x of
None \<Rightarrow> {}
| Some ko \<Rightarrow> if is_aligned x (objBitsKO ko) \<and> ps_clear x (objBitsKO ko) s
then refs_of' ko else {}"
fun live' :: "kernel_object \<Rightarrow> bool" where
"live' (KOTCB tcb) =
(bound (tcbBoundNotification tcb) \<or>
(tcbState tcb \<noteq> Inactive \<and> tcbState tcb \<noteq> IdleThreadState) \<or> tcbQueued tcb)"
| "live' (KOEndpoint ep) = (ep \<noteq> IdleEP)"
| "live' (KONotification ntfn) = (bound (ntfnBoundTCB ntfn) \<or> (\<exists>ts. ntfnObj ntfn = WaitingNtfn ts))"
| "live' _ = False"
fun zobj_refs' :: "capability \<Rightarrow> obj_ref set" where
"zobj_refs' (EndpointCap r _ _ _ _ _) = {r}"
| "zobj_refs' (NotificationCap r _ _ _) = {r}"
| "zobj_refs' (ThreadCap r) = {r}"
| "zobj_refs' _ = {}"
definition ex_nonz_cap_to' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ex_nonz_cap_to' ref \<equiv> \<lambda>s. \<exists>cref. cte_wp_at' (\<lambda>c. ref \<in> zobj_refs' (cteCap c)) cref s"
definition if_live_then_nonz_cap' :: "kernel_state \<Rightarrow> bool" where
"if_live_then_nonz_cap' s \<equiv> \<forall>ptr. ko_wp_at' live' ptr s \<longrightarrow> ex_nonz_cap_to' ptr s"
fun cte_refs' :: "capability \<Rightarrow> obj_ref \<Rightarrow> obj_ref set" where
"cte_refs' (CNodeCap ref bits _ _) x = (\<lambda>x. ref + x << cteSizeBits) ` {0 .. mask bits}"
| "cte_refs' (ThreadCap ref) x = (\<lambda>x. ref + x) ` dom tcb_cte_cases"
| "cte_refs' (Zombie ref _ n) x = (\<lambda>x. ref + x << cteSizeBits) ` {0 ..< of_nat n}"
| "cte_refs' (IRQHandlerCap irq) x = {x + ucast irq << cteSizeBits}"
| "cte_refs' _ _ = {}"
abbreviation irq_node' :: "kernel_state \<Rightarrow> obj_ref" where
"irq_node' s \<equiv> intStateIRQNode (ksInterruptState s)"
definition ex_cte_cap_wp_to' :: "(capability \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ex_cte_cap_wp_to' P ptr \<equiv>
\<lambda>s. \<exists>cref. cte_wp_at' (\<lambda>c. P (cteCap c) \<and> ptr \<in> cte_refs' (cteCap c) (irq_node' s)) cref s"
abbreviation ex_cte_cap_to' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"ex_cte_cap_to' \<equiv> ex_cte_cap_wp_to' \<top>"
definition if_unsafe_then_cap' :: "kernel_state \<Rightarrow> bool" where
"if_unsafe_then_cap' s \<equiv>
\<forall>cref. cte_wp_at' (\<lambda>c. cteCap c \<noteq> NullCap) cref s \<longrightarrow> ex_cte_cap_to' cref s"
section "Valid caps and objects (design spec)"
context begin interpretation Arch .
primrec acapBits :: "arch_capability \<Rightarrow> nat" where
"acapBits (ASIDPoolCap _ _) = asidLowBits + word_size_bits"
| "acapBits ASIDControlCap = asidHighBits + word_size_bits"
| "acapBits (FrameCap _ _ sz _ _) = pageBitsForSize sz"
| "acapBits (PageTableCap _ _) = table_size"
end
primrec zBits :: "zombie_type \<Rightarrow> nat" where
"zBits (ZombieCNode n) = objBits (undefined::cte) + n"
| "zBits (ZombieTCB) = tcbBlockSizeBits"
primrec capBits :: "capability \<Rightarrow> nat" where
"capBits NullCap = 0"
| "capBits DomainCap = 0"
| "capBits (UntypedCap _ _ b _) = b"
| "capBits (EndpointCap _ _ _ _ _ _) = objBits (undefined::endpoint)"
| "capBits (NotificationCap _ _ _ _) = objBits (undefined::Structures_H.notification)"
| "capBits (CNodeCap _ b _ _) = objBits (undefined::cte) + b"
| "capBits (ThreadCap _) = objBits (undefined::tcb)"
| "capBits (Zombie _ z _) = zBits z"
| "capBits (IRQControlCap) = 0"
| "capBits (IRQHandlerCap _) = 0"
| "capBits (ReplyCap _ _ _) = objBits (undefined :: tcb)"
| "capBits (ArchObjectCap x) = acapBits x"
definition capAligned :: "capability \<Rightarrow> bool" where
"capAligned c \<equiv> is_aligned (capUntypedPtr c) (capBits c) \<and> capBits c < word_bits"
definition obj_range' :: "machine_word \<Rightarrow> kernel_object \<Rightarrow> machine_word set" where
"obj_range' p ko \<equiv> ptr_range p (objBitsKO ko)"
primrec (nonexhaustive) usableUntypedRange :: "capability \<Rightarrow> machine_word set" where
"usableUntypedRange (UntypedCap _ p n f) = (if f < 2^n then {p+of_nat f .. p + mask n} else {})"
definition valid_untyped' :: "bool \<Rightarrow> obj_ref \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> kernel_state \<Rightarrow> bool" where
"valid_untyped' d ptr bits idx s \<equiv>
\<forall>ptr'. \<not> ko_wp_at' (\<lambda>ko. ptr_range ptr bits \<subset> obj_range' ptr' ko
\<or> obj_range' ptr' ko \<inter>
usableUntypedRange (UntypedCap d ptr bits idx) \<noteq> {}) ptr' s"
primrec zombieCTEs :: "zombie_type \<Rightarrow> nat" where
"zombieCTEs ZombieTCB = 5"
| "zombieCTEs (ZombieCNode n) = 2 ^ n"
context begin interpretation Arch .
definition page_table_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"page_table_at' x \<equiv> \<lambda>s.
is_aligned x ptBits \<and>
(\<forall>y < 2 ^ ptTranslationBits. typ_at' (ArchT PTET) (x + (y << word_size_bits)) s)"
lemmas vspace_table_at'_defs = page_table_at'_def
abbreviation asid_pool_at' :: "obj_ref \<Rightarrow> kernel_state \<Rightarrow> bool" where
"asid_pool_at' \<equiv> typ_at' (ArchT ASIDPoolT)"
definition asid_wf :: "asid \<Rightarrow> bool" where
"asid_wf asid \<equiv> asid \<le> mask asid_bits"
(* FIXME RISCV: complete design spec invariants *)
end
end