(* * Copyright 2014, General Dynamics C4 Systems * * SPDX-License-Identifier: GPL-2.0-only *) theory Bits_R imports Corres begin crunch_ignore (add: bind return "when" get gets fail assert put modify unless select alternative assert_opt gets_the returnOk throwError lift bindE liftE whenE unlessE throw_opt assertE liftM liftME sequence_x zipWithM_x mapM_x sequence mapM sequenceE_x sequenceE mapME mapME_x catch select_f handleE' handleE handle_elseE forM forM_x zipWithM filterM forME_x withoutFailure throw catchFailure rethrowFailure capFaultOnFailure lookupErrorOnFailure nullCapOnFailure nothingOnFailure without_preemption withoutPreemption preemptionPoint cap_fault_on_failure lookup_error_on_failure const_on_failure ignore_failure ignoreFailure empty_on_failure emptyOnFailure unifyFailure unify_failure throw_on_false storeWordVM loadWord setRegister getRegister getRestartPC debugPrint setNextPC maskInterrupt clearMemory throw_on_false unifyFailure ignoreFailure empty_on_failure emptyOnFailure clearMemoryVM null_cap_on_failure setNextPC getRestartPC assertDerived throw_on_false getObject setObject updateObject loadObject) context Arch begin (*FIXME: arch_split*) crunch_ignore (add: invalidateLocalTLB_ASID invalidateLocalTLB_VAASID cleanByVA cleanByVA_PoU invalidateByVA invalidateByVA_I invalidate_I_PoU cleanInvalByVA branchFlush clean_D_PoU cleanInvalidate_D_PoC cleanInvalidateL2Range invalidateL2Range cleanL2Range flushBTAC writeContextID isb dsb dmb setHardwareASID setCurrentPD) end context begin interpretation Arch . (*FIXME: arch_split*) lemma withoutFailure_wp [wp]: "\P\ f \Q\ \ \P\ withoutFailure f \Q\,\E\" "\P\ f \Q\ \ \P\ withoutFailure f \Q\,-" "\\\ withoutFailure f -,\E\" by (auto simp: validE_R_def validE_E_def valid_def) lemma no_fail_typeError [simp, wp]: "no_fail \ (typeError xs ko)" by (simp add: typeError_def) lemma isCap_simps: "isZombie v = (\v0 v1 v2. v = Zombie v0 v1 v2)" "isArchObjectCap v = (\v0. v = ArchObjectCap v0)" "isThreadCap v = (\v0. v = ThreadCap v0)" "isCNodeCap v = (\v0 v1 v2 v3. v = CNodeCap v0 v1 v2 v3)" "isNotificationCap v = (\v0 v1 v2 v3. v = NotificationCap v0 v1 v2 v3)" "isEndpointCap v = (\v0 v1 v2 v3 v4 v5. v = EndpointCap v0 v1 v2 v3 v4 v5)" "isUntypedCap v = (\d v0 v1 f. v = UntypedCap d v0 v1 f)" "isReplyCap v = (\v0 v1 v2. v = ReplyCap v0 v1 v2)" "isIRQControlCap v = (v = IRQControlCap)" "isIRQHandlerCap v = (\v0. v = IRQHandlerCap v0)" "isNullCap v = (v = NullCap)" "isDomainCap v = (v = DomainCap)" "isPageCap w = (\d v0 v1 v2 v3. w = PageCap d v0 v1 v2 v3)" "isPageTableCap w = (\v0 v1. w = PageTableCap v0 v1)" "isPageDirectoryCap w = (\v0 v1. w = PageDirectoryCap v0 v1)" "isASIDControlCap w = (w = ASIDControlCap)" "isASIDPoolCap w = (\v0 v1. w = ASIDPoolCap v0 v1)" "isArchPageCap cap = (\d ref rghts sz data. cap = ArchObjectCap (PageCap d ref rghts sz data))" "isVCPUCap w = (\v. w = VCPUCap v)" by (auto simp: isCap_defs split: capability.splits arch_capability.splits) lemma untyped_not_null [simp]: "\ isUntypedCap NullCap" by (simp add: isCap_simps) text \Miscellaneous facts about low level constructs\ lemma projectKO_tcb: "(projectKO_opt ko = Some t) = (ko = KOTCB t)" by (cases ko) (auto simp: projectKO_opts_defs) lemma projectKO_cte: "(projectKO_opt ko = Some t) = (ko = KOCTE t)" by (cases ko) (auto simp: projectKO_opts_defs) lemma projectKO_ep: "(projectKO_opt ko = Some t) = (ko = KOEndpoint t)" by (cases ko) (auto simp: projectKO_opts_defs) lemma projectKO_ntfn: "(projectKO_opt ko = Some t) = (ko = KONotification t)" by (cases ko) (auto simp: projectKO_opts_defs) lemma projectKO_ASID: "(projectKO_opt ko = Some t) = (ko = KOArch (KOASIDPool t))" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemma projectKO_PTE: "(projectKO_opt ko = Some t) = (ko = KOArch (KOPTE t))" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemma projectKO_PDE: "(projectKO_opt ko = Some t) = (ko = KOArch (KOPDE t))" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemma projectKO_user_data: "(projectKO_opt ko = Some (t :: user_data)) = (ko = KOUserData)" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemma projectKO_user_data_device: "(projectKO_opt ko = Some (t :: user_data_device)) = (ko = KOUserDataDevice)" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemma projectKO_VCPU: "(projectKO_opt ko = Some t) = (ko = KOArch (KOVCPU t))" by (cases ko) (auto simp: projectKO_opts_defs split: arch_kernel_object.splits) lemmas projectKOs = projectKO_ntfn projectKO_ep projectKO_cte projectKO_tcb projectKO_VCPU projectKO_ASID projectKO_PTE projectKO_PDE projectKO_user_data projectKO_user_data_device projectKO_eq projectKO_eq2 lemma capAligned_epI: "ep_at' p s \ capAligned (EndpointCap p a b c d e)" apply (clarsimp simp: obj_at'_real_def capAligned_def objBits_simps word_bits_def) apply (drule ko_wp_at_norm) apply clarsimp apply (drule ko_wp_at_aligned) apply (simp add: objBits_simps' projectKOs capUntypedPtr_def isCap_simps) done lemma capAligned_ntfnI: "ntfn_at' p s \ capAligned (NotificationCap p a b c)" apply (clarsimp simp: obj_at'_real_def capAligned_def objBits_simps word_bits_def capUntypedPtr_def isCap_simps) apply (fastforce dest: ko_wp_at_norm dest!: ko_wp_at_aligned simp: objBits_simps' projectKOs) done lemma capAligned_tcbI: "tcb_at' p s \ capAligned (ThreadCap p)" apply (clarsimp simp: obj_at'_real_def capAligned_def objBits_simps word_bits_def capUntypedPtr_def isCap_simps) apply (fastforce dest: ko_wp_at_norm dest!: ko_wp_at_aligned simp: objBits_simps' projectKOs) done lemma capAligned_reply_tcbI: "tcb_at' p s \ capAligned (ReplyCap p m r)" apply (clarsimp simp: obj_at'_real_def capAligned_def objBits_simps word_bits_def capUntypedPtr_def isCap_simps) apply (fastforce dest: ko_wp_at_norm dest!: ko_wp_at_aligned simp: objBits_simps' projectKOs) done lemma ko_at_valid_objs': assumes ko: "ko_at' k p s" assumes vo: "valid_objs' s" assumes k: "\ko. projectKO_opt ko = Some k \ injectKO k = ko" shows "valid_obj' (injectKO k) s" using ko vo by (clarsimp simp: valid_objs'_def obj_at'_def projectKOs project_inject ranI) lemma obj_at_valid_objs': "\ obj_at' P p s; valid_objs' s \ \ \k. P k \ ((\ko. projectKO_opt ko = Some k \ injectKO k = ko) \ valid_obj' (injectKO k) s)" apply (drule obj_at_ko_at') apply clarsimp apply (rule_tac x=ko in exI) apply clarsimp apply (erule (1) ko_at_valid_objs') apply simp done lemma tcb_in_valid_state': "\ st_tcb_at' P t s; valid_objs' s \ \ \st. P st \ valid_tcb_state' st s" apply (clarsimp simp: pred_tcb_at'_def) apply (drule obj_at_valid_objs') apply fastforce apply (clarsimp simp: projectKOs) apply (fastforce simp add: valid_obj'_def valid_tcb'_def) done lemma getCurThread_corres [corres]: "corres (=) \ \ (gets cur_thread) getCurThread" by (simp add: getCurThread_def curthread_relation) lemma gct_wp [wp]: "\\s. P (ksCurThread s) s\ getCurThread \P\" by (unfold getCurThread_def, wp) lemma getIdleThread_corres: "corres (=) \ \ (gets idle_thread) getIdleThread" by (simp add: getIdleThread_def state_relation_def) lemma git_wp [wp]: "\\s. P (ksIdleThread s) s\ getIdleThread \P\" by (unfold getIdleThread_def, wp) lemma gsa_wp [wp]: "\\s. P (ksSchedulerAction s) s\ getSchedulerAction \P\" by (unfold getSchedulerAction_def, wp) text \Shorthand names for the relations between faults, errors and failures\ definition fr :: "ExceptionTypes_A.fault \ Fault_H.fault \ bool" where fr_def[simp]: "fr x y \ (y = fault_map x)" definition ser :: "ExceptionTypes_A.syscall_error \ Fault_H.syscall_error \ bool" where ser_def[simp]: "ser x y \ (y = syscall_error_map x)" definition lfr :: "ExceptionTypes_A.lookup_failure \ Fault_H.lookup_failure \ bool" where lfr_def[simp]: "lfr x y \ (y = lookup_failure_map x)" text \Correspondence and weakest precondition rules for the "on failure" transformers\ lemma corres_injection: assumes x: "t = injection_handler fn" assumes y: "t' = injection_handler fn'" assumes z: "\ft ft'. f' ft ft' \ f (fn ft) (fn' ft')" shows "corres (f' \ r) P P' m m' \ corres (f \ r) P P' (t m) (t' m')" apply (simp add: injection_handler_def handleE'_def x y) apply (rule corres_guard_imp) apply (rule corres_split) apply assumption apply (case_tac v, (clarsimp simp: z)+) apply (rule wp_post_taut) apply (rule wp_post_taut) apply simp apply simp done lemma rethrowFailure_injection: "rethrowFailure = injection_handler" by (intro ext, simp add: rethrowFailure_def injection_handler_def o_def) lemma capFault_injection: "capFaultOnFailure addr b = injection_handler (Fault_H.CapFault addr b)" apply (rule ext) apply (simp add: capFaultOnFailure_def rethrowFailure_injection) done lemma lookupError_injection: "lookupErrorOnFailure b = injection_handler (Fault_H.FailedLookup b)" apply (rule ext) apply (simp add: lookupErrorOnFailure_def rethrowFailure_injection) done lemma corres_cap_fault: "corres (lfr \ r) P P' f g \ corres (fr \ r) P P' (cap_fault_on_failure addr b f) (capFaultOnFailure addr b g)" by (fastforce intro: corres_injection[where f'=lfr] simp: cap_fault_injection capFault_injection) lemmas corresK_cap_fault = corres_cap_fault[atomized, THEN corresK_lift_rule, rule_format, corresK] lemmas capFault_wp[wp] = injection_wp[OF capFault_injection] lemmas capFault_wp_E[wp] = injection_wp_E[OF capFault_injection] lemmas capFault_bindE = injection_bindE[OF capFault_injection capFault_injection] lemmas capFault_liftE[simp] = injection_liftE[OF capFault_injection] lemma corres_lookup_error: "\ corres (lfr \ r) P P' f g \ \ corres (ser \ r) P P' (lookup_error_on_failure b f) (lookupErrorOnFailure b g)" by (fastforce intro: corres_injection[where f'=lfr] simp: lookup_error_injection lookupError_injection) lemmas corresK_lookup_error = corres_lookup_error[atomized, THEN corresK_lift_rule, rule_format, corresK] lemmas lookupError_wp[wp] = injection_wp[OF lookupError_injection] lemmas lookupError_wp_E[wp] = injection_wp_E[OF lookupError_injection] lemmas lookupError_bindE = injection_bindE[OF lookupError_injection lookupError_injection] lemmas lookupError_liftE[simp] = injection_liftE[OF lookupError_injection] lemma unifyFailure_injection: "unifyFailure = injection_handler (\x. ())" by (rule ext, simp add: unifyFailure_def injection_handler_def rethrowFailure_def o_def) lemmas unifyFailure_injection_corres = corres_injection [where f=dc, simplified, OF _ unifyFailure_injection] lemmas unifyFailure_discard = unifyFailure_injection_corres [OF id_injection, simplified] lemmas unifyFailure_wp = injection_wp [OF unifyFailure_injection] lemmas unifyFailure_wp_E[wp] = injection_wp_E [OF unifyFailure_injection] lemmas corres_unify_failure = corres_injection [OF unify_failure_injection unifyFailure_injection, rotated] lemma ignoreFailure_wp[wp_split]: "\P\ v \\rv. Q ()\,\\rv. Q ()\ \ \P\ ignoreFailure v \Q\" by (simp add: ignoreFailure_def const_def) wp lemma ep'_cases_weak_wp: assumes "\P_A\ a \Q\" assumes "\q. \P_B\ b q \Q\" assumes "\q. \P_C\ c q \Q\" shows "\P_A and P_B and P_C\ case ts of IdleEP \ a | SendEP q \ b q | RecvEP q \ c q \Q\" apply (cases ts) apply (simp, rule hoare_weaken_pre, rule assms, simp)+ done lemma ntfn'_cases_weak_wp: assumes "\P_A\ a \Q\" assumes "\q. \P_B\ b q \Q\" assumes "\bdg. \P_C\ c bdg \Q\" shows "\P_A and P_B and P_C\ case ts of IdleNtfn \ a | WaitingNtfn q \ b q | ActiveNtfn bdg \ c bdg \Q\" apply (cases ts) apply (simp, rule hoare_weaken_pre, rule assms, simp)+ done lemma ko_at_imp_cte_wp_at': fixes x :: cte shows "\ ko_at' x ptr s \ \ cte_wp_at' (\cte. cte = x) ptr s" apply (erule obj_atE') apply (clarsimp simp: projectKOs objBits_simps') apply (erule cte_wp_at_cteI') apply (simp add: cte_level_bits_def)+ done lemma modify_map_casesD: "modify_map m p f p' = Some cte \ (p \ p' \ m p' = Some cte) \ (p = p' \ (\cap node. m p = Some (CTE cap node) \ f (CTE cap node) = cte))" apply (simp add: modify_map_def split: if_split_asm) apply clarsimp apply (case_tac z) apply auto done lemma modify_map_casesE: "\ modify_map m p f p' = Some cte; \ p \ p'; m p' = Some cte \ \ P; \cap node. \ p = p'; m p = Some (CTE cap node); cte = f (CTE cap node) \ \ P \ \ P" by (auto dest: modify_map_casesD) lemma modify_map_cases: "(modify_map m p f p' = Some cte) = ((p \ p' \ m p' = Some cte) \ (p = p' \ (\cap node. m p = Some (CTE cap node) \ f (CTE cap node) = cte)))" apply (rule iffI) apply (erule modify_map_casesD) apply (clarsimp simp: modify_map_def) done lemma no_0_modify_map [simp]: "no_0 (modify_map m p f) = no_0 m" by (simp add: no_0_def modify_map_def) lemma modify_map_0 [simp]: "no_0 m \ modify_map m 0 f = m" by (rule ext) (auto simp add: modify_map_def no_0_def) lemma modify_map_exists: "\cap node. m p = Some (CTE cap node) \ \cap' node'. modify_map m q f p = Some (CTE cap' node')" apply clarsimp apply (case_tac "f (CTE cap node)") apply (cases "q=p") apply (auto simp add: modify_map_cases) done lemma modify_map_exists_rev: "modify_map m q f p = Some (CTE cap node) \ \cap' node'. m p = Some (CTE cap' node')" apply (case_tac "f (CTE cap node)") apply (cases "q=p") apply (auto simp add: modify_map_cases) done lemma modify_map_if: "(modify_map m p f p' = Some cte) = (if p = p' then \cap node. m p = Some (CTE cap node) \ f (CTE cap node) = cte else \cap node. m p' = Some (CTE cap node) \ cte = CTE cap node)" apply (cases cte) apply (rule iffI) apply (drule modify_map_casesD) apply auto[1] apply (auto simp: modify_map_def) done lemma corres_empty_on_failure: "corres ((\x y. r [] []) \ r) P P' m m' \ corres r P P' (empty_on_failure m) (emptyOnFailure m')" apply (simp add: empty_on_failure_def emptyOnFailure_def) apply (rule corres_guard_imp) apply (rule corres_split_catch) apply assumption apply (rule corres_trivial, simp) apply wp+ apply simp+ done lemmas corresK_empty_on_failure = corres_empty_on_failure[atomized, THEN corresK_lift_rule, rule_format, corresK] lemma emptyOnFailure_wp[wp]: "\P\ m \Q\,\\rv. Q []\ \ \P\ emptyOnFailure m \Q\" by (simp add: emptyOnFailure_def) wp lemma withoutPreemption_lift: "\P\ f \Q\ \ \P\ withoutPreemption f \Q\, \E\" by simp lemma withoutPreemption_R: "\\\ withoutPreemption f -, \Q\" by (wp withoutPreemption_lift) lemma ko_at_cte_ipcbuffer: "ko_at' tcb p s \ cte_wp_at' (\x. x = tcbIPCBufferFrame tcb) (p + tcbIPCBufferSlot * 0x10) s" apply (clarsimp simp: obj_at'_def projectKOs objBits_simps) apply (erule (2) cte_wp_at_tcbI') apply (fastforce simp add: tcb_cte_cases_def tcbIPCBufferSlot_def) apply simp done lemma set_ep_arch': "\\s. P (ksArchState s)\ setEndpoint ntfn p \\_ s. P (ksArchState s)\" apply (simp add: setEndpoint_def setObject_def split_def) apply (wp updateObject_default_inv|simp)+ done lemma corres_const_on_failure: "corres ((\_ _. r x y) \ r) P P' m m' \ corres r P P' (const_on_failure x m) (constOnFailure y m')" apply (simp add: const_on_failure_def constOnFailure_def) apply (rule corres_guard_imp) apply (rule corres_split_catch) apply assumption apply (rule corres_trivial, simp) apply (clarsimp simp: const_def) apply wp+ apply simp+ done lemmas corresK_const_on_failure = corres_const_on_failure[atomized, THEN corresK_lift_rule, rule_format, corresK] lemma constOnFailure_wp : "\P\ m \Q\, \\rv. Q n\ \ \P\ constOnFailure n m \Q\" apply (simp add: constOnFailure_def const_def) apply (wp|simp)+ done lemma corres_throwError_str [corresK_concrete_rER]: "corres_underlyingK sr nf nf' (r (Inl a) (Inl b)) r \ \ (throwError a) (throw b)" "corres_underlyingK sr nf nf' (r (Inl a) (Inl b)) r \ \ (throwError a) (throwError b)" by (simp add: corres_underlyingK_def)+ end end