(* * 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 Invariants_H imports LevityCatch "AInvs.Deterministic_AI" "AInvs.AInvs" "Lib.AddUpdSimps" begin context Arch begin lemmas [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 context begin interpretation Arch . (*FIXME: arch_split*) \ \---------------------------------------------------------------------------\ section "Invariants on Executable Spec" definition "ps_clear p n s \ ({p .. p + (1 << n) - 1} - {p}) \ dom (ksPSpace s) = {}" definition "pspace_no_overlap' ptr bits \ \s. \x ko. ksPSpace s x = Some ko \ ({x .. x + (2 ^ objBitsKO ko) - 1}) \ {ptr .. (ptr &&~~ mask bits) + (2 ^ bits - 1)} = {}" definition "ko_wp_at' P p s \ \ko. ksPSpace s p = Some ko \ is_aligned p (objBitsKO ko) \ P ko \ ps_clear p (objBitsKO ko) s" definition obj_at' :: "('a::pspace_storable \ bool) \ word32 \ kernel_state \ bool" where obj_at'_real_def: "obj_at' P p s \ ko_wp_at' (\ko. \obj. projectKO_opt ko = Some obj \ P obj) p s" definition typ_at' :: "kernel_object_type \ word32 \ kernel_state \ bool" where "typ_at' T \ ko_wp_at' (\ko. koTypeOf ko = T)" abbreviation "ep_at' \ obj_at' ((\x. True) :: endpoint \ bool)" abbreviation "ntfn_at' \ obj_at' ((\x. True) :: Structures_H.notification \ bool)" abbreviation "tcb_at' \ obj_at' ((\x. True) :: tcb \ bool)" abbreviation "real_cte_at' \ obj_at' ((\x. True) :: cte \ bool)" abbreviation "ko_at' v \ obj_at' (\k. k = v)" abbreviation "pde_at' \ typ_at' (ArchT PDET)" abbreviation "pte_at' \ typ_at' (ArchT PTET)" end record itcb' = itcbState :: thread_state itcbFaultHandler :: cptr itcbIPCBuffer :: vptr itcbBoundNotification :: "word32 option" itcbPriority :: priority itcbFault :: "fault option" itcbTimeSlice :: nat itcbMCP :: priority definition "tcb_to_itcb' tcb \ \ itcbState = tcbState tcb, itcbFaultHandler = tcbFaultHandler tcb, itcbIPCBuffer = tcbIPCBuffer tcb, itcbBoundNotification = tcbBoundNotification tcb, itcbPriority = tcbPriority tcb, itcbFault = tcbFault tcb, itcbTimeSlice = tcbTimeSlice tcb, itcbMCP = tcbMCP tcb\" lemma [simp]: "itcbState (tcb_to_itcb' tcb) = tcbState tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbFaultHandler (tcb_to_itcb' tcb) = tcbFaultHandler tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbIPCBuffer (tcb_to_itcb' tcb) = tcbIPCBuffer tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbBoundNotification (tcb_to_itcb' tcb) = tcbBoundNotification tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbPriority (tcb_to_itcb' tcb) = tcbPriority tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbFault (tcb_to_itcb' tcb) = tcbFault tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbTimeSlice (tcb_to_itcb' tcb) = tcbTimeSlice tcb" by (auto simp: tcb_to_itcb'_def) lemma [simp]: "itcbMCP (tcb_to_itcb' tcb) = tcbMCP tcb" by (auto simp: tcb_to_itcb'_def) definition pred_tcb_at' :: "(itcb' \ 'a) \ ('a \ bool) \ word32 \ kernel_state \ bool" where "pred_tcb_at' proj test \ obj_at' (\ko. test (proj (tcb_to_itcb' ko)))" abbreviation "st_tcb_at' \ pred_tcb_at' itcbState" abbreviation "bound_tcb_at' \ pred_tcb_at' itcbBoundNotification" abbreviation "mcpriority_tcb_at' \ pred_tcb_at' itcbMCP" lemma st_tcb_at'_def: "st_tcb_at' test \ obj_at' (test \ tcbState)" by (simp add: pred_tcb_at'_def o_def) text {* cte with property at *} definition "cte_wp_at' P p s \ \cte::cte. fst (getObject p s) = {(cte,s)} \ P cte" abbreviation "cte_at' \ cte_wp_at' \" definition tcb_cte_cases :: "word32 \ ((tcb \ cte) \ ((cte \ cte) \ tcb \ tcb))" where "tcb_cte_cases \ [ 0 \ (tcbCTable, tcbCTable_update), 16 \ (tcbVTable, tcbVTable_update), 32 \ (tcbReply, tcbReply_update), 48 \ (tcbCaller, tcbCaller_update), 64 \ (tcbIPCBufferFrame, tcbIPCBufferFrame_update) ]" definition max_ipc_words :: word32 where "max_ipc_words \ capTransferDataSize + msgMaxLength + msgMaxExtraCaps + 2" definition tcb_st_refs_of' :: "Structures_H.thread_state \ (word32 \ reftype) set" where "tcb_st_refs_of' z \ case z of (Running) => {} | (Inactive) => {} | (Restart) => {} | (BlockedOnReceive x) => {(x, TCBBlockedRecv)} | (BlockedOnSend x a b c) => {(x, TCBBlockedSend)} | (BlockedOnNotification x) => {(x, TCBSignal)} | (BlockedOnReply) => {} | (IdleThreadState) => {}" definition ep_q_refs_of' :: "Structures_H.endpoint \ (word32 \ reftype) set" where "ep_q_refs_of' x \ case x of IdleEP => {} | (RecvEP q) => set q \ {EPRecv} | (SendEP q) => set q \ {EPSend}" definition ntfn_q_refs_of' :: "Structures_H.ntfn \ (word32 \ reftype) set" where "ntfn_q_refs_of' x \ case x of IdleNtfn => {} | (WaitingNtfn q) => set q \ {NTFNSignal} | (ActiveNtfn b) => {}" definition ntfn_bound_refs' :: "word32 option \ (word32 \ reftype) set" where "ntfn_bound_refs' t \ set_option t \ {NTFNBound}" definition tcb_bound_refs' :: "word32 option \ (word32 \ reftype) set" where "tcb_bound_refs' a \ set_option a \ {TCBBound}" definition refs_of' :: "Structures_H.kernel_object \ (word32 \ reftype) set" where "refs_of' x \ case x of (KOTCB tcb) => tcb_st_refs_of' (tcbState tcb) \ tcb_bound_refs' (tcbBoundNotification tcb) | (KOCTE cte) => {} | (KOEndpoint ep) => ep_q_refs_of' ep | (KONotification ntfn) => ntfn_q_refs_of' (ntfnObj ntfn) \ ntfn_bound_refs' (ntfnBoundTCB ntfn) | (KOUserData) => {} | (KOUserDataDevice) => {} | (KOKernelData) => {} | (KOArch ako) => {}" definition state_refs_of' :: "kernel_state \ word32 \ (word32 \ reftype) set" where "state_refs_of' s \ (\x. case (ksPSpace s x) of None \ {} | Some ko \ (if is_aligned x (objBitsKO ko) \ ps_clear x (objBitsKO ko) s then refs_of' ko else {}))" primrec live' :: "Structures_H.kernel_object \ bool" where "live' (KOTCB tcb) = (bound (tcbBoundNotification tcb) \ (tcbState tcb \ Inactive \ tcbState tcb \ IdleThreadState) \ tcbQueued tcb)" | "live' (KOCTE cte) = False" | "live' (KOEndpoint ep) = (ep \ IdleEP)" | "live' (KONotification ntfn) = (bound (ntfnBoundTCB ntfn) \ (\ts. ntfnObj ntfn = WaitingNtfn ts))" | "live' (KOUserData) = False" | "live' (KOUserDataDevice) = False" | "live' (KOKernelData) = False" | "live' (KOArch ako) = False" primrec zobj_refs' :: "capability \ word32 set" where "zobj_refs' NullCap = {}" | "zobj_refs' DomainCap = {}" | "zobj_refs' (UntypedCap d r n f) = {}" | "zobj_refs' (EndpointCap r badge x y z) = {r}" | "zobj_refs' (NotificationCap r badge x y) = {r}" | "zobj_refs' (CNodeCap r b g gsz) = {}" | "zobj_refs' (ThreadCap r) = {r}" | "zobj_refs' (Zombie r b n) = {}" | "zobj_refs' (ArchObjectCap ac) = {}" | "zobj_refs' (IRQControlCap) = {}" | "zobj_refs' (IRQHandlerCap irq) = {}" | "zobj_refs' (ReplyCap tcb m) = {}" definition ex_nonz_cap_to' :: "word32 \ kernel_state \ bool" where "ex_nonz_cap_to' ref \ (\s. \cref. cte_wp_at' (\c. ref \ zobj_refs' (cteCap c)) cref s)" definition if_live_then_nonz_cap' :: "kernel_state \ bool" where "if_live_then_nonz_cap' s \ \ptr. ko_wp_at' live' ptr s \ ex_nonz_cap_to' ptr s" primrec cte_refs' :: "capability \ word32 \ word32 set" where "cte_refs' (UntypedCap d p n f) x = {}" | "cte_refs' (NullCap) x = {}" | "cte_refs' (DomainCap) x = {}" | "cte_refs' (EndpointCap ref badge s r g) x = {}" | "cte_refs' (NotificationCap ref badge s r) x = {}" | "cte_refs' (CNodeCap ref bits g gs) x = (\x. ref + (x * 2 ^ cteSizeBits)) ` {0 .. 2 ^ bits - 1}" | "cte_refs' (ThreadCap ref) x = (\x. ref + x) ` (dom tcb_cte_cases)" | "cte_refs' (Zombie r b n) x = (\x. r + (x * 2 ^ cteSizeBits)) ` {0 ..< of_nat n}" | "cte_refs' (ArchObjectCap cap) x = {}" | "cte_refs' (IRQControlCap) x = {}" | "cte_refs' (IRQHandlerCap irq) x = {x + (ucast irq) * 16}" | "cte_refs' (ReplyCap tcb m) x = {}" abbreviation "irq_node' s \ intStateIRQNode (ksInterruptState s)" definition ex_cte_cap_wp_to' :: "(capability \ bool) \ word32 \ kernel_state \ bool" where "ex_cte_cap_wp_to' P ptr \ \s. \cref. cte_wp_at' (\c. P (cteCap c) \ ptr \ cte_refs' (cteCap c) (irq_node' s)) cref s" abbreviation "ex_cte_cap_to' \ ex_cte_cap_wp_to' \" definition if_unsafe_then_cap' :: "kernel_state \ bool" where "if_unsafe_then_cap' s \ \cref. cte_wp_at' (\c. cteCap c \ NullCap) cref s \ ex_cte_cap_to' cref s" section "Valid caps and objects (Haskell)" context begin interpretation Arch . (*FIXME: arch_split*) primrec acapBits :: "arch_capability \ nat" where "acapBits (ASIDPoolCap x y) = asidLowBits + 2" | "acapBits ASIDControlCap = asidHighBits + 2" | "acapBits (PageCap d x y sz z) = pageBitsForSize sz" | "acapBits (PageTableCap x y) = 10" | "acapBits (PageDirectoryCap x y) = 14" end primrec zBits :: "zombie_type \ nat" where "zBits (ZombieCNode n) = objBits (undefined::cte) + n" | "zBits (ZombieTCB) = tcbBlockSizeBits" primrec capBits :: "capability \ nat" where "capBits NullCap = 0" | "capBits DomainCap = 0" | "capBits (UntypedCap d r b f) = b" | "capBits (EndpointCap r b x y z) = objBits (undefined::endpoint)" | "capBits (NotificationCap r b x y) = objBits (undefined::Structures_H.notification)" | "capBits (CNodeCap r b g gs) = objBits (undefined::cte) + b" | "capBits (ThreadCap r) = objBits (undefined::tcb)" | "capBits (Zombie r z n) = zBits z" | "capBits (IRQControlCap) = 0" | "capBits (IRQHandlerCap irq) = 0" | "capBits (ReplyCap tcb m) = objBits (undefined :: tcb)" | "capBits (ArchObjectCap x) = acapBits x" lemmas objBits_defs = tcbBlockSizeBits_def epSizeBits_def ntfnSizeBits_def cteSizeBits_def definition "capAligned c \ is_aligned (capUntypedPtr c) (capBits c) \ capBits c < word_bits" definition "obj_range' (p::word32) ko \ {p .. p + 2 ^ objBitsKO ko - 1}" primrec (nonexhaustive) usableUntypedRange :: "capability \ word32 set" where "usableUntypedRange (UntypedCap d p n f) = (if f < 2^n then {p+of_nat f .. p + 2 ^ n - 1} else {})" definition "valid_untyped' d ptr bits idx s \ \ptr'. \ ko_wp_at' (\ko. {ptr .. ptr + 2 ^ bits - 1} \ obj_range' ptr' ko \ obj_range' ptr' ko \ usableUntypedRange(UntypedCap d ptr bits idx) \ {}) ptr' s" context begin interpretation Arch . (*FIXME: arch_split*) definition page_table_at' :: "word32 \ kernel_state \ bool" where "page_table_at' x \ \s. is_aligned x ptBits \ (\y < 2 ^ 8. typ_at' (ArchT PTET) (x + (y << 2)) s)" definition page_directory_at' :: "word32 \ kernel_state \ bool" where "page_directory_at' x \ \s. is_aligned x pdBits \ (\y < 2 ^ 12. typ_at' (ArchT PDET) (x + (y << 2)) s)" abbreviation "asid_pool_at' \ typ_at' (ArchT ASIDPoolT)" (* FIXME: duplicated with vmsz_aligned *) definition "vmsz_aligned' ref sz \ is_aligned ref (pageBitsForSize sz)" primrec zombieCTEs :: "zombie_type \ nat" where "zombieCTEs ZombieTCB = 5" | "zombieCTEs (ZombieCNode n) = (2 ^ n)" definition valid_cap' :: "capability \ kernel_state \ bool" where valid_cap'_def: "valid_cap' c s \ capAligned c \ (case c of Structures_H.NullCap \ True | Structures_H.DomainCap \ True | Structures_H.UntypedCap d r n f \ valid_untyped' d r n f s \ r \ 0 \ minUntypedSizeBits \ n \ n \ maxUntypedSizeBits \ f \ 2^n \ is_aligned (of_nat f :: word32) minUntypedSizeBits | Structures_H.EndpointCap r badge x y z \ ep_at' r s | Structures_H.NotificationCap r badge x y \ ntfn_at' r s | Structures_H.CNodeCap r bits guard guard_sz \ bits \ 0 \ bits + guard_sz \ word_bits \ guard && mask guard_sz = guard \ (\addr. real_cte_at' (r + 2^cteSizeBits * (addr && mask bits)) s) | Structures_H.ThreadCap r \ tcb_at' r s | Structures_H.ReplyCap r m \ tcb_at' r s | Structures_H.IRQControlCap \ True | Structures_H.IRQHandlerCap irq \ irq \ maxIRQ | Structures_H.Zombie r b n \ n \ zombieCTEs b \ zBits b < word_bits \ (case b of ZombieTCB \ tcb_at' r s | ZombieCNode n \ n \ 0 \ (\addr. real_cte_at' (r + 2^cteSizeBits * (addr && mask n)) s)) | Structures_H.ArchObjectCap ac \ (case ac of ASIDPoolCap pool asid \ typ_at' (ArchT ASIDPoolT) pool s \ is_aligned asid asid_low_bits \ asid \ 2^asid_bits - 1 | ASIDControlCap \ True | PageCap d ref rghts sz mapdata \ ref \ 0 \ (\p < 2 ^ (pageBitsForSize sz - pageBits). typ_at' (if d then UserDataDeviceT else UserDataT) (ref + p * 2 ^ pageBits) s) \ (case mapdata of None \ True | Some (asid, ref) \ 0 < asid \ asid \ 2 ^ asid_bits - 1 \ vmsz_aligned' ref sz \ ref < kernelBase) | PageTableCap ref mapdata \ page_table_at' ref s \ (case mapdata of None \ True | Some (asid, ref) \ 0 < asid \ asid \ 2^asid_bits - 1 \ ref < kernelBase) | PageDirectoryCap ref mapdata \ page_directory_at' ref s \ case_option True (\asid. 0 < asid \ asid \ 2^asid_bits - 1) mapdata))" abbreviation (input) valid_cap'_syn :: "kernel_state \ capability \ bool" ("_ \' _" [60, 60] 61) where "s \' c \ valid_cap' c s" definition valid_cte' :: "cte \ kernel_state \ bool" where "valid_cte' cte s \ s \' (cteCap cte)" definition valid_tcb_state' :: "Structures_H.thread_state \ kernel_state \ bool" where "valid_tcb_state' ts s \ case ts of Structures_H.BlockedOnReceive ref \ ep_at' ref s | Structures_H.BlockedOnSend ref b d c \ ep_at' ref s | Structures_H.BlockedOnNotification ref \ ntfn_at' ref s | _ \ True" definition valid_ipc_buffer_ptr' :: "word32 \ kernel_state \ bool" where "valid_ipc_buffer_ptr' a s \ is_aligned a msg_align_bits \ typ_at' UserDataT (a && ~~ mask pageBits) s" definition valid_bound_ntfn' :: "word32 option \ kernel_state \ bool" where "valid_bound_ntfn' ntfn_opt s \ case ntfn_opt of None \ True | Some a \ ntfn_at' a s" definition is_device_page_cap' :: "capability \ bool" where "is_device_page_cap' cap \ case cap of capability.ArchObjectCap (arch_capability.PageCap dev _ _ _ _) \ dev | _ \ False" definition valid_tcb' :: "Structures_H.tcb \ kernel_state \ bool" where "valid_tcb' t s \ (\(getF, setF) \ ran tcb_cte_cases. s \' cteCap (getF t)) \ valid_tcb_state' (tcbState t) s \ is_aligned (tcbIPCBuffer t) msg_align_bits \ valid_bound_ntfn' (tcbBoundNotification t) s \ tcbDomain t \ maxDomain \ tcbPriority t \ maxPriority \ tcbMCP t \ maxPriority" definition valid_ep' :: "Structures_H.endpoint \ kernel_state \ bool" where "valid_ep' ep s \ case ep of Structures_H.IdleEP \ True | Structures_H.SendEP ts \ (ts \ [] \ (\t \ set ts. tcb_at' t s) \ distinct ts) | Structures_H.RecvEP ts \ (ts \ [] \ (\t \ set ts. tcb_at' t s) \ distinct ts)" definition valid_bound_tcb' :: "word32 option \ kernel_state \ bool" where "valid_bound_tcb' tcb_opt s \ case tcb_opt of None \ True | Some t \ tcb_at' t s" definition valid_ntfn' :: "Structures_H.notification \ kernel_state \ bool" where "valid_ntfn' ntfn s \ (case ntfnObj ntfn of Structures_H.IdleNtfn \ True | Structures_H.WaitingNtfn ts \ (ts \ [] \ (\t \ set ts. tcb_at' t s) \ distinct ts \ (case ntfnBoundTCB ntfn of Some tcb \ ts = [tcb] | _ \ True)) | Structures_H.ActiveNtfn b \ True) \ valid_bound_tcb' (ntfnBoundTCB ntfn) s" definition valid_mapping' :: "word32 \ vmpage_size \ kernel_state \ bool" where "valid_mapping' x sz s \ is_aligned x (pageBitsForSize sz) \ ptrFromPAddr x \ 0" primrec valid_pte' :: "ARM_H.pte \ kernel_state \ bool" where "valid_pte' (InvalidPTE) = \" | "valid_pte' (LargePagePTE ptr _ _ _ _) = (valid_mapping' ptr ARMLargePage)" | "valid_pte' (SmallPagePTE ptr _ _ _ _) = (valid_mapping' ptr ARMSmallPage)" primrec valid_pde' :: "ARM_H.pde \ kernel_state \ bool" where "valid_pde' (InvalidPDE) = \" | "valid_pde' (SectionPDE ptr _ _ _ _ _ _) = (valid_mapping' ptr ARMSection)" | "valid_pde' (SuperSectionPDE ptr _ _ _ _ _) = (valid_mapping' ptr ARMSuperSection)" | "valid_pde' (PageTablePDE ptr _ _) = (\_. is_aligned ptr ptBits)" primrec valid_asid_pool' :: "asidpool \ kernel_state \ bool" where "valid_asid_pool' (ASIDPool pool) = (\s. dom pool \ {0 .. 2^asid_low_bits - 1} \ 0 \ ran pool \ (\x \ ran pool. is_aligned x pdBits))" primrec valid_arch_obj' :: "arch_kernel_object \ kernel_state \ bool" where "valid_arch_obj' (KOASIDPool pool) = valid_asid_pool' pool" | "valid_arch_obj' (KOPDE pde) = valid_pde' pde" | "valid_arch_obj' (KOPTE pte) = valid_pte' pte" definition valid_obj' :: "Structures_H.kernel_object \ kernel_state \ bool" where "valid_obj' ko s \ case ko of KOEndpoint endpoint \ valid_ep' endpoint s | KONotification notification \ valid_ntfn' notification s | KOKernelData \ False | KOUserData \ True | KOUserDataDevice \ True | KOTCB tcb \ valid_tcb' tcb s | KOCTE cte \ valid_cte' cte s | KOArch arch_kernel_object \ valid_arch_obj' arch_kernel_object s" definition pspace_aligned' :: "kernel_state \ bool" where "pspace_aligned' s \ \x \ dom (ksPSpace s). is_aligned x (objBitsKO (the (ksPSpace s x)))" definition pspace_distinct' :: "kernel_state \ bool" where "pspace_distinct' s \ \x \ dom (ksPSpace s). ps_clear x (objBitsKO (the (ksPSpace s x))) s" definition valid_objs' :: "kernel_state \ bool" where "valid_objs' s \ \obj \ ran (ksPSpace s). valid_obj' obj s" type_synonym cte_heap = "word32 \ cte option" definition map_to_ctes :: "(word32 \ kernel_object) \ cte_heap" where "map_to_ctes m \ \x. let cte_bits = objBitsKO (KOCTE undefined); tcb_bits = objBitsKO (KOTCB undefined); y = (x && (~~ mask tcb_bits)) in if \cte. m x = Some (KOCTE cte) \ is_aligned x cte_bits \ {x + 1 .. x + (1 << cte_bits) - 1} \ dom m = {} then case m x of Some (KOCTE cte) \ Some cte else if \tcb. m y = Some (KOTCB tcb) \ {y + 1 .. y + (1 << tcb_bits) - 1} \ dom m = {} then case m y of Some (KOTCB tcb) \ option_map (\(getF, setF). getF tcb) (tcb_cte_cases (x - y)) else None" abbreviation "ctes_of s \ map_to_ctes (ksPSpace s)" definition mdb_next :: "cte_heap \ word32 \ word32 option" where "mdb_next s c \ option_map (mdbNext o cteMDBNode) (s c)" definition mdb_next_rel :: "cte_heap \ (word32 \ word32) set" where "mdb_next_rel m \ {(x, y). mdb_next m x = Some y}" abbreviation mdb_next_direct :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ \ _" [60,0,60] 61) where "m \ a \ b \ (a, b) \ mdb_next_rel m" abbreviation mdb_next_trans :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ \\<^sup>+ _" [60,0,60] 61) where "m \ a \\<^sup>+ b \ (a,b) \ (mdb_next_rel m)\<^sup>+" abbreviation mdb_next_rtrans :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ \\<^sup>* _" [60,0,60] 61) where "m \ a \\<^sup>* b \ (a,b) \ (mdb_next_rel m)\<^sup>*" definition "valid_badges m \ \p p' cap node cap' node'. m p = Some (CTE cap node) \ m p' = Some (CTE cap' node') \ (m \ p \ p') \ (sameRegionAs cap cap') \ (isEndpointCap cap \ capEPBadge cap \ capEPBadge cap' \ capEPBadge cap' \ 0 \ mdbFirstBadged node') \ (isNotificationCap cap \ capNtfnBadge cap \ capNtfnBadge cap' \ capNtfnBadge cap' \ 0 \ mdbFirstBadged node')" fun (sequential) untypedRange :: "capability \ word32 set" where "untypedRange (UntypedCap d p n f) = {p .. p + 2 ^ n - 1}" | "untypedRange c = {}" primrec acapClass :: "arch_capability \ capclass" where "acapClass (ASIDPoolCap x y) = PhysicalClass" | "acapClass ASIDControlCap = ASIDMasterClass" | "acapClass (PageCap d x y sz z) = PhysicalClass" | "acapClass (PageTableCap x y) = PhysicalClass" | "acapClass (PageDirectoryCap x y) = PhysicalClass" primrec capClass :: "capability \ capclass" where "capClass (NullCap) = NullClass" | "capClass (DomainCap) = DomainClass" | "capClass (UntypedCap d p n f) = PhysicalClass" | "capClass (EndpointCap ref badge s r g) = PhysicalClass" | "capClass (NotificationCap ref badge s r) = PhysicalClass" | "capClass (CNodeCap ref bits g gs) = PhysicalClass" | "capClass (ThreadCap ref) = PhysicalClass" | "capClass (Zombie r b n) = PhysicalClass" | "capClass (IRQControlCap) = IRQClass" | "capClass (IRQHandlerCap irq) = IRQClass" | "capClass (ReplyCap tcb m) = ReplyClass tcb" | "capClass (ArchObjectCap cap) = acapClass cap" definition "capRange cap \ if capClass cap \ PhysicalClass then {} else {capUntypedPtr cap .. capUntypedPtr cap + 2 ^ capBits cap - 1}" definition "caps_contained' m \ \p p' c n c' n'. m p = Some (CTE c n) \ m p' = Some (CTE c' n') \ \isUntypedCap c' \ capRange c' \ untypedRange c \ {} \ capRange c' \ untypedRange c" definition valid_dlist :: "cte_heap \ bool" where "valid_dlist m \ \p cte. m p = Some cte \ (let prev = mdbPrev (cteMDBNode cte); next = mdbNext (cteMDBNode cte) in (prev \ 0 \ (\cte'. m prev = Some cte' \ mdbNext (cteMDBNode cte') = p)) \ (next \ 0 \ (\cte'. m next = Some cte' \ mdbPrev (cteMDBNode cte') = p)))" definition "no_0 m \ m 0 = None" definition "no_loops m \ \c. \ m \ c \\<^sup>+ c" definition "mdb_chain_0 m \ \x \ dom m. m \ x \\<^sup>+ 0" definition "class_links m \ \p p' cte cte'. m p = Some cte \ m p' = Some cte' \ m \ p \ p' \ capClass (cteCap cte) = capClass (cteCap cte')" definition "is_chunk m cap p p' \ \p''. m \ p \\<^sup>+ p'' \ m \ p'' \\<^sup>* p' \ (\cap'' n''. m p'' = Some (CTE cap'' n'') \ sameRegionAs cap cap'')" definition "mdb_chunked m \ \p p' cap cap' n n'. m p = Some (CTE cap n) \ m p' = Some (CTE cap' n') \ sameRegionAs cap cap' \ p \ p' \ (m \ p \\<^sup>+ p' \ m \ p' \\<^sup>+ p) \ (m \ p \\<^sup>+ p' \ is_chunk m cap p p') \ (m \ p' \\<^sup>+ p \ is_chunk m cap' p' p)" definition parentOf :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ parentOf _") where "s \ c' parentOf c \ \cte' cte. s c = Some cte \ s c' = Some cte' \ isMDBParentOf cte' cte" context notes [[inductive_internals =true]] begin inductive subtree :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ \ _" [60,0,60] 61) for s :: cte_heap and c :: word32 where direct_parent: "\ s \ c \ c'; c' \ 0; s \ c parentOf c'\ \ s \ c \ c'" | trans_parent: "\ s \ c \ c'; s \ c' \ c''; c'' \ 0; s \ c parentOf c'' \ \ s \ c \ c''" end definition "descendants_of' c s \ {c'. s \ c \ c'}" definition "untyped_mdb' m \ \p p' c n c' n'. m p = Some (CTE c n) \ isUntypedCap c \ m p' = Some (CTE c' n') \ \ isUntypedCap c' \ capRange c' \ untypedRange c \ {} \ p' \ descendants_of' p m" definition "untyped_inc' m \ \p p' c c' n n'. m p = Some (CTE c n) \ isUntypedCap c \ m p' = Some (CTE c' n') \ isUntypedCap c' \ (untypedRange c \ untypedRange c' \ untypedRange c' \ untypedRange c \ untypedRange c \ untypedRange c' = {}) \ (untypedRange c \ untypedRange c' \ (p \ descendants_of' p' m \ untypedRange c \ usableUntypedRange c' ={})) \ (untypedRange c' \ untypedRange c \ (p' \ descendants_of' p m \ untypedRange c' \ usableUntypedRange c ={})) \ (untypedRange c = untypedRange c' \ (p' \ descendants_of' p m \ usableUntypedRange c={} \ p \ descendants_of' p' m \ usableUntypedRange c' = {} \ p = p'))" definition "valid_nullcaps m \ \p n. m p = Some (CTE NullCap n) \ n = nullMDBNode" definition "ut_revocable' m \ \p cap n. m p = Some (CTE cap n) \ isUntypedCap cap \ mdbRevocable n" definition "irq_control m \ \p n. m p = Some (CTE IRQControlCap n) \ mdbRevocable n \ (\p' n'. m p' = Some (CTE IRQControlCap n') \ p' = p)" definition isArchPageCap :: "capability \ bool" where "isArchPageCap cap \ case cap of ArchObjectCap (PageCap d ref rghts sz data) \ True | _ \ False" definition distinct_zombie_caps :: "(word32 \ capability option) \ bool" where "distinct_zombie_caps caps \ \ptr ptr' cap cap'. caps ptr = Some cap \ caps ptr' = Some cap' \ ptr \ ptr' \ isZombie cap \ capClass cap' = PhysicalClass \ \ isUntypedCap cap' \ \ isArchPageCap cap' \ capBits cap = capBits cap' \ capUntypedPtr cap \ capUntypedPtr cap'" definition distinct_zombies :: "cte_heap \ bool" where "distinct_zombies m \ distinct_zombie_caps (option_map cteCap \ m)" definition reply_masters_rvk_fb :: "cte_heap \ bool" where "reply_masters_rvk_fb ctes \ \cte \ ran ctes. isReplyCap (cteCap cte) \ capReplyMaster (cteCap cte) \ mdbRevocable (cteMDBNode cte) \ mdbFirstBadged (cteMDBNode cte)" definition valid_mdb_ctes :: "cte_heap \ bool" where "valid_mdb_ctes \ \m. valid_dlist m \ no_0 m \ mdb_chain_0 m \ valid_badges m \ caps_contained' m \ mdb_chunked m \ untyped_mdb' m \ untyped_inc' m \ valid_nullcaps m \ ut_revocable' m \ class_links m \ distinct_zombies m \ irq_control m \ reply_masters_rvk_fb m" definition valid_mdb' :: "kernel_state \ bool" where "valid_mdb' \ \s. valid_mdb_ctes (ctes_of s)" definition "no_0_obj' \ \s. ksPSpace s 0 = None" definition vs_ptr_align :: "Structures_H.kernel_object \ nat" where "vs_ptr_align obj \ case obj of KOArch (KOPTE (pte.LargePagePTE _ _ _ _ _)) \ 6 | KOArch (KOPDE (pde.SuperSectionPDE _ _ _ _ _ _)) \ 6 | _ \ 0" definition "vs_valid_duplicates' \ \h. \x y. case h x of None \ True | Some ko \ is_aligned y 2 \ x && ~~ mask (vs_ptr_align ko) = y && ~~ mask (vs_ptr_align ko) \ h x = h y" definition valid_pspace' :: "kernel_state \ bool" where "valid_pspace' \ valid_objs' and pspace_aligned' and pspace_distinct' and no_0_obj' and valid_mdb'" primrec runnable' :: "Structures_H.thread_state \ bool" where "runnable' (Structures_H.Running) = True" | "runnable' (Structures_H.Inactive) = False" | "runnable' (Structures_H.Restart) = True" | "runnable' (Structures_H.IdleThreadState) = False" | "runnable' (Structures_H.BlockedOnReceive a) = False" | "runnable' (Structures_H.BlockedOnReply) = False" | "runnable' (Structures_H.BlockedOnSend a b c d) = False" | "runnable' (Structures_H.BlockedOnNotification x) = False" definition inQ :: "domain \ priority \ tcb \ bool" where "inQ d p tcb \ tcbQueued tcb \ tcbPriority tcb = p \ tcbDomain tcb = d" definition (* for given domain and priority, the scheduler bitmap indicates a thread is in the queue *) (* second level of the bitmap is stored in reverse for better cache locality in common case *) bitmapQ :: "domain \ priority \ kernel_state \ bool" where "bitmapQ d p s \ ksReadyQueuesL1Bitmap s d !! prioToL1Index p \ ksReadyQueuesL2Bitmap s (d, invertL1Index (prioToL1Index p)) !! unat (p && mask wordRadix)" definition valid_queues_no_bitmap :: "kernel_state \ bool" where "valid_queues_no_bitmap \ \s. (\d p. (\t \ set (ksReadyQueues s (d, p)). obj_at' (inQ d p and runnable' \ tcbState) t s) \ distinct (ksReadyQueues s (d, p)) \ (d > maxDomain \ p > maxPriority \ ksReadyQueues s (d,p) = []))" definition (* A priority is used as a two-part key into the bitmap structure. If an L2 bitmap entry is set without an L1 entry, updating the L1 entry (shared by many priorities) may make unexpected threads schedulable *) bitmapQ_no_L2_orphans :: "kernel_state \ bool" where "bitmapQ_no_L2_orphans \ \s. \d i j. ksReadyQueuesL2Bitmap s (d, invertL1Index i) !! j \ i < l2BitmapSize \ (ksReadyQueuesL1Bitmap s d !! i)" definition (* If the scheduler finds a set bit in L1 of the bitmap, it must find some bit set in L2 when it looks there. This lets it omit a check. L2 entries have wordBits bits each. That means the L1 word only indexes a small number of L2 entries, despite being stored in a wordBits word. We allow only bits corresponding to L2 indices to be set. *) bitmapQ_no_L1_orphans :: "kernel_state \ bool" where "bitmapQ_no_L1_orphans \ \s. \d i. ksReadyQueuesL1Bitmap s d !! i \ ksReadyQueuesL2Bitmap s (d, invertL1Index i) \ 0 \ i < l2BitmapSize" definition valid_bitmapQ :: "kernel_state \ bool" where "valid_bitmapQ \ \s. (\d p. bitmapQ d p s \ ksReadyQueues s (d,p) \ [])" definition valid_queues :: "kernel_state \ bool" where "valid_queues \ \s. valid_queues_no_bitmap s \ valid_bitmapQ s \ bitmapQ_no_L2_orphans s \ bitmapQ_no_L1_orphans s" definition (* when a thread gets added to / removed from a queue, but before bitmap updated *) valid_bitmapQ_except :: "domain \ priority \ kernel_state \ bool" where "valid_bitmapQ_except d' p' \ \s. (\d p. (d \ d' \ p \ p') \ (bitmapQ d p s \ ksReadyQueues s (d,p) \ []))" lemmas bitmapQ_defs = valid_bitmapQ_def valid_bitmapQ_except_def bitmapQ_def bitmapQ_no_L2_orphans_def bitmapQ_no_L1_orphans_def definition valid_queues' :: "kernel_state \ bool" where "valid_queues' \ \s. \d p t. obj_at' (inQ d p) t s \ t \ set (ksReadyQueues s (d, p))" definition tcb_in_cur_domain' :: "32 word \ kernel_state \ bool" where "tcb_in_cur_domain' t \ \s. obj_at' (\tcb. ksCurDomain s = tcbDomain tcb) t s" definition ct_idle_or_in_cur_domain' :: "kernel_state \ bool" where "ct_idle_or_in_cur_domain' \ \s. ksSchedulerAction s = ResumeCurrentThread \ ksCurThread s = ksIdleThread s \ tcb_in_cur_domain' (ksCurThread s) s" definition "ct_in_state' test \ \s. st_tcb_at' test (ksCurThread s) s" definition "ct_not_inQ \ \s. ksSchedulerAction s = ResumeCurrentThread \ obj_at' (Not \ tcbQueued) (ksCurThread s) s" abbreviation "idle' \ \st. st = Structures_H.IdleThreadState" abbreviation "activatable' st \ runnable' st \ idle' st" primrec sch_act_wf :: "scheduler_action \ kernel_state \ bool" where "sch_act_wf ResumeCurrentThread = ct_in_state' activatable'" | "sch_act_wf ChooseNewThread = \" | "sch_act_wf (SwitchToThread t) = (\s. st_tcb_at' runnable' t s \ tcb_in_cur_domain' t s)" definition sch_act_simple :: "kernel_state \ bool" where "sch_act_simple \ \s. (ksSchedulerAction s = ResumeCurrentThread) \ (ksSchedulerAction s = ChooseNewThread)" definition sch_act_sane :: "kernel_state \ bool" where "sch_act_sane \ \s. \t. ksSchedulerAction s = SwitchToThread t \ t \ ksCurThread s" abbreviation "sch_act_not t \ \s. ksSchedulerAction s \ SwitchToThread t" abbreviation "idle_tcb_at' \ pred_tcb_at' (\t. (itcbState t, itcbBoundNotification t))" definition valid_idle' :: "kernel_state \ bool" where "valid_idle' \ \s. idle_tcb_at' (\p. idle' (fst p) \ snd p = None) (ksIdleThread s) s" definition valid_irq_node' :: "word32 \ kernel_state \ bool" where "valid_irq_node' x \ \s. is_aligned x 12 \ (\irq :: irq. real_cte_at' (x + 16 * (ucast irq)) s)" definition valid_refs' :: "word32 set \ cte_heap \ bool" where "valid_refs' R \ \m. \c \ ran m. R \ capRange (cteCap c) = {}" definition page_directory_refs' :: "word32 \ word32 set" where "page_directory_refs' x \ (\y. x + (y << 2)) ` {y. y < 2 ^ 12}" definition page_table_refs' :: "word32 \ word32 set" where "page_table_refs' x \ (\y. x + (y << 2)) ` {y. y < 2 ^ 8}" definition global_refs' :: "kernel_state \ obj_ref set" where "global_refs' \ \s. {ksIdleThread s} \ page_directory_refs' (armKSGlobalPD (ksArchState s)) \ (\pt \ set (armKSGlobalPTs (ksArchState s)). page_table_refs' pt) \ range (\irq :: irq. irq_node' s + 16 * ucast irq)" definition valid_cap_sizes' :: "nat \ cte_heap \ bool" where "valid_cap_sizes' n hp = (\cte \ ran hp. 2 ^ capBits (cteCap cte) \ n)" definition valid_global_refs' :: "kernel_state \ bool" where "valid_global_refs' \ \s. valid_refs' kernel_data_refs (ctes_of s) \ global_refs' s \ kernel_data_refs \ valid_cap_sizes' (gsMaxObjectSize s) (ctes_of s)" definition pspace_domain_valid :: "kernel_state \ bool" where "pspace_domain_valid = (\s. \x ko. ksPSpace s x = Some ko \ ({x .. x + (2 ^ objBitsKO ko) - 1}) \ kernel_data_refs = {})" definition valid_asid_table' :: "(asid \ word32) \ kernel_state \ bool" where "valid_asid_table' table \ \s. dom table \ {0 .. 2^asid_high_bits - 1} \ 0 \ ran table" definition valid_global_pts' :: "word32 list \ kernel_state \ bool" where "valid_global_pts' pts \ \s. \p \ set pts. page_table_at' p s" definition valid_asid_map' :: "(word32 \ word8 \ word32) \ bool" where "valid_asid_map' m \ inj_on (option_map snd o m) (dom m) \ dom m \ ({0 .. mask asid_bits} - {0})" definition valid_arch_state' :: "kernel_state \ bool" where "valid_arch_state' \ \s. valid_asid_table' (armKSASIDTable (ksArchState s)) s \ page_directory_at' (armKSGlobalPD (ksArchState s)) s \ valid_global_pts' (armKSGlobalPTs (ksArchState s)) s \ is_inv (armKSHWASIDTable (ksArchState s)) (option_map fst o armKSASIDMap (ksArchState s)) \ valid_asid_map' (armKSASIDMap (ksArchState s))" definition irq_issued' :: "irq \ kernel_state \ bool" where "irq_issued' irq \ \s. intStateIRQTable (ksInterruptState s) irq = IRQSignal" definition cteCaps_of :: "kernel_state \ word32 \ capability option" where "cteCaps_of s \ option_map cteCap \ ctes_of s" definition valid_irq_handlers' :: "kernel_state \ bool" where "valid_irq_handlers' \ \s. \cap \ ran (cteCaps_of s). \irq. cap = IRQHandlerCap irq \ irq_issued' irq s" definition "irqs_masked' \ \s. \irq > maxIRQ. intStateIRQTable (ksInterruptState s) irq = IRQInactive" definition pd_asid_slot :: word32 where "pd_asid_slot \ 0xff0" (* ideally, all mappings above kernel_base are global and kernel-only, and of them one particular mapping is clear. at the moment all we can easily say is that the mapping is clear. *) definition valid_pde_mapping_offset' :: "word32 \ bool" where "valid_pde_mapping_offset' offset \ offset \ pd_asid_slot * 4" definition valid_pde_mapping' :: "word32 \ pde \ bool" where "valid_pde_mapping' offset pde \ pde = InvalidPDE \ valid_pde_mapping_offset' offset" definition valid_pde_mappings' :: "kernel_state \ bool" where "valid_pde_mappings' \ \s. \x pde. ko_at' pde x s \ valid_pde_mapping' (x && mask pdBits) pde" definition "valid_irq_masks' table masked \ \irq. table irq = IRQInactive \ masked irq" abbreviation "valid_irq_states' s \ valid_irq_masks' (intStateIRQTable (ksInterruptState s)) (irq_masks (ksMachineState s))" defs pointerInUserData_def: "pointerInUserData p \ \s. (typ_at' UserDataT (p && ~~ mask pageBits) s)" (* pointerInDeviceData is not defined in spec but is necessary for valid_machine_state' *) definition pointerInDeviceData :: "machine_word \ kernel_state \ bool" where "pointerInDeviceData p \ \s. (typ_at' UserDataDeviceT (p && ~~ mask pageBits) s)" definition "valid_machine_state' \ \s. \p. pointerInUserData p s \ pointerInDeviceData p s \ underlying_memory (ksMachineState s) p = 0" definition "untyped_ranges_zero_inv cps urs \ urs = ran (untypedZeroRange \\<^sub>m cps)" abbreviation "untyped_ranges_zero' s \ untyped_ranges_zero_inv (cteCaps_of s) (gsUntypedZeroRanges s)" (* FIXME: this really should be a definition like the above. *) (* The schedule is invariant. *) abbreviation "valid_dom_schedule' \ \s. ksDomSchedule s \ [] \ (\x\set (ksDomSchedule s). dschDomain x \ maxDomain \ 0 < dschLength x) \ ksDomSchedule s = ksDomSchedule (newKernelState undefined) \ ksDomScheduleIdx s < length (ksDomSchedule (newKernelState undefined))" definition valid_state' :: "kernel_state \ bool" where "valid_state' \ \s. valid_pspace' s \ sch_act_wf (ksSchedulerAction s) s \ valid_queues s \ sym_refs (state_refs_of' s) \ if_live_then_nonz_cap' s \ if_unsafe_then_cap' s \ valid_idle' s \ valid_global_refs' s \ valid_arch_state' s \ valid_irq_node' (irq_node' s) s \ valid_irq_handlers' s \ valid_irq_states' s \ valid_machine_state' s \ irqs_masked' s \ valid_queues' s \ ct_not_inQ s \ ct_idle_or_in_cur_domain' s \ valid_pde_mappings' s \ pspace_domain_valid s \ ksCurDomain s \ maxDomain \ valid_dom_schedule' s \ untyped_ranges_zero' s" definition "cur_tcb' s \ tcb_at' (ksCurThread s) s" definition invs' :: "kernel_state \ bool" where "invs' \ valid_state' and cur_tcb'" subsection "Derived concepts" abbreviation "awaiting_reply' ts \ ts = Structures_H.BlockedOnReply" (* x-symbol doesn't have a reverse leadsto.. *) definition mdb_prev :: "cte_heap \ word32 \ word32 \ bool" ("_ \ _ \ _" [60,0,60] 61) where "m \ c \ c' \ (\z. m c' = Some z \ c = mdbPrev (cteMDBNode z))" definition makeObjectT :: "kernel_object_type \ kernel_object" where "makeObjectT tp \ case tp of EndpointT \ injectKO (makeObject :: endpoint) | NotificationT \ injectKO (makeObject :: Structures_H.notification) | CTET \ injectKO (makeObject :: cte) | TCBT \ injectKO (makeObject :: tcb) | UserDataT \ injectKO (makeObject :: user_data) | UserDataDeviceT \ injectKO (makeObject :: user_data_device) | KernelDataT \ KOKernelData | ArchT atp \ (case atp of PDET \ injectKO (makeObject :: pde) | PTET \ injectKO (makeObject :: pte) | ASIDPoolT \ injectKO (makeObject :: asidpool))" definition objBitsT :: "kernel_object_type \ nat" where "objBitsT tp \ objBitsKO (makeObjectT tp)" abbreviation "active' st \ st = Structures_H.Running \ st = Structures_H.Restart" abbreviation "simple' st \ st = Structures_H.Inactive \ st = Structures_H.Running \ st = Structures_H.Restart \ idle' st \ awaiting_reply' st" abbreviation "ct_active' \ ct_in_state' active'" abbreviation "ct_running' \ ct_in_state' (\st. st = Structures_H.Running)" abbreviation(input) "all_invs_but_sym_refs_ct_not_inQ' \ \s. valid_pspace' s \ sch_act_wf (ksSchedulerAction s) s \ valid_queues s \ if_live_then_nonz_cap' s \ if_unsafe_then_cap' s \ valid_idle' s \ valid_global_refs' s \ valid_arch_state' s \ valid_irq_node' (irq_node' s) s \ valid_irq_handlers' s \ valid_irq_states' s \ irqs_masked' s \ valid_machine_state' s \ cur_tcb' s \ valid_queues' s \ ct_idle_or_in_cur_domain' s \ valid_pde_mappings' s \ pspace_domain_valid s \ ksCurDomain s \ maxDomain \ valid_dom_schedule' s \ untyped_ranges_zero' s" abbreviation(input) "all_invs_but_ct_not_inQ' \ \s. valid_pspace' s \ sch_act_wf (ksSchedulerAction s) s \ valid_queues s \ sym_refs (state_refs_of' s) \ if_live_then_nonz_cap' s \ if_unsafe_then_cap' s \ valid_idle' s \ valid_global_refs' s \ valid_arch_state' s \ valid_irq_node' (irq_node' s) s \ valid_irq_handlers' s \ valid_irq_states' s \ irqs_masked' s \ valid_machine_state' s \ cur_tcb' s \ valid_queues' s \ ct_idle_or_in_cur_domain' s \ valid_pde_mappings' s \ pspace_domain_valid s \ ksCurDomain s \ maxDomain \ valid_dom_schedule' s \ untyped_ranges_zero' s" lemma all_invs_but_sym_refs_not_ct_inQ_check': "(all_invs_but_sym_refs_ct_not_inQ' and sym_refs \ state_refs_of' and ct_not_inQ) = invs'" by (simp add: pred_conj_def conj_commute conj_left_commute invs'_def valid_state'_def) lemma all_invs_but_not_ct_inQ_check': "(all_invs_but_ct_not_inQ' and ct_not_inQ) = invs'" by (simp add: pred_conj_def conj_commute conj_left_commute invs'_def valid_state'_def) definition "all_invs_but_ct_idle_or_in_cur_domain' \ \s. valid_pspace' s \ sch_act_wf (ksSchedulerAction s) s \ valid_queues s \ sym_refs (state_refs_of' s) \ if_live_then_nonz_cap' s \ if_unsafe_then_cap' s \ valid_idle' s \ valid_global_refs' s \ valid_arch_state' s \ valid_irq_node' (irq_node' s) s \ valid_irq_handlers' s \ valid_irq_states' s \ irqs_masked' s \ valid_machine_state' s \ cur_tcb' s \ valid_queues' s \ ct_not_inQ s \ valid_pde_mappings' s \ pspace_domain_valid s \ ksCurDomain s \ maxDomain \ valid_dom_schedule' s \ untyped_ranges_zero' s" lemmas invs_no_cicd'_def = all_invs_but_ct_idle_or_in_cur_domain'_def lemma all_invs_but_ct_idle_or_in_cur_domain_check': "(all_invs_but_ct_idle_or_in_cur_domain' and ct_idle_or_in_cur_domain') = invs'" by (simp add: all_invs_but_ct_idle_or_in_cur_domain'_def pred_conj_def conj_left_commute conj_commute invs'_def valid_state'_def) abbreviation (input) "invs_no_cicd' \ all_invs_but_ct_idle_or_in_cur_domain'" lemma invs'_to_invs_no_cicd'_def: "invs' = (all_invs_but_ct_idle_or_in_cur_domain' and ct_idle_or_in_cur_domain')" by (fastforce simp: invs'_def all_invs_but_ct_idle_or_in_cur_domain'_def valid_state'_def ) end locale mdb_next = fixes m :: cte_heap fixes greater_eq defines "greater_eq a b \ m \ a \\<^sup>* b" fixes greater defines "greater a b \ m \ a \\<^sup>+ b" locale mdb_order = mdb_next + assumes no_0: "no_0 m" assumes chain: "mdb_chain_0 m" \ \---------------------------------------------------------------------------\ section "Alternate split rules for preserving subgoal order" context begin interpretation Arch . (*FIXME: arch_split*) lemma capability_splits[split]: "P (case capability of capability.ThreadCap x \ f1 x | capability.NullCap \ f2 | capability.NotificationCap x xa xb xc \ f3 x xa xb xc | capability.IRQHandlerCap x \ f4 x | capability.EndpointCap x xa xb xc xd \ f5 x xa xb xc xd | capability.DomainCap \ f6 | capability.Zombie x xa xb \ f7 x xa xb | capability.ArchObjectCap x \ f8 x | capability.ReplyCap x xa \ f9 x xa | capability.UntypedCap dev x xa xb \ f10 dev x xa xb | capability.CNodeCap x xa xb xc \ f11 x xa xb xc | capability.IRQControlCap \ f12) = ((\x1. capability = capability.ThreadCap x1 \ P (f1 x1)) \ (capability = capability.NullCap \ P f2) \ (\x31 x32 x33 x34. capability = capability.NotificationCap x31 x32 x33 x34 \ P (f3 x31 x32 x33 x34)) \ (\x4. capability = capability.IRQHandlerCap x4 \ P (f4 x4)) \ (\x51 x52 x53 x54 x55. capability = capability.EndpointCap x51 x52 x53 x54 x55 \ P (f5 x51 x52 x53 x54 x55)) \ (capability = capability.DomainCap \ P f6) \ (\x71 x72 x73. capability = capability.Zombie x71 x72 x73 \ P (f7 x71 x72 x73)) \ (\x8. capability = capability.ArchObjectCap x8 \ P (f8 x8)) \ (\x91 x92. capability = capability.ReplyCap x91 x92 \ P (f9 x91 x92)) \ (\dev x101 x102 x103. capability = capability.UntypedCap dev x101 x102 x103 \ P (f10 dev x101 x102 x103)) \ (\x111 x112 x113 x114. capability = capability.CNodeCap x111 x112 x113 x114 \ P (f11 x111 x112 x113 x114)) \ (capability = capability.IRQControlCap \ P f12))" "P (case capability of capability.ThreadCap x \ f1 x | capability.NullCap \ f2 | capability.NotificationCap x xa xb xc \ f3 x xa xb xc | capability.IRQHandlerCap x \ f4 x | capability.EndpointCap x xa xb xc xd \ f5 x xa xb xc xd | capability.DomainCap \ f6 | capability.Zombie x xa xb \ f7 x xa xb | capability.ArchObjectCap x \ f8 x | capability.ReplyCap x xa \ f9 x xa | capability.UntypedCap dev x xa xb \ f10 dev x xa xb | capability.CNodeCap x xa xb xc \ f11 x xa xb xc | capability.IRQControlCap \ f12) = (\ ((\x1. capability = capability.ThreadCap x1 \ \ P (f1 x1)) \ capability = capability.NullCap \ \ P f2 \ (\x31 x32 x33 x34. capability = capability.NotificationCap x31 x32 x33 x34 \ \ P (f3 x31 x32 x33 x34)) \ (\x4. capability = capability.IRQHandlerCap x4 \ \ P (f4 x4)) \ (\x51 x52 x53 x54 x55. capability = capability.EndpointCap x51 x52 x53 x54 x55 \ \ P (f5 x51 x52 x53 x54 x55)) \ capability = capability.DomainCap \ \ P f6 \ (\x71 x72 x73. capability = capability.Zombie x71 x72 x73 \ \ P (f7 x71 x72 x73)) \ (\x8. capability = capability.ArchObjectCap x8 \ \ P (f8 x8)) \ (\x91 x92. capability = capability.ReplyCap x91 x92 \ \ P (f9 x91 x92)) \ (\x101 x102 x103 dev. capability = capability.UntypedCap dev x101 x102 x103 \ \ P (f10 dev x101 x102 x103)) \ (\x111 x112 x113 x114. capability = capability.CNodeCap x111 x112 x113 x114 \ \ P (f11 x111 x112 x113 x114)) \ capability = capability.IRQControlCap \ \ P f12))" by (case_tac capability; simp)+ lemma thread_state_splits[split]: " P (case thread_state of Structures_H.thread_state.BlockedOnReceive x \ f1 x | Structures_H.thread_state.BlockedOnReply \ f2 | Structures_H.thread_state.BlockedOnNotification x \ f3 x | Structures_H.thread_state.Running \ f4 | Structures_H.thread_state.Inactive \ f5 | Structures_H.thread_state.IdleThreadState \ f6 | Structures_H.thread_state.BlockedOnSend x xa xb xc \ f7 x xa xb xc | Structures_H.thread_state.Restart \ f8) = ((\x11. thread_state = Structures_H.thread_state.BlockedOnReceive x11 \ P (f1 x11)) \ (awaiting_reply' thread_state \ P f2) \ (\x3. thread_state = Structures_H.thread_state.BlockedOnNotification x3 \ P (f3 x3)) \ (thread_state = Structures_H.thread_state.Running \ P f4) \ (thread_state = Structures_H.thread_state.Inactive \ P f5) \ (idle' thread_state \ P f6) \ (\x71 x72 x73 x74. thread_state = Structures_H.thread_state.BlockedOnSend x71 x72 x73 x74 \ P (f7 x71 x72 x73 x74)) \ (thread_state = Structures_H.thread_state.Restart \ P f8))" "P (case thread_state of Structures_H.thread_state.BlockedOnReceive x \ f1 x | Structures_H.thread_state.BlockedOnReply \ f2 | Structures_H.thread_state.BlockedOnNotification x \ f3 x | Structures_H.thread_state.Running \ f4 | Structures_H.thread_state.Inactive \ f5 | Structures_H.thread_state.IdleThreadState \ f6 | Structures_H.thread_state.BlockedOnSend x xa xb xc \ f7 x xa xb xc | Structures_H.thread_state.Restart \ f8) = (\ ((\x11. thread_state = Structures_H.thread_state.BlockedOnReceive x11 \ \ P (f1 x11)) \ awaiting_reply' thread_state \ \ P f2 \ (\x3. thread_state = Structures_H.thread_state.BlockedOnNotification x3 \ \ P (f3 x3)) \ thread_state = Structures_H.thread_state.Running \ \ P f4 \ thread_state = Structures_H.thread_state.Inactive \ \ P f5 \ idle' thread_state \ \ P f6 \ (\x71 x72 x73 x74. thread_state = Structures_H.thread_state.BlockedOnSend x71 x72 x73 x74 \ \ P (f7 x71 x72 x73 x74)) \ thread_state = Structures_H.thread_state.Restart \ \ P f8))" by (case_tac thread_state; simp)+ lemma ntfn_splits[split]: " P (case ntfn of Structures_H.ntfn.IdleNtfn \ f1 | Structures_H.ntfn.ActiveNtfn x \ f2 x | Structures_H.ntfn.WaitingNtfn x \ f3 x) = ((ntfn = Structures_H.ntfn.IdleNtfn \ P f1) \ (\x2. ntfn = Structures_H.ntfn.ActiveNtfn x2 \ P (f2 x2)) \ (\x3. ntfn = Structures_H.ntfn.WaitingNtfn x3 \ P (f3 x3)))" "P (case ntfn of Structures_H.ntfn.IdleNtfn \ f1 | Structures_H.ntfn.ActiveNtfn x \ f2 x | Structures_H.ntfn.WaitingNtfn x \ f3 x) = (\ (ntfn = Structures_H.ntfn.IdleNtfn \ \ P f1 \ (\x2. ntfn = Structures_H.ntfn.ActiveNtfn x2 \ \ P (f2 x2)) \ (\x3. ntfn = Structures_H.ntfn.WaitingNtfn x3 \ \ P (f3 x3))))" by (case_tac ntfn; simp)+ \ \---------------------------------------------------------------------------\ section "Lemmas" schematic_goal wordBits_def': "wordBits = numeral ?n" (* arch-specific consequence *) by (simp add: wordBits_def word_size) lemma valid_bound_ntfn'_None[simp]: "valid_bound_ntfn' None = \" by (auto simp: valid_bound_ntfn'_def) lemma valid_bound_ntfn'_Some[simp]: "valid_bound_ntfn' (Some x) = ntfn_at' x" by (auto simp: valid_bound_ntfn'_def) lemma valid_bound_tcb'_None[simp]: "valid_bound_tcb' None = \" by (auto simp: valid_bound_tcb'_def) lemma valid_bound_tcb'_Some[simp]: "valid_bound_tcb' (Some x) = tcb_at' x" by (auto simp: valid_bound_tcb'_def) lemmas untypedBits_defs = minUntypedSizeBits_def maxUntypedSizeBits_def lemmas objBits_simps = objBits_def objBitsKO_def word_size_def lemmas objBits_simps' = objBits_simps objBits_defs lemmas wordRadix_def' = wordRadix_def[simplified] lemma valid_duplicates'_D: "\vs_valid_duplicates' m; m (p::word32) = Some ko;is_aligned p' 2; p && ~~ mask (vs_ptr_align ko) = p' && ~~ mask (vs_ptr_align ko)\ \ m p' = Some ko " apply (clarsimp simp:vs_valid_duplicates'_def) apply (drule_tac x = p in spec) apply auto done lemma ps_clear_def2: "p \ p + 1 \ ps_clear p n s = ({p + 1 .. p + (1 << n) - 1} \ dom (ksPSpace s) = {})" apply (simp add: ps_clear_def) apply safe apply (drule_tac a=x in equals0D) apply clarsimp apply (drule mp, simp) apply (erule disjE) apply simp apply clarsimp apply (drule_tac a=x in equals0D) apply clarsimp apply (case_tac "p + 1 \ x") apply clarsimp apply (simp add: linorder_not_le) apply (drule plus_one_helper, simp) done lemma projectKO_stateI: "fst (projectKO e s) = {(obj, s)} \ fst (projectKO e s') = {(obj, s')}" unfolding projectKO_def by (auto simp: fail_def return_def valid_def split: option.splits) lemma singleton_in_magnitude_check: "(x, s) \ fst (magnitudeCheck a b c s') \ \s'. fst (magnitudeCheck a b c s') = {(x, s')}" by (simp add: magnitudeCheck_def when_def in_monad return_def split: if_split_asm option.split_asm) lemma wordSizeCase_simp [simp]: "wordSizeCase a b = a" by (simp add: wordSizeCase_def wordBits_def word_size) lemma projectKO_eq: "(fst (projectKO ko c) = {(obj, c)}) = (projectKO_opt ko = Some obj)" by (simp add: projectKO_def fail_def return_def split: option.splits) lemma lookupBefore_None: "(lookupBefore x m = None) = (\y \ x. m y = None)" by (simp add: lookupBefore_def Let_def dom_def, fastforce) lemma lookupBefore_exact: "m x = Some y \ lookupBefore x m = Some (x, y)" apply (simp add: lookupBefore_def Let_def cong: conj_cong) apply (rule context_conjI) apply (rule exI[where x=x]) apply (simp add: domI) apply (rule order_antisym) apply simp apply (rule Max_ge) apply simp apply simp apply (simp add: domI) done lemma obj_at'_def': "obj_at' P p s = (\ko obj. ksPSpace s p = Some ko \ is_aligned p (objBitsKO ko) \ fst (projectKO ko s) = {(obj,s)} \ P obj \ ps_clear p (objBitsKO ko) s)" apply (simp add: obj_at'_real_def ko_wp_at'_def projectKO_eq True_notin_set_replicate_conv objBits_def) apply fastforce done lemma obj_at'_def: "obj_at' P p s \ \ko obj. ksPSpace s p = Some ko \ is_aligned p (objBitsKO ko) \ fst (projectKO ko s) = {(obj,s)} \ P obj \ ps_clear p (objBitsKO ko) s" by (simp add: obj_at'_def') lemma obj_atE' [elim?]: assumes objat: "obj_at' P ptr s" and rl: "\ko obj. \ ksPSpace s ptr = Some ko; is_aligned ptr (objBitsKO ko); fst (projectKO ko s) = {(obj,s)}; P obj; ps_clear ptr (objBitsKO ko) s \ \ R" shows "R" using objat unfolding obj_at'_def by (auto intro!: rl) lemma obj_atI' [intro?]: "\ ksPSpace s ptr = Some ko; is_aligned ptr (objBitsKO ko); fst (projectKO ko s) = {(obj, s)}; P obj; ps_clear ptr (objBitsKO ko) s \ \ obj_at' P ptr s" unfolding obj_at'_def by (auto) lemma cte_at'_def: "cte_at' p s \ \cte::cte. fst (getObject p s) = {(cte,s)}" by (simp add: cte_wp_at'_def) lemma tcb_cte_cases_simps[simp]: "tcb_cte_cases 0 = Some (tcbCTable, tcbCTable_update)" "tcb_cte_cases 16 = Some (tcbVTable, tcbVTable_update)" "tcb_cte_cases 32 = Some (tcbReply, tcbReply_update)" "tcb_cte_cases 48 = Some (tcbCaller, tcbCaller_update)" "tcb_cte_cases 64 = Some (tcbIPCBufferFrame, tcbIPCBufferFrame_update)" by (simp add: tcb_cte_cases_def)+ lemma refs_of'_simps[simp]: "refs_of' (KOTCB tcb) = tcb_st_refs_of' (tcbState tcb) \ tcb_bound_refs' (tcbBoundNotification tcb)" "refs_of' (KOCTE cte) = {}" "refs_of' (KOEndpoint ep) = ep_q_refs_of' ep" "refs_of' (KONotification ntfn) = ntfn_q_refs_of' (ntfnObj ntfn) \ ntfn_bound_refs' (ntfnBoundTCB ntfn)" "refs_of' (KOUserData) = {}" "refs_of' (KOUserDataDevice) = {}" "refs_of' (KOKernelData) = {}" "refs_of' (KOArch ako) = {}" by (auto simp: refs_of'_def) lemma tcb_st_refs_of'_simps[simp]: "tcb_st_refs_of' (Running) = {}" "tcb_st_refs_of' (Inactive) = {}" "tcb_st_refs_of' (Restart) = {}" "\x. tcb_st_refs_of' (BlockedOnReceive x) = {(x, TCBBlockedRecv)}" "\x c. tcb_st_refs_of' (BlockedOnSend x a b c) = {(x, TCBBlockedSend)}" "\x. tcb_st_refs_of' (BlockedOnNotification x) = {(x, TCBSignal)}" "tcb_st_refs_of' (BlockedOnReply) = {}" "tcb_st_refs_of' (IdleThreadState) = {}" by (auto simp: tcb_st_refs_of'_def) lemma ep_q_refs_of'_simps[simp]: "ep_q_refs_of' IdleEP = {}" "ep_q_refs_of' (RecvEP q) = set q \ {EPRecv}" "ep_q_refs_of' (SendEP q) = set q \ {EPSend}" by (auto simp: ep_q_refs_of'_def) lemma ntfn_q_refs_of'_simps[simp]: "ntfn_q_refs_of' IdleNtfn = {}" "ntfn_q_refs_of' (WaitingNtfn q) = set q \ {NTFNSignal}" "ntfn_q_refs_of' (ActiveNtfn b) = {}" by (auto simp: ntfn_q_refs_of'_def) lemma ntfn_bound_refs'_simps[simp]: "ntfn_bound_refs' (Some t) = {(t, NTFNBound)}" "ntfn_bound_refs' None = {}" by (auto simp: ntfn_bound_refs'_def) lemma tcb_bound_refs'_simps[simp]: "tcb_bound_refs' (Some a) = {(a, TCBBound)}" "tcb_bound_refs' None = {}" by (auto simp: tcb_bound_refs'_def) lemma refs_of_rev': "(x, TCBBlockedRecv) \ refs_of' ko = (\tcb. ko = KOTCB tcb \ tcbState tcb = BlockedOnReceive x)" "(x, TCBBlockedSend) \ refs_of' ko = (\tcb. ko = KOTCB tcb \ (\a b c. tcbState tcb = BlockedOnSend x a b c))" "(x, TCBSignal) \ refs_of' ko = (\tcb. ko = KOTCB tcb \ tcbState tcb = BlockedOnNotification x)" "(x, EPRecv) \ refs_of' ko = (\ep. ko = KOEndpoint ep \ (\q. ep = RecvEP q \ x \ set q))" "(x, EPSend) \ refs_of' ko = (\ep. ko = KOEndpoint ep \ (\q. ep = SendEP q \ x \ set q))" "(x, NTFNSignal) \ refs_of' ko = (\ntfn. ko = KONotification ntfn \ (\q. ntfnObj ntfn = WaitingNtfn q \ x \ set q))" "(x, TCBBound) \ refs_of' ko = (\tcb. ko = KOTCB tcb \ (tcbBoundNotification tcb = Some x))" "(x, NTFNBound) \ refs_of' ko = (\ntfn. ko = KONotification ntfn \ (ntfnBoundTCB ntfn = Some x))" by (auto simp: refs_of'_def tcb_st_refs_of'_def ep_q_refs_of'_def ntfn_q_refs_of'_def ntfn_bound_refs'_def tcb_bound_refs'_def split: Structures_H.kernel_object.splits Structures_H.thread_state.splits Structures_H.endpoint.splits Structures_H.notification.splits Structures_H.ntfn.splits)+ lemma ko_wp_at'_weakenE: "\ ko_wp_at' P p s; \ko. P ko \ Q ko \ \ ko_wp_at' Q p s" by (clarsimp simp: ko_wp_at'_def) lemma projectKO_opt_tcbD: "projectKO_opt ko = Some (tcb :: tcb) \ ko = KOTCB tcb" by (cases ko, simp_all add: projectKO_opt_tcb) lemma st_tcb_at_refs_of_rev': "ko_wp_at' (\ko. (x, TCBBlockedRecv) \ refs_of' ko) t s = st_tcb_at' (\ts. ts = BlockedOnReceive x ) t s" "ko_wp_at' (\ko. (x, TCBBlockedSend) \ refs_of' ko) t s = st_tcb_at' (\ts. \a b c. ts = BlockedOnSend x a b c) t s" "ko_wp_at' (\ko. (x, TCBSignal) \ refs_of' ko) t s = st_tcb_at' (\ts. ts = BlockedOnNotification x) t s" by (fastforce simp: refs_of_rev' pred_tcb_at'_def obj_at'_real_def projectKO_opt_tcb[where e="KOTCB y" for y] elim!: ko_wp_at'_weakenE dest!: projectKO_opt_tcbD)+ lemma state_refs_of'_elemD: "\ ref \ state_refs_of' s x \ \ ko_wp_at' (\obj. ref \ refs_of' obj) x s" by (clarsimp simp add: state_refs_of'_def ko_wp_at'_def split: option.splits if_split_asm) lemma state_refs_of'_eqD: "\ state_refs_of' s x = S; S \ {} \ \ ko_wp_at' (\obj. refs_of' obj = S) x s" by (clarsimp simp add: state_refs_of'_def ko_wp_at'_def split: option.splits if_split_asm) lemma obj_at_state_refs_ofD': "obj_at' P p s \ \obj. P obj \ state_refs_of' s p = refs_of' (injectKO obj)" apply (clarsimp simp: obj_at'_real_def project_inject ko_wp_at'_def conj_commute) apply (rule exI, erule conjI) apply (clarsimp simp: state_refs_of'_def) done lemma ko_at_state_refs_ofD': "ko_at' ko p s \ state_refs_of' s p = refs_of' (injectKO ko)" by (clarsimp dest!: obj_at_state_refs_ofD') definition tcb_ntfn_is_bound' :: "word32 option \ tcb \ bool" where "tcb_ntfn_is_bound' ntfn tcb \ tcbBoundNotification tcb = ntfn" lemma st_tcb_at_state_refs_ofD': "st_tcb_at' P t s \ \ts ntfnptr. P ts \ obj_at' (tcb_ntfn_is_bound' ntfnptr) t s \ state_refs_of' s t = (tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr)" by (auto simp: pred_tcb_at'_def tcb_ntfn_is_bound'_def obj_at'_def projectKO_eq project_inject state_refs_of'_def) lemma bound_tcb_at_state_refs_ofD': "bound_tcb_at' P t s \ \ts ntfnptr. P ntfnptr \ obj_at' (tcb_ntfn_is_bound' ntfnptr) t s \ state_refs_of' s t = (tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr)" by (auto simp: pred_tcb_at'_def obj_at'_def tcb_ntfn_is_bound'_def projectKO_eq project_inject state_refs_of'_def) lemma sym_refs_obj_atD': "\ obj_at' P p s; sym_refs (state_refs_of' s) \ \ \obj. P obj \ state_refs_of' s p = refs_of' (injectKO obj) \ (\(x, tp)\refs_of' (injectKO obj). ko_wp_at' (\ko. (p, symreftype tp) \ refs_of' ko) x s)" apply (drule obj_at_state_refs_ofD') apply (erule exEI, clarsimp) apply (drule sym, simp) apply (drule(1) sym_refsD) apply (erule state_refs_of'_elemD) done lemma sym_refs_ko_atD': "\ ko_at' ko p s; sym_refs (state_refs_of' s) \ \ state_refs_of' s p = refs_of' (injectKO ko) \ (\(x, tp)\refs_of' (injectKO ko). ko_wp_at' (\ko. (p, symreftype tp) \ refs_of' ko) x s)" by (drule(1) sym_refs_obj_atD', simp) lemma sym_refs_st_tcb_atD': "\ st_tcb_at' P t s; sym_refs (state_refs_of' s) \ \ \ts ntfnptr. P ts \ obj_at' (tcb_ntfn_is_bound' ntfnptr) t s \ state_refs_of' s t = tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr \ (\(x, tp)\tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr. ko_wp_at' (\ko. (t, symreftype tp) \ refs_of' ko) x s)" apply (drule st_tcb_at_state_refs_ofD') apply (erule exE)+ apply (rule_tac x=ts in exI) apply (rule_tac x=ntfnptr in exI) apply clarsimp apply (frule obj_at_state_refs_ofD') apply (drule (1)sym_refs_obj_atD') apply auto done lemma sym_refs_bound_tcb_atD': "\ bound_tcb_at' P t s; sym_refs (state_refs_of' s) \ \ \ts ntfnptr. P ntfnptr \ obj_at' (tcb_ntfn_is_bound' ntfnptr) t s \ state_refs_of' s t = tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr \ (\(x, tp)\tcb_st_refs_of' ts \ tcb_bound_refs' ntfnptr. ko_wp_at' (\ko. (t, symreftype tp) \ refs_of' ko) x s)" apply (drule bound_tcb_at_state_refs_ofD') apply (erule exE)+ apply (rule_tac x=ts in exI) apply (rule_tac x=ntfnptr in exI) apply clarsimp apply (frule obj_at_state_refs_ofD') apply (drule (1)sym_refs_obj_atD') apply auto done lemma ex_nonz_cap_toE': "\ ex_nonz_cap_to' p s; \cref. cte_wp_at' (\c. p \ zobj_refs' (cteCap c)) cref s \ Q \ \ Q" by (fastforce simp: ex_nonz_cap_to'_def) lemma refs_of_live': "refs_of' ko \ {} \ live' ko" apply (cases ko, simp_all) apply clarsimp apply (rename_tac notification) apply (case_tac "ntfnObj notification"; simp) apply fastforce+ done lemma if_live_then_nonz_capE': "\ if_live_then_nonz_cap' s; ko_wp_at' live' p s \ \ ex_nonz_cap_to' p s" by (fastforce simp: if_live_then_nonz_cap'_def) lemma if_live_then_nonz_capD': assumes x: "if_live_then_nonz_cap' s" "ko_wp_at' P p s" assumes y: "\obj. \ P obj; ksPSpace s p = Some obj; is_aligned p (objBitsKO obj) \ \ live' obj" shows "ex_nonz_cap_to' p s" using x by (clarsimp elim!: if_live_then_nonz_capE' y simp: ko_wp_at'_def) lemma if_live_state_refsE: "\ if_live_then_nonz_cap' s; state_refs_of' s p \ {} \ \ ex_nonz_cap_to' p s" by (clarsimp simp: state_refs_of'_def ko_wp_at'_def split: option.splits if_split_asm elim!: refs_of_live' if_live_then_nonz_capE') lemmas ex_cte_cap_to'_def = ex_cte_cap_wp_to'_def lemma if_unsafe_then_capD': "\ cte_wp_at' P p s; if_unsafe_then_cap' s; \cte. P cte \ cteCap cte \ NullCap \ \ ex_cte_cap_to' p s" unfolding if_unsafe_then_cap'_def apply (erule allE, erule mp) apply (clarsimp simp: cte_wp_at'_def) done lemmas valid_cap_simps' = valid_cap'_def[split_simps capability.split arch_capability.split] lemma max_ipc_words: "max_ipc_words = 0x80" unfolding max_ipc_words_def by (simp add: msgMaxLength_def msgLengthBits_def msgMaxExtraCaps_def msgExtraCapBits_def capTransferDataSize_def) lemma valid_objsI' [intro]: "(\obj x. ksPSpace s x = Some obj \ valid_obj' obj s) \ valid_objs' s" unfolding valid_objs'_def by (auto elim: ranE) lemma valid_objsE' [elim]: "\ valid_objs' s; ksPSpace s x = Some obj; valid_obj' obj s \ R \ \ R" unfolding valid_objs'_def by auto lemma pspace_distinctD': "\ ksPSpace s x = Some v; pspace_distinct' s \ \ ps_clear x (objBitsKO v) s" apply (simp add: pspace_distinct'_def) apply (drule bspec, erule domI) apply simp done lemma pspace_alignedD': "\ ksPSpace s x = Some v; pspace_aligned' s \ \ is_aligned x (objBitsKO v)" apply (simp add: pspace_aligned'_def) apply (drule bspec, erule domI) apply simp done lemma next_unfold: "mdb_next s c = (case s c of Some cte \ Some (mdbNext (cteMDBNode cte)) | None \ None)" by (simp add: mdb_next_def split: option.split) lemma is_physical_cases: "(capClass cap = PhysicalClass) = (case cap of NullCap \ False | DomainCap \ False | IRQControlCap \ False | IRQHandlerCap irq \ False | ReplyCap r m \ False | ArchObjectCap ASIDControlCap \ False | _ \ True)" by (simp split: capability.splits arch_capability.splits zombie_type.splits) lemma sch_act_sane_not: "sch_act_sane s = sch_act_not (ksCurThread s) s" by (auto simp: sch_act_sane_def) lemma objBits_cte_conv: "objBits (cte :: cte) = cteSizeBits" by (simp add: objBits_def objBitsKO_def wordSizeCase_def word_size) lemma valid_pde_mapping'_simps[simp]: "valid_pde_mapping' offset (InvalidPDE) = True" "valid_pde_mapping' offset (SectionPDE ptr a b c d e w) = valid_pde_mapping_offset' offset" "valid_pde_mapping' offset (SuperSectionPDE ptr a' b' c' d' w) = valid_pde_mapping_offset' offset" "valid_pde_mapping' offset (PageTablePDE ptr x z'') = valid_pde_mapping_offset' offset" by (clarsimp simp: valid_pde_mapping'_def)+ lemmas valid_irq_states'_def = valid_irq_masks'_def lemma valid_pspaceI' [intro]: "\valid_objs' s; pspace_aligned' s; pspace_distinct' s; valid_mdb' s; no_0_obj' s\ \ valid_pspace' s" unfolding valid_pspace'_def by simp lemma valid_pspaceE' [elim]: "\valid_pspace' s; \ valid_objs' s; pspace_aligned' s; pspace_distinct' s; no_0_obj' s; valid_mdb' s\ \ R \ \ R" unfolding valid_pspace'_def by simp lemma idle'_no_refs: "valid_idle' s \ state_refs_of' s (ksIdleThread s) = {}" by (clarsimp simp: valid_idle'_def pred_tcb_at'_def obj_at'_def tcb_ntfn_is_bound'_def projectKO_eq project_inject state_refs_of'_def) lemma idle'_not_queued': "\valid_idle' s; sym_refs (state_refs_of' s); state_refs_of' s ptr = insert t queue \ {rt}\\ ksIdleThread s \ queue" by (frule idle'_no_refs, fastforce simp: valid_idle'_def sym_refs_def) lemma idle'_not_queued: "\valid_idle' s; sym_refs (state_refs_of' s); state_refs_of' s ptr = queue \ {rt}\ \ ksIdleThread s \ queue" by (frule idle'_no_refs, fastforce simp: valid_idle'_def sym_refs_def) lemma obj_at_conj': "\ obj_at' P p s; obj_at' Q p s \ \ obj_at' (\k. P k \ Q k) p s" by (auto simp: obj_at'_def) lemma pred_tcb_at_conj': "\ pred_tcb_at' proj P t s; pred_tcb_at' proj Q t s \ \ pred_tcb_at' proj (\a. P a \ Q a) t s" apply (simp add: pred_tcb_at'_def) apply (erule (1) obj_at_conj') done lemma obj_at_False' [simp]: "obj_at' (\k. False) t s = False" by (simp add: obj_at'_def) lemma pred_tcb_at_False' [simp]: "pred_tcb_at' proj (\st. False) t s = False" by (simp add: pred_tcb_at'_def obj_at'_def) lemma obj_at'_pspaceI: "obj_at' t ref s \ ksPSpace s = ksPSpace s' \ obj_at' t ref s'" by (auto intro!: projectKO_stateI simp: obj_at'_def ps_clear_def) lemma cte_wp_at'_pspaceI: "\cte_wp_at' P p s; ksPSpace s = ksPSpace s'\ \ cte_wp_at' P p s'" apply (clarsimp simp add: cte_wp_at'_def getObject_def) apply (drule equalityD2) apply (clarsimp simp: in_monad loadObject_cte gets_def get_def bind_def return_def split_def) apply (case_tac b) apply (simp_all add: in_monad typeError_def) prefer 2 apply (simp add: in_monad return_def alignError_def assert_opt_def alignCheck_def magnitudeCheck_def when_def bind_def split: if_split_asm option.splits) apply (clarsimp simp: in_monad return_def alignError_def fail_def assert_opt_def alignCheck_def bind_def when_def objBits_cte_conv tcbCTableSlot_def tcbVTableSlot_def tcbReplySlot_def cteSizeBits_def split: if_split_asm dest!: singleton_in_magnitude_check) done lemma valid_untyped'_pspaceI: "\ksPSpace s = ksPSpace s'; valid_untyped' d p n idx s\ \ valid_untyped' d p n idx s'" by (simp add: valid_untyped'_def ko_wp_at'_def ps_clear_def) lemma typ_at'_pspaceI: "typ_at' T p s \ ksPSpace s = ksPSpace s' \ typ_at' T p s'" by (simp add: typ_at'_def ko_wp_at'_def ps_clear_def) lemma valid_cap'_pspaceI: "s \' cap \ ksPSpace s = ksPSpace s' \ s' \' cap" unfolding valid_cap'_def by (cases cap) (force intro: obj_at'_pspaceI[rotated] cte_wp_at'_pspaceI valid_untyped'_pspaceI typ_at'_pspaceI[rotated] simp: page_table_at'_def page_directory_at'_def split: arch_capability.split zombie_type.split option.splits)+ lemma valid_arch_obj'_pspaceI: "valid_arch_obj' obj s \ ksPSpace s = ksPSpace s' \ valid_arch_obj' obj s'" apply (cases obj; simp) apply (rename_tac asidpool) apply (case_tac asidpool, auto simp: page_directory_at'_def intro: typ_at'_pspaceI[rotated])[1] apply (rename_tac pte) apply (case_tac pte; simp add: valid_mapping'_def) apply (rename_tac pde) apply (case_tac pde; auto simp: page_table_at'_def valid_mapping'_def intro: typ_at'_pspaceI[rotated]) done lemma valid_obj'_pspaceI: "valid_obj' obj s \ ksPSpace s = ksPSpace s' \ valid_obj' obj s'" unfolding valid_obj'_def by (cases obj) (auto simp: valid_ep'_def valid_ntfn'_def valid_tcb'_def valid_cte'_def valid_tcb_state'_def valid_arch_obj'_pspaceI valid_bound_tcb'_def valid_bound_ntfn'_def split: Structures_H.endpoint.splits Structures_H.notification.splits Structures_H.thread_state.splits ntfn.splits option.splits intro: obj_at'_pspaceI valid_cap'_pspaceI) lemma valid_objs'_pspaceI: "\valid_objs' s; ksPSpace s = ksPSpace s'\ \ valid_objs' s'" by (auto simp: valid_objs'_def intro: valid_obj'_pspaceI) lemma pred_tcb_at'_pspaceI: "pred_tcb_at' proj P t s \ ksPSpace s = ksPSpace s' \ pred_tcb_at' proj P t s'" unfolding pred_tcb_at'_def by (fast intro: obj_at'_pspaceI) lemma valid_mdb'_pspaceI: "valid_mdb' s \ ksPSpace s = ksPSpace s' \ valid_mdb' s'" unfolding valid_mdb'_def by simp lemma state_refs_of'_pspaceI: "P (state_refs_of' s) \ ksPSpace s = ksPSpace s' \ P (state_refs_of' s')" unfolding state_refs_of'_def ps_clear_def by simp lemma if_live_then_nonz_cap'_pspaceI: "if_live_then_nonz_cap' s \ ksPSpace s = ksPSpace s' \ if_live_then_nonz_cap' s'" unfolding if_live_then_nonz_cap'_def ex_nonz_cap_to'_def apply (simp add: ko_wp_at'_def ps_clear_def) apply (erule allEI) apply (fastforce intro: cte_wp_at'_pspaceI) done lemma no_0_obj_pspaceI: "no_0_obj' s \ ksPSpace s = ksPSpace s' \ no_0_obj' s'" by (simp add: no_0_obj'_def) lemma valid_pspace': "valid_pspace' s \ ksPSpace s = ksPSpace s' \ valid_pspace' s'" by (auto simp add: valid_pspace'_def valid_objs'_def pspace_aligned'_def pspace_distinct'_def ps_clear_def no_0_obj'_def ko_wp_at'_def typ_at'_def intro: valid_obj'_pspaceI valid_mdb'_pspaceI) lemma ex_cte_cap_to_pspaceI'[elim]: "ex_cte_cap_to' p s \ ksPSpace s = ksPSpace s' \ intStateIRQNode (ksInterruptState s) = intStateIRQNode (ksInterruptState s') \ ex_cte_cap_to' p s'" by (fastforce simp: ex_cte_cap_to'_def elim: cte_wp_at'_pspaceI) lemma ifunsafe_valid_pspaceI'[elim]: "if_unsafe_then_cap' s \ ksPSpace s = ksPSpace s' \ intStateIRQNode (ksInterruptState s) = intStateIRQNode (ksInterruptState s') \ if_unsafe_then_cap' s'" by (fastforce simp: if_unsafe_then_cap'_def intro: cte_wp_at'_pspaceI) lemma valid_idle'_pspace_itI[elim]: "\ valid_idle' s; ksPSpace s = ksPSpace s'; ksIdleThread s = ksIdleThread s' \ \ valid_idle' s'" apply (clarsimp simp: valid_idle'_def ex_nonz_cap_to'_def) apply (erule pred_tcb_at'_pspaceI, assumption) done lemma obj_at'_weaken: assumes x: "obj_at' P t s" assumes y: "\obj. P obj \ P' obj" shows "obj_at' P' t s" by (insert x, clarsimp simp: obj_at'_def y) lemma cte_wp_at_weakenE': "\cte_wp_at' P t s; \c. P c \ P' c\ \ cte_wp_at' P' t s" by (fastforce simp: cte_wp_at'_def) lemma obj_at'_weakenE: "\ obj_at' P p s; \k. P k \ P' k \ \ obj_at' P' p s" by (clarsimp simp: obj_at'_def) lemma pred_tcb'_weakenE: "\ pred_tcb_at' proj P t s; \st. P st \ P' st \ \ pred_tcb_at' proj P' t s" apply (simp add: pred_tcb_at'_def) apply (erule obj_at'_weakenE) apply clarsimp done lemma lookupBefore_fst_snd: "lookupBefore x s = Some v \ snd v = the (s (fst v))" by (clarsimp simp add: lookupBefore_def Let_def split: if_split_asm) lemma lookupBefore_exact2: "\ lookupBefore x s = Some v; fst v = x \ \ s x = Some (snd v)" apply (cases v) apply (clarsimp simp add: lookupBefore_def Let_def split: if_split_asm) apply (drule subst[where P="\x. x \ y" for y, OF _ Max_in]) apply simp apply fastforce apply clarsimp done lemma lookupBefore_char: "(lookupBefore x s = Some (y, v)) = (y \ x \ s y = Some v \ (\z. z \ x \ y < z \ s z = None))" apply (simp add: lookupBefore_def Let_def cong: conj_cong) apply (rule conjI) apply (clarsimp simp: dom_def) apply clarsimp apply (rule iffI) apply (erule conjE) apply (frule subst[where P="\x. x \ y'" for y', OF _ Max_in]) apply simp apply fastforce apply clarsimp apply (rule ccontr, clarsimp) apply (subst(asm) Max_less_iff) apply simp apply fastforce apply (drule_tac x=z in bspec) apply fastforce apply simp apply clarsimp apply (rule order_antisym) apply (subst Max_le_iff) apply simp apply fastforce apply fastforce apply (rule Max_ge) apply simp apply fastforce done lemma lookupAround2_char1: "(fst (lookupAround2 x s) = Some (y, v)) = (y \ x \ s y = Some v \ (\z. y < z \ z \ x \ s z = None))" apply (simp add: lookupAround2_def Let_def split_def lookupAround_def split del: if_split split: option.split) apply (intro conjI impI iffI) apply (clarsimp split: if_split_asm) apply (rule Max_prop) apply (simp add: order_less_imp_le) apply fastforce apply (clarsimp split: if_split_asm) apply (rule Max_prop) apply clarsimp apply fastforce apply (clarsimp split: if_split_asm) apply (subst(asm) Max_less_iff) apply simp apply fastforce apply (fastforce intro: order_neq_le_trans) apply (clarsimp cong: conj_cong) apply (rule conjI) apply fastforce apply (rule order_antisym) apply (subst Max_le_iff) apply simp apply fastforce apply clarsimp apply (rule ccontr) apply (fastforce simp add: linorder_not_le) apply (rule Max_ge) apply simp apply fastforce apply (intro allI impI iffI) apply clarsimp apply simp apply clarsimp apply (drule spec[where x=x]) apply simp done lemma lookupAround2_None1: "(fst (lookupAround2 x s) = None) = (\y \ x. s y = None)" apply (simp add: lookupAround2_def Let_def split_def lookupAround_def split del: if_split split: option.split) apply safe apply (fastforce split: if_split_asm) apply (clarsimp simp: order_less_imp_le) apply fastforce done lemma lookupAround2_None2: "(snd (lookupAround2 x s) = None) = (\y. x < y \ s y = None)" apply (simp add: lookupAround2_def Let_def split_def del: maybe_def split: option.splits) apply (simp add: o_def map_option_is_None [where f=fst, unfolded map_option_case]) apply (simp add: lookupAround_def Let_def) apply fastforce done lemma lookupAround2_char2: "(snd (lookupAround2 x s) = Some y) = (x < y \ s y \ None \ (\z. x < z \ z < y \ s z = None))" apply (simp add: lookupAround2_def Let_def split_def o_def del: maybe_def split: option.splits) apply (simp add: o_def map_option_is_None [where f=fst, unfolded map_option_case]) apply (simp add: lookupAround_def Let_def) apply (rule conjI) apply fastforce apply clarsimp apply (rule iffI) apply (frule subst[where P="\x. x \ y2" for y2, OF _ Min_in]) apply simp apply fastforce apply clarsimp apply (subst(asm) Min_gr_iff, simp, fastforce, simp(no_asm_use), fastforce) apply clarsimp apply (rule order_antisym) apply (fastforce intro: Min_le) apply (subst Min_ge_iff) apply simp apply fastforce apply clarsimp apply (rule ccontr, simp add: linorder_not_le) done lemma ps_clearI: "\ is_aligned p n; (1 :: word32) < 2 ^ n; \x. \ x > p; x \ p + 2 ^ n - 1 \ \ ksPSpace s x = None \ \ ps_clear p n s" apply (subgoal_tac "p \ p + 1") apply (simp add: ps_clear_def2) apply (rule ccontr, erule nonemptyE, clarsimp) apply (drule minus_one_helper[where x="z + 1" for z]) apply clarsimp apply simp apply (erule is_aligned_get_word_bits) apply (erule(1) is_aligned_no_wrap') apply simp done lemma ps_clear_lookupAround2: "\ ps_clear p' n s; ksPSpace s p' = Some x; p' \ p; p \ p' + 2 ^ n - 1; \ fst (lookupAround2 p (ksPSpace s)) = Some (p', x); case_option True (\x. x - p' >= 2 ^ n) (snd (lookupAround2 p (ksPSpace s))) \ \ P (lookupAround2 p (ksPSpace s)) \ \ P (lookupAround2 p (ksPSpace s))" apply (drule meta_mp) apply (cases "fst (lookupAround2 p (ksPSpace s))") apply (simp add: lookupAround2_None1) apply clarsimp apply (clarsimp simp: lookupAround2_char1) apply (frule spec[where x=p']) apply (simp add: linorder_not_less ps_clear_def) apply (drule_tac f="\S. a \ S" in arg_cong) apply (simp add: domI) apply (frule(1) order_trans, simp) apply (erule meta_mp) apply (clarsimp split: option.split) apply (clarsimp simp: lookupAround2_char2 ps_clear_def) apply (drule_tac a=x2 in equals0D) apply (simp add: domI) apply (subst(asm) order_less_imp_le[OF order_le_less_trans[where y=p]], assumption, assumption) apply simp apply (erule impCE, simp_all) apply (simp add: linorder_not_le) apply (subst(asm) add_diff_eq[symmetric], subst(asm) add.commute, drule word_l_diffs(2), fastforce simp only: field_simps) apply (rule ccontr, simp add: linorder_not_le) apply (drule minus_one_helper3, fastforce) done lemma in_magnitude_check: "\ is_aligned x n; (1 :: word32) < 2 ^ n; ksPSpace s x = Some y \ \ ((v, s') \ fst (magnitudeCheck x (snd (lookupAround2 x (ksPSpace s))) n s)) = (s' = s \ ps_clear x n s)" apply (rule iffI) apply (clarsimp simp: magnitudeCheck_def in_monad lookupAround2_None2 lookupAround2_char2 split: option.split_asm) apply (erule(1) ps_clearI) apply simp apply (erule(1) ps_clearI) apply (simp add: linorder_not_less) apply (drule minus_one_helper[where x="2 ^ n"]) apply (clarsimp simp: power_overflow) apply (drule word_l_diffs) apply simp apply (simp add: field_simps) apply clarsimp apply (erule is_aligned_get_word_bits) apply (erule(1) ps_clear_lookupAround2) apply simp apply (simp add: is_aligned_no_overflow) apply (clarsimp simp add: magnitudeCheck_def in_monad split: option.split_asm) apply simp apply (simp add: power_overflow) done lemma in_magnitude_check3: "\ \z. x < z \ z \ y \ ksPSpace s z = None; is_aligned x n; (1 :: word32) < 2 ^ n; ksPSpace s x = Some v; x \ y; y - x < 2 ^ n \ \ fst (magnitudeCheck x (snd (lookupAround2 y (ksPSpace s))) n s) = (if ps_clear x n s then {((), s)} else {})" apply (rule set_eqI, rule iffI) apply (clarsimp simp: magnitudeCheck_def lookupAround2_char2 lookupAround2_None2 in_monad split: option.split_asm) apply (drule(1) range_convergence1) apply (erule(1) ps_clearI) apply simp apply (erule is_aligned_get_word_bits) apply (drule(1) range_convergence2) apply (erule(1) ps_clearI) apply (simp add: linorder_not_less) apply (drule minus_one_helper[where x="2 ^ n" for n], simp) apply (drule word_l_diffs, simp) apply (simp add: field_simps) apply (simp add: power_overflow) apply (clarsimp split: if_split_asm) apply (erule(1) ps_clear_lookupAround2) apply simp apply (drule minus_one_helper3[where x="y - x"]) apply (drule word_plus_mono_right[where x=x and y="y - x"]) apply (erule is_aligned_get_word_bits) apply (simp add: field_simps is_aligned_no_overflow) apply simp apply (simp add: field_simps) apply (simp add: magnitudeCheck_def return_def iffD2[OF linorder_not_less] when_def split: option.split_asm) done lemma in_alignCheck[simp]: "((v, s') \ fst (alignCheck x n s)) = (s' = s \ is_aligned x n)" by (simp add: alignCheck_def in_monad is_aligned_mask[symmetric] alignError_def conj_comms cong: conj_cong) lemma tcb_space_clear: "\ tcb_cte_cases (y - x) = Some (getF, setF); is_aligned x tcbBlockSizeBits; ps_clear x tcbBlockSizeBits s; ksPSpace s x = Some (KOTCB tcb); ksPSpace s y = Some v; \ x = y; getF = tcbCTable; setF = tcbCTable_update \ \ P \ \ P" apply (cases "x = y") apply simp apply (clarsimp simp: ps_clear_def) apply (drule_tac a=y in equals0D) apply (simp add: domI) apply (subgoal_tac "\z. y = x + z \ z < 2 ^ tcbBlockSizeBits") apply (elim exE conjE) apply (frule(1) is_aligned_no_wrap'[rotated, rotated]) apply (simp add: word_bits_conv objBits_defs) apply (erule notE, subst field_simps, rule word_plus_mono_right) apply (drule minus_one_helper3,simp,erule is_aligned_no_wrap') apply (simp add: word_bits_conv) apply (simp add: objBits_defs) apply (rule_tac x="y - x" in exI) apply (simp add: tcb_cte_cases_def split: if_split_asm) done lemma tcb_ctes_clear: "\ tcb_cte_cases (y - x) = Some (getF, setF); is_aligned x tcbBlockSizeBits; ps_clear x tcbBlockSizeBits s; ksPSpace s x = Some (KOTCB tcb) \ \ \ ksPSpace s y = Some (KOCTE cte)" apply clarsimp apply (erule(4) tcb_space_clear) apply simp done lemma cte_wp_at_cases': shows "cte_wp_at' P p s = ((\cte. ksPSpace s p = Some (KOCTE cte) \ is_aligned p cte_level_bits \ P cte \ ps_clear p cteSizeBits s) \ (\n tcb getF setF. ksPSpace s (p - n) = Some (KOTCB tcb) \ is_aligned (p - n) tcbBlockSizeBits \ tcb_cte_cases n = Some (getF, setF) \ P (getF tcb) \ ps_clear (p - n) tcbBlockSizeBits s))" (is "?LHS = ?RHS") apply (rule iffI) apply (clarsimp simp: cte_wp_at'_def split_def getObject_def bind_def simpler_gets_def assert_opt_def return_def fail_def split: option.splits del: disjCI) apply (clarsimp simp: loadObject_cte typeError_def alignError_def fail_def return_def objBits_simps' is_aligned_mask[symmetric] alignCheck_def tcbVTableSlot_def field_simps tcbCTableSlot_def tcbReplySlot_def tcbCallerSlot_def tcbIPCBufferSlot_def lookupAround2_char1 cte_level_bits_def Ball_def unless_def when_def bind_def split: kernel_object.splits if_split_asm option.splits del: disjCI) apply (subst(asm) in_magnitude_check3, simp+, simp split: if_split_asm, (rule disjI2)?, intro exI, rule conjI, erule rsubst[where P="\x. ksPSpace s x = v" for s v], fastforce simp add: field_simps, simp)+ apply (subst(asm) in_magnitude_check3, simp+) apply (simp split: if_split_asm) apply (simp add: cte_wp_at'_def getObject_def split_def bind_def simpler_gets_def return_def assert_opt_def fail_def objBits_simps' split: option.splits) apply (elim disjE conjE exE) apply (erule(1) ps_clear_lookupAround2) apply simp apply (simp add: field_simps) apply (erule is_aligned_no_wrap') apply (simp add: cte_level_bits_def word_bits_conv) apply (simp add: cte_level_bits_def) apply (simp add: loadObject_cte unless_def alignCheck_def is_aligned_mask[symmetric] objBits_simps' cte_level_bits_def magnitudeCheck_def return_def fail_def) apply (clarsimp simp: bind_def return_def when_def fail_def split: option.splits) apply simp apply (erule(1) ps_clear_lookupAround2) prefer 3 apply (simp add: loadObject_cte unless_def alignCheck_def is_aligned_mask[symmetric] objBits_simps' cte_level_bits_def magnitudeCheck_def return_def fail_def tcbCTableSlot_def tcbVTableSlot_def tcbIPCBufferSlot_def tcbReplySlot_def tcbCallerSlot_def split: option.split_asm) apply (clarsimp simp: bind_def tcb_cte_cases_def split: if_split_asm) apply (clarsimp simp: bind_def tcb_cte_cases_def iffD2[OF linorder_not_less] when_False return_def split: if_split_asm) apply (subgoal_tac "p - n \ (p - n) + n", simp) apply (erule is_aligned_no_wrap') apply (simp add: word_bits_conv) apply (simp add: tcb_cte_cases_def split: if_split_asm) apply (subgoal_tac "(p - n) + n \ (p - n) + 511") apply (simp add: field_simps) apply (rule word_plus_mono_right) apply (simp add: tcb_cte_cases_def split: if_split_asm) apply (erule is_aligned_no_wrap') apply simp done lemma tcb_at_cte_at': "tcb_at' t s \ cte_at' t s" apply (clarsimp simp add: cte_wp_at_cases' obj_at'_def projectKO_def del: disjCI) apply (case_tac ko) apply (simp_all add: projectKO_opt_tcb fail_def) apply (rule exI[where x=0]) apply (clarsimp simp add: return_def objBits_simps) done lemma cte_wp_atE' [consumes 1, case_names CTE TCB]: assumes cte: "cte_wp_at' P ptr s" and r1: "\cte. \ ksPSpace s ptr = Some (KOCTE cte); ps_clear ptr cte_level_bits s; is_aligned ptr cte_level_bits; P cte \ \ R" and r2: "\ tcb ptr' getF setF. \ ksPSpace s ptr' = Some (KOTCB tcb); ps_clear ptr' tcbBlockSizeBits s; is_aligned ptr' tcbBlockSizeBits; tcb_cte_cases (ptr - ptr') = Some (getF, setF); P (getF tcb) \ \ R" shows "R" by (rule disjE [OF iffD1 [OF cte_wp_at_cases' cte]]) (auto intro: r1 r2 simp: cte_level_bits_def objBits_defs) lemma cte_wp_at_cteI': assumes "ksPSpace s ptr = Some (KOCTE cte)" assumes "is_aligned ptr cte_level_bits" assumes "ps_clear ptr cte_level_bits s" assumes "P cte" shows "cte_wp_at' P ptr s" using assms by (simp add: cte_wp_at_cases' cte_level_bits_def objBits_defs) lemma cte_wp_at_tcbI': assumes "ksPSpace s ptr' = Some (KOTCB tcb)" assumes "is_aligned ptr' tcbBlockSizeBits" assumes "ps_clear ptr' tcbBlockSizeBits s" and "tcb_cte_cases (ptr - ptr') = Some (getF, setF)" and "P (getF tcb)" shows "cte_wp_at' P ptr s" using assms apply (simp add: cte_wp_at_cases') apply (rule disjI2, rule exI[where x="ptr - ptr'"]) apply simp done lemma obj_at_ko_at': "obj_at' P p s \ \ko. ko_at' ko p s \ P ko" by (auto simp add: obj_at'_def) lemma obj_at_aligned': fixes P :: "('a :: pspace_storable) \ bool" assumes oat: "obj_at' P p s" and oab: "\(v :: 'a) (v' :: 'a). objBits v = objBits v'" shows "is_aligned p (objBits (obj :: 'a))" using oat apply (clarsimp simp add: obj_at'_def) apply (clarsimp simp add: projectKO_def fail_def return_def project_inject objBits_def[symmetric] split: option.splits) apply (erule subst[OF oab]) done (* locateSlot *) lemma locateSlot_conv: "locateSlotBasic A B = return (A + 2 ^ cte_level_bits * B)" "locateSlotTCB = locateSlotBasic" "locateSlotCNode A bits B = (do x \ stateAssert (\s. case (gsCNodes s A) of None \ False | Some n \ n = bits \ B < 2 ^ n) []; locateSlotBasic A B od)" "locateSlotCap c B = (do x \ stateAssert (\s. ((isCNodeCap c \ (isZombie c \ capZombieType c \ ZombieTCB)) \ (case gsCNodes s (capUntypedPtr c) of None \ False | Some n \ (isCNodeCap c \ n = capCNodeBits c \ isZombie c \ n = zombieCTEBits (capZombieType c)) \ B < 2 ^ n)) \ isThreadCap c \ (isZombie c \ capZombieType c = ZombieTCB)) []; locateSlotBasic (capUntypedPtr c) B od)" apply (simp_all add: locateSlotCap_def locateSlotTCB_def fun_eq_iff) apply (simp add: locateSlotBasic_def objBits_simps cte_level_bits_def objBits_defs) apply (simp add: locateSlotCNode_def stateAssert_def) apply (cases c, simp_all add: locateSlotCNode_def isZombie_def isThreadCap_def isCNodeCap_def capUntypedPtr_def stateAssert_def bind_assoc exec_get locateSlotTCB_def objBits_simps' split: zombie_type.split) done lemma typ_at_tcb': "typ_at' TCBT = tcb_at'" apply (rule ext)+ apply (simp add: obj_at'_real_def typ_at'_def) apply (simp add: ko_wp_at'_def) apply (rule iffI) apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_tcb)[9] apply (case_tac ko) apply (auto simp: projectKO_opt_tcb) done lemma typ_at_ep: "typ_at' EndpointT = ep_at'" apply (rule ext)+ apply (simp add: obj_at'_real_def typ_at'_def) apply (simp add: ko_wp_at'_def) apply (rule iffI) apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_ep)[9] apply (case_tac ko) apply (auto simp: projectKO_opt_ep) done lemma typ_at_ntfn: "typ_at' NotificationT = ntfn_at'" apply (rule ext)+ apply (simp add: obj_at'_real_def typ_at'_def) apply (simp add: ko_wp_at'_def) apply (rule iffI) apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_ntfn)[8] apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_ntfn) done lemma typ_at_cte: "typ_at' CTET = real_cte_at'" apply (rule ext)+ apply (simp add: obj_at'_real_def typ_at'_def) apply (simp add: ko_wp_at'_def) apply (rule iffI) apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_cte)[8] apply clarsimp apply (case_tac ko) apply (auto simp: projectKO_opt_cte) done lemma cte_at_typ': "cte_at' c = (\s. typ_at' CTET c s \ (\n. typ_at' TCBT (c - n) s \ n \ dom tcb_cte_cases))" proof - have P: "\ko. (koTypeOf ko = CTET) = (\cte. ko = KOCTE cte)" "\ko. (koTypeOf ko = TCBT) = (\tcb. ko = KOTCB tcb)" by (case_tac ko, simp_all)+ have Q: "\P f. (\x. (\y. x = f y) \ P x) = (\y. P (f y))" by fastforce show ?thesis by (fastforce simp: cte_wp_at_cases' obj_at'_real_def typ_at'_def ko_wp_at'_def objBits_simps' P Q conj_comms cte_level_bits_def) qed lemma typ_at_lift_tcb': "\typ_at' TCBT p\ f \\_. typ_at' TCBT p\ \ \tcb_at' p\ f \\_. tcb_at' p\" by (simp add: typ_at_tcb') lemma typ_at_lift_ep': "\typ_at' EndpointT p\ f \\_. typ_at' EndpointT p\ \ \ep_at' p\ f \\_. ep_at' p\" by (simp add: typ_at_ep) lemma typ_at_lift_ntfn': "\typ_at' NotificationT p\ f \\_. typ_at' NotificationT p\ \ \ntfn_at' p\ f \\_. ntfn_at' p\" by (simp add: typ_at_ntfn) lemma typ_at_lift_cte': "\typ_at' CTET p\ f \\_. typ_at' CTET p\ \ \real_cte_at' p\ f \\_. real_cte_at' p\" by (simp add: typ_at_cte) lemma typ_at_lift_cte_at': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\cte_at' c\ f \\rv. cte_at' c\" apply (simp only: cte_at_typ') apply (wp hoare_vcg_disj_lift hoare_vcg_ex_lift x) done lemma typ_at_lift_page_directory_at': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\page_directory_at' p\ f \\rv. page_directory_at' p\" unfolding page_directory_at'_def All_less_Ball by (wp hoare_vcg_const_Ball_lift x) lemma typ_at_lift_page_table_at': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\page_table_at' p\ f \\rv. page_table_at' p\" unfolding page_table_at'_def All_less_Ball by (wp hoare_vcg_const_Ball_lift x) lemma ko_wp_typ_at': "ko_wp_at' P p s \ \T. typ_at' T p s" by (clarsimp simp: typ_at'_def ko_wp_at'_def) lemma koType_obj_range': "koTypeOf k = koTypeOf k' \ obj_range' p k = obj_range' p k'" apply (rule ccontr) apply (simp add: obj_range'_def objBitsKO_def archObjSize_def split: kernel_object.splits arch_kernel_object.splits) done lemma typ_at_lift_valid_untyped': assumes P: "\T p. \\s. \typ_at' T p s\ f \\rv s. \typ_at' T p s\" shows "\\s. valid_untyped' d p n idx s\ f \\rv s. valid_untyped' d p n idx s\" apply (clarsimp simp: valid_untyped'_def split del:if_split) apply (rule hoare_vcg_all_lift) apply (clarsimp simp: valid_def split del:if_split) apply (frule ko_wp_typ_at') apply clarsimp apply (cut_tac T=T and p=ptr' in P) apply (simp add: valid_def) apply (erule_tac x=s in allE) apply (erule impE) prefer 2 apply (drule (1) bspec) apply simp apply (clarsimp simp: typ_at'_def ko_wp_at'_def simp del:atLeastAtMost_iff) apply (elim disjE) apply (clarsimp simp:psubset_eq simp del:atLeastAtMost_iff) apply (drule_tac p=ptr' in koType_obj_range') apply (erule impE) apply simp apply simp apply (drule_tac p = ptr' in koType_obj_range') apply (clarsimp split:if_splits) done lemma typ_at_lift_asid_at': "(\T p. \typ_at' T p\ f \\_. typ_at' T p\) \ \asid_pool_at' p\ f \\_. asid_pool_at' p\" by assumption lemma typ_at_lift_valid_cap': assumes P: "\P T p. \\s. P (typ_at' T p s)\ f \\rv s. P (typ_at' T p s)\" shows "\\s. valid_cap' cap s\ f \\rv s. valid_cap' cap s\" including no_pre apply (simp add: valid_cap'_def) apply wp apply (case_tac cap; simp add: valid_cap'_def P [where P=id, simplified] typ_at_lift_tcb' hoare_vcg_prop typ_at_lift_ep' typ_at_lift_ntfn' typ_at_lift_cte_at' hoare_vcg_conj_lift [OF typ_at_lift_cte_at']) apply (rename_tac zombie_type nat) apply (case_tac zombie_type; simp) apply (wp typ_at_lift_tcb' P hoare_vcg_all_lift typ_at_lift_cte')+ apply (rename_tac arch_capability) apply (case_tac arch_capability, simp_all add: P [where P=id, simplified] page_table_at'_def hoare_vcg_prop page_directory_at'_def All_less_Ball split del: if_splits) apply (wp hoare_vcg_const_Ball_lift P typ_at_lift_valid_untyped' hoare_vcg_all_lift typ_at_lift_cte')+ done lemma typ_at_lift_valid_irq_node': assumes P: "\P T p. \\s. P (typ_at' T p s)\ f \\rv s. P (typ_at' T p s)\" shows "\valid_irq_node' p\ f \\_. valid_irq_node' p\" apply (simp add: valid_irq_node'_def) apply (wp hoare_vcg_all_lift P typ_at_lift_cte') done lemma valid_pde_lift': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\\s. valid_pde' pde s\ f \\rv s. valid_pde' pde s\" by (cases pde) (simp add: valid_mapping'_def|wp x typ_at_lift_page_table_at')+ lemma valid_pte_lift': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\\s. valid_pte' pte s\ f \\rv s. valid_pte' pte s\" by (cases pte) (simp add: valid_mapping'_def|wp x typ_at_lift_page_directory_at')+ lemma valid_asid_pool_lift': assumes x: "\T p. \typ_at' T p\ f \\rv. typ_at' T p\" shows "\\s. valid_asid_pool' ap s\ f \\rv s. valid_asid_pool' ap s\" by (cases ap) (simp|wp x typ_at_lift_page_directory_at' hoare_vcg_const_Ball_lift)+ lemma valid_bound_tcb_lift: "(\T p. \typ_at' T p\ f \\_. typ_at' T p\) \ \valid_bound_tcb' tcb\ f \\_. valid_bound_tcb' tcb\" by (auto simp: valid_bound_tcb'_def valid_def typ_at_tcb'[symmetric] split: option.splits) lemmas typ_at_lifts = typ_at_lift_tcb' typ_at_lift_ep' typ_at_lift_ntfn' typ_at_lift_cte' typ_at_lift_cte_at' typ_at_lift_page_table_at' typ_at_lift_page_directory_at' typ_at_lift_asid_at' typ_at_lift_valid_untyped' typ_at_lift_valid_cap' valid_pde_lift' valid_pte_lift' valid_asid_pool_lift' valid_bound_tcb_lift lemma mdb_next_unfold: "s \ c \ c' = (\z. s c = Some z \ c' = mdbNext (cteMDBNode z))" by (auto simp add: mdb_next_rel_def mdb_next_def) lemma valid_dlist_prevD: "\ valid_dlist m; c \ 0; c' \ 0 \ \ m \ c \ c' = m \ c \ c'" by (fastforce simp add: valid_dlist_def Let_def mdb_next_unfold mdb_prev_def) lemma no_0_simps [simp]: assumes "no_0 m" shows "((m 0 = Some cte) = False) \ ((Some cte = m 0) = False)" using assms by (simp add: no_0_def) lemma valid_dlist_def2: "no_0 m \ valid_dlist m = (\c c'. c \ 0 \ c' \ 0 \ m \ c \ c' = m \ c \ c')" apply (rule iffI) apply (simp add: valid_dlist_prevD) apply (clarsimp simp: valid_dlist_def Let_def mdb_next_unfold mdb_prev_def) apply (subgoal_tac "p\0") prefer 2 apply clarsimp apply (rule conjI) apply clarsimp apply (erule_tac x="mdbPrev (cteMDBNode cte)" in allE) apply simp apply (erule_tac x=p in allE) apply clarsimp apply clarsimp apply (erule_tac x=p in allE) apply simp apply (erule_tac x="mdbNext (cteMDBNode cte)" in allE) apply clarsimp done lemma valid_dlist_def3: "valid_dlist m = ((\c c'. m \ c \ c' \ c' \ 0 \ m \ c \ c') \ (\c c'. m \ c \ c' \ c \ 0 \ m \ c \ c'))" apply (rule iffI) apply (simp add: valid_dlist_def Let_def mdb_next_unfold mdb_prev_def) apply fastforce apply (clarsimp simp add: valid_dlist_def Let_def mdb_next_unfold mdb_prev_def) apply fastforce done lemma vdlist_prevD: "\ m \ c \ c'; m c = Some cte; valid_dlist m; no_0 m \ \ m \ c \ c'" by (fastforce simp: valid_dlist_def3) lemma vdlist_nextD: "\ m \ c \ c'; m c' = Some cte; valid_dlist m; no_0 m \ \ m \ c \ c'" by (fastforce simp: valid_dlist_def3) lemma vdlist_prevD0: "\ m \ c \ c'; c \ 0; valid_dlist m \ \ m \ c \ c'" by (fastforce simp: valid_dlist_def3) lemma vdlist_nextD0: "\ m \ c \ c'; c' \ 0; valid_dlist m \ \ m \ c \ c'" by (fastforce simp: valid_dlist_def3) lemma vdlist_prev_src_unique: "\ m \ p \ x; m \ p \ y; p \ 0; valid_dlist m \ \ x = y" by (drule (2) vdlist_prevD0)+ (clarsimp simp: mdb_next_unfold) lemma vdlist_next_src_unique: "\ m \ x \ p; m \ y \ p; p \ 0; valid_dlist m \ \ x = y" by (drule (2) vdlist_nextD0)+ (clarsimp simp: mdb_prev_def) lemma cte_at_cte_wp_atD: "cte_at' p s \ \cte. cte_wp_at' ((=) cte) p s" by (clarsimp simp add: cte_wp_at'_def) lemma cte_at_cte_wp_atE: "\ cte_at' p s; \cte. cte_wp_at' ((=) cte) p s \ P \ \ P" by (blast dest: cte_at_cte_wp_atD) lemma valid_pspace_no_0 [elim]: "valid_pspace' s \ no_0 (ctes_of s)" by (auto simp: valid_pspace'_def valid_mdb'_def valid_mdb_ctes_def) lemma valid_pspace_dlist [elim]: "valid_pspace' s \ valid_dlist (ctes_of s)" by (auto simp: valid_pspace'_def valid_mdb'_def valid_mdb_ctes_def) lemma cte_wp_at_conj': "\ cte_wp_at' P p s; cte_wp_at' Q p s \ \ cte_wp_at' (P and Q) p s" by (fastforce simp add: cte_wp_at'_def) lemma next_rtrancl_tranclE [consumes 1, case_names eq trancl]: assumes major: "m \ x \\<^sup>* y" and r1: "x = y \ P" and r2: "\ x \ y; m \ x \\<^sup>+ y \ \ P" shows "P" using major by (auto dest: rtranclD intro: r1 r2) lemmas trancl_induct' [induct set] = trancl_induct [consumes 1, case_names base step] lemma next_single_value: "\ m \ x \ y; m \ x \ z \ \ y = z" unfolding mdb_next_rel_def by simp lemma loop_split: assumes loop: "m \ c \\<^sup>+ c" and split: "m \ c \\<^sup>+ c'" shows "m \ c' \\<^sup>+ c" using split loop proof induct case base thus ?case by (auto dest: next_single_value elim: tranclE2) next case (step y z) hence "m \ y \\<^sup>+ c" by simp hence "m \ z \\<^sup>* c" using step.hyps by (auto dest: next_single_value elim: tranclE2 intro: trancl_into_rtrancl) thus ?case using step.prems by (cases rule: next_rtrancl_tranclE, simp_all) qed lemma no_0_lhs: "\ m \ c \ y; no_0 m \ \ c \ 0" unfolding no_0_def by (erule contrapos_pn, simp add: mdb_next_unfold) lemma no_0_lhs_trancl: "\ m \ c \\<^sup>+ y; no_0 m \ \ c \ 0" by (erule tranclE2, (rule no_0_lhs, simp_all)+) lemma mdb_chain_0_no_loops: assumes asm: "mdb_chain_0 m" and no0: "no_0 m" shows "no_loops m" proof - { fix c assume mc: "m \ c \\<^sup>+ c" with asm have "m \ c \\<^sup>+ 0" unfolding mdb_chain_0_def apply - apply (erule bspec, erule tranclE2) apply (auto intro: domI simp: mdb_next_unfold) done with mc have "m \ 0 \\<^sup>+ c" by (rule loop_split) hence False using no0 by (clarsimp dest!: no_0_lhs_trancl) } thus "no_loops m" unfolding no_loops_def by auto qed lemma valid_mdb_ctesE [elim]: "\valid_mdb_ctes m; \ valid_dlist m; no_0 m; mdb_chain_0 m; valid_badges m; caps_contained' m; mdb_chunked m; untyped_mdb' m; untyped_inc' m; valid_nullcaps m; ut_revocable' m; class_links m; distinct_zombies m; irq_control m; reply_masters_rvk_fb m \ \ P\ \ P" unfolding valid_mdb_ctes_def by auto lemma valid_mdb_ctesI [intro]: "\valid_dlist m; no_0 m; mdb_chain_0 m; valid_badges m; caps_contained' m; mdb_chunked m; untyped_mdb' m; untyped_inc' m; valid_nullcaps m; ut_revocable' m; class_links m; distinct_zombies m; irq_control m; reply_masters_rvk_fb m \ \ valid_mdb_ctes m" unfolding valid_mdb_ctes_def by auto lemma mdb_next_fold: "(m \ p \ c) = (mdb_next m p = Some c)" unfolding mdb_next_rel_def by simp end locale PSpace_update_eq = fixes f :: "kernel_state \ kernel_state" assumes pspace: "ksPSpace (f s) = ksPSpace s" begin lemma state_refs_of'_eq[iff]: "state_refs_of' (f s) = state_refs_of' s" by (rule state_refs_of'_pspaceI [OF _ pspace], rule refl) lemma valid_space_update [iff]: "valid_pspace' (f s) = valid_pspace' s" by (fastforce simp: valid_pspace' pspace) lemma obj_at_update [iff]: "obj_at' P p (f s) = obj_at' P p s" by (fastforce intro: obj_at'_pspaceI simp: pspace) lemma ko_wp_at_update [iff]: "ko_wp_at' P p (f s) = ko_wp_at' P p s" by (simp add: pspace ko_wp_at'_def ps_clear_def) lemma cte_wp_at_update [iff]: "cte_wp_at' P p (f s) = cte_wp_at' P p s" by (fastforce intro: cte_wp_at'_pspaceI simp: pspace) lemma ex_nonz_cap_to_eq'[iff]: "ex_nonz_cap_to' p (f s) = ex_nonz_cap_to' p s" by (simp add: ex_nonz_cap_to'_def) lemma iflive_update [iff]: "if_live_then_nonz_cap' (f s) = if_live_then_nonz_cap' s" by (simp add: if_live_then_nonz_cap'_def ex_nonz_cap_to'_def) lemma valid_objs_update [iff]: "valid_objs' (f s) = valid_objs' s" apply (simp add: valid_objs'_def pspace) apply (fastforce intro: valid_obj'_pspaceI simp: pspace) done lemma pspace_aligned_update [iff]: "pspace_aligned' (f s) = pspace_aligned' s" by (simp add: pspace pspace_aligned'_def) lemma pspace_distinct_update [iff]: "pspace_distinct' (f s) = pspace_distinct' s" by (simp add: pspace pspace_distinct'_def ps_clear_def) lemma pred_tcb_at_update [iff]: "pred_tcb_at' proj P p (f s) = pred_tcb_at' proj P p s" by (simp add: pred_tcb_at'_def) lemma valid_cap_update [iff]: "(f s) \' c = s \' c" by (auto intro: valid_cap'_pspaceI simp: pspace) lemma typ_at_update' [iff]: "typ_at' T p (f s) = typ_at' T p s" by (simp add: typ_at'_def) lemma valid_asid_table_update' [iff]: "valid_asid_table' t (f s) = valid_asid_table' t s" by (simp add: valid_asid_table'_def) lemma page_table_at_update' [iff]: "page_table_at' p (f s) = page_table_at' p s" by (simp add: page_table_at'_def) lemma page_directory_at_update' [iff]: "page_directory_at' p (f s) = page_directory_at' p s" by (simp add: page_directory_at'_def) lemma valid_global_pts_update' [iff]: "valid_global_pts' pts (f s) = valid_global_pts' pts s" by (simp add: valid_global_pts'_def) lemma no_0_obj'_update [iff]: "no_0_obj' (f s) = no_0_obj' s" by (simp add: no_0_obj'_def pspace) lemma valid_pde_mappings'_update [iff]: "valid_pde_mappings' (f s) = valid_pde_mappings' s" by (simp add: valid_pde_mappings'_def) lemma pointerInUserData_update[iff]: "pointerInUserData p (f s) = pointerInUserData p s" by (simp add: pointerInUserData_def) lemma pointerInDeviceData_update[iff]: "pointerInDeviceData p (f s) = pointerInDeviceData p s" by (simp add: pointerInDeviceData_def) lemma pspace_domain_valid_update [iff]: "pspace_domain_valid (f s) = pspace_domain_valid s" by (simp add: pspace_domain_valid_def pspace) end locale Arch_Idle_update_eq = fixes f :: "kernel_state \ kernel_state" assumes arch: "ksArchState (f s) = ksArchState s" assumes idle: "ksIdleThread (f s) = ksIdleThread s" assumes int_nd: "intStateIRQNode (ksInterruptState (f s)) = intStateIRQNode (ksInterruptState s)" assumes maxObj: "gsMaxObjectSize (f s) = gsMaxObjectSize s" begin lemma global_refs_update' [iff]: "global_refs' (f s) = global_refs' s" by (simp add: global_refs'_def arch idle int_nd) end locale P_Arch_Idle_update_eq = PSpace_update_eq + Arch_Idle_update_eq begin lemma valid_global_refs_update' [iff]: "valid_global_refs' (f s) = valid_global_refs' s" by (simp add: valid_global_refs'_def pspace arch idle maxObj) lemma valid_arch_state_update' [iff]: "valid_arch_state' (f s) = valid_arch_state' s" by (simp add: valid_arch_state'_def arch) lemma valid_idle_update' [iff]: "valid_idle' (f s) = valid_idle' s" by (auto simp: pspace idle) lemma ifunsafe_update [iff]: "if_unsafe_then_cap' (f s) = if_unsafe_then_cap' s" by (simp add: if_unsafe_then_cap'_def ex_cte_cap_to'_def int_nd) end locale Int_update_eq = fixes f :: "kernel_state \ kernel_state" assumes int: "ksInterruptState (f s) = ksInterruptState s" begin lemma irqs_masked_update [iff]: "irqs_masked' (f s) = irqs_masked' s" by (simp add: irqs_masked'_def int) lemma irq_issued_update'[iff]: "irq_issued' irq (f s) = irq_issued' irq s" by (simp add: irq_issued'_def int) end locale P_Cur_update_eq = PSpace_update_eq + assumes curt: "ksCurThread (f s) = ksCurThread s" assumes curd: "ksCurDomain (f s) = ksCurDomain s" begin lemma sch_act_wf[iff]: "sch_act_wf ks (f s) = sch_act_wf ks s" apply (cases ks) apply (simp_all add: ct_in_state'_def st_tcb_at'_def tcb_in_cur_domain'_def curt curd) done end locale P_Int_update_eq = PSpace_update_eq + Int_update_eq begin lemma valid_irq_handlers_update'[iff]: "valid_irq_handlers' (f s) = valid_irq_handlers' s" by (simp add: valid_irq_handlers'_def cteCaps_of_def pspace) end locale P_Int_Cur_update_eq = P_Int_update_eq + P_Cur_update_eq locale P_Arch_Idle_Int_update_eq = P_Arch_Idle_update_eq + P_Int_update_eq locale P_Arch_Idle_Int_Cur_update_eq = P_Arch_Idle_Int_update_eq + P_Cur_update_eq interpretation sa_update: P_Arch_Idle_Int_Cur_update_eq "ksSchedulerAction_update f" by unfold_locales auto interpretation ready_queue_update: P_Arch_Idle_Int_Cur_update_eq "ksReadyQueues_update f" by unfold_locales auto interpretation ready_queue_bitmap1_update: P_Arch_Idle_Int_Cur_update_eq "ksReadyQueuesL1Bitmap_update f" by unfold_locales auto interpretation ready_queue_bitmap2_update: P_Arch_Idle_Int_Cur_update_eq "ksReadyQueuesL2Bitmap_update f" by unfold_locales auto interpretation cur_thread_update': P_Arch_Idle_Int_update_eq "ksCurThread_update f" by unfold_locales auto interpretation machine_state_update': P_Arch_Idle_Int_Cur_update_eq "ksMachineState_update f" by unfold_locales auto interpretation interrupt_state_update': P_Cur_update_eq "ksInterruptState_update f" by unfold_locales auto interpretation idle_update': P_Int_Cur_update_eq "ksIdleThread_update f" by unfold_locales auto interpretation arch_state_update': P_Int_Cur_update_eq "ksArchState_update f" by unfold_locales auto interpretation wu_update': P_Arch_Idle_Int_Cur_update_eq "ksWorkUnitsCompleted_update f" by unfold_locales auto interpretation gsCNodes_update: P_Arch_Idle_update_eq "gsCNodes_update f" by unfold_locales simp_all interpretation gsUserPages_update: P_Arch_Idle_update_eq "gsUserPages_update f" by unfold_locales simp_all lemma ko_wp_at_aligned: "ko_wp_at' ((=) ko) p s \ is_aligned p (objBitsKO ko)" by (simp add: ko_wp_at'_def) interpretation ksCurDomain: P_Arch_Idle_Int_update_eq "ksCurDomain_update f" by unfold_locales auto interpretation ksDomScheduleIdx: P_Arch_Idle_Int_Cur_update_eq "ksDomScheduleIdx_update f" by unfold_locales auto interpretation ksDomSchedule: P_Arch_Idle_Int_Cur_update_eq "ksDomSchedule_update f" by unfold_locales auto interpretation ksDomainTime: P_Arch_Idle_Int_Cur_update_eq "ksDomainTime_update f" by unfold_locales auto interpretation gsUntypedZeroRanges: P_Arch_Idle_Int_Cur_update_eq "gsUntypedZeroRanges_update f" by unfold_locales auto lemma ko_wp_at_norm: "ko_wp_at' P p s \ \ko. P ko \ ko_wp_at' ((=) ko) p s" by (auto simp add: ko_wp_at'_def) lemma valid_mdb'_queues [iff]: "valid_mdb' (ksReadyQueues_update f s) = valid_mdb' s" by (simp add: valid_mdb'_def) lemma valid_mdb_machine_state [iff]: "valid_mdb' (ksMachineState_update f s) = valid_mdb' s" by (simp add: valid_mdb'_def) lemma cte_wp_at_norm': "cte_wp_at' P p s \ \cte. cte_wp_at' ((=) cte) p s \ P cte" by (simp add: cte_wp_at'_def) lemma pred_tcb_at'_disj: "(pred_tcb_at' proj P t s \ pred_tcb_at' proj Q t s) = pred_tcb_at' proj (\a. P a \ Q a) t s" by (fastforce simp add: pred_tcb_at'_def obj_at'_def) lemma pred_tcb_at' [elim!]: "pred_tcb_at' proj P t s \ tcb_at' t s" by (auto simp add: pred_tcb_at'_def obj_at'_def) lemma valid_pspace_mdb' [elim!]: "valid_pspace' s \ valid_mdb' s" by (simp add: valid_pspace'_def) lemmas hoare_use_eq_irq_node' = hoare_use_eq[where f=irq_node'] lemma ex_cte_cap_to'_pres: "\ \P p. \cte_wp_at' P p\ f \\rv. cte_wp_at' P p\; \P. \\s. P (irq_node' s)\ f \\rv s. P (irq_node' s)\ \ \ \ex_cte_cap_wp_to' P p\ f \\rv. ex_cte_cap_wp_to' P p\" apply (simp add: ex_cte_cap_wp_to'_def) apply (rule hoare_pre) apply (erule hoare_use_eq_irq_node') apply (rule hoare_vcg_ex_lift) apply assumption apply simp done context begin interpretation Arch . (*FIXME: arch_split*) lemma page_directory_pde_atI': "\ page_directory_at' p s; x < 2 ^ pageBits \ \ pde_at' (p + (x << 2)) s" by (simp add: page_directory_at'_def pageBits_def) lemma page_table_pte_atI': "\ page_table_at' p s; x < 2^(ptBits - 2) \ \ pte_at' (p + (x << 2)) s" by (simp add: page_table_at'_def pageBits_def ptBits_def pteBits_def) lemma valid_global_refsD': "\ ctes_of s p = Some cte; valid_global_refs' s \ \ kernel_data_refs \ capRange (cteCap cte) = {} \ global_refs' s \ kernel_data_refs" by (clarsimp simp: valid_global_refs'_def valid_refs'_def ran_def) blast lemma no_0_prev: "no_0 m \ \ m \ p \ 0" by (simp add: mdb_prev_def) lemma ut_revocableD': "\m p = Some (CTE cap n); isUntypedCap cap; ut_revocable' m \ \ mdbRevocable n" unfolding ut_revocable'_def by blast lemma nullcapsD': "\m p = Some (CTE NullCap n); valid_nullcaps m \ \ n = nullMDBNode" unfolding valid_nullcaps_def by blast lemma untyped_mdbD': "\m p = Some (CTE c n); isUntypedCap c; m p' = Some (CTE c' n'); \isUntypedCap c'; capRange c' \ untypedRange c \ {}; untyped_mdb' m \ \ p' \ descendants_of' p m" unfolding untyped_mdb'_def by blast lemma untyped_incD': "\ m p = Some (CTE c n); isUntypedCap c; m p' = Some (CTE c' n'); isUntypedCap c'; untyped_inc' m \ \ (untypedRange c \ untypedRange c' \ untypedRange c' \ untypedRange c \ untypedRange c \ untypedRange c' = {}) \ (untypedRange c \ untypedRange c' \ (p \ descendants_of' p' m \ untypedRange c \ usableUntypedRange c' = {})) \ (untypedRange c' \ untypedRange c \ (p' \ descendants_of' p m \ untypedRange c' \ usableUntypedRange c = {})) \ (untypedRange c = untypedRange c' \ (p' \ descendants_of' p m \ usableUntypedRange c = {} \ p \ descendants_of' p' m \ usableUntypedRange c' = {} \ p = p'))" unfolding untyped_inc'_def apply (drule_tac x = p in spec) apply (drule_tac x = p' in spec) apply (elim allE impE) apply simp+ done lemma caps_containedD': "\ m p = Some (CTE c n); m p' = Some (CTE c' n'); \ isUntypedCap c'; capRange c' \ untypedRange c \ {}; caps_contained' m\ \ capRange c' \ untypedRange c" unfolding caps_contained'_def by blast lemma class_linksD: "\ m p = Some cte; m p' = Some cte'; m \ p \ p'; class_links m \ \ capClass (cteCap cte) = capClass (cteCap cte')" using class_links_def by blast lemma mdb_chunkedD: "\ m p = Some (CTE cap n); m p' = Some (CTE cap' n'); sameRegionAs cap cap'; p \ p'; mdb_chunked m \ \ (m \ p \\<^sup>+ p' \ m \ p' \\<^sup>+ p) \ (m \ p \\<^sup>+ p' \ is_chunk m cap p p') \ (m \ p' \\<^sup>+ p \ is_chunk m cap' p' p)" using mdb_chunked_def by blast lemma irq_controlD: "\ m p = Some (CTE IRQControlCap n); m p' = Some (CTE IRQControlCap n'); irq_control m \ \ p' = p" unfolding irq_control_def by blast lemma irq_revocable: "\ m p = Some (CTE IRQControlCap n); irq_control m \ \ mdbRevocable n" unfolding irq_control_def by blast lemma sch_act_wf_arch [simp]: "sch_act_wf sa (ksArchState_update f s) = sch_act_wf sa s" by (cases sa) (simp_all add: ct_in_state'_def tcb_in_cur_domain'_def) lemma valid_queues_arch [simp]: "valid_queues (ksArchState_update f s) = valid_queues s" by (simp add: valid_queues_def valid_queues_no_bitmap_def bitmapQ_defs) lemma if_unsafe_then_cap_arch' [simp]: "if_unsafe_then_cap' (ksArchState_update f s) = if_unsafe_then_cap' s" by (simp add: if_unsafe_then_cap'_def ex_cte_cap_to'_def) lemma valid_idle_arch' [simp]: "valid_idle' (ksArchState_update f s) = valid_idle' s" by (simp add: valid_idle'_def) lemma valid_irq_node_arch' [simp]: "valid_irq_node' w (ksArchState_update f s) = valid_irq_node' w s" by (simp add: valid_irq_node'_def) lemma sch_act_wf_machine_state [simp]: "sch_act_wf sa (ksMachineState_update f s) = sch_act_wf sa s" by (cases sa) (simp_all add: ct_in_state'_def tcb_in_cur_domain'_def) lemma valid_queues_machine_state [simp]: "valid_queues (ksMachineState_update f s) = valid_queues s" by (simp add: valid_queues_def valid_queues_no_bitmap_def bitmapQ_defs) lemma valid_queues_arch' [simp]: "valid_queues' (ksArchState_update f s) = valid_queues' s" by (simp add: valid_queues'_def) lemma valid_queues_machine_state' [simp]: "valid_queues' (ksMachineState_update f s) = valid_queues' s" by (simp add: valid_queues'_def) lemma valid_irq_node'_machine_state [simp]: "valid_irq_node' x (ksMachineState_update f s) = valid_irq_node' x s" by (simp add: valid_irq_node'_def) (* these should be reasonable safe for automation because of the 0 pattern *) lemma no_0_ko_wp' [elim!]: "\ ko_wp_at' Q 0 s; no_0_obj' s \ \ P" by (simp add: ko_wp_at'_def no_0_obj'_def) lemma no_0_obj_at' [elim!]: "\ obj_at' Q 0 s; no_0_obj' s \ \ P" by (simp add: obj_at'_def no_0_obj'_def) lemma no_0_typ_at' [elim!]: "\ typ_at' T 0 s; no_0_obj' s \ \ P" by (clarsimp simp: typ_at'_def) lemma no_0_ko_wp'_eq [simp]: "no_0_obj' s \ ko_wp_at' P 0 s = False" by (simp add: ko_wp_at'_def no_0_obj'_def) lemma no_0_obj_at'_eq [simp]: "no_0_obj' s \ obj_at' P 0 s = False" by (simp add: obj_at'_def no_0_obj'_def) lemma no_0_typ_at'_eq [simp]: "no_0_obj' s \ typ_at' P 0 s = False" by (simp add: typ_at'_def) lemma valid_pspace_valid_objs'[elim!]: "valid_pspace' s \ valid_objs' s" by (simp add: valid_pspace'_def) declare badgeBits_def [simp] lemma ex_cte_cap_to'_pres_asm: "\ \P p. \cte_wp_at' P p and Q\ f \\rv. cte_wp_at' P p\; \P. \\s. P (irq_node' s)\ f \\rv s. P (irq_node' s)\ \ \ \ex_cte_cap_wp_to' P p and Q\ f \\rv. ex_cte_cap_wp_to' P p\" apply (simp add: ex_cte_cap_to'_def pred_conj_def) apply (rule hoare_pre, erule hoare_use_eq_irq_node') apply (rule hoare_vcg_ex_lift, assumption) apply simp done lemma simple_sane_strg: "sch_act_simple s \ sch_act_sane s" by (simp add: sch_act_sane_def sch_act_simple_def) lemma sch_act_wf_cases: "sch_act_wf action = (case action of ResumeCurrentThread \ ct_in_state' activatable' | ChooseNewThread \ \ | SwitchToThread t \ \s. st_tcb_at' runnable' t s \ tcb_in_cur_domain' t s)" by (cases action) auto end lemma (in PSpace_update_eq) cteCaps_of_update[iff]: "cteCaps_of (f s) = cteCaps_of s" by (simp add: cteCaps_of_def pspace) lemma vms_sch_act_update'[iff]: "valid_machine_state' (ksSchedulerAction_update f s) = valid_machine_state' s" by (simp add: valid_machine_state'_def ) context begin interpretation Arch . (*FIXME: arch_split*) lemma objBitsT_simps: "objBitsT EndpointT = epSizeBits" "objBitsT NotificationT = ntfnSizeBits" "objBitsT CTET = cteSizeBits" "objBitsT TCBT = tcbBlockSizeBits" "objBitsT UserDataT = pageBits" "objBitsT UserDataDeviceT = pageBits" "objBitsT KernelDataT = pageBits" "objBitsT (ArchT PDET) = 2" "objBitsT (ArchT PTET) = 2" "objBitsT (ArchT ASIDPoolT) = pageBits" unfolding objBitsT_def makeObjectT_def by (simp_all add: makeObject_simps objBits_simps archObjSize_def pteBits_def pdeBits_def) lemma objBitsT_koTypeOf : "(objBitsT (koTypeOf ko)) = objBitsKO ko" apply (cases ko; simp add: objBits_simps objBitsT_simps) apply (rename_tac arch_kernel_object) apply (case_tac arch_kernel_object; simp add: archObjSize_def objBitsT_simps pteBits_def pdeBits_def) done lemma sane_update [intro!]: "sch_act_sane (s\ksSchedulerAction := ChooseNewThread\)" by (simp add: sch_act_sane_def) lemma typ_at_aligned': "\ typ_at' tp p s \ \ is_aligned p (objBitsT tp)" by (clarsimp simp add: typ_at'_def ko_wp_at'_def objBitsT_koTypeOf) lemma valid_queues_obj_at'D: "\ t \ set (ksReadyQueues s (d, p)); valid_queues s \ \ obj_at' (inQ d p) t s" apply (unfold valid_queues_def valid_queues_no_bitmap_def) apply (elim conjE) apply (drule_tac x=d in spec) apply (drule_tac x=p in spec) apply (clarsimp) apply (drule(1) bspec) apply (erule obj_at'_weakenE) apply (clarsimp) done lemma obj_at'_and: "obj_at' (P and P') t s = (obj_at' P t s \ obj_at' P' t s)" by (rule iffI, (clarsimp simp: obj_at'_def)+) lemma obj_at'_activatable_st_tcb_at': "obj_at' (activatable' \ tcbState) t = st_tcb_at' activatable' t" by (rule ext, clarsimp simp: st_tcb_at'_def) lemma st_tcb_at'_runnable_is_activatable: "st_tcb_at' runnable' t s \ st_tcb_at' activatable' t s" by (simp add: st_tcb_at'_def) (fastforce elim: obj_at'_weakenE) lemma tcb_at'_has_tcbPriority: "tcb_at' t s \ \p. obj_at' (\tcb. tcbPriority tcb = p) t s" by (clarsimp simp add: obj_at'_def) lemma pred_tcb_at'_Not: "pred_tcb_at' f (Not o P) t s = (tcb_at' t s \ \ pred_tcb_at' f P t s)" by (auto simp: pred_tcb_at'_def obj_at'_def) lemma obj_at'_conj_distrib: "obj_at' (\ko. P ko \ Q ko) p s \ obj_at' P p s \ obj_at' Q p s" by (auto simp: obj_at'_def) lemma not_obj_at'_strengthen: "obj_at' (Not \ P) p s \ \ obj_at' P p s" by (clarsimp simp: obj_at'_def) lemma not_pred_tcb_at'_strengthen: "pred_tcb_at' f (Not \ P) p s \ \ pred_tcb_at' f P p s" by (clarsimp simp: pred_tcb_at'_def obj_at'_def) lemma obj_at'_ko_at'_prop: "ko_at' ko t s \ obj_at' P t s = P ko" by (drule obj_at_ko_at', clarsimp simp: obj_at'_def) lemma idle_tcb_at'_split: "idle_tcb_at' (\p. P (fst p) \ Q (snd p)) t s \ st_tcb_at' P t s \ bound_tcb_at' Q t s" by (clarsimp simp: pred_tcb_at'_def dest!: obj_at'_conj_distrib) lemma valid_queues_no_bitmap_def': "valid_queues_no_bitmap = (\s. \d p. (\t\set (ksReadyQueues s (d, p)). obj_at' (inQ d p) t s \ st_tcb_at' runnable' t s) \ distinct (ksReadyQueues s (d, p)) \ (d > maxDomain \ p > maxPriority \ ksReadyQueues s (d,p) = []))" apply (rule ext, rule iffI) apply (clarsimp simp: valid_queues_def valid_queues_no_bitmap_def obj_at'_and pred_tcb_at'_def o_def elim!: obj_at'_weakenE)+ done lemma valid_queues_running: assumes Q: "t \ set(ksReadyQueues s (d, p))" "valid_queues s" shows "st_tcb_at' runnable' t s" using assms by (clarsimp simp add: valid_queues_def valid_queues_no_bitmap_def') lemma valid_refs'_cteCaps: "valid_refs' S (ctes_of s) = (\c \ ran (cteCaps_of s). S \ capRange c = {})" by (fastforce simp: valid_refs'_def cteCaps_of_def elim!: ranE) lemma valid_cap_sizes_cteCaps: "valid_cap_sizes' n (ctes_of s) = (\c \ ran (cteCaps_of s). 2 ^ capBits c \ n)" apply (simp add: valid_cap_sizes'_def cteCaps_of_def) apply (fastforce elim!: ranE) done lemma cte_at_valid_cap_sizes_0: "valid_cap_sizes' n ctes \ ctes p = Some cte \ 0 < n" apply (clarsimp simp: valid_cap_sizes'_def) apply (drule bspec, erule ranI) apply (rule Suc_le_lessD, erule order_trans[rotated]) apply simp done lemma invs_valid_stateI' [elim!]: "invs' s \ valid_state' s" by (simp add: invs'_def) lemma tcb_at_invs' [elim!]: "invs' s \ tcb_at' (ksCurThread s) s" by (simp add: invs'_def cur_tcb'_def) lemma invs_valid_objs' [elim!]: "invs' s \ valid_objs' s" by (simp add: invs'_def valid_state'_def valid_pspace'_def) lemma invs_pspace_aligned' [elim!]: "invs' s \ pspace_aligned' s" by (simp add: invs'_def valid_state'_def valid_pspace'_def) lemma invs_pspace_distinct' [elim!]: "invs' s \ pspace_distinct' s" by (simp add: invs'_def valid_state'_def valid_pspace'_def) lemma invs_valid_pspace' [elim!]: "invs' s \ valid_pspace' s" by (simp add: invs'_def valid_state'_def) lemma invs_arch_state' [elim!]: "invs' s \ valid_arch_state' s" by (simp add: invs'_def valid_state'_def) lemma invs_cur' [elim!]: "invs' s \ cur_tcb' s" by (simp add: invs'_def) lemma invs_mdb' [elim!]: "invs' s \ valid_mdb' s" by (simp add: invs'_def valid_state'_def valid_pspace'_def) lemma valid_mdb_no_loops [elim!]: "valid_mdb_ctes m \ no_loops m" by (auto intro: mdb_chain_0_no_loops) lemma invs_no_loops [elim!]: "invs' s \ no_loops (ctes_of s)" apply (rule valid_mdb_no_loops) apply (simp add: invs'_def valid_state'_def valid_pspace'_def valid_mdb'_def) done lemma invs_iflive'[elim!]: "invs' s \ if_live_then_nonz_cap' s" by (simp add: invs'_def valid_state'_def) lemma invs_unsafe_then_cap' [elim!]: "invs' s \ if_unsafe_then_cap' s" by (simp add: invs'_def valid_state'_def) lemma invs_sym' [elim!]: "invs' s \ sym_refs (state_refs_of' s)" by (simp add: invs'_def valid_state'_def) lemma invs_sch_act_wf' [elim!]: "invs' s \ sch_act_wf (ksSchedulerAction s) s" by (simp add: invs'_def valid_state'_def) lemma invs_queues [elim!]: "invs' s \ valid_queues s" by (simp add: invs'_def valid_state'_def) lemma invs_valid_idle'[elim!]: "invs' s \ valid_idle' s" by (fastforce simp: invs'_def valid_state'_def) lemma invs_valid_global'[elim!]: "invs' s \ valid_global_refs' s" by (fastforce simp: invs'_def valid_state'_def) lemma invs_invs_no_cicd': "invs' s \ all_invs_but_ct_idle_or_in_cur_domain' s" by (simp add: invs'_to_invs_no_cicd'_def) lemma valid_queues_valid_bitmapQ: "valid_queues s \ valid_bitmapQ s" by (simp add: valid_queues_def) lemma valid_queues_valid_queues_no_bitmap: "valid_queues s \ valid_queues_no_bitmap s" by (simp add: valid_queues_def) lemma valid_queues_bitmapQ_no_L1_orphans: "valid_queues s \ bitmapQ_no_L1_orphans s" by (simp add: valid_queues_def) lemma invs'_bitmapQ_no_L1_orphans: "invs' s \ bitmapQ_no_L1_orphans s" by (drule invs_queues, simp add: valid_queues_def) lemma invs_ksCurDomain_maxDomain' [elim!]: "invs' s \ ksCurDomain s \ maxDomain" by (simp add: invs'_def valid_state'_def) lemma ksCurThread_active_not_idle': "\ ct_active' s ; valid_idle' s \ \ ksCurThread s \ ksIdleThread s" apply clarsimp apply (clarsimp simp: ct_in_state'_def valid_idle'_def) apply (drule idle_tcb_at'_split) apply (clarsimp simp: pred_tcb_at'_def obj_at'_def) done lemma simple_st_tcb_at_state_refs_ofD': "st_tcb_at' simple' t s \ bound_tcb_at' (\x. tcb_bound_refs' x = state_refs_of' s t) t s" by (fastforce simp: pred_tcb_at'_def obj_at'_def state_refs_of'_def projectKO_eq project_inject) lemma cur_tcb_arch' [iff]: "cur_tcb' (ksArchState_update f s) = cur_tcb' s" by (simp add: cur_tcb'_def) lemma cur_tcb'_machine_state [simp]: "cur_tcb' (ksMachineState_update f s) = cur_tcb' s" by (simp add: cur_tcb'_def) lemma invs_no_0_obj'[elim!]: "invs' s \ no_0_obj' s" by (simp add: invs'_def valid_state'_def valid_pspace'_def) lemma invs'_ksSchedulerAction: "\ invs' s; sch_act_wf sa s; sa \ ResumeCurrentThread \ \ invs' (s \ksSchedulerAction := sa\)" by (clarsimp simp add: invs'_def valid_state'_def valid_queues_def valid_queues_no_bitmap_def bitmapQ_defs valid_irq_node'_def valid_queues'_def cur_tcb'_def ct_idle_or_in_cur_domain'_def tcb_in_cur_domain'_def ct_not_inQ_def) lemma invs'_gsCNodes_update[simp]: "invs' (gsCNodes_update f s') = invs' s'" apply (clarsimp simp: invs'_def valid_state'_def valid_queues_def valid_queues_no_bitmap_def bitmapQ_defs valid_queues'_def valid_irq_node'_def valid_irq_handlers'_def irq_issued'_def irqs_masked'_def valid_machine_state'_def cur_tcb'_def) apply (cases "ksSchedulerAction s'") apply (simp_all add: ct_in_state'_def tcb_in_cur_domain'_def ct_idle_or_in_cur_domain'_def ct_not_inQ_def) done lemma invs'_gsUserPages_update[simp]: "invs' (gsUserPages_update f s') = invs' s'" apply (clarsimp simp: invs'_def valid_state'_def valid_queues_def valid_queues_no_bitmap_def bitmapQ_defs valid_queues'_def valid_irq_node'_def valid_irq_handlers'_def irq_issued'_def irqs_masked'_def valid_machine_state'_def cur_tcb'_def) apply (cases "ksSchedulerAction s'") apply (simp_all add: ct_in_state'_def ct_idle_or_in_cur_domain'_def tcb_in_cur_domain'_def ct_not_inQ_def) done lemma invs_queues_tcb_in_cur_domain': "\ ksReadyQueues s (d, p) = x # xs; invs' s; d = ksCurDomain s\ \ tcb_in_cur_domain' x s" apply (subgoal_tac "x \ set (ksReadyQueues s (d, p))") apply (drule (1) valid_queues_obj_at'D[OF _ invs_queues]) apply (auto simp: inQ_def tcb_in_cur_domain'_def elim: obj_at'_weakenE) done lemma invs_no_cicd_queues_tcb_in_cur_domain': "\ ksReadyQueues s (d, p) = x # xs; all_invs_but_ct_idle_or_in_cur_domain' s; d = ksCurDomain s\ \ tcb_in_cur_domain' x s" apply (simp add: all_invs_but_ct_idle_or_in_cur_domain'_def valid_pspace'_def tcb_in_cur_domain'_def) apply (elim conjE) apply (subgoal_tac "x \ set (ksReadyQueues s (d, p))") apply (drule (1) valid_queues_obj_at'D) apply (auto simp: inQ_def elim: obj_at'_weakenE) done lemma pred_tcb'_neq_contra: "\ pred_tcb_at' proj P p s; pred_tcb_at' proj Q p s; \st. P st \ Q st \ \ False" by (clarsimp simp: pred_tcb_at'_def obj_at'_def) lemma invs'_ksDomSchedule: "invs' s \ KernelStateData_H.ksDomSchedule s = KernelStateData_H.ksDomSchedule (newKernelState undefined)" unfolding invs'_def valid_state'_def by clarsimp lemma invs'_ksDomScheduleIdx: "invs' s \ KernelStateData_H.ksDomScheduleIdx s < length (KernelStateData_H.ksDomSchedule (newKernelState undefined))" unfolding invs'_def valid_state'_def by clarsimp lemma valid_bitmap_valid_bitmapQ_exceptE: "\ valid_bitmapQ_except d p s ; (bitmapQ d p s \ ksReadyQueues s (d,p) \ []) ; bitmapQ_no_L2_orphans s \ \ valid_bitmapQ s" unfolding valid_bitmapQ_def valid_bitmapQ_except_def by force lemma valid_bitmap_valid_bitmapQ_exceptI[intro]: "valid_bitmapQ s \ valid_bitmapQ_except d p s" unfolding valid_bitmapQ_except_def valid_bitmapQ_def by simp lemma mask_wordRadix_less_wordBits: assumes sz: "wordRadix \ size w" shows "unat ((w::'a::len word) && mask wordRadix) < wordBits" proof - note pow_num = semiring_numeral_class.power_numeral { assume "wordRadix = size w" hence ?thesis by (fastforce intro!: unat_lt2p[THEN order_less_le_trans] simp: wordRadix_def wordBits_def' word_size) } moreover { assume "wordRadix < size w" hence ?thesis unfolding wordRadix_def wordBits_def' mask_def apply simp apply (subst unat_less_helper, simp_all) apply (rule word_and_le1[THEN order_le_less_trans]) apply (simp add: word_size bintrunc_mod2p) apply (subst int_mod_eq', simp_all) apply (rule order_le_less_trans[where y="2^wordRadix", simplified wordRadix_def], simp) apply (simp del: pow_num) apply (subst int_mod_eq', simp_all) apply (rule order_le_less_trans[where y="2^wordRadix", simplified wordRadix_def], simp) apply (simp del: pow_num) done } ultimately show ?thesis using sz by fastforce qed lemma priority_mask_wordRadix_size: "unat ((w::priority) && mask wordRadix) < wordBits" by (rule mask_wordRadix_less_wordBits, simp add: wordRadix_def word_size) end (* The normalise_obj_at' tactic was designed to simplify situations similar to: ko_at' ko p s \ obj_at' (complicated_P (obj_at' (complicated_Q (obj_at' ...)) p s)) p s It seems to also offer assistance in cases where there is lots of st_tcb_at', ko_at', obj_at' confusion. If your goal looks like that kind of mess, try it out. It can help to not unfold obj_at'_def which speeds up proofs. *) context begin private definition "ko_at'_defn v \ ko_at' v" private lemma ko_at_defn_rewr: "ko_at'_defn ko p s \ (obj_at' P p s = P ko)" unfolding ko_at'_defn_def by (auto simp: obj_at'_def) private lemma ko_at_defn_uniqueD: "ko_at'_defn ko p s \ ko_at'_defn ko' p s \ ko' = ko" unfolding ko_at'_defn_def by (auto simp: obj_at'_def) private lemma ko_at_defn_pred_tcb_at': "ko_at'_defn ko p s \ (pred_tcb_at' proj P p s = P (proj (tcb_to_itcb' ko)))" by (auto simp: pred_tcb_at'_def ko_at_defn_rewr) private lemma ko_at_defn_ko_wp_at': "ko_at'_defn ko p s \ (ko_wp_at' P p s = P (injectKO ko))" by (clarsimp simp: ko_at'_defn_def obj_at'_real_def ko_wp_at'_def project_inject) method normalise_obj_at' = (clarsimp?, elim obj_at_ko_at'[folded ko_at'_defn_def, elim_format], clarsimp simp: ko_at_defn_rewr ko_at_defn_pred_tcb_at' ko_at_defn_ko_wp_at', ((drule(1) ko_at_defn_uniqueD)+)?, clarsimp simp: ko_at'_defn_def) end add_upd_simps "invs' (gsUntypedZeroRanges_update f s) \ valid_queues (gsUntypedZeroRanges_update f s)" (obj_at'_real_def) declare upd_simps[simp] end