(* * Copyright 2014, NICTA * * 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(NICTA_GPL) *) theory ADT_IF imports Noninterference_Base "../access-control/Syscall_AC" "../access-control/ADT_AC" IRQMasks_IF FinalCaps Scheduler_IF UserOp_IF begin inductive_set sub_big_steps :: "('a,'b,'c) data_type \ ('a \ 'a \ bool) \ 'a \ ('a \ 'c list) set" for A :: "('a,'b,'c) data_type" and R :: "('a \ 'a \ bool)" and s :: "'a" where nil: "\evlist = []; t = s; \ R s s\ \ (t,evlist) \ sub_big_steps A R s" | step: "\evlist = evlist' @ [e]; (s',evlist') \ sub_big_steps A R s; (s',t) \ data_type.Step A e; \ R s t\ \ (t,evlist) \ sub_big_steps A R s" text {* Turn the (observable) multi-step executions of one automaton into the steps of another. We call this second automaton a \emph{big step} automaton of the first. We use a relation on observable states of the original automaton to demarcate one big step from the next. *} inductive_set big_steps :: "('a,'b,'c) data_type \ ('a \ 'a \ bool) \ ('c list \ 'd) \ ('d \ ('a \ 'a) set)" for A :: "('a,'b,'c) data_type" and R :: "'a \ 'a \ bool" and exmap :: "'c list \ 'd" and ev :: "'d" where cstep: "\(s',as) \ sub_big_steps A R s; (s',t) \ data_type.Step A a; R s t; ev = exmap (as @ [a])\ \ (s,t) \ big_steps A R exmap ev" definition big_step_adt :: "('a,'b,'c) data_type \ ('a \ 'a \ bool) \ ('c list \ 'd) \ ('a,'b,'d) data_type" where "big_step_adt A R exmap \ \Init = Init A, Fin = Fin A, Step = big_steps A R exmap\" lemma system_Step_def_raw: "system.Step = (\A a. {(s,s') . s' \ execution A s [a]})" apply(rule ext) apply(rule ext) apply(subst system.Step_def) by(rule refl) lemma big_stepsD: "(s,t) \ big_steps A R exmap ev \ \ s' as a. (s',as) \ sub_big_steps A R s \ (s',t) \ data_type.Step A a \ R s t \ ev = exmap (as @ [a])" apply(erule big_steps.induct) apply blast done lemma big_stepsE: "\(s,t) \ big_steps A R exmap ev; (\ s' as a. \(s',as) \ sub_big_steps A R s; (s',t) \ data_type.Step A a; R s t; ev = exmap (as @ [a])\ \ V)\ \ V" apply(drule big_stepsD) apply blast done lemma Run_subset: "(\ ev. Stepf ev \ Stepf' ev) \ Run Stepf as \ Run Stepf' as" apply(induct as) apply simp apply auto done lemma rtranclp_def2: "(R\<^sup>*\<^sup>* s0 s) = (R\<^sup>+\<^sup>+ s0 s \ s = s0)" apply (safe) apply (drule rtranclpD) apply simp apply (erule tranclp_into_rtranclp) done definition Fin_trancl where "Fin_trancl A R s s' \ R\<^sup>+\<^sup>+ s s' \ Fin A s = Fin A s'" text {* A sufficient condition to show that the big steps of a big step ADT terminate (i.e. that the relation R eventually becomes satisfied.) *} definition rel_terminate :: "('a,'b,'c) data_type \ 'b \ ('a \ 'a \ bool) \ ('a set) \ ('a \ 'a \ nat) \ bool" where "rel_terminate A s0 R I measuref \ (\s. s \ I \ (\s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s) \ (\ as s'. (s',as) \ sub_big_steps A R s \ (\s'' a. (s',s'') \ data_type.Step A a \ ((measuref s s'' < measuref s s') \ (measuref s s' > 0 \ measuref s s'' = 0 \ R s s'')))))" lemma rel_terminateE: assumes a: "rel_terminate A s0 R I measuref" assumes b: "\(\s s' as s'' a. \s \ I; \s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s; (s',as) \ sub_big_steps A R s; (s',s'') \ data_type.Step A a; measuref s s' > 0; measuref s s'' = 0\ \ R s s''); (\s s' as s'' a. \s \ I; \s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s; (s',as) \ sub_big_steps A R s; (s',s'') \ data_type.Step A a\ \ measuref s s'' < measuref s s')\ \ C" shows "C" apply(rule b) using a apply(fastforce simp: rel_terminate_def)+ done lemma Run_big_steps_tranclp: "(s0, s) \ Run (big_steps C R exmap) js \ R\<^sup>*\<^sup>* s0 s" apply(induct js arbitrary: s rule: rev_induct) apply simp apply(fastforce dest: Run_mid elim: big_steps.cases) done lemma Step_system_reachable_trans: "Step_system A s0 \ system.reachable A s0 s \ system.reachable A s s' \ system.reachable A s0 s'" apply(clarsimp simp: system.reachable_def) apply(rule Step_system.reachable_execution[simplified system.reachable_def]) apply blast+ done lemma Step_system_reachable: "Step_system A s0 \ system.reachable A s0 s \ Step_system A s" apply(subst Step_system_def) apply(rule conjI) apply(fastforce simp: system.reachable_def Step_system.execution_Run intro: exI[where x="[]"]) apply clarsimp apply(frule Step_system_reachable_trans, assumption+) apply(simp add: Step_system.execution_Run) done lemma Step_system_execution_Run_s0: "Step_system A s0 \ execution A s0 as = {s'. (s0,s') \ Run (system.Step A) as}" apply(rule Step_system.execution_Run, assumption) apply(erule Step_system.reachable_s0) done text {* Define a relation on states that is basically the inverse of the Step relation for states @{term y} reachable from a given state @{term s} before the next big step has finished. *} definition step_measuref_rel_from :: "('a,'b,'c) data_type \ ('a \ 'a \ bool) \ 'a \ ('a \ 'a) set" where "step_measuref_rel_from A R s \ {(x,y). \a as. (y,x) \ data_type.Step A a \ (y,as) \ sub_big_steps A R s}" lemma wf_step_measuref_rel_from: "\rel_terminate A s0 R I measuref; s \ I; \s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s\ \ wf (step_measuref_rel_from A R s)" apply(cut_tac wf_measure[where f="measuref s"]) apply(erule wf_subset) apply(fastforce simp: measure_def inv_image_def step_measuref_rel_from_def rel_terminate_def) done lemma system_Step_one: "(x, s') \ system.Step A a \ (x, s') \ Run (system.Step A) [a]" apply simp done definition inv_holds :: "('a,'b,'j) data_type \ 'a set \ bool" (infix "[>" 60) where "D [> I \ (\j. Step D j `` I \ I)" lemma inv_holdsI: "\ \j. Step D j `` I \ I \ \ D [> I" by (simp add: inv_holds_def) lemma inv_holds_conjI: "D [> P \ D [> Q \ D [> P \ Q" by (simp add: inv_holds_def) blast lemma inv_holds_steps: assumes I:"A [> I" assumes start_I: "B \ I" shows "steps (Simulation.Step A) B as \ I" apply clarsimp apply (induct as arbitrary: x rule: rev_induct) apply (simp add: steps_def) apply (rule set_mp) apply (rule start_I) apply simp apply (simp add: steps_def) apply (erule ImageE) apply (drule_tac x=xb in meta_spec) apply simp apply (rule set_mp) apply (rule I[simplified inv_holds_def,rule_format]) apply (rule ImageI) apply assumption apply simp done locale serial_system_weak = system + fixes I assumes I: "A [> I" assumes serial: "\s' a. s' \ I \ (\t. (s', t) \ data_type.Step A a)" begin lemma step_serial: assumes nonempty_start: "B \ {}" assumes invariant_start: "B \ I" shows "steps (Simulation.Step A) B as \ {}" apply (induct as rule: rev_induct) apply (simp add: steps_def nonempty_start) apply (erule nonemptyE) apply (frule set_mp[OF inv_holds_steps[OF I invariant_start]]) apply (frule_tac a=x in serial) apply (elim exE) apply (rule_tac x=t in notemptyI) apply (fastforce simp: steps_def) done end lemma sub_big_steps_I_holds: "A [> I \ s \ I \ (x, xs) \ sub_big_steps A R s \ x \ I" apply (erule sub_big_steps.induct) apply simp apply (simp add: inv_holds_def) apply blast done lemma rel_terminate_terminates: assumes ss: "serial_system_weak A I" assumes rt: "rel_terminate A s0 R I measuref" assumes si: "s \ I" assumes sR: "\s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s" shows "\js. (x,js) \ sub_big_steps A R s \ (\ as s' a s''. (s',(js@as)) \ sub_big_steps A R s \ (s',s'') \ data_type.Step A a \ R s s'')" proof - show ?thesis apply(induct x rule: wf_induct) apply(rule wf_step_measuref_rel_from[OF rt si sR]) apply clarsimp apply (frule sub_big_steps_I_holds[OF ss[THEN serial_system_weak.I] si]) apply (frule_tac serial_system_weak.serial[OF ss]) apply(erule exE, rename_tac s') apply(drule_tac x=s' in spec) apply(erule impE) apply(fastforce simp: step_measuref_rel_from_def) apply(case_tac "R s s'") apply(rule_tac x="[]" in exI) apply(rule_tac x=x in exI) apply fastforce apply(fastforce intro: sub_big_steps.step) done qed lemma sub_big_steps_nrefl: "(\s. \ R s s) \ (s,[]) \ sub_big_steps A R s" apply(blast intro: nil) done lemma big_steps_enabled: assumes ss: " serial_system_weak A I" assumes rt: "rel_terminate A s0 R I measuref" assumes s_I: " s \ I" assumes nrefl: "(\s. \ R s s)" shows "\s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s \ \x s'. (s, s') \ big_steps A R exmap x" apply(frule rel_terminate_terminates[OF ss rt s_I]) apply(drule_tac x="[]" in spec) apply(erule impE[OF _ sub_big_steps_nrefl]) apply(rule nrefl) apply(fastforce intro: cstep) done text {* We assume here that there is only one event that can ever occur. This is overly restrictive in general, but should be fine for the seL4 automata (which shouldn't need multiple event labels since it should only ever be able to perform one event in each state). *} lemma Step_system_to_enabled_system: assumes single_event: "(\(x::'b) (y::'b). x = y)" assumes st: "Step_system A s0" assumes en: "\s. system.reachable A s0 s \ \(x::'b) s'. (s,s') \ system.Step A x" shows "enabled_system A s0" apply(clarsimp simp: enabled_system_def) proof - fix s js jsa assume a: "s \ execution A s0 js" show "\ s'. s' \ execution A s jsa" proof - have er: "\ as. execution A s as = {s'. (s,s') \ Run (system.Step A) as}" apply(rule Step_system.execution_Run[OF st]) using a apply(fastforce simp: system.reachable_def) done show ?thesis apply(induct jsa rule: rev_induct) apply(simp add: er) apply(clarsimp simp: er) apply(cut_tac s=s' in en) apply(rule Step_system.reachable_execution[OF st]) using a apply(fastforce simp: system.reachable_def) apply(simp add: er) apply clarify apply(rename_tac b s'a) apply(rule_tac x=s'a in exI) apply(rule Run_trans, assumption) apply(rule system_Step_one) apply(cut_tac x=b and xa=x in single_event[rule_format], simp) done qed qed lemma steps_subset: "A \ B \ steps steps1 A as \ steps steps1 B as" apply (simp add: steps_def Image_def) apply (induct as rule: rev_induct) apply simp apply force done locale Init_Fin_serial_weak = serial_system_weak + assumes Init_Fin: "\s'. s' \ I \ s' \ Init A (Fin A s')" assumes s0_I: "Init A s0 \ I" begin lemma enabled: "enabled_system A s0" apply (clarsimp simp: enabled_system_def) apply (induct_tac jsa rule: rev_induct) apply (clarsimp simp: execution_def steps_def) apply (fold steps_def) apply (rule_tac x="Fin A x" in exI) apply (rule imageI) apply (rule Init_Fin) apply (rule set_mp) apply (rule inv_holds_steps[OF I]) apply (rule s0_I) apply simp apply (clarsimp simp: execution_def steps_def) apply (fold steps_def) apply (subgoal_tac "steps (data_type.Step A) (Init A (Fin A xa)) xs \ I \ {}") apply (erule nonemptyE) apply clarsimp apply (drule_tac a=x in serial) apply clarsimp apply (rule_tac x="Fin A t" in exI) apply (rule imageI) apply (rule ImageI) apply assumption apply assumption apply (cut_tac inv_holds_steps[OF I s0_I]) apply (drule(1) subsetD) apply (cut_tac B="{xa}" and as=xs in inv_holds_steps[OF I]) apply simp apply (cut_tac B="{xa}" and as=xs in step_serial) apply simp+ apply (cut_tac A="{xa}" and B="Init A (Fin A xa)" in steps_subset) apply (simp add: Init_Fin) apply force done end lemma invariant_holds_steps: assumes I:"A \ I" assumes start_I: "B \ I" shows "steps (Simulation.Step A) B as \ I" apply clarsimp apply (induct as arbitrary: x rule: rev_induct) apply (simp add: steps_def) apply (rule set_mp) apply (rule start_I) apply simp apply (simp add: steps_def) apply (erule ImageE) apply (drule_tac x=xb in meta_spec) apply simp apply (rule set_mp) apply (rule I[simplified invariant_holds_def, THEN conjunct2,rule_format]) apply (rule ImageI) apply assumption apply simp done locale serial_system = system + fixes I assumes I: "A \ I" assumes serial: "\s' a. s' \ I \ (\t. (s', t) \ data_type.Step A a)" begin lemma step_serial: assumes nonempty_start: "B \ {}" assumes invariant_start: "B \ I" shows "steps (Simulation.Step A) B as \ {}" apply (induct as rule: rev_induct) apply (simp add: steps_def nonempty_start) apply (erule nonemptyE) apply (frule set_mp[OF invariant_holds_steps[OF I invariant_start]]) apply (frule_tac a=x in serial) apply (elim exE) apply (rule_tac x=t in notemptyI) apply (fastforce simp: steps_def) done lemma fw_sim_serial: assumes refines: "LI B A R (I_b \ I_a)" assumes B_I_b: "B \ I_b'" (*assumes A_I_a: "A \ I_a"*) assumes A_I_as: "I \ I_a" assumes B_I_bs': "I_b' \ I_b" assumes constrained_B: "\s. s \ I_b' \ \s'. s' \ I \ (s,s') \ R" shows "serial_system B I_b'" apply unfold_locales apply (rule B_I_b) apply (insert refines) apply (clarsimp simp: LI_def) apply (drule_tac x=a in spec) apply (frule_tac s=s' in constrained_B) apply clarsimp apply (frule_tac a=a in serial) apply (clarsimp simp: rel_semi_def) apply (cut_tac B_I_bs' A_I_as) apply blast done end locale Init_Fin_serial = serial_system + assumes Init_Fin: "\s'. s' \ I \ s' \ Init A (Fin A s')" assumes s0_I: "Init A s0 \ I" begin lemma enabled: "enabled_system A s0" apply (clarsimp simp: enabled_system_def) apply (induct_tac jsa rule: rev_induct) apply (clarsimp simp: execution_def steps_def) apply (fold steps_def) apply (rule_tac x="Fin A x" in exI) apply (rule imageI) apply (rule Init_Fin) apply (rule set_mp) apply (rule invariant_holds_steps[OF I]) apply (rule s0_I) apply simp apply (clarsimp simp: execution_def steps_def) apply (fold steps_def) apply (subgoal_tac "xb \ I") apply (drule_tac a=x in serial) apply clarsimp apply (rule_tac x="Fin A t" in exI) apply (rule imageI) apply (rule ImageI) apply assumption apply assumption apply (rule set_mp) apply (rule invariant_holds_steps[OF I]) prefer 2 apply assumption apply (rule I[simplified invariant_holds_def, THEN conjunct1,rule_format]) done end sublocale Init_Fin_serial \ enabled_system apply (rule enabled) done sublocale Init_Fin_serial \ Init_Fin_serial_weak apply (unfold_locales) using I apply (simp add: inv_holds_def invariant_holds_def) apply (erule serial) apply (erule Init_Fin) apply (rule s0_I) done lemma (in Init_Fin_serial) serial_to_weak: "Init_Fin_serial_weak A s0 I" by intro_locales definition inv_from_rel :: "('a, 'b, 'j) data_type \ 'b \ ('a \ 'a \ bool) \ 'a set" where "inv_from_rel A s0 R \ {s. \s0'\ Init A s0. R\<^sup>*\<^sup>* s0' s}" lemma big_step_adt_R_tranclp_inv: "(big_step_adt C R exmap) [> inv_from_rel C s0 R" apply (rule inv_holdsI) apply (clarsimp simp: big_step_adt_def inv_from_rel_def Fin_trancl_def) apply (rule_tac x="s0'" in bexI) apply (force elim: big_steps.cases) apply simp done lemma big_steps_I_holds: "\(xa, x) \ big_steps A R exmap j; xa \ I; A [> I\ \ x \ I" apply (erule big_stepsE) apply (frule sub_big_steps_I_holds, assumption+) apply (simp add: inv_holds_def) apply blast done lemma big_step_adt_inv_holds: "A [> I \ big_step_adt A R exmap [> I" apply (simp add: big_step_adt_def inv_holds_def) apply clarsimp apply (rule big_steps_I_holds, assumption+) apply (simp add: inv_holds_def) done lemma big_step_adt_Init_Fin_serial_weak: assumes single_event: "(\(x::'b) (y::'b). x = y)" assumes nrefl: "(\s. \ R s s)" assumes ifsw: "Init_Fin_serial_weak A s0 I" assumes rt: "rel_terminate A s0 R I measuref" assumes J_def: "J = inv_from_rel A s0 R \ I" shows "Init_Fin_serial_weak (big_step_adt A R (exmap::('a list \ 'b))) s0 J" using ifsw apply (unfold_locales) apply (simp add: J_def) apply (rule inv_holds_conjI) apply (rule big_step_adt_R_tranclp_inv) apply (rule big_step_adt_inv_holds) apply (simp add: Init_Fin_serial_weak_def serial_system_weak.I) apply (simp add: big_step_adt_def J_def inv_from_rel_def) apply (elim conjE exE) apply (cut_tac s=s' and I=I and exmap=exmap in big_steps_enabled) apply (force simp: Init_Fin_serial_weak_def) apply (rule rt) apply assumption apply (simp add: nrefl) apply simp apply clarsimp apply (cut_tac x=x and xa=a in single_event[rule_format]) apply blast apply (simp add: J_def big_step_adt_def Init_Fin_serial_weak.Init_Fin) apply (simp add: big_step_adt_def Init_Fin_serial_weak.s0_I J_def inv_from_rel_def, force) done lemma big_step_adt_enabled_system: assumes single_event: "(\(x::'b) (y::'b). x = y)" assumes nrefl: "(\s. \ R s s)" assumes ifsw: "Init_Fin_serial_weak A s0 I" assumes rt: "rel_terminate A s0 R I measuref" shows "enabled_system (big_step_adt A R (exmap::('a list \ 'b))) s0" apply (cut_tac big_step_adt_Init_Fin_serial_weak[OF single_event nrefl ifsw rt]) apply (erule Init_Fin_serial_weak.enabled) apply simp done (* For reachability in big_step_adt we need to consider internal reachability. *) definition reachable_i where "reachable_i A s0 s \ \js. (s0, s) \ Run (data_type.Step A) js" lemma sub_big_steps_Run: "(t,evlist) \ sub_big_steps A R s \ (s, t) \ Run (Step A) evlist \ \ R s t" apply(induct t evlist rule: sub_big_steps.induct) apply simp apply clarsimp apply (rule Run_trans) apply assumption apply simp done lemma big_step_adt_reachable_i_states: "(s0, s) \ Run (data_type.Step (big_step_adt C R exmap)) js \ \js. (s0, s) \ Run (Step C) js" apply(induct js arbitrary: s0) apply (rule_tac x="[]" in exI, simp) apply (clarsimp simp: big_step_adt_def) apply(rename_tac s0 sa) apply(erule big_stepsE) apply(drule sub_big_steps_Run) apply(subgoal_tac "(s0,sa) \ Run (data_type.Step C) (as@[aa])") apply (blast intro: Run_trans) apply(fastforce intro: Run_trans) done lemma reachable_i_big_step_adt: "reachable_i (big_step_adt C R exmap) s0 s \ reachable_i C s0 s" apply(clarsimp simp: reachable_i_def) apply(blast intro: big_step_adt_reachable_i_states) done lemma steps_eq_Run: "(s' \ steps (Step A) (Init A s0) js) = (\s0'. s0' \ Init A s0 \ (s0', s') \ Run (Step A) js)" apply (rule iffI) apply (clarsimp simp: steps_def image_def Image_def) apply (induct js arbitrary: s' rule: rev_induct) apply simp apply (force intro: Run_trans) apply (clarsimp simp: steps_def image_def Image_def) apply (induct js arbitrary: s' rule: rev_induct) apply simp apply clarsimp apply (drule Run_mid, force) done lemma reachable_reachable_i: "system.reachable A s0 s \ \s0' s'. s0' \ Init A s0 \ Fin A s' = s \ reachable_i A s0' s'" by (force simp: system.reachable_def reachable_i_def execution_def steps_eq_Run) lemma reachable_i_reachable: "\reachable_i A s0' s'; s0' \ Init A s0; Fin A s' = s\ \ system.reachable A s0 s" by (force simp: system.reachable_def reachable_i_def execution_def steps_eq_Run) lemma reachable_big_step_adt: "system.reachable (big_step_adt C R exmap) s0 s \ system.reachable C s0 s" by (force dest: reachable_reachable_i intro: reachable_i_reachable reachable_i_big_step_adt simp: big_step_adt_def) lemma big_step_adt_Init_inv_Fin_system: "Init_inv_Fin_system A s0 \ Init_inv_Fin_system (big_step_adt A R exmap) s0" apply (clarsimp simp: Init_inv_Fin_system_def big_step_adt_def) apply (erule_tac x=s in allE) apply (force intro: reachable_big_step_adt simp: big_step_adt_def) done lemma big_step_adt_Step_system: "Init_inv_Fin_system C s0 \ Step_system (big_step_adt C R exmap) s0" apply(rule Init_Fin_system_Step_system) apply(rule Init_inv_Fin_system_Init_Fin_system) apply(rule big_step_adt_Init_inv_Fin_system) apply simp done lemma big_step_adt_enabled_Step_system: assumes single_event: "(\(x::'b) (y::'b). x = y)" assumes nrefl: "(\s. \ R s s)" assumes ifsw: "Init_Fin_serial_weak A s0 I" assumes iifs: "Init_inv_Fin_system A s0" assumes rt: "rel_terminate A s0 R I measuref" shows "enabled_Step_system (big_step_adt A R (examp::('a list \ 'b))) s0" using assms apply(simp add: enabled_Step_system_def big_step_adt_Step_system big_step_adt_enabled_system) done context begin interpretation Arch . (*FIXME: arch_split*) text {* We define a bunch of states that the system can be in. The first two are when the processor is in user mode, the final four are for when in kernel mode. - in user mode (a user-level thread is running) - in idle mode (the idle thread is running) - kernel entry for some event e (kernel entry is occurring) - in kernel mode where kernel execution has been pre-empted by interrupt arrival - in kernel mode where the scheduler is about to execute -- the boolean here is ghost state to capture when the schedule event follows interrupt-handling (i.e. is True when the previous mode was KernelEntry Interrupt or KernelPreempted) - in kernel mode, about to exit to userspace *} datatype sys_mode = InUserMode | InIdleMode | KernelEntry event | KernelPreempted | KernelSchedule bool | KernelExit type_synonym 'k global_sys_state = "(user_context \ 'k) \ sys_mode" text {* We take the @{term global_automaton} and split the kernel transitions into multiple steps. This is done because, while the entire execution from kernel entry to exit is atomic, different parts of it need to be considered as being done on behalf of different domains. For instance, the part that does kernel entry and then handles the event should happen on behalf of the domain of the currently running thread, but the part that handles pre-emptions will probably need to purport to happen on behalf of the scheduler domain. - a transition for kernel entry on event e (kernel entry happens, and we handle the event, possibly gettting pre-empted along the way) - a transition for handling those pre-emptions - a transition for running the scheduler at the end of every kernel event - a transition for kernel exit TODO: schedule and kernel exit may be able to be put into the same transition. It depends on what domain each transition needs to purport to run on behalf of We also have the user operations possibly give an event, which gives us a handle on modelling when user programs request system calls or cause other exceptions to occur. *} definition global_automaton_if :: "((user_context \ 'k) \ irq option \ (user_context \ 'k)) set \ ((user_context \ 'k) \ event option \ (user_context \ 'k)) set \ (event \ ((user_context \ 'k) \ bool \ (user_context \ 'k)) set) \ (((user_context \ 'k) \ unit \ (user_context \ 'k)) set) \ (((user_context \ 'k) \ unit \ (user_context \ 'k)) set) \ (((user_context \ 'k) \ sys_mode \ (user_context \ 'k)) set) \ ('k global_sys_state \ 'k global_sys_state) set" where "global_automaton_if get_active_irqf do_user_opf kernel_callf preemptionf schedulef kernel_exitf \ (* Kernel entry with preemption during event handling NOTE: kernel cannot be preempted while servicing an interrupt *) { ( (s, KernelEntry e), (s', KernelPreempted) ) |s s' e. (s, True, s') \ kernel_callf e \ e \ Interrupt} \ (* kernel entry without preemption during event handling *) { ( (s, KernelEntry e), (s', KernelSchedule (e = Interrupt)) ) |s s' e. (s, False, s') \ kernel_callf e } \ (* handle in-kernel preemption *) { ( (s, KernelPreempted), (s', KernelSchedule True) ) |s s'. (s, (), s') \ preemptionf } \ (* schedule *) { ( (s, KernelSchedule b), (s', KernelExit) ) |s s' b. (s, (), s') \ schedulef } \ (* kernel exit *) { ( (s, KernelExit), (s', m) ) |s s' m. (s, m, s') \ kernel_exitf } \ (* User runs, causes exception *) { ( (s, InUserMode), (s', KernelEntry e ) ) |s s_aux s' e. (s, None, s_aux) \ get_active_irqf \ (s_aux, Some e, s') \ do_user_opf \ e \ Interrupt} \ (* User runs, no exception happens *) { ( (s, InUserMode), (s', InUserMode) ) |s s_aux s'. (s, None, s_aux) \ get_active_irqf \ (s_aux, None, s') \ do_user_opf} \ (* Interrupt while in user mode *) { ( (s, InUserMode), (s', KernelEntry Interrupt) ) |s s' i. (s, Some i, s') \ get_active_irqf} \ (* Interrupt while in idle mode *) { ( (s, InIdleMode), (s', KernelEntry Interrupt) ) |s s' i. (s, Some i, s') \ get_active_irqf} \ (* No interrupt while in idle mode *) { ( (s, InIdleMode), (s', InIdleMode) ) |s s'. (s, None, s') \ get_active_irqf}" type_synonym user_state_if = "user_context \ user_mem \ device_state \ exclusive_monitors" text {* A user transition gives back a possible event that is the next event the user wants to perform *} type_synonym user_transition_if = "obj_ref \ (word32 \ word32) \ (word32 \ vm_rights) \ (word32 \ bool) \ user_state_if \ (event option \ user_state_if) set" lemma dmo_getExMonitor_wp[wp]: "\\s. P (exclusive_state (machine_state s)) s\ do_machine_op getExMonitor \P\" apply(simp add: do_machine_op_def) apply(wp modify_wp | wpc)+ apply clarsimp apply(erule use_valid) apply wp apply simp done lemma setExMonitor_wp[wp]: "\\ms. P (ms\exclusive_state := es\)\ setExMonitor es \\_. P\" apply(simp add: setExMonitor_def | wp)+ done lemma dmo_setExMonitor_wp[wp]: "\\s. P (s\machine_state := machine_state s \exclusive_state := es\\)\ do_machine_op (setExMonitor es) \\_. P\" apply(simp add: do_machine_op_def) apply(wp modify_wp | wpc)+ apply clarsimp apply(erule use_valid) apply wp apply simp done lemma valid_state_exclusive_state_update[iff]: "valid_state (s\machine_state := machine_state s\exclusive_state := es\\) = valid_state s" by (simp add: valid_state_def valid_irq_states_def valid_machine_state_def) lemma cur_tcb_exclusive_state_update[iff]: "cur_tcb (s\machine_state := machine_state s\exclusive_state := es\\) = cur_tcb s" by (simp add: cur_tcb_def) lemma invs_exclusive_state_update[iff]: "invs (s\machine_state := machine_state s\exclusive_state := es\\) = invs s" by (simp add: invs_def) (* FIXME: clagged from AInvs.do_user_op_invs *) lemma do_user_op_if_invs: "\invs and ct_running\ do_user_op_if f tc \\_. invs and ct_running\" apply (simp add: do_user_op_if_def split_def) apply (wp ct_running_machine_op select_wp device_update_invs | wp_once dmo_invs | simp)+ apply (clarsimp simp: user_mem_def user_memory_update_def simpler_modify_def restrict_map_def invs_def cur_tcb_def ptable_rights_s_def ptable_lift_s_def) apply (frule ptable_rights_imp_frame) apply fastforce apply simp apply (clarsimp simp: valid_state_def device_frame_in_device_region) done crunch domain_sep_inv[wp]: do_user_op_if "domain_sep_inv irqs st" (ignore: user_memory_update wp: select_wp) crunch valid_sched[wp]: do_user_op_if "valid_sched" (ignore: user_memory_update wp: select_wp) lemma no_irq_user_memory_update[simp]: "no_irq (user_memory_update a)" apply(wpsimp simp: no_irq_def user_memory_update_def) done lemma no_irq_device_memory_update[simp]: "no_irq (device_memory_update a)" apply(wpsimp simp: no_irq_def device_memory_update_def) done crunch irq_masks[wp]: do_user_op_if "\s. P (irq_masks_of_state s)" (ignore: user_memory_update wp: select_wp dmo_wp no_irq) crunch valid_list[wp]: do_user_op_if "valid_list" (ignore: user_memory_update wp: select_wp) lemma do_user_op_if_scheduler_action[wp]: "\(\s. P (scheduler_action s))\ do_user_op_if f tc \\_ s. P (scheduler_action s)\" apply(simp add: do_user_op_if_def | wp select_wp | wpc)+ done lemma do_user_op_silc_inv[wp]: "\silc_inv aag st\ do_user_op_if f tc \\_. silc_inv aag st\" apply (simp add: do_user_op_if_def) apply (wp select_wp | wpc | simp)+ done lemma do_user_op_pas_refined[wp]: "\pas_refined aag\ do_user_op_if f tc \\_. pas_refined aag\" apply (simp add: do_user_op_if_def) apply (wp select_wp | wpc | simp)+ done crunch cur_thread[wp]: do_user_op_if "\s. P (cur_thread s)" (wp: select_wp ignore: user_memory_update) crunch cur_domain[wp]: do_user_op_if "\s. P (cur_domain s)" (wp: select_wp ignore: user_memory_update) crunch idle_thread[wp]: do_user_op_if "\s. P (idle_thread s)" (wp: select_wp ignore: user_memory_update) lemma do_use_op_guarded_pas_domain[wp]: "\guarded_pas_domain aag\ do_user_op_if f tc \\_. guarded_pas_domain aag\" by (rule guarded_pas_domain_lift; wp) crunch domain_fields[wp]: do_user_op_if "domain_fields P" (wp: select_wp ignore: user_memory_update) definition do_user_op_A_if :: "user_transition_if \ ((user_context \ det_state) \ event option \ (user_context \ det_state)) set" where "do_user_op_A_if uop \ {(s,e,(tc,s'))| s e tc s'. ((e,tc),s') \ fst (split (do_user_op_if uop) s)}" text {* Enter the kernel, and handle the event. Leave the user context unchanged; although it shouldn't matter really what its value is while we are still in kernel mode. *} definition kernel_entry_if :: "event \ user_context \ (((interrupt + unit) \ user_context),det_ext) s_monad" where "kernel_entry_if e tc \ do t \ gets cur_thread; thread_set (\tcb. tcb \ tcb_arch := arch_tcb_context_set tc (tcb_arch tcb)\) t; r \ handle_event e; return (r,tc) od" crunch cur_domain[wp]: kernel_entry_if "\s. P (cur_domain s)" crunch idle_thread[wp]: kernel_entry_if "\s::det_state. P (idle_thread s)" crunch cur_thread [wp]: kernel_entry_if "\s. P (cur_thread s)" lemma thread_set_tcb_context_update_ct_active[wp]: "\ct_active\ thread_set (tcb_arch_update (arch_tcb_context_set f)) t \\rv. ct_active\" apply(simp add: thread_set_def ct_in_state_def | wp set_object_wp)+ apply(clarsimp simp: st_tcb_at_def obj_at_def get_tcb_def) done lemma thread_set_tcb_context_update_not_ct_active[wp]: "\\s. \ ct_active s\ thread_set (tcb_arch_update (arch_tcb_context_set f)) t \\r s. \ ct_active s\" apply(simp add: thread_set_def ct_in_state_def | wp set_object_wp)+ apply(clarsimp simp: st_tcb_at_def obj_at_def get_tcb_def split: kernel_object.splits option.splits) done (*FIXME: Move to FinalCaps*) lemma thread_set_silc_inv_trivial: "(\tcb. \(getF, v)\ran tcb_cap_cases. getF (F tcb) = getF tcb) \ \silc_inv aag st\ thread_set F word \\xa. silc_inv aag st\" unfolding thread_set_def apply(rule silc_inv_pres) apply(wp set_object_wp) apply (simp split: kernel_object.splits) apply(rule impI | simp)+ apply(fastforce simp: silc_inv_def dest: get_tcb_SomeD simp: obj_at_def is_cap_table_def) apply(wp set_object_wp | simp)+ apply(case_tac "word = fst slot") apply(clarsimp split: kernel_object.splits) apply(erule notE) apply(erule cte_wp_atE) apply(fastforce simp: obj_at_def) apply(drule get_tcb_SomeD) apply(rule cte_wp_at_tcbI) apply(simp) apply assumption apply (clarsimp simp: tcb_cap_cases_def tcb_registers_caps_merge_def split: if_splits) apply(fastforce elim: cte_wp_atE intro: cte_wp_at_cteI cte_wp_at_tcbI) done lemma kernel_entry_if_invs: "\invs and (\s. e \ Interrupt \ ct_active s)\ kernel_entry_if e tc \\_. invs\" unfolding kernel_entry_if_def apply (wpsimp wp: thread_set_invs_trivial static_imp_wp simp: arch_tcb_update_aux2 tcb_cap_cases_def)+ done lemma idle_equiv_as_globals_equiv: "arm_global_pd (arch_state s) \ idle_thread s \ idle_equiv st s = globals_equiv (st\arch_state := (arch_state s), machine_state := (machine_state s),kheap:= ((kheap st)((arm_global_pd (arch_state s)) := (kheap s (arm_global_pd (arch_state s))))),cur_thread := cur_thread s\) s" apply (clarsimp simp: idle_equiv_def globals_equiv_def tcb_at_def2) done lemma idle_globals_lift: assumes g: "\st. \globals_equiv st and P\ f \\_. globals_equiv st\" assumes i: "\s. P s \ arm_global_pd (arch_state s) \ idle_thread s" shows "\idle_equiv st and P\ f \\_. idle_equiv st\" apply (clarsimp simp: valid_def) apply (subgoal_tac "arm_global_pd (arch_state s) \ idle_thread s") apply (subst (asm) idle_equiv_as_globals_equiv,simp+) apply (frule use_valid[OF _ g]) apply simp+ apply (clarsimp simp: idle_equiv_def globals_equiv_def tcb_at_def2) apply (erule i) done lemma idle_equiv_as_globals_equiv_scheduler: "arm_global_pd (arch_state s) \ idle_thread s \ idle_equiv st s = globals_equiv_scheduler (st\arch_state := (arch_state s), machine_state := (machine_state s),kheap:= ((kheap st)((arm_global_pd (arch_state s)) := (kheap s (arm_global_pd (arch_state s)))))\) s" apply (clarsimp simp: idle_equiv_def globals_equiv_scheduler_def tcb_at_def2) done lemma idle_globals_lift_scheduler: assumes g: "\st. \globals_equiv_scheduler st and P\ f \\_. globals_equiv_scheduler st\" assumes i: "\s. P s \ arm_global_pd (arch_state s) \ idle_thread s" shows "\idle_equiv st and P\ f \\_. idle_equiv st\" apply (clarsimp simp: valid_def) apply (subgoal_tac "arm_global_pd (arch_state s) \ idle_thread s") apply (subst (asm) idle_equiv_as_globals_equiv_scheduler,simp+) apply (frule use_valid[OF _ g]) apply simp+ apply (clarsimp simp: idle_equiv_def globals_equiv_scheduler_def tcb_at_def2) apply (erule i) done lemma invs_pd_not_idle_thread[intro]: "invs s \ arm_global_pd (arch_state s) \ idle_thread s" apply (fastforce simp: invs_def valid_state_def valid_global_objs_def obj_at_def valid_idle_def pred_tcb_at_def empty_table_def) done lemma kernel_entry_if_globals_equiv: "\invs and (\s. e \ Interrupt \ ct_active s) and globals_equiv st and (\s. ct_idle s \ tc = idle_context s) \ kernel_entry_if e tc \\_. globals_equiv st\" apply (simp add: kernel_entry_if_def) apply (wp static_imp_wp handle_event_globals_equiv thread_set_invs_trivial thread_set_context_globals_equiv | simp add: tcb_cap_cases_def arch_tcb_update_aux2)+ apply (clarsimp simp: cur_thread_idle) done lemma kernel_entry_if_idle_equiv: "\invs and (\s. e \ Interrupt \ ct_active s) and idle_equiv st and (\s. ct_idle s \ tc = idle_context s) \ kernel_entry_if e tc \\_. idle_equiv st\" apply (rule hoare_pre) apply (rule idle_globals_lift) apply (wp kernel_entry_if_globals_equiv) apply force apply (fastforce intro!: invs_pd_not_idle_thread)+ done lemma thread_set_tcb_context_update_neg_cte_wp_at[wp]: "\\s. \ cte_wp_at P slot s\ thread_set (tcb_arch_update (arcb_tcb_context_set blah)) param_a \\_ s. \ cte_wp_at P slot s\" apply(simp add: thread_set_def) apply(wp set_object_wp get_object_wp | simp)+ apply(case_tac "param_a = fst slot") apply(clarsimp split: kernel_object.splits) apply(erule notE) apply(erule cte_wp_atE) apply(fastforce simp: obj_at_def) apply(drule get_tcb_SomeD) apply(rule cte_wp_at_tcbI) apply(simp) apply assumption apply (fastforce simp: tcb_cap_cases_def split: if_splits) apply(fastforce elim: cte_wp_atE intro: cte_wp_at_cteI cte_wp_at_tcbI) done lemma thread_set_tcb_context_update_domain_sep_inv[wp]: "\domain_sep_inv irqs st\ thread_set (tcb_arch_update (arch_tcb_context_set f)) t \\rv. domain_sep_inv irqs st\" apply(wp domain_sep_inv_triv) done lemma kernel_entry_silc_inv[wp]: "\silc_inv aag st and einvs and simple_sched_action and (\s. ev \ Interrupt \ ct_active s) and pas_refined aag and (\s. ct_active s \ is_subject aag (cur_thread s)) and domain_sep_inv (pasMaySendIrqs aag) st'\ kernel_entry_if ev tc \\_. silc_inv aag st\" unfolding kernel_entry_if_def apply (wpsimp simp: tcb_cap_cases_def arch_tcb_update_aux2 wp: static_imp_wp handle_event_silc_inv thread_set_silc_inv_trivial thread_set_invs_trivial thread_set_not_state_valid_sched thread_set_pas_refined | wp_once hoare_vcg_imp_lift)+ apply force done lemma kernel_entry_pas_refined[wp]: "\pas_refined aag and guarded_pas_domain aag and domain_sep_inv (pasMaySendIrqs aag) st and einvs and schact_is_rct and (\s. ct_active s \ is_subject aag (cur_thread s)) and (\s. ev \ Interrupt \ ct_active s)\ kernel_entry_if ev tc \\rv. pas_refined aag\" unfolding kernel_entry_if_def apply (wpsimp simp: tcb_cap_cases_def schact_is_rct_def arch_tcb_update_aux2 tcb_arch_ref_def wp: static_imp_wp handle_event_pas_refined thread_set_pas_refined guarded_pas_domain_lift thread_set_invs_trivial thread_set_not_state_valid_sched)+ apply force done lemma kernel_entry_if_domain_sep_inv: "\domain_sep_inv irqs st and einvs and (\s. e \ Interrupt \ ct_active s)\ kernel_entry_if e tc \\_. domain_sep_inv irqs st\" unfolding kernel_entry_if_def apply( wpsimp simp: tcb_cap_cases_def arch_tcb_update_aux2 tcb_arch_ref_def wp: handle_event_domain_sep_inv static_imp_wp thread_set_invs_trivial thread_set_not_state_valid_sched)+ done lemma kernel_entry_if_guarded_pas_domain: "\guarded_pas_domain aag\ kernel_entry_if e tc \\_. guarded_pas_domain aag\" apply (simp add: kernel_entry_if_def) apply (wp guarded_pas_domain_lift) done lemma kernel_entry_if_valid_sched: "\valid_sched and invs and (ct_active or ct_idle) and (\s. (e \ Interrupt \ ct_active s) \ scheduler_action s = resume_cur_thread)\ kernel_entry_if e tc \\_. valid_sched\" apply(wpsimp simp: kernel_entry_if_def tcb_cap_cases_def arch_tcb_update_aux2 tcb_arch_ref_def wp: handle_event_valid_sched thread_set_invs_trivial hoare_vcg_disj_lift thread_set_no_change_tcb_state ct_in_state_thread_state_lift thread_set_not_state_valid_sched static_imp_wp)+ done lemma kernel_entry_if_irq_masks: "\(\s. P (irq_masks_of_state s)) and domain_sep_inv False st and invs\ kernel_entry_if e tc \\_ s. P (irq_masks_of_state s)\" apply( simp add: kernel_entry_if_def tcb_cap_cases_def arch_tcb_update_aux2 tcb_arch_ref_def | wp handle_event_irq_masks thread_set_invs_trivial)+ by fastforce crunch valid_list[wp]: kernel_entry_if "valid_list" definition kernel_call_A_if :: "event \ ((user_context \ det_state) \ bool \ (user_context \ det_state)) set" where "kernel_call_A_if e \ {(s, b, (tc,s'))|s b tc s' r. ((r,tc),s') \ fst (split (kernel_entry_if e) s) \ b = (case r of Inl _ \ True | Inr _ \ False)}" text {* Since this executes entirely in kernel mode, leave the user context unchanged *} definition handle_preemption_if :: "user_context \ (user_context,det_ext) s_monad" where "handle_preemption_if tc \ do irq \ do_machine_op (getActiveIRQ False); when (irq \ None) $ handle_interrupt (the irq); return tc od" lemma handle_preemption_if_invs: "\invs\ handle_preemption_if tc \\_. invs\" apply(simp add: handle_preemption_if_def | wp)+ done lemma handle_preemption_if_domain_sep_inv: "\domain_sep_inv irqs st\ handle_preemption_if e \\_. domain_sep_inv irqs st\" apply(simp add: handle_preemption_if_def | wp)+ done lemma handle_preemption_if_silc_inv[wp]: "\silc_inv aag st\ handle_preemption_if tc \\_. silc_inv aag st\" apply (simp add: handle_preemption_if_def) apply (wp handle_interrupt_silc_inv do_machine_op_silc_inv | simp)+ done lemma handle_preemption_if_pas_refined[wp]: "\pas_refined aag\ handle_preemption_if tc \\_. pas_refined aag\" apply (simp add: handle_preemption_if_def) apply (wp handle_interrupt_pas_refined | simp)+ done crunch cur_thread[wp]: handle_preemption_if "\s. P (cur_thread s)" crunch cur_domain[wp]: handle_preemption_if " \s. P (cur_domain s)" crunch idle_thread[wp]: handle_preemption_if "\s::det_state. P (idle_thread s)" lemma handle_preemption_if_guarded_pas_domain[wp]: "\guarded_pas_domain aag\ handle_preemption_if tc \\_. guarded_pas_domain aag\" by (rule guarded_pas_domain_lift; wp) (* crunch valid_sched[wp]: handle_interrupt "valid_sched" (wp: crunch_wps simp: crunch_simps ignore: getActiveIRQ) *) lemma handle_preemption_if_valid_sched[wp]: "\valid_sched and invs and (\s. irq \ non_kernel_IRQs \ scheduler_act_sane s \ ct_not_queued s)\ handle_preemption_if irq \\_. valid_sched\" apply (wpsimp simp: handle_preemption_if_def non_kernel_IRQs_def)+ apply (wpsimp wp: hoare_drop_imp hoare_vcg_if_lift2)+ done context begin interpretation Arch . (*FIXME: arch_split*) lemma handle_preemption_if_irq_masks: "\(\s. P (irq_masks_of_state s)) and domain_sep_inv False st\ handle_preemption_if tc \\_ s. P (irq_masks_of_state s)\" apply(simp add: handle_preemption_if_def | wp handle_interrupt_irq_masks[where st=st])+ apply(rule_tac Q="\rv s. P (irq_masks_of_state s) \ domain_sep_inv False st s \ (\x. rv = Some x \ x \ maxIRQ) " in hoare_strengthen_post) by(wp | simp)+ end crunch valid_list[wp]: handle_preemption_if "valid_list" (ignore: getActiveIRQ) definition kernel_handle_preemption_if :: "((user_context \ det_state) \ unit \ (user_context \ det_state)) set" where "kernel_handle_preemption_if \ {(s, u, s'). s' \ fst (split handle_preemption_if s)}" text {* Since this executes entirely in kernel mode, leave the user context unchanged *} definition schedule_if :: "user_context \ (user_context,det_ext) s_monad" where "schedule_if tc \ do schedule; activate_thread; return tc od" lemma schedule_if_invs[wp]: "\invs\ schedule_if tc \\_. invs\" apply(simp add: schedule_if_def | wp)+ apply(rule hoare_strengthen_post[OF activate_invs] | simp | wp)+ done crunch pas_refined[wp]: schedule_if "pas_refined aag" crunch silc_inv[wp]: schedule_if "silc_inv aag st" crunch domain_sep_inv[wp]: schedule_if "\s::det_state. domain_sep_inv irqs st s" crunch cur_thread[wp]: activate_thread "\s. P (cur_thread s)" crunch cur_domain[wp]: activate_thread "\s. P (cur_domain s)" crunch idle_thread[wp]: activate_thread "\s. P (idle_thread s)" lemma activate_thread_guarded_pas_domain[wp]: "\guarded_pas_domain aag\ activate_thread \\_. guarded_pas_domain aag\" by (rule guarded_pas_domain_lift; wp activate_thread_cur_thread) lemma guarded_pas_domain_arch_state_update[simp]: "guarded_pas_domain aag (s\arch_state := x\) = guarded_pas_domain aag s" apply (simp add: guarded_pas_domain_def) done lemma switch_to_thread_guarded_pas_domain: "\\s. pasDomainAbs aag (cur_domain s) = pasObjectAbs aag t\ switch_to_thread t \\_. guarded_pas_domain aag\" apply (simp add: switch_to_thread_def) apply (wp modify_wp hoare_drop_imps| simp add: guarded_pas_domain_def)+ done lemma guarded_pas_domain_machine_state_update[simp]: "guarded_pas_domain aag (s\machine_state := x\) = guarded_pas_domain aag s" apply (simp add: guarded_pas_domain_def) done (* FIXME: Why was the [wp] attribute clobbered by interpretation of the Arch locale? *) declare storeWord_irq_masks[wp] lemma switch_to_idle_thread_guarded_pas_domain[wp]: "\\\ switch_to_idle_thread \\xb. guarded_pas_domain aag\" apply (simp add: switch_to_idle_thread_def arch_switch_to_idle_thread_def bind_assoc double_gets_drop_regets) apply (wp modify_wp dmo_wp hoare_vcg_imp_lift | wp_once | simp add: guarded_pas_domain_def)+ done lemma choose_thread_guarded_pas_domain: "\pas_refined aag and valid_queues\ choose_thread \\xb. guarded_pas_domain aag\" apply (simp add: choose_thread_def guarded_switch_to_def | wp switch_to_thread_respects switch_to_idle_thread_respects gts_wp switch_to_thread_guarded_pas_domain)+ apply (clarsimp simp: pas_refined_def) apply (clarsimp simp: tcb_domain_map_wellformed_aux_def) apply (erule_tac x="(hd (max_non_empty_queue (ready_queues s (cur_domain s))), cur_domain s)" in ballE) apply simp apply (clarsimp simp: valid_queues_def is_etcb_at_def) apply (erule_tac x="cur_domain s" in allE) apply (erule_tac x="Max {prio. ready_queues s (cur_domain s) prio \ []}" in allE) apply clarsimp apply (erule_tac x="hd (max_non_empty_queue (ready_queues s (cur_domain s)))" in ballE) apply (clarsimp) apply (erule notE, rule domtcbs) apply force apply (simp add: etcb_at_def) apply (simp add: max_non_empty_queue_def) apply (erule_tac P="hd A \ B" for A B in notE) apply (rule Max_prop) apply force+ done lemma switch_within_domain: "\scheduler_action s = switch_thread x;valid_sched s; pas_refined aag s\ \ pasDomainAbs aag (cur_domain s) = pasObjectAbs aag x" apply (clarsimp simp add: valid_sched_def valid_sched_action_def switch_in_cur_domain_def in_cur_domain_def etcb_at_def valid_etcbs_def st_tcb_at_def is_etcb_at_def weak_valid_sched_action_def) apply (drule_tac x=x in spec) apply (simp add: obj_at_def) apply (clarsimp simp add: pas_refined_def tcb_domain_map_wellformed_aux_def) apply (drule_tac x="(x,tcb_domain y)" in bspec) apply (rule domtcbs) apply simp+ done lemma schedule_guarded_pas_domain: "\guarded_pas_domain aag and einvs and pas_refined aag\ schedule \\_. guarded_pas_domain aag\" supply ethread_get_wp[wp del] apply (simp add: schedule_def) apply (wpsimp wp: guarded_pas_domain_lift[where f="activate_thread"] guarded_pas_domain_lift[where f="set_scheduler_action f" for f] guarded_switch_to_lift switch_to_thread_guarded_pas_domain next_domain_valid_queues activate_thread_cur_thread gts_wp | wpc | rule choose_thread_guarded_pas_domain | simp add: schedule_choose_new_thread_def ethread_get_when_def split del: if_split | wp_once hoare_drop_imp[where f="ethread_get t v" for t v] | wp_once hoare_drop_imp[where f="schedule_switch_thread_fastfail c i cp p" for c i cp p])+ apply (wp hoare_drop_imp) apply (wpsimp wp: guarded_pas_domain_lift[where f="activate_thread"] guarded_pas_domain_lift[where f="set_scheduler_action f" for f] guarded_switch_to_lift switch_to_thread_guarded_pas_domain next_domain_valid_queues activate_thread_cur_thread gts_wp | wpc | rule choose_thread_guarded_pas_domain | simp add: schedule_choose_new_thread_def ethread_get_when_def split del: if_split | wp_once hoare_drop_imp[where f="ethread_get t v" for t v] | wp_once hoare_drop_imp[where f="schedule_switch_thread_fastfail c i cp p" for c i cp p])+ apply (fastforce intro: switch_within_domain switch_thread_runnable simp: valid_sched_def elim!: st_tcb_weakenE)+ done lemma schedule_if_guarded_pas_domain[wp]: "\guarded_pas_domain aag and einvs and pas_refined aag\ schedule_if tc \\_. guarded_pas_domain aag\" apply (simp add: schedule_if_def) apply (wp schedule_guarded_pas_domain) done lemma schedule_if_ct_running_or_ct_idle[wp]: "\invs\ schedule_if tc \\_ s. ct_running s \ ct_idle s\" apply(simp add: schedule_if_def | wp)+ apply(rule hoare_strengthen_post[OF activate_invs] | simp | wp)+ done lemma set_thread_state_scheduler_action: "\(\s. P (scheduler_action (s::det_state))) and st_tcb_at runnable t and K (runnable s)\ set_thread_state t s \\_ s. P (scheduler_action s)\" apply(simp add: set_thread_state_def | wp sts_ext_running_noop set_object_wp)+ apply(clarsimp simp: st_tcb_at_def obj_at_def) done lemma activate_thread_scheduler_action[wp]: "\ \s. P (scheduler_action (s::det_state)) \ activate_thread \ \_ s. P (scheduler_action s)\" apply(simp add: activate_thread_def arch_activate_idle_thread_def | wp set_thread_state_scheduler_action gts_wp | wpc)+ apply(fastforce elim: st_tcb_weakenE) done declare gts_st_tcb_at[wp del] lemma schedule_if_scheduler_action[wp]: "\\\ schedule_if tc \\_ (s::det_state). scheduler_action s = resume_cur_thread\" apply(simp add: schedule_if_def | wp | wpc)+ apply(simp add: schedule_def schedule_choose_new_thread_def split del: if_split | wp | wpc)+ done crunch valid_sched[wp]: schedule_if "valid_sched" lemma schedule_if_irq_masks: "\(\s. P (irq_masks_of_state s)) and domain_sep_inv False st\ schedule_if tc \\_ s. P (irq_masks_of_state s)\" apply(simp add: schedule_if_def | wp)+ done crunch valid_list[wp]: schedule_if "valid_list" definition kernel_schedule_if :: "((user_context \ det_state) \ unit \ (user_context \ det_state)) set" where "kernel_schedule_if \ {(s, e, s'). s' \ fst (split schedule_if s)}" text {* Restore the user context *} definition kernel_exit_if :: "user_context \ (user_context,det_ext) s_monad" where "kernel_exit_if tc \ do t' \ gets cur_thread; thread_get (arch_tcb_context_get o tcb_arch) t' od" crunch inv[wp]: kernel_exit_if "P" definition kernel_exit_A_if :: "((user_context \ det_state) \ sys_mode \ (user_context \ det_state)) set" where "kernel_exit_A_if \ {(s, m, s'). s' \ fst (split kernel_exit_if s) \ m = (if ct_running (snd s') then InUserMode else InIdleMode)}" type_synonym observable_if = "det_state global_sys_state" text {* Check for active IRQs without updating the user context *} definition check_active_irq_if :: "user_context \ (irq option \ user_context, ('z :: state_ext)) s_monad" where "check_active_irq_if tc \ do irq \ do_machine_op (getActiveIRQ False); return (irq, tc) od" definition check_active_irq_A_if :: "((user_context \ ('z :: state_ext) state) \ irq option \ (user_context \ ('z :: state_ext) state)) set" where "check_active_irq_A_if \ {((tc, s), irq, (tc', s')). ((irq, tc'), s') \ fst (check_active_irq_if tc s)}" abbreviation internal_state_if :: "((MachineTypes.register \ 32 word) \ 'a) \ sys_mode \ 'a" where "internal_state_if \ \s. (snd (fst s))" lemma valid_device_abs_state_eq: "\valid_machine_state s\ \ abs_state s = s" apply (simp add: abs_state_def observable_memory_def) apply (case_tac s) apply clarsimp apply (case_tac machine_state) apply clarsimp apply (rule ext) apply (fastforce simp: user_mem_def option_to_0_def valid_machine_state_def) done (*Weakened invs_if to properties only necessary for refinement*) definition full_invs_if :: "observable_if set" where "full_invs_if \ {s. einvs (internal_state_if s) \ (snd s \ KernelSchedule True \ domain_time (internal_state_if s) > 0) \ (domain_time (internal_state_if s) = 0 \ scheduler_action (internal_state_if s) = choose_new_thread) \ valid_domain_list (internal_state_if s) \ (case (snd s) of (KernelEntry e) \ (e \ Interrupt \ ct_running (internal_state_if s)) \ (ct_running (internal_state_if s) \ ct_idle (internal_state_if s)) \ scheduler_action (internal_state_if s) = resume_cur_thread | KernelExit \ (ct_running (internal_state_if s) \ ct_idle (internal_state_if s)) \ scheduler_action (internal_state_if s) = resume_cur_thread | InUserMode \ ct_running (internal_state_if s) \ scheduler_action (internal_state_if s) = resume_cur_thread | InIdleMode \ ct_idle (internal_state_if s) \ scheduler_action (internal_state_if s) = resume_cur_thread | _ \ True) }" end (*We'll define this later, currently it doesn't matter if we restrict the permitted steps of the system*) consts step_restrict :: "(det_state global_sys_state) \ bool" context begin interpretation Arch . (*FIXME: arch_split*) definition ADT_A_if :: "(user_transition_if) \ (det_state global_sys_state, observable_if, unit) data_type" where "ADT_A_if uop \ \ Init = \s. {s} \ full_invs_if \ {s. step_restrict s}, Fin = id, Step = (\u. global_automaton_if check_active_irq_A_if (do_user_op_A_if uop) kernel_call_A_if kernel_handle_preemption_if kernel_schedule_if kernel_exit_A_if \ {(s,s'). step_restrict s'})\" lemma check_active_irq_if_wp: "\\s. P ((irq_at (irq_state (machine_state s) + 1) (irq_masks (machine_state s))),tc) (s\machine_state := (machine_state s\irq_state := irq_state (machine_state s) + 1\)\)\ check_active_irq_if tc \P\" apply(simp add: check_active_irq_if_def | wp dmo_getActiveIRQ_wp)+ done lemma do_user_op_if_only_timer_irq_inv[wp]: "\only_timer_irq_inv irq (st::det_state)\ do_user_op_if a b \\_. only_timer_irq_inv irq st\" apply(rule hoare_pre) apply(wp only_timer_irq_inv_pres | simp | blast)+ done lemma kernel_entry_if_only_timer_irq_inv: "\only_timer_irq_inv irq st and einvs and (\s. e \ Interrupt \ ct_active s)\ kernel_entry_if e tc \\_. only_timer_irq_inv irq st\" apply(rule hoare_pre) apply(wp only_timer_irq_inv_pres kernel_entry_if_irq_masks kernel_entry_if_domain_sep_inv | simp)+ by blast lemma handle_preemption_if_only_timer_irq_inv[wp]: "\only_timer_irq_inv irq st\ handle_preemption_if tc \\_. only_timer_irq_inv irq st\" apply(rule hoare_pre) apply(wp only_timer_irq_inv_pres handle_preemption_if_irq_masks handle_preemption_if_domain_sep_inv | simp | blast)+ done lemma schedule_if_only_timer_irq_inv[wp]: "\only_timer_irq_inv irq st\ schedule_if tc \\_. only_timer_irq_inv irq st\" apply(rule hoare_pre) apply(wp only_timer_irq_inv_pres schedule_if_irq_masks | blast)+ done fun interrupted_modes where "interrupted_modes KernelPreempted = True" | "interrupted_modes (KernelEntry Interrupt) = True" | "interrupted_modes _ = False" text {* A first attempt at defining the big steps. They look like this: user mode +-----------+ +------ ... - - - - - - - - / \ / kernel mode / +---------------+ KernelExit interrupted KernelExit big steps --------------> --------------> ------- ... dom current dom scheduler current dom That is, a step of the current domain lasts from its kernel exit until the point at which the kernel services the next interrupt, either because the arrival of that interrupt traps from user- to kernel-mode (in which case the system has just moved into KernelEntry Interrupt state) or because a long-running system call was pre-empted by the arrival of an interrupt (in which case the system has just moved into the KernelPreempted state). The scheduler domain then runs until the next kernel exit, at which point whoever is now the current domain begins its big execution step. *} definition big_step_R :: "det_state global_sys_state \ det_state global_sys_state \ bool" where "big_step_R \ \ s s'. (snd s = KernelExit \ interrupted_modes (snd s')) \ (interrupted_modes (snd s) \ snd s' = KernelExit)" definition big_step_evmap :: "unit list \ unit" where "big_step_evmap evs \ ()" definition big_step_ADT_A_if (*:: "user_transition_if \ (observable_if, observable_if, unit) data_type"*) where "big_step_ADT_A_if utf \ big_step_adt (ADT_A_if utf) big_step_R big_step_evmap" lemma guarded_active_ct_cur_domain: "\guarded_pas_domain aag s; ct_active s; invs s\ \ pasObjectAbs aag (cur_thread s) = pasDomainAbs aag (cur_domain s)" apply (fastforce simp add: guarded_pas_domain_def invs_def valid_state_def valid_idle_def ct_in_state_def pred_tcb_at_def obj_at_def) done lemma ct_active_not_idle: "ct_active s \ invs s \ cur_thread s \ idle_thread s" apply (clarsimp simp add: ct_in_state_def valid_state_def valid_idle_def pred_tcb_at_def obj_at_def invs_def) done definition cur_context where "cur_context s = arch_tcb_context_get (tcb_arch (the (get_tcb (cur_thread s) s)))" end (* the second argument of det_inv the user_context, which is saved in kernel state on kernel_entry_if, and restored on kernel_exit_if. Between these sys_modes the user_context that is passed through is not used, rather cur_context is. *) locale invariant_over_ADT_if = fixes det_inv :: "sys_mode \ user_context \ det_state \ bool" fixes utf :: "user_transition_if" assumes det_inv_abs_state: "\e tc s. valid_machine_state s \ det_inv e tc s \ det_inv e tc (abs_state s)" assumes kernel_entry_if_det_inv: "\e tc. \einvs and det_inv (KernelEntry e) tc and ct_running and K (e \ Interrupt)\ kernel_entry_if e tc \\rv s. case (fst rv) of Inl irq \ det_inv KernelPreempted (cur_context s) s | Inr () \ det_inv (KernelSchedule False) (cur_context s) s\" assumes kernel_entry_if_Interrupt_det_inv: "\tc. \einvs and det_inv (KernelEntry Interrupt) tc and (\s. ct_running s \ ct_idle s)\ kernel_entry_if Interrupt tc \\rv s. case (fst rv) of Inl irq \ det_inv KernelPreempted (cur_context s) s | Inr () \ det_inv (KernelSchedule True) (cur_context s) s\" assumes handle_preemption_if_det_inv: "\tc. \einvs and (\s. det_inv KernelPreempted (cur_context s) s)\ handle_preemption_if tc \\rv s. det_inv (KernelSchedule True) (cur_context s) s\" assumes schedule_if_det_inv: "\b tc. \einvs and (\s. det_inv (KernelSchedule b) (cur_context s) s)\ schedule_if tc \\rv s. det_inv KernelExit (cur_context s) s\" assumes kernel_exit_if_det_inv: "\tc. \einvs and (\s. det_inv KernelExit (cur_context s) s) and (\s. ct_running s \ ct_idle s)\ kernel_exit_if tc \\rv s. if ct_running s then det_inv InUserMode rv s else det_inv InIdleMode rv s\" assumes do_user_op_if_det_inv: "\tc. \einvs and det_inv InUserMode tc and ct_running\ do_user_op_if utf tc \\rv. case (fst rv) of Some e \ det_inv (KernelEntry e) (snd rv) | None \ det_inv InUserMode (snd rv)\" assumes check_active_irq_if_User_det_inv: "\tc. \einvs and det_inv InUserMode tc and ct_running\ check_active_irq_if tc \\rv. case (fst rv) of Some irq \ det_inv (KernelEntry Interrupt) (snd rv) | None \ det_inv InUserMode (snd rv)\" assumes check_active_irq_if_Idle_det_inv: "\tc. \einvs and det_inv InIdleMode tc and ct_idle\ check_active_irq_if tc \\rv. case (fst rv) of Some irq \ det_inv (KernelEntry Interrupt) (snd rv) | None \ det_inv InIdleMode (snd rv)\" locale valid_initial_state_noenabled = invariant_over_ADT_if + Arch + (* FIXME: arch_split *) fixes s0_internal :: det_state fixes initial_aag :: "'a subject_label PAS" fixes timer_irq :: "10 word" fixes current_aag fixes s0 :: observable_if fixes s0_context :: user_context defines "current_aag t \ (initial_aag\ pasSubject := pasDomainAbs initial_aag (cur_domain t) \)" (* Run the system from right where we exit the kernel for the first time to user-space. It shouldn't matter what the initial machine context is since the first thing that should happen on a KernelExit is to restore it from the cur_thread *) defines "s0 \ ((if ct_idle s0_internal then idle_context s0_internal else s0_context,s0_internal),KernelExit)" assumes cur_domain_subject_s0: "pasDomainAbs initial_aag (cur_domain s0_internal) = pasSubject initial_aag" assumes policy_wellformed: "pas_wellformed_noninterference initial_aag" fixes Invs defines "Invs s \ einvs s \ only_timer_irq_inv timer_irq s0_internal s \ silc_inv (current_aag s) s0_internal s \ domain_sep_inv False s0_internal s \ pas_refined (current_aag s) s \ guarded_pas_domain (current_aag s) s \ idle_equiv s0_internal s \ valid_domain_list s \ valid_pdpt_objs s" assumes Invs_s0_internal: "Invs s0_internal" assumes det_inv_s0: "det_inv KernelExit (cur_context s0_internal) s0_internal" assumes scheduler_action_s0_internal: "scheduler_action s0_internal = resume_cur_thread" assumes ct_running_or_ct_idle_s0_internal: "ct_running s0_internal \ ct_idle s0_internal" assumes domain_time_s0_internal: "domain_time s0_internal > 0" assumes num_domains_sanity: "num_domains > 1" assumes utf_det: "\pl pr pxn tc um ds es s. det_inv InUserMode tc s \ einvs s \ context_matches_state pl pr pxn um ds es s \ ct_running s \ (\x. utf (cur_thread s) pl pr pxn (tc, um, ds, es) = {x})" assumes utf_non_empty: "\t pl pr pxn tc um ds es. utf t pl pr pxn (tc, um, ds, es) \ {}" assumes utf_non_interrupt: "\t pl pr pxn tc um ds es e f g. (e,f,g) \ utf t pl pr pxn (tc, um, ds, es) \ e \ Some Interrupt" assumes extras_s0: "step_restrict s0" assumes pasMaySendIrqs_initial_aag[simp]: "pasMaySendIrqs initial_aag = False" locale valid_initial_state = valid_initial_state_noenabled + assumes ADT_A_if_enabled_system: "enabled_system (ADT_A_if utf) s0" assumes ADT_A_if_Init_Fin_serial: "Init_Fin_serial (ADT_A_if utf) s0 (full_invs_if \ {s. step_restrict s})" function (domintros) next_irq_state :: "nat \ (10 word \ bool) \ nat" where "next_irq_state cur masks = (if irq_at cur masks = None then next_irq_state (Suc cur) masks else cur)" by(pat_completeness, auto) lemma recurring_next_irq_state_dom: "irq_is_recurring irq s \ next_irq_state_dom (n,irq_masks (machine_state s))" apply(clarsimp simp: irq_is_recurring_def) apply(drule_tac x=n in spec) apply(erule exE) proof - fix m assume i: "is_irq_at s irq (n + m)" have "n \ n + m" by simp thus "next_irq_state_dom (n, irq_masks (machine_state s))" proof(induct rule: inc_induct) from i obtain irq where a: "irq_at (n + m) (irq_masks (machine_state s)) = Some irq" by(fastforce simp: is_irq_at_def) show "next_irq_state_dom (n + m, irq_masks (machine_state s))" using a by(fastforce intro: next_irq_state.domintros) next fix i assume "next_irq_state_dom (Suc i, irq_masks (machine_state s))" thus "next_irq_state_dom (i, irq_masks (machine_state s))" by(rule next_irq_state.domintros) qed qed context begin interpretation Arch . (*FIXME: arch_split*) crunch irq_state_of_state[wp]: cap_move "\s. P (irq_state_of_state s)" crunch domain_fields[wp]: handle_yield "domain_fields P" crunch domain_fields[wp]: handle_vm_fault, handle_hypervisor_fault "domain_fields P" (ignore: getFAR getDFSR getIFSR) crunch domain_list[wp]: timer_tick "\s. P (domain_list s)" crunch domain_list[wp]: handle_event "\s. P (domain_list s)" (ignore: resetTimer ackInterrupt ignore: without_preemption) crunch domain_list[wp]: next_domain "\s. P (domain_list s)" (wp: crunch_wps simp: crunch_simps) crunch domain_list[wp]: schedule_if "\s. P (domain_list s)" (wp: crunch_wps simp: crunch_simps) crunch domain_fields[wp]: activate_thread "domain_fields P" lemma next_domain_domain_time_nonzero: "\valid_domain_list\ next_domain \\r s. domain_time s > 0\" apply(simp add: next_domain_def) apply wp apply(clarsimp simp: Let_def valid_domain_list_2_def) apply(drule_tac x="(fst (domain_list s ! (Suc (domain_index s) mod length (domain_list s))),snd (domain_list s ! (Suc (domain_index s) mod length (domain_list s))))" in bspec) apply simp apply(simp split: prod.splits) done lemma nonzero_gt_zero[simp]: "x \ (0::word32) \ x > 0" apply(rule nonzero_unat_simp) apply(simp add: unat_gt_0) done lemma schedule_if_domain_time_nonzero': "\valid_domain_list and (\s. domain_time s = 0 \ scheduler_action s = choose_new_thread)\ schedule_if tc \(\_ s. domain_time s > 0)\" apply (simp add: schedule_if_def schedule_def) apply (wp next_domain_domain_time_nonzero | wpc | simp add: crunch_simps guarded_switch_to_def switch_to_thread_def choose_thread_def switch_to_idle_thread_def arch_switch_to_idle_thread_def)+ apply(wp hoare_drop_imps) apply(wp hoare_drop_imps) apply wp+ apply (simp add: choose_thread_def switch_to_idle_thread_def arch_switch_to_idle_thread_def guarded_switch_to_def switch_to_thread_def | wp)+ apply (wp gts_wp)+ apply auto done lemma schedule_if_domain_time_nonzero: "\valid_domain_list and (\s. domain_time s = 0 \ scheduler_action s = choose_new_thread)\ schedule_if tc \(\_ s. domain_time s \ 0)\" apply(rule hoare_strengthen_post[OF schedule_if_domain_time_nonzero']) apply simp done lemma handle_event_domain_fields: notes hy_inv[wp del] shows "\domain_fields P and K (e \ Interrupt)\ handle_event e \\_. domain_fields P\" apply(rule hoare_gen_asm) apply(rule hoare_pre) apply(case_tac e) apply(rename_tac syscall) apply(case_tac syscall) apply(wp | simp add: handle_call_def)+ done crunch domain_list[wp]: kernel_entry_if "\s. P (domain_list s)" crunch domain_list[wp]: handle_preemption_if "\s. P (domain_list s)" lemma kernel_entry_if_domain_fields: "\domain_fields P and K (e \ Interrupt)\ kernel_entry_if e tc \\_. domain_fields P\" apply(simp add: kernel_entry_if_def) apply(wp handle_event_domain_fields | simp)+ done lemma hoare_vcg_imp_lift': "\P'\ f \\rv s. \ P rv s\ \ \\s. P' s\ f \\rv s. P rv s \ Q rv s\" apply(auto simp: valid_def) done lemma timer_tick_domain_time_sched_action: "num_domains > 1 \ \ \ \ timer_tick \\r s. domain_time s = 0 \ scheduler_action s = choose_new_thread\" apply(simp add: timer_tick_def reschedule_required_def | wp | wpc)+ done lemma gt_zero_nonzero[simp]: "(0::word32) < x \ x \ 0" by (metis word_not_simps(1)) lemma handle_interrupt_domain_time_sched_action: "num_domains > 1 \ \\s. domain_time s > 0\ handle_interrupt e \\r s. domain_time s = 0 \ scheduler_action s = choose_new_thread\" apply(simp add: handle_interrupt_def split del: if_split) apply (rule hoare_pre) apply (wp) apply(case_tac "st \ IRQTimer") apply(( wp hoare_vcg_imp_lift' | simp add: handle_reserved_irq_def | wpc)+)[1] apply((wp timer_tick_domain_time_sched_action | simp)+)[1] apply(wp| simp add: get_irq_state_def)+ done lemma kernel_entry_if_domain_time_sched_action: "num_domains > 1 \ \\s. domain_time s > 0\ kernel_entry_if e tc \\_ s. domain_time s = 0 \ scheduler_action s = choose_new_thread\" apply(case_tac "e = Interrupt") apply (simp add: kernel_entry_if_def) apply (wp handle_interrupt_domain_time_sched_action| wpc | simp)+ apply(rule_tac Q="\r s. domain_time s > 0" in hoare_strengthen_post) apply (wp | simp)+ apply(wp hoare_vcg_imp_lift' kernel_entry_if_domain_fields | simp)+ done lemma handle_preemption_if_domain_time_sched_action: "num_domains > 1 \ \\s. domain_time s > 0\ handle_preemption_if tc \\_ s. domain_time s = 0 \ scheduler_action s = choose_new_thread\" apply (simp add: handle_preemption_if_def) apply (wp handle_interrupt_domain_time_sched_action| wpc | simp)+ apply(rule_tac Q="\r s. domain_time s > 0" in hoare_strengthen_post) apply (wp | simp)+ done definition user_context_of :: "'k global_sys_state \ user_context" where "user_context_of \ \s. fst (fst s)" lemma user_context_of_simp[simp]: "user_context_of ((uc,s),mode) = uc" by(simp add: user_context_of_def) definition sys_mode_of :: "'k global_sys_state \ sys_mode" where "sys_mode_of \ \s. snd s" lemma sys_mode_of_simp[simp]: "sys_mode_of ((uc,s),mode) = mode" by(simp add: sys_mode_of_def) lemma exit_idle_context: "\ct_idle and invs\ kernel_exit_if tc' \\tc s. tc = idle_context s\" apply (simp add: kernel_exit_if_def thread_get_def) apply wp apply (subgoal_tac "cur_thread s = idle_thread s") apply (clarsimp simp: cur_thread_idle idle_context_def)+ done lemma check_active_irq_context: "\\\ check_active_irq_if tc' \\tc s. (snd tc) = tc'\" apply (simp add: check_active_irq_if_def) apply (wp del: no_irq| simp)+ done lemma kernel_entry_context: "\\\ kernel_entry_if e tc' \\tc s. (snd tc) = tc'\" apply (simp add: kernel_entry_if_def) apply (wp del: no_irq| simp)+ done lemma handle_preemption_context: "\\\ handle_preemption_if tc' \\tc s. tc = tc'\" apply (simp add: handle_preemption_if_def) apply (wp del: no_irq| simp)+ done lemma get_tcb_machine_stat_update[simp]: "get_tcb t (s\machine_state := x\) = get_tcb t s" apply (simp add: get_tcb_def) done lemma handle_preemption_globals_equiv[wp]: "\globals_equiv st and invs\ handle_preemption_if a \\_. globals_equiv st\" apply (simp add: handle_preemption_if_def) apply (wp handle_interrupt_globals_equiv dmo_getActiveIRQ_globals_equiv crunch_wps | simp add: crunch_simps)+ done lemmas handle_preemption_idle_equiv[wp] = idle_globals_lift[OF handle_preemption_globals_equiv invs_pd_not_idle_thread,simplified] lemma schedule_if_globals_equiv_scheduler[wp]: "\globals_equiv_scheduler st and invs\ schedule_if tc \\_. globals_equiv_scheduler st\" apply (simp add: schedule_if_def) apply wp apply (wp globals_equiv_scheduler_inv'[where P="invs"] activate_thread_globals_equiv) apply (simp add: invs_valid_ko_at_arm invs_valid_idle) apply (wp | simp)+ done lemmas schedule_if_idle_equiv[wp] = idle_globals_lift_scheduler[OF schedule_if_globals_equiv_scheduler invs_pd_not_idle_thread,simplified] lemma not_in_global_refs_vs_lookup: "\(\\p) s; valid_vs_lookup s; valid_global_refs s; valid_arch_state s; valid_global_objs s\ \ p \ global_refs s" apply (clarsimp dest!: valid_vs_lookupD) apply (drule(1) valid_global_refsD2) apply (simp add: cap_range_def) apply blast done lemma ptrFromPAddr_add_helper: "ptrFromPAddr (a + b) = ptrFromPAddr a + b" apply(simp add: ptrFromPAddr_def) done lemma dmo_user_memory_update_idle_equiv: "\idle_equiv st\ do_machine_op (user_memory_update um) \\y. idle_equiv st\" by (wpsimp wp: dmo_wp) lemma dmo_device_memory_update_idle_equiv: "\idle_equiv st\ do_machine_op (device_memory_update um) \\y. idle_equiv st\" by (wpsimp wp: dmo_wp) lemma do_user_op_if_idle_equiv[wp]: "\idle_equiv st and invs\ do_user_op_if tc uop \\_. idle_equiv st\" unfolding do_user_op_if_def by (wpsimp wp: dmo_user_memory_update_idle_equiv dmo_device_memory_update_idle_equiv select_wp) lemma ct_active_not_idle': "ct_active s \ \ ct_idle s" apply (clarsimp simp add: ct_in_state_def st_tcb_at_def obj_at_def) done lemma Init_Fin_serial_weak_strengthen: "Init_Fin_serial_weak A s0 I \ A [> J \ J \ I \ Init A s0 \ J \ Init_Fin_serial_weak A s0 J" by (force simp: Init_Fin_serial_weak_def serial_system_weak_def Init_Fin_serial_weak_axioms_def) lemma rel_terminate_weaken: "rel_terminate A s0 R I measuref \ J \ I \ rel_terminate A s0 R J measuref" by (force simp: rel_terminate_def) end context valid_initial_state begin interpretation Arch . (*FIXME arch_split*) lemma current_aag_initial: "current_aag s0_internal = initial_aag" apply (simp add: current_aag_def cur_domain_subject_s0) done definition cur_thread_context_of :: "observable_if \ user_context" where "cur_thread_context_of \ \s. case sys_mode_of s of InUserMode \ user_context_of s | InIdleMode \ user_context_of s | KernelEntry e \ user_context_of s | _ \ cur_context (internal_state_if s)" definition invs_if :: "observable_if \ bool" where "invs_if s \ Invs (internal_state_if s) \ det_inv (sys_mode_of s) (cur_thread_context_of s) (internal_state_if s) \ (snd s \ KernelSchedule True \ domain_time (internal_state_if s) > 0) \ (domain_time (internal_state_if s) = 0 \ scheduler_action (internal_state_if s) = choose_new_thread) \ (snd s \ KernelExit \ (ct_idle (internal_state_if s) \ user_context_of s = idle_context (internal_state_if s))) \ (case (snd s) of KernelEntry e \ (e \ Interrupt \ ct_running (internal_state_if s)) \ (ct_running (internal_state_if s) \ ct_idle (internal_state_if s)) \ scheduler_action (internal_state_if s) = resume_cur_thread | KernelExit \ (ct_running (internal_state_if s) \ ct_idle (internal_state_if s)) \ scheduler_action (internal_state_if s) = resume_cur_thread | InUserMode \ ct_running (internal_state_if s) \ scheduler_action (internal_state_if s) = resume_cur_thread | InIdleMode \ ct_idle (internal_state_if s) \ scheduler_action (internal_state_if s) = resume_cur_thread | _ \ True)" lemma invs_if_s0[simp]: "invs_if s0" apply(clarsimp simp: s0_def invs_if_def Invs_s0_internal[simplified] ct_running_or_ct_idle_s0_internal domain_time_s0_internal det_inv_s0 cur_thread_context_of_def) apply(simp add: scheduler_action_s0_internal) done lemma only_timer_irq_inv_irq_state_update[simp]: "only_timer_irq_inv timer_irq s0_internal (b\machine_state := machine_state b \irq_state := Suc (irq_state (machine_state b))\\) = only_timer_irq_inv timer_irq s0_internal b" apply(clarsimp simp: only_timer_irq_inv_def only_timer_irq_def irq_is_recurring_def is_irq_at_def) done lemma initial_aag_bak: "initial_aag = (current_aag s)\pasSubject := pasDomainAbs (current_aag s) (cur_domain s0_internal)\" apply (simp add: current_aag_def cur_domain_subject_s0) done lemma pas_wellformed_cur[iff]: "pas_wellformed_noninterference (current_aag s)" apply (cut_tac policy_wellformed) apply (simp add: pas_wellformed_noninterference_def current_aag_def) done declare policy_wellformed[iff] lemma current_aag_lift: assumes b: "(\aag. \P aag\ f \\r s. Q aag r s\)" assumes a: "(\P. \\s. P (cur_domain s)\ f \\r s. P (cur_domain s)\)" shows "\\s. P (current_aag s) s\ f \\r s. Q (current_aag s) r s\" apply (simp add: current_aag_def) apply (rule hoare_lift_Pf3[where f="cur_domain", OF b a]) done lemma silc_inv_cur: "silc_inv (current_aag s) st s = silc_inv initial_aag st s" apply (rule iffI) apply (subst initial_aag_bak[where s=s]) apply (rule silc_inv_pasSubject_update) apply (simp)+ apply (simp add: current_aag_def) apply (rule silc_inv_pasSubject_update) apply (simp)+ done lemma guarded_pas_domain_cur: "guarded_pas_domain (current_aag s) s = guarded_pas_domain initial_aag s" apply (simp add: current_aag_def) done lemma pas_refined_cur: "pas_refined (current_aag s) s = pas_refined initial_aag s" apply (rule iffI) apply (subst initial_aag_bak[where s=s]) apply (rule pas_refined_pasSubject_update) apply simp+ apply (simp add: current_aag_def) apply (rule pas_refined_pasSubject_update) apply simp+ done lemma subject_current_aag: "pasSubject (current_aag s) = pasDomainAbs initial_aag (cur_domain s)" apply (simp add: current_aag_def) done lemma pasObjectAbs_current_aag: "pasObjectAbs (current_aag x) = pasObjectAbs initial_aag" by(simp add: current_aag_def) lemma pasIRQAbs_current_aag: "pasIRQAbs (current_aag x) = pasIRQAbs initial_aag" by(simp add: current_aag_def) lemma pasASIDAbs_current_aag: "pasASIDAbs (current_aag x) = pasASIDAbs initial_aag" by(simp add: current_aag_def) lemma pasPolicy_current_aag: "pasPolicy (current_aag x) = pasPolicy initial_aag" by(simp add: current_aag_def) lemma guarded_pas_is_subject_current_aag: "guarded_pas_domain (current_aag s) s \ invs s \ (ct_active s \ is_subject (current_aag s) (cur_thread s))" apply (clarsimp simp add: guarded_pas_domain_def current_aag_def) apply (rule sym) apply (erule mp) apply (rule ct_active_not_idle,assumption+) done lemma guarded_pas_domain_machine_state_update[simp]: "guarded_pas_domain aag (s\machine_state := x\) = guarded_pas_domain aag s" apply (simp add: guarded_pas_domain_def) done lemma handle_event_was_not_Interrupt: "\\\ handle_event e -,\\ r s. e \ Interrupt\" apply(case_tac e) apply(simp | wp | wpc)+ done lemma kernel_entry_if_was_not_Interrupt: "\(x, ba) \ fst (kernel_entry_if e a b)\ \ (case fst x of Inr a \ True | _ \ e \ Interrupt)" apply(simp add: kernel_entry_if_def) apply(erule use_valid) apply wp apply simp apply(rule handle_event_was_not_Interrupt[simplified validE_E_def validE_def]) apply wpsimp+ done lemma ct_idle_lift: assumes a: "\P. \\s. P (cur_thread s)\ f \\r s. P (cur_thread s)\" assumes d: "\P. \\s. P (idle_thread s)\ f \\r s. P (idle_thread s)\" assumes b: "\Q\ f \\_. invs\" assumes c: "\s. Q s \ invs s" shows "\Q and (\s. P (ct_idle s))\ f \\r s. P (ct_idle s)\" apply (rule hoare_add_post[OF b],simp) apply (clarsimp simp: valid_def) apply (drule c) apply (clarsimp simp: cur_thread_idle) apply (rule use_valid[OF _ a],assumption) apply (erule use_valid[OF _ d],simp) done lemma idle_equiv_context_equiv: "idle_equiv s s' \ invs s' \ idle_context s' = idle_context s" apply (clarsimp simp add: idle_equiv_def idle_context_def invs_def valid_state_def valid_idle_def) apply (drule pred_tcb_at_tcb_at) apply (clarsimp simp add: tcb_at_def2 get_tcb_def) done lemma kernel_entry_if_valid_pdpt_objs[wp]: "\valid_pdpt_objs and invs and (\s. e \ Interrupt \ ct_active s)\kernel_entry_if e tc \\s. valid_pdpt_objs\" apply (case_tac "e = Interrupt") apply (simp add: kernel_entry_if_def) apply (wp|wpc|simp add: kernel_entry_if_def)+ apply (wpsimp simp: tcb_cap_cases_def arch_tcb_update_aux2 wp: static_imp_wp thread_set_invs_trivial)+ done lemma kernel_entry_if_det_inv': "\e tc. \einvs and det_inv (KernelEntry e) tc and (\s. ct_running s \ ct_idle s) and (\s. e \ Interrupt \ ct_running s)\ kernel_entry_if e tc \\rv s. det_inv (case (fst rv) of Inl irq \ KernelPreempted | Inr () \ KernelSchedule (e = Interrupt)) (cur_context s) s\" apply (case_tac "e = Interrupt") apply simp apply (rule hoare_strengthen_post[OF kernel_entry_if_Interrupt_det_inv]) apply (simp split: sum.splits unit.splits) apply simp apply (rule hoare_weaken_pre[OF hoare_strengthen_post[OF kernel_entry_if_det_inv]]) apply (simp split: sum.splits unit.splits) apply simp done lemma pasMaySendIrqs_current_aag[simp]: "pasMaySendIrqs (current_aag s) = False" apply(simp add: current_aag_def) done lemma handle_preemption_if_valid_pdpt_objs[wp]: "\valid_pdpt_objs\ handle_preemption_if a \\rv s. valid_pdpt_objs s\" by (simp add: handle_preemption_if_def | wp)+ lemma schedule_if_valid_pdpt_objs[wp]: "\valid_pdpt_objs\ schedule_if a \\rv s. valid_pdpt_objs s\" by (simp add: schedule_if_def | wp)+ lemma do_user_op_if_valid_pdpt_objs[wp]: "\valid_pdpt_objs\ do_user_op_if a b \\rv s. valid_pdpt_objs s\" by (simp add: do_user_op_if_def | wp select_wp | wpc)+ lemma invs_if_Step_ADT_A_if: notes active_from_running[simp] shows "\invs_if s; (s,t) \ data_type.Step (ADT_A_if utf) e\ \ invs_if t" apply(clarsimp simp add: ADT_A_if_def global_automaton_if_def invs_if_def Invs_def cur_thread_context_of_def | rule guarded_active_ct_cur_domain | clarify )+ apply (elim disjE) apply(clarsimp simp: kernel_call_A_if_def) apply(case_tac r, simp_all)[1] apply (frule kernel_entry_if_was_not_Interrupt) apply (frule use_valid[OF _ kernel_entry_if_det_inv]) apply simp apply simp apply(erule use_valid) apply (rule current_aag_lift) apply(wp kernel_entry_if_invs kernel_entry_silc_inv[where st'=s0_internal] kernel_entry_pas_refined[where st=s0_internal] kernel_entry_if_valid_sched kernel_entry_if_only_timer_irq_inv kernel_entry_if_domain_sep_inv kernel_entry_if_guarded_pas_domain kernel_entry_if_domain_fields kernel_entry_if_idle_equiv kernel_entry_if_domain_time_sched_action[OF num_domains_sanity] hoare_vcg_imp_lift' ct_idle_lift | clarsimp intro!: guarded_pas_is_subject_current_aag[rule_format] simp: active_from_running | intro conjI)+ apply (rule guarded_pas_is_subject_current_aag[rule_format],assumption+) apply (simp add: schact_is_rct_def active_from_running)+ apply (rule guarded_pas_is_subject_current_aag[rule_format],assumption+) apply(simp add: ct_active_not_idle' active_from_running | elim exE)+ apply(simp add: kernel_call_A_if_def | elim exE conjE)+ apply (rule context_conjI) apply(erule use_valid) apply (rule kernel_entry_if_invs,simp add: active_from_running) apply (subgoal_tac "idle_equiv s0_internal ba") prefer 2 apply (erule use_valid) apply (rule kernel_entry_if_idle_equiv) apply simp apply (simp add: idle_equiv_context_equiv) apply (frule use_valid[OF _ kernel_entry_context],simp) apply (frule use_valid[OF _ kernel_entry_if_det_inv']) apply simp apply (simp split: unit.splits) apply (erule use_valid) apply (rule current_aag_lift) apply(wp hoare_vcg_const_imp_lift kernel_entry_if_invs kernel_entry_silc_inv[where st'=s0_internal] kernel_entry_pas_refined[where st=s0_internal] kernel_entry_if_valid_sched kernel_entry_if_only_timer_irq_inv kernel_entry_if_domain_sep_inv kernel_entry_if_guarded_pas_domain kernel_entry_if_domain_time_sched_action[OF num_domains_sanity] ct_idle_lift | clarsimp intro: guarded_pas_is_subject_current_aag | wp kernel_entry_if_domain_fields)+ apply (rule conjI, fastforce intro!: active_from_running) apply (simp add: schact_is_rct_def) apply (rule guarded_pas_is_subject_current_aag,assumption+) apply (simp_all only: silc_inv_cur pas_refined_cur guarded_pas_domain_cur) apply(simp | elim exE)+ apply (elim exE conjE) apply (clarsimp simp add: kernel_handle_preemption_if_def) apply (subgoal_tac "idle_equiv s0_internal ba \ invs ba") prefer 2 apply (erule use_valid) apply (wp handle_preemption_if_invs | simp)+ apply (clarsimp simp add: idle_equiv_context_equiv) apply (erule use_valid) apply (rule hoare_add_post[OF handle_preemption_context, OF TrueI],simp,rule hoare_drop_imps) apply (wp handle_preemption_if_invs handle_preemption_if_domain_sep_inv handle_preemption_if_domain_time_sched_action[OF num_domains_sanity] handle_preemption_if_det_inv ct_idle_lift| simp add: non_kernel_IRQs_def)+ apply(simp add: kernel_schedule_if_def | elim exE conjE)+ apply(erule use_valid) apply((wp schedule_if_ct_running_or_ct_idle schedule_if_domain_time_nonzero' schedule_if_domain_time_nonzero schedule_if_det_inv hoare_vcg_imp_lift' | simp add: invs_valid_idle)+)[2] apply(simp add: kernel_exit_A_if_def | elim exE conjE)+ apply(frule state_unchanged[OF kernel_exit_if_inv]) apply(frule use_valid[OF _ kernel_exit_if_det_inv]) apply simp apply(clarsimp) apply (elim disjE) apply (simp add: ct_active_not_idle' active_from_running)+ apply (erule use_valid[OF _ exit_idle_context],simp+) apply(simp add: do_user_op_A_if_def check_active_irq_A_if_def | elim exE conjE)+ apply (frule use_valid[OF _ do_user_op_if_det_inv]) apply (frule use_valid[OF _ check_active_irq_if_User_det_inv]) apply simp apply simp apply (erule use_valid[OF _ check_active_irq_if_wp]) apply simp apply simp apply(erule use_valid, erule use_valid[OF _ check_active_irq_if_wp]) apply(rule_tac Q="\a. (invs and ct_running) and (\b. valid_pdpt_objs b \ valid_list b \ valid_sched b \ only_timer_irq_inv timer_irq s0_internal b \ silc_inv initial_aag s0_internal b \ pas_refined initial_aag b \ guarded_pas_domain initial_aag b \ idle_equiv s0_internal b \ domain_sep_inv False s0_internal b \ valid_domain_list b \ 0 < domain_time b \ scheduler_action b = resume_cur_thread)" in hoare_strengthen_post) apply((wp do_user_op_if_invs ct_idle_lift | simp add: active_from_running ct_active_not_idle' | clarsimp)+)[2] apply(erule use_valid[OF _ check_active_irq_if_wp]) apply(simp add: ct_in_state_def) apply(simp add: do_user_op_A_if_def check_active_irq_A_if_def | elim exE conjE)+ apply (frule use_valid[OF _ do_user_op_if_det_inv]) apply (frule use_valid[OF _ check_active_irq_if_User_det_inv]) apply simp apply simp apply (erule use_valid[OF _ check_active_irq_if_wp]) apply simp apply simp apply(erule use_valid, erule use_valid[OF _ check_active_irq_if_wp]) apply(rule_tac Q="\a. (invs and ct_running) and (\b. valid_pdpt_objs b \ valid_list b \ valid_sched b \ only_timer_irq_inv timer_irq s0_internal b \ silc_inv initial_aag s0_internal b \ pas_refined initial_aag b \ guarded_pas_domain initial_aag b \ idle_equiv s0_internal b \ domain_sep_inv False s0_internal b \ valid_domain_list b \ 0 < domain_time b \ scheduler_action b = resume_cur_thread)" in hoare_strengthen_post) apply((wp do_user_op_if_invs | simp | clarsimp simp: ct_active_not_idle')+)[2] apply(erule use_valid[OF _ check_active_irq_if_wp]) apply(simp add: ct_in_state_def) apply(simp add: check_active_irq_A_if_def | elim exE conjE)+ apply (frule use_valid[OF _ check_active_irq_if_User_det_inv]) apply simp apply simp apply(erule use_valid[OF _ check_active_irq_if_wp]) apply(clarsimp simp add: ct_in_state_def st_tcb_at_def obj_at_def) apply(simp add: check_active_irq_A_if_def | elim exE conjE)+ apply (frule use_valid[OF _ check_active_irq_context],simp) apply (frule use_valid[OF _ check_active_irq_if_Idle_det_inv]) apply simp apply simp apply(erule use_valid[OF _ check_active_irq_if_wp]) apply(simp add: ct_in_state_def idle_context_def) apply(simp add: check_active_irq_A_if_def | elim exE conjE)+ apply (frule use_valid[OF _ check_active_irq_if_Idle_det_inv]) apply simp apply simp apply(rule use_valid[OF _ check_active_irq_if_wp],assumption) apply(simp add: ct_in_state_def) apply (frule use_valid[OF _ check_active_irq_context],simp+) apply (simp add: idle_context_def) done lemma Fin_ADT_if: "Fin (ADT_A_if utf) = id" apply (simp add: ADT_A_if_def) done lemma Init_ADT_if: "Init (ADT_A_if utf) = (\s. {s} \ full_invs_if \ {s. step_restrict s})" apply (simp add: ADT_A_if_def) done lemma execution_invs: assumes e: "s \ execution (ADT_A_if utf) s0 js" shows "invs_if s" apply (insert e) apply (induct js arbitrary: s rule: rev_induct) apply (clarsimp simp add: execution_def Fin_ADT_if Init_ADT_if image_def) apply (simp add: execution_def Fin_ADT_if Init_ADT_if steps_def) apply (simp add: execution_def steps_def image_def) apply (erule bexE) unfolding Image_def apply (drule CollectD) apply (erule bexE) apply simp apply (rule invs_if_Step_ADT_A_if) apply (drule_tac meta_spec) apply (fastforce) apply simp apply (clarsimp simp: Fin_ADT_if ADT_A_if_def) done lemma execution_restrict: assumes e: "s \ execution (ADT_A_if utf) s0 js" shows "step_restrict s" apply (insert e) apply (induct js arbitrary: s rule: rev_induct) apply (clarsimp simp add: execution_def ADT_A_if_def steps_def) apply (clarsimp simp add: execution_def Fin_ADT_if Init_ADT_if steps_def) apply (simp add: ADT_A_if_def) done lemma invs_if_full_invs_if: "invs_if s \ s \ full_invs_if" by (clarsimp simp add: full_invs_if_def invs_if_def Invs_def) lemma ADT_A_if_Step_system: "Step_system (ADT_A_if utf) s0" apply(rule Init_Fin_system_Step_system) apply(rule Init_inv_Fin_system_Init_Fin_system) apply(clarsimp simp add: Init_inv_Fin_system_def ADT_A_if_def invs_if_full_invs_if system.reachable_def extras_s0) apply (frule execution_invs[simplified ADT_A_if_def]) apply (frule execution_restrict[simplified ADT_A_if_def]) apply (frule invs_if_full_invs_if,force) done lemma ADT_A_if_Run_reachable: "(s0, t) \ Run (system.Step (ADT_A_if utf)) as \ system.reachable (ADT_A_if utf) s0 t" apply(simp add: system.reachable_def) apply(simp add: Step_system_execution_Run_s0[OF ADT_A_if_Step_system]) by blast lemma Step_ADT_A_if: "system.reachable (ADT_A_if utf) s0 s \ ((s,s') \ system.Step (ADT_A_if utf) u) = ((s,s') \ Step (ADT_A_if utf) u)" apply (simp add: system.reachable_def) apply (clarsimp) apply (frule execution_invs) apply (frule invs_if_full_invs_if) apply (frule execution_restrict) apply(simp add: system.Step_def execution_def steps_def ADT_A_if_def) done lemma Step_ADT_A_if': "((s,s') \ system.Step (ADT_A_if utf) u) \ ((s,s') \ Step (ADT_A_if utf) u)" apply(simp add: system.Step_def execution_def steps_def ADT_A_if_def) apply fastforce done lemma ADT_A_if_reachable_invs_if: "system.reachable (ADT_A_if utf) s0 s \ invs_if s" apply(clarsimp simp: system.reachable_def) apply (erule execution_invs) done lemma ADT_A_if_reachable_full_invs_if: "system.reachable (ADT_A_if utf) s0 s \ s \ full_invs_if" apply(clarsimp simp: system.reachable_def) apply (rule invs_if_full_invs_if) apply (rule ADT_A_if_reachable_invs_if) apply (simp add: system.reachable_def) apply force done lemma ADT_A_if_enabled_Step_system: "enabled_Step_system (ADT_A_if utf) s0" apply(simp add: enabled_Step_system_def ADT_A_if_Step_system ADT_A_if_enabled_system) done definition irq_measure_if where "irq_measure_if s \ let cur = Suc (irq_state (machine_state s)) in (next_irq_state cur (irq_masks (machine_state s))) - cur" definition measuref_if :: "det_state global_sys_state \ det_state global_sys_state \ nat" where "measuref_if s s' \ (if (snd s) = KernelExit then (if interrupted_modes (snd s') then 0 else 1 + (4 * irq_measure_if (internal_state_if s')) + (case (snd s') of (KernelEntry e) \ 3 | _ \ (if (\ b. (snd s') = KernelSchedule b) then 2 else (if (snd s') = KernelExit then 1 else 0) ) ) ) else (if interrupted_modes (snd s') then 2 else (if (\ b. (snd s') = KernelSchedule b) then 1 else 0) ) )" crunch irq_state_of_state_inv[wp]: device_memory_update "\ms. P (irq_state ms)" crunch irq_masks_inv[wp]: device_memory_update "\ms. P (irq_masks ms)" (wp: crunch_wps simp: crunch_simps no_irq_device_memory_update no_irq_def) lemma do_user_op_if_irq_state_of_state: "\\s. P (irq_state_of_state s)\ do_user_op_if utf uc \\_ s. P (irq_state_of_state s)\" apply(rule hoare_pre) apply(simp add: do_user_op_if_def user_memory_update_def | wp dmo_wp select_wp | wpc)+ done lemma do_user_op_if_irq_masks_of_state: "\\s. P (irq_masks_of_state s)\ do_user_op_if utf uc \\_ s. P (irq_masks_of_state s)\" apply(rule hoare_pre) apply(simp add: do_user_op_if_def user_memory_update_def | wp dmo_wp select_wp | wpc)+ done lemma do_user_op_if_irq_measure_if: "\\s. P (irq_measure_if s)\ do_user_op_if utf uc \\_ s. P (irq_measure_if s)\" apply(rule hoare_pre) apply(simp add: do_user_op_if_def user_memory_update_def irq_measure_if_def | wps |wp dmo_wp select_wp | wpc)+ done lemma next_irq_state_Suc: "\irq_at cur masks = None; next_irq_state_dom (cur,masks)\ \ next_irq_state (Suc cur) masks = next_irq_state cur masks" apply(simp add: next_irq_state.psimps split: if_splits) done lemma next_irq_state_Suc': "\irq_at cur masks = Some i; next_irq_state_dom (cur,masks)\ \ next_irq_state cur masks = cur" apply(simp add: next_irq_state.psimps split: if_splits) done lemma getActiveIRQ_None: "(None,s') \ fst (do_machine_op (getActiveIRQ in_kernel) s) \ irq_at (irq_state (machine_state s) + 1) (irq_masks (machine_state s)) = None" apply(erule use_valid) apply(wp dmo_getActiveIRQ_wp) by simp lemma getActiveIRQ_Some: "(Some i,s') \ fst (do_machine_op (getActiveIRQ in_kernel) s) \ irq_at (irq_state (machine_state s) + 1) (irq_masks (machine_state s)) = Some i" apply(erule use_valid) apply(wp dmo_getActiveIRQ_wp) by simp lemma is_irq_at_next_irq_state_dom': "is_irq_at s irq pos \ next_irq_state_dom (pos,irq_masks (machine_state s))" apply(rule next_irq_state.domintros) apply(fastforce simp: is_irq_at_def irq_at_def) done lemma is_irq_at_next_irq_state_dom: "\pos \ next; is_irq_at s irq next\ \ next_irq_state_dom (pos,irq_masks (machine_state s))" apply(induct rule: inc_induct) apply(erule is_irq_at_next_irq_state_dom') apply(rule next_irq_state.domintros) apply(blast) done lemma is_irq_at_next_irq_state: "is_irq_at s irq pos \ next_irq_state pos (irq_masks (machine_state s)) = pos" apply(subst next_irq_state.psimps[OF is_irq_at_next_irq_state_dom']) apply assumption apply(fastforce simp: is_irq_at_def) done lemma next_irq_state_le: "\irq_is_recurring irq s; masks = (irq_masks (machine_state s))\ \ cur \ next_irq_state cur masks" apply(clarsimp simp: irq_is_recurring_def) apply(drule_tac x=cur in spec) apply(erule exE) proof - fix m assume i: "is_irq_at s irq (cur + m)" have le: "cur \ cur + m" by simp thus "cur \ next_irq_state cur (irq_masks (machine_state s))" apply - apply(induct rule: inc_induct) apply(clarsimp simp: is_irq_at_next_irq_state[OF i]) apply(case_tac "is_irq_at s irq n") apply(simp add: is_irq_at_next_irq_state) apply(subst next_irq_state.psimps) apply(rule is_irq_at_next_irq_state_dom[OF _ i]) apply simp apply simp done qed lemma next_irq_state_mono: assumes lep: "pos \ pos'" assumes recur: "irq_is_recurring irq s" assumes m: "masks = irq_masks (machine_state s)" shows "next_irq_state pos masks \ next_irq_state pos' masks" apply(insert recur m) apply(clarsimp simp: irq_is_recurring_def) apply(drule_tac x=pos' in spec) apply(erule exE) proof - fix m assume i: "is_irq_at s irq (pos' + m)" from lep have le: "pos \ pos' + m" by fastforce from lep show "next_irq_state pos (irq_masks (machine_state s)) \ next_irq_state pos' (irq_masks (machine_state s))" apply - apply(induct rule: inc_induct) apply simp apply(case_tac "is_irq_at s irq n") apply(simp add: is_irq_at_next_irq_state) apply(rule less_imp_le_nat) apply(erule less_le_trans) apply(blast intro: next_irq_state_le[OF recur]) apply(subst next_irq_state.psimps) apply(rule is_irq_at_next_irq_state_dom[OF _ i]) apply simp apply(clarsimp simp: is_irq_at_def irq_at_def Let_def) apply(rule less_imp_le_nat) apply(erule less_le_trans) apply(blast intro: next_irq_state_le[OF recur]) done qed lemma next_irq_state_less: "\irq_at cur masks = None; irq_is_recurring irq s; masks = (irq_masks (machine_state s))\ \ cur < next_irq_state cur masks" apply(frule_tac n=cur in recurring_next_irq_state_dom) apply(simp add: next_irq_state.psimps) apply(rule less_le_trans[OF _ next_irq_state_le]) apply simp apply assumption apply(rule refl) done lemma next_irq_state_Suc_le: assumes recur: "irq_is_recurring irq s" assumes m: "masks = irq_masks (machine_state s)" shows "next_irq_state pos masks \ next_irq_state (Suc pos) masks" apply(rule next_irq_state_mono[OF _ recur m], simp) done lemma kernel_exit_if_inv: "\P\ kernel_exit_if blah \\_. P\" apply(simp add: kernel_exit_if_def | wp)+ done lemma invs_if_irq_is_recurring[simp]: "invs_if s \ irq_is_recurring timer_irq (internal_state_if s)" apply(clarsimp simp: invs_if_def Invs_def only_timer_irq_inv_def only_timer_irq_def) done definition irq_measure_if_inv where "irq_measure_if_inv st s \ irq_measure_if (s::det_state) \ irq_measure_if (st::det_state)" definition irq_state_inv where "irq_state_inv (st::det_state) (s::det_state) \ irq_state (machine_state s) \ irq_state (machine_state st) \ irq_masks (machine_state s) = irq_masks (machine_state st) \ next_irq_state (Suc (irq_state (machine_state s))) (irq_masks (machine_state s)) = next_irq_state (Suc (irq_state (machine_state st))) (irq_masks (machine_state s))" lemma irq_state_inv_refl: "irq_state_inv s s" apply(simp add: irq_state_inv_def) done lemma irq_state_inv_triv: assumes irq_state: "\ P. \ \s. P (irq_state_of_state s)\ f \\_ s. P (irq_state_of_state s)\" assumes irq_masks: "\ P. \ \s. P (irq_masks_of_state s)\ f \\_ s. P (irq_masks_of_state s)\" shows "\irq_state_inv st\ f \\_. irq_state_inv st\" apply(clarsimp simp: valid_def irq_state_inv_def) apply(rule use_valid[OF _ irq_state], assumption) apply(erule use_valid[OF _ irq_masks]) apply simp done lemma irq_state_inv_triv': assumes irq_state: "\ P. \ \s. P (irq_state_of_state s)\ f \\_ s. P (irq_state_of_state s)\" assumes irq_masks: "\ P. \ (\s. P (irq_masks_of_state s)) and Q\ f \\_ s. P (irq_masks_of_state s)\" shows "\irq_state_inv st and Q\ f \\_. irq_state_inv st\" apply(clarsimp simp: valid_def irq_state_inv_def) apply(rule use_valid[OF _ irq_state], assumption) apply(erule use_valid[OF _ irq_masks]) apply simp done lemma OR_choiceE_wp: assumes a: "\s. \P and op = s\ b \\ r s'. (r \ P' s) \ (\ r \ P'' s)\" assumes b: "\P'\ f \Q\,\E\" assumes c: "\P''\ g \Q\,\E\" shows "\P::det_state \ bool\ OR_choiceE b f g \Q\,\E\" apply(simp add: OR_choiceE_def) apply (wp b c| wpc)+ apply(clarsimp simp: mk_ef_def wrap_ext_bool_det_ext_ext_def) apply(drule a[simplified valid_def, rule_format, rotated]) apply simp apply(fastforce split: prod.splits) done definition irq_state_next where "irq_state_next (st::det_state) (s::det_state) \ irq_state (machine_state s) \ irq_state (machine_state st) \ irq_masks (machine_state s) = irq_masks (machine_state st) \ irq_state (machine_state s) = next_irq_state (Suc (irq_state (machine_state st))) (irq_masks (machine_state s))" lemma preemption_point_irq_state_inv'[wp]: "\irq_state_inv st and K (irq_is_recurring irq st)\ preemption_point \\a. irq_state_inv st\, \\_. irq_state_next st\" apply (simp add: preemption_point_def) apply (wp OR_choiceE_wp[where P'="irq_state_inv st and K(irq_is_recurring irq st)" and P''="irq_state_inv st and K(irq_is_recurring irq st)"] dmo_getActiveIRQ_wp | wpc | simp add: reset_work_units_def)+ apply (elim conjE) apply simp apply (wp OR_choiceE_wp[where P'="irq_state_inv st" and P''="irq_state_inv st"] dmo_getActiveIRQ_wp | wpc | simp add: reset_work_units_def)+ apply(clarsimp simp: irq_state_inv_def) apply(simp add: next_irq_state_Suc[OF _ recurring_next_irq_state_dom]) apply (clarsimp simp: irq_state_next_def) apply(simp add: next_irq_state_Suc'[OF _ recurring_next_irq_state_dom]) apply(wp | simp add: update_work_units_def irq_state_inv_def | fastforce)+ done lemma validE_validE_E': "\P\ f \Q\,\E\ \ \P\ f -,\E\" apply (rule validE_validE_E) apply (rule hoare_post_impErr) apply assumption apply simp+ done lemmas preemption_point_irq_state_inv[wp] = validE_validE_R'[OF preemption_point_irq_state_inv'] lemmas preemption_point_irq_state_next[wp] = validE_validE_E'[OF preemption_point_irq_state_inv'] lemma hoare_add_postE: "\S\ f \\_. S'\ \ \P\ f \\r s. S' s \ Q r s\,\\r s. S' s \ E r s\ \ \P and S\ f \Q\,\E\" apply (clarsimp simp: validE_def) apply (rule hoare_add_post) apply assumption apply simp apply (rule hoare_strengthen_post) apply (rule hoare_pre) apply assumption back apply simp apply (clarsimp split: sum.splits) done lemma rec_del_irq_state_inv': notes drop_spec_valid[wp_split del] drop_spec_validE[wp_split del] rec_del.simps[simp del] shows "s \ \irq_state_inv st and domain_sep_inv False sta and K (irq_is_recurring irq st)\ rec_del call \\a s. (case call of FinaliseSlotCall x y \ y \ fst a \ snd a = NullCap | _ \ True) \ domain_sep_inv False sta s \ irq_state_inv st s\, \\_. irq_state_next st\" proof (induct s arbitrary: rule: rec_del.induct, simp_all only: rec_del_fails hoare_fail_any) case (1 slot exposed s) show ?case apply(simp add: split_def rec_del.simps) apply(wp drop_spec_validE[OF returnOk_wp] drop_spec_validE[OF liftE_wp] empty_slot_domain_sep_inv) apply(wp irq_state_inv_triv' empty_slot_irq_masks) apply(rule spec_strengthen_postE[OF "1.hyps", simplified]) apply fastforce done next case (2 slot exposed s) show ?case apply(rule hoare_spec_gen_asm) apply(simp add: rec_del.simps split del: if_split) apply(rule hoare_pre_spec_validE) apply(wp drop_spec_validE[OF returnOk_wp] drop_spec_validE[OF liftE_wp] set_cap_domain_sep_inv |simp add: split_def split del: if_split)+ apply(wp irq_state_inv_triv)[1] apply (wp | simp split del: if_split)+ apply(rule spec_strengthen_postE) apply(rule "2.hyps"[simplified], fastforce+) apply(rule drop_spec_validE, (wp preemption_point_irq_state_inv[where irq=irq] | simp)+)[1] apply(rule spec_strengthen_postE) apply(rule "2.hyps"[simplified], fastforce+) apply(wp finalise_cap_domain_sep_inv_cap get_cap_wp finalise_cap_returns_NullCap[where irqs=False, simplified] drop_spec_validE[OF liftE_wp] set_cap_domain_sep_inv |simp add: without_preemption_def split del: if_split |wp_once hoare_drop_imps |wp irq_state_inv_triv)+ apply(blast dest: cte_wp_at_domain_sep_inv_cap) done next case (3 ptr bits n slot s) show ?case apply(simp add: rec_del.simps) apply (wp drop_spec_validE[OF returnOk_wp] drop_spec_validE[OF liftE_wp] irq_state_inv_triv) apply(rule hoare_pre_spec_validE) apply (wp drop_spec_validE[OF assertE_wp]) apply(fastforce) done next case (4 ptr bits n slot s) show ?case apply(simp add: rec_del.simps) apply (wp drop_spec_validE[OF returnOk_wp] drop_spec_validE[OF liftE_wp] set_cap_domain_sep_inv drop_spec_validE[OF assertE_wp] get_cap_wp | simp add: without_preemption_def | wp irq_state_inv_triv)+ apply (rule spec_strengthen_postE[OF "4.hyps", simplified]) apply(simp add: returnOk_def return_def) apply(clarsimp simp: domain_sep_inv_cap_def) done qed lemma rec_del_irq_state_inv: "\irq_state_inv st and domain_sep_inv False sta and K (irq_is_recurring irq st)\ rec_del call \\a s. irq_state_inv st s\, \\_. irq_state_next st\" apply(rule hoare_post_impErr) apply(rule use_spec) apply(rule rec_del_irq_state_inv') apply auto done lemma cap_delete_irq_state_inv': "\irq_state_inv st and domain_sep_inv False sta and K (irq_is_recurring irq st)\ cap_delete slot \\_. irq_state_inv st\, \\_. irq_state_next st\" apply(simp add: cap_delete_def | wp rec_del_irq_state_inv)+ by auto lemmas cap_delete_irq_state_inv[wp] = validE_validE_R'[OF cap_delete_irq_state_inv'] lemmas cap_delete_irq_state_next[wp] = validE_validE_E'[OF cap_delete_irq_state_inv'] lemma cap_revoke_irq_state_inv'': notes drop_spec_valid[wp_split del] drop_spec_validE[wp_split del] shows "s \ \ irq_state_inv st and domain_sep_inv False sta and K (irq_is_recurring irq st)\ cap_revoke slot \ \_ s. irq_state_inv st s\, \\_. irq_state_next st\" proof(induct rule: cap_revoke.induct[where ?a1.0=s]) case (1 slot s) show ?case apply(subst cap_revoke.simps) apply(rule hoare_spec_gen_asm) apply(rule hoare_pre_spec_validE) apply (wp "1.hyps") apply(wp spec_valid_conj_liftE2 | simp)+ apply(wp drop_spec_validE[OF preemption_point_irq_state_inv[simplified validE_R_def]] drop_spec_validE[OF preemption_point_irq_state_inv'[where irq=irq]] drop_spec_validE[OF valid_validE[OF preemption_point_domain_sep_inv]] cap_delete_domain_sep_inv cap_delete_irq_state_inv drop_spec_validE[OF assertE_wp] drop_spec_validE[OF returnOk_wp] drop_spec_validE[OF liftE_wp] select_wp drop_spec_validE[OF hoare_vcg_conj_liftE1] | simp | wp_once hoare_drop_imps)+ apply fastforce done qed lemmas cap_revoke_irq_state_inv' = use_spec(2)[OF cap_revoke_irq_state_inv''] lemmas cap_revoke_irq_state_inv[wp] = validE_validE_R'[OF cap_revoke_irq_state_inv'] lemmas cap_revoke_irq_state_next[wp] = validE_validE_E'[OF cap_revoke_irq_state_inv'] lemma finalise_slot_irq_state_inv: "\irq_state_inv st and domain_sep_inv False sta and K (irq_is_recurring irq st)\ finalise_slot p e \\_ s. irq_state_inv st s\,\\_. irq_state_next st\" apply(simp add: finalise_slot_def | wp rec_del_irq_state_inv[folded validE_R_def])+ by blast lemma invoke_cnode_irq_state_inv: "\irq_state_inv st and domain_sep_inv False sta and valid_cnode_inv cnode_invocation and K (irq_is_recurring irq st)\ invoke_cnode cnode_invocation \\y. irq_state_inv st\, \\_. irq_state_next st\" apply (rule hoare_assume_preE) apply(simp add: invoke_cnode_def) apply(rule hoare_pre) apply wpc apply((wp cap_revoke_irq_state_inv' cap_delete_irq_state_inv hoare_vcg_all_lift | wpc | simp add: cap_move_def split del: if_split | wp_once irq_state_inv_triv | wp_once hoare_drop_imps)+)[7] apply fastforce done lemma checked_insert_irq_state_of_state[wp]: "\\ s. P (irq_state_of_state s)\ check_cap_at a b (check_cap_at c d (cap_insert e f g)) \\r s. P (irq_state_of_state s)\" apply(wp | simp add: check_cap_at_def)+ done lemma irq_state_inv_invoke_domain[wp]: "\irq_state_inv st\ invoke_domain a b \\_. irq_state_inv st\" apply (simp add: irq_state_inv_def[abs_def]) apply (rule hoare_pre) apply wps apply (wp | clarsimp)+ done crunch irq_state_of_state: bind_notification "\s. P (irq_state_of_state s)" lemmas bind_notification_irq_state_inv[wp] = irq_state_inv_triv[OF bind_notification_irq_state_of_state bind_notification_irq_masks] crunch machine_state[wp]: set_mcpriority "\s. P (machine_state s)" lemma invoke_tcb_irq_state_inv: "\(\s. irq_state_inv st s) and domain_sep_inv False sta and Tcb_AI.tcb_inv_wf tinv and K (irq_is_recurring irq st)\ invoke_tcb tinv \\_ s. irq_state_inv st s\,\\_. irq_state_next st\" apply(case_tac tinv) apply((wp hoare_vcg_if_lift mapM_x_wp[OF _ subset_refl] | wpc | simp split del: if_split add: check_cap_at_def | clarsimp | wp_once irq_state_inv_triv)+)[3] defer apply((wp irq_state_inv_triv | simp )+)[2] (* just ThreadControl left *) apply (simp add: split_def cong: option.case_cong) by (wp hoare_vcg_all_lift_R hoare_vcg_all_lift hoare_vcg_const_imp_lift_R checked_cap_insert_domain_sep_inv cap_delete_deletes cap_delete_irq_state_inv[where st=st and sta=sta and irq=irq] cap_delete_irq_state_next[where st=st and sta=sta and irq=irq] cap_delete_valid_cap cap_delete_cte_at |wpc |simp add: emptyable_def tcb_cap_cases_def tcb_cap_valid_def tcb_at_st_tcb_at option_update_thread_def |strengthen use_no_cap_to_obj_asid_strg |wp_once irq_state_inv_triv |wp_once hoare_drop_imps | clarsimp split: option.splits | intro impI conjI allI)+ lemma do_reply_transfer_irq_state_inv_triv[wp]: "\irq_state_inv st\ do_reply_transfer a b c \\_. irq_state_inv st\" apply (wp irq_state_inv_triv) done lemma set_domain_irq_state_inv_triv[wp]: "\irq_state_inv st\ set_domain a b \\_. irq_state_inv st\" apply (wp irq_state_inv_triv) done lemma invoke_irq_control_noErr[wp]: "\\\ invoke_irq_control a -,\Q\" apply (cases a) apply (wp | simp add: arch_invoke_irq_control_def)+ done lemma arch_perform_invocation_noErr[wp]: "\\\ arch_perform_invocation a -,\Q\" apply (simp add: arch_perform_invocation_def) apply wp done lemma use_validE_E: "\(Inl r, s') \ fst (fa s); \P\ fa -, \Q\; P s\ \ Q r s'" apply (fastforce simp: validE_E_def validE_def valid_def) done lemma irq_state_inv_trivE': assumes irq_state: "\ P. \ \s. P (irq_state_of_state s)\ f \\_ s. P (irq_state_of_state s)\" assumes irq_masks: "\ P. \ (\s. P (irq_masks_of_state s)) and Q\ f \\_ s. P (irq_masks_of_state s)\" assumes no_err: "\ P. \\\ f -,\P\" shows "\irq_state_inv st and Q\ f \\_. irq_state_inv st\, \\_. irq_state_next st\" apply(clarsimp simp: validE_def valid_def irq_state_inv_def split: sum.splits) apply(rule use_valid[OF _ irq_state], assumption) apply(rule use_valid[OF _ irq_masks],assumption) apply clarsimp apply (erule use_validE_E[OF _ no_err]) apply simp done crunch irq_state_of_state[wp]: init_arch_objects "\s. P (irq_state_of_state s)" (wp: crunch_wps dmo_wp ignore: do_machine_op) lemma reset_untyped_cap_irq_state_inv: "\irq_state_inv st and K (irq_is_recurring irq st)\ reset_untyped_cap slot \\y. irq_state_inv st\, \\y. irq_state_next st\" apply (cases "irq_is_recurring irq st", simp_all) apply (simp add: reset_untyped_cap_def) apply (rule hoare_pre) apply (wp no_irq_clearMemory mapME_x_wp' hoare_vcg_const_imp_lift preemption_point_irq_state_inv'[where irq=irq] get_cap_wp | rule irq_state_inv_triv | simp add: unless_def | wp_once dmo_wp)+ done lemma invoke_untyped_irq_state_inv: "\irq_state_inv st and K (irq_is_recurring irq st)\ invoke_untyped ui \\y. irq_state_inv st\, \\y. irq_state_next st\" apply (cases ui, simp add: invoke_untyped_def mapM_x_def[symmetric]) apply (rule hoare_pre) apply (wp mapM_x_wp' hoare_whenE_wp reset_untyped_cap_irq_state_inv[where irq=irq] | rule irq_state_inv_triv | simp)+ done lemma perform_invocation_irq_state_inv: "\irq_state_inv st and (\s. \blah. oper = InvokeIRQHandler blah \ (\ptr'. cte_wp_at (op = (IRQHandlerCap (irq_of_handler_inv blah))) ptr' s)) and domain_sep_inv False sta and valid_invocation oper and K (irq_is_recurring irq st)\ perform_invocation x y oper \\_. irq_state_inv st\, \\_. irq_state_next st\" apply(case_tac oper; simp; (solves \(wp invoke_untyped_irq_state_inv[where irq=irq] invoke_tcb_irq_state_inv invoke_cnode_irq_state_inv[simplified validE_R_def] irq_state_inv_triv | simp | clarsimp | simp add: invoke_domain_def)+\)?) apply wp apply (wp irq_state_inv_triv' invoke_irq_control_irq_masks) apply clarsimp apply assumption apply auto[1] apply wp apply(wp irq_state_inv_triv' invoke_irq_handler_irq_masks | clarsimp)+ apply assumption apply auto[1] done lemma hoare_drop_impE: assumes a: "\P\ f \Q\,\E\" shows "\P\ f \\ r s. R r s \ Q r s\,\E\" using assms apply(fastforce simp: validE_def valid_def split: sum.splits) done lemma handle_invocation_irq_state_inv: "\invs and domain_sep_inv False sta and irq_state_inv st and K (irq_is_recurring irq st)\ handle_invocation x y \\_. irq_state_inv st\, \\_. irq_state_next st\" apply (simp add: handle_invocation_def ts_Restart_case_helper split_def liftE_liftM_liftME liftME_def bindE_assoc split del: if_split) apply(wp syscall_valid) apply ((wp irq_state_inv_triv | wpc | simp)+)[2] apply(wp static_imp_wp perform_invocation_irq_state_inv hoare_vcg_all_lift hoare_vcg_ex_lift decode_invocation_IRQHandlerCap | wpc | wp_once hoare_drop_imps | simp split del: if_split | wp_once irq_state_inv_triv)+ apply fastforce done lemma handle_event_irq_state_inv: "event \ Interrupt \ \irq_state_inv st and invs and domain_sep_inv False sta and K (irq_is_recurring irq st)\ handle_event event \\_. irq_state_inv st\, \\_. irq_state_next st\" apply(case_tac event; simp) apply(rename_tac syscall) apply(case_tac syscall) apply simp_all apply ((simp add: handle_send_def handle_call_def | wp handle_invocation_irq_state_inv[where sta=sta and irq=irq] irq_state_inv_triv[OF handle_recv_irq_state_of_state] irq_state_inv_triv[OF handle_reply_irq_state_of_state])+) apply (wp irq_state_inv_triv hy_inv | simp)+ done lemma schedule_if_irq_state_inv: "\irq_state_inv st\ schedule_if tc \\_. irq_state_inv st\" apply(wp irq_state_inv_triv | simp add: schedule_if_def activate_thread_def arch_activate_idle_thread_def | wpc | wp_once hoare_drop_imps)+ done lemma irq_measure_if_inv: assumes irq_state: "\ st. \P st\ f \\_. irq_state_inv st\,-" shows "\\s. irq_measure_if_inv st s \ (irq_state_inv s s \ P s s)\ f \\_. irq_measure_if_inv st\,-" apply (clarsimp simp: valid_def validE_R_def validE_def) apply (simp add: irq_measure_if_inv_def) apply (erule order_trans[rotated]) apply (simp add: irq_state_inv_refl) apply (drule use_validE_R, rule irq_state, assumption) apply (simp add: irq_state_inv_def irq_measure_if_inv_def Let_def irq_measure_if_def) apply auto done lemma irq_measure_if_inv_old: assumes irq_state: "\ st. \irq_state_inv st and Q\ f \\_. irq_state_inv st\,-" shows "\irq_measure_if_inv st and Q\ f \\_. irq_measure_if_inv st\,-" by (wpsimp wp: irq_measure_if_inv irq_state) lemma irq_measure_if_inv': assumes irq_state: "\ st. \P st\ f \\_. irq_state_inv st\" shows "\\s. irq_measure_if_inv st s \ (irq_state_inv s s \ P s s)\ f \\_. irq_measure_if_inv st\" apply(clarsimp simp: valid_def irq_measure_if_inv_def irq_state_inv_refl) apply(erule le_trans[rotated]) apply(drule(1) use_valid[OF _ irq_state]) apply(clarsimp simp: irq_measure_if_def Let_def irq_state_inv_def) apply auto done lemma irq_measure_if_inv_old': assumes irq_state: "\ st. \irq_state_inv st and Q\ f \\_. irq_state_inv st\" shows "\irq_measure_if_inv st and Q\ f \\_. irq_measure_if_inv st\" by (wpsimp wp: irq_measure_if_inv' irq_state) lemma irq_state_inv_irq_is_recurring: "irq_state_inv sta s \ irq_is_recurring irq sta = irq_is_recurring irq s" apply(clarsimp simp: irq_is_recurring_def irq_state_inv_def is_irq_at_def) done abbreviation next_irq_state_of_state where "next_irq_state_of_state s \ next_irq_state (Suc (irq_state_of_state s)) (irq_masks_of_state s)" lemma kernel_entry_if_next_irq_state_of_state: "\event \ Interrupt; invs i_s; domain_sep_inv False st i_s; irq_is_recurring irq i_s\ \ ((Inr (), a), b) \ fst (kernel_entry_if event uc i_s) \ next_irq_state_of_state b = next_irq_state_of_state i_s" apply(simp add: kernel_entry_if_def in_bind in_return | elim conjE exE)+ apply(erule use_validE_R) apply(rule_tac Q'="\_. irq_state_inv i_s" in hoare_post_imp_R) apply (rule validE_validE_R') apply(rule handle_event_irq_state_inv[where sta=st and irq=irq] | simp)+ apply(clarsimp simp: irq_state_inv_def) apply (simp add: arch_tcb_update_aux2) apply(erule_tac f="thread_set (tcb_arch_update (arch_tcb_context_set uc)) t" in use_valid) apply(wpsimp wp: irq_measure_if_inv' irq_state_inv_triv thread_set_invs_trivial irq_is_recurring_triv[where Q="\"] simp: tcb_cap_cases_def tcb_arch_ref_def)+ apply(erule use_valid) apply (wp | simp )+ apply(simp add: irq_state_inv_def) done lemma kernel_entry_if_next_irq_state_of_state_next: "\event \ Interrupt; invs i_s; domain_sep_inv False st i_s; irq_is_recurring irq i_s; ((Inl r, a), b) \ fst (kernel_entry_if event uc i_s)\ \ irq_state_of_state b = next_irq_state_of_state i_s" apply(simp add: kernel_entry_if_def in_bind in_return | elim conjE exE)+ apply(erule use_validE_E) apply (rule validE_validE_E) apply (rule hoare_post_impErr) apply (rule handle_event_irq_state_inv[where sta=st and irq=irq and st=i_s]) apply simp+ apply (simp add: irq_state_next_def) apply (simp add: arch_tcb_update_aux2) apply(erule_tac f="thread_set (tcb_arch_update (arch_tcb_context_set uc)) t" in use_valid) apply(wpsimp wp: irq_measure_if_inv' irq_state_inv_triv thread_set_invs_trivial irq_is_recurring_triv[where Q="\"] simp: tcb_cap_cases_def tcb_arch_ref_def)+ apply(erule use_valid) apply (wp | simp )+ apply(simp add: irq_state_inv_def) done lemma kernel_entry_if_irq_measure: "\event \ Interrupt; invs i_s; domain_sep_inv False st i_s; irq_is_recurring irq i_s\ \ ((Inr (), a), b) \ fst (kernel_entry_if event uc i_s) \ irq_measure_if b \ irq_measure_if i_s" apply (fold irq_measure_if_inv_def) apply (rule mp) apply (erule_tac P="op = i_s" and Q="\rv s. (isRight (fst rv)) \ Q s" for Q in use_valid) apply (simp_all add: isRight_def) apply (simp add: kernel_entry_if_def) apply (rule hoare_pre, wp) apply (rule validE_cases_valid, simp) apply (wp irq_measure_if_inv handle_event_irq_state_inv[THEN validE_validE_R'])+ apply(wpsimp wp: irq_measure_if_inv' irq_state_inv_triv thread_set_invs_trivial irq_is_recurring_triv[where Q="\"] simp: tcb_cap_cases_def arch_tcb_update_aux2 tcb_arch_ref_def irq_state_inv_refl)+ apply(simp add: irq_measure_if_inv_def) done lemma schedule_if_irq_measure_if: "(r, b) \ fst (schedule_if uc i_s) \ irq_measure_if b \ irq_measure_if i_s" apply(fold irq_measure_if_inv_def) apply(erule use_valid[OF _ irq_measure_if_inv'] | wp schedule_if_irq_state_inv | simp)+ apply(simp add: irq_measure_if_inv_def) done lemma schedule_if_next_irq_state_of_state: "(r, b) \ fst (schedule_if uc i_s) \ next_irq_state_of_state b = next_irq_state_of_state i_s" apply(erule use_valid) apply(rule_tac Q="\_. irq_state_inv i_s" in hoare_strengthen_post) apply(wp schedule_if_irq_state_inv) apply(auto simp: irq_state_inv_def) done lemma next_irq_state_of_state_triv: assumes masks: "\P. \\ s. P (irq_masks_of_state s)\ f \\_ s. P (irq_masks_of_state s)\" assumes sta: "\P. \\ s. P (irq_state_of_state s)\ f \\_ s. P (irq_state_of_state s)\" shows "\\s. P (next_irq_state_of_state s)\ f \\_ s. P (next_irq_state_of_state s)\" apply(clarsimp simp: valid_def) apply(frule use_valid[OF _ masks]) apply assumption apply(erule use_valid[OF _ sta]) by assumption lemmas do_user_op_if_next_irq_state_of_state = next_irq_state_of_state_triv[OF do_user_op_if_irq_masks_of_state do_user_op_if_irq_state_of_state] lemma interrupted_modes_KernelEntry[simp]: "interrupted_modes (KernelEntry e) = (e = Interrupt)" apply(case_tac e, simp_all) done lemma rah4: "b < a \ 4 * (a - Suc b) + 3 < 4 * (a - b)" apply(rule Suc_le_lessD) apply (simp) done lemma tranclp_s0: "big_step_R\<^sup>*\<^sup>* s0 s \ interrupted_modes (snd s) \ (snd s) = KernelExit" apply (simp only: rtranclp_def2) apply(erule disjE) apply(induct rule: tranclp.induct) apply (auto simp: big_step_R_def s0_def) done lemma ADT_A_if_sub_big_steps_measuref_if: "\(s',evs) \ sub_big_steps (ADT_A_if utf) big_step_R s; big_step_R\<^sup>*\<^sup>* s0 s\ \ measuref_if s s' > 0" apply(drule tranclp_s0) apply(erule sub_big_steps.induct) apply(clarsimp simp: big_step_R_def measuref_if_def) apply(clarsimp simp: big_step_R_def measuref_if_def split: if_splits) apply(case_tac ba, simp_all, case_tac bc, simp_all add: Step_ADT_A_if') apply(simp_all add: ADT_A_if_def global_automaton_if_def) done lemma rah_simp: "(\b. b) = False" apply blast done lemma ADT_A_if_Step_measure_if': "\(s,s') \ data_type.Step (ADT_A_if utf) x; invs_if s; measuref_if y s > 0\ \ measuref_if y s' < measuref_if y s \ (\ interrupted_modes (snd s) \ \ interrupted_modes (snd s') \ next_irq_state_of_state (internal_state_if s') = next_irq_state_of_state (internal_state_if s))" apply(frule invs_if_irq_is_recurring) apply(case_tac s, clarsimp) apply(rename_tac uc i_s mode) apply(case_tac mode) apply(simp_all add: rah_simp system.Step_def execution_def steps_def ADT_A_if_def global_automaton_if_def check_active_irq_A_if_def do_user_op_A_if_def check_active_irq_if_def in_monad measuref_if_def | safe | split if_splits)+ apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_irq_measure_if]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(blast intro: rah4[OF next_irq_state_less]) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_next_irq_state_of_state]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(clarsimp split: if_splits) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_irq_measure_if]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(fastforce dest: next_irq_state_less) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_next_irq_state_of_state]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(clarsimp split: if_splits)+ apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(fastforce dest: next_irq_state_less) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(clarsimp split: if_splits) apply(clarsimp simp: kernel_call_A_if_def kernel_entry_if_def in_monad) apply(clarsimp split: if_splits) apply(rule Suc_le_lessD) apply simp apply(simp add: kernel_call_A_if_def) apply(elim exE conjE) apply(rule_tac event=x3 in kernel_entry_if_irq_measure) apply((simp add: invs_if_def Invs_def only_timer_irq_inv_def | elim conjE | assumption)+)[4] apply(simp) apply(simp add: kernel_call_A_if_def | elim conjE exE)+ apply(erule kernel_entry_if_next_irq_state_of_state) apply((simp add: invs_if_def Invs_def only_timer_irq_inv_def | elim conjE | assumption)+)[4] apply(clarsimp split: if_splits) apply(rule Suc_le_lessD) apply(simp add: kernel_schedule_if_def) apply(blast intro: schedule_if_irq_measure_if) apply(simp add: kernel_schedule_if_def) apply(blast intro: schedule_if_next_irq_state_of_state) apply(simp add: kernel_schedule_if_def) apply(blast intro: schedule_if_next_irq_state_of_state) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp split: if_splits)+ apply(clarsimp split: sys_mode.splits | safe)+ apply(clarsimp simp: irq_measure_if_def kernel_exit_A_if_def split: if_splits) apply(drule state_unchanged[OF kernel_exit_if_inv], simp) apply(clarsimp simp: irq_measure_if_def kernel_exit_A_if_def split: if_splits) apply(drule state_unchanged[OF kernel_exit_if_inv], simp) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) done lemma ADT_A_if_Step_measure_if'': "\(s,s') \ data_type.Step (ADT_A_if utf) x; invs_if s; measuref_if y s > 0\ \ measuref_if y s' < measuref_if y s \ (\ interrupted_modes (snd s) \ interrupted_modes (snd s') \ irq_state_of_state (internal_state_if s') = next_irq_state_of_state (internal_state_if s))" apply(frule invs_if_irq_is_recurring) apply(case_tac s, clarsimp) apply(rename_tac uc i_s mode) apply(case_tac mode) apply(simp_all add: rah_simp system.Step_def execution_def steps_def ADT_A_if_def global_automaton_if_def check_active_irq_A_if_def do_user_op_A_if_def check_active_irq_if_def in_monad measuref_if_def | safe | split if_splits)+ apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_irq_measure_if]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(blast intro: rah4[OF next_irq_state_less]) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_next_irq_state_of_state]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(clarsimp split: if_splits) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_irq_measure_if]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(fastforce dest: next_irq_state_less) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ do_user_op_if_next_irq_state_of_state]) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(clarsimp split: if_splits)+ apply (frule getActiveIRQ_Some) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc' recurring_next_irq_state_dom) apply(clarsimp split: if_splits) apply (frule getActiveIRQ_Some) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(simp add: next_irq_state_Suc' recurring_next_irq_state_dom) apply(clarsimp split: if_splits) apply(frule getActiveIRQ_None) apply(erule use_valid[OF _ dmo_getActiveIRQ_wp]) apply(clarsimp simp: irq_measure_if_def Let_def) apply(simp add: next_irq_state_Suc recurring_next_irq_state_dom) apply(fastforce dest: next_irq_state_less) apply(clarsimp split: if_splits) apply(clarsimp simp: kernel_call_A_if_def in_monad) apply (case_tac r ; simp) apply (rule kernel_entry_if_next_irq_state_of_state_next,assumption+) prefer 4 apply fastforce apply((simp add: invs_if_def Invs_def only_timer_irq_inv_def | elim conjE | assumption)+)[3] apply(clarsimp split: if_splits) apply(rule Suc_le_lessD) apply simp apply(simp add: kernel_call_A_if_def) apply(elim exE conjE) apply(rule_tac event=x3 in kernel_entry_if_irq_measure) apply((simp add: invs_if_def Invs_def only_timer_irq_inv_def | elim conjE | assumption)+)[4] apply(simp) apply(clarsimp split: if_splits) apply(rule Suc_le_lessD) apply(simp add: kernel_schedule_if_def) apply(blast intro: schedule_if_irq_measure_if) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp split: if_splits)+ apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp split: if_splits) apply(clarsimp split: sys_mode.splits | safe)+ apply(clarsimp simp: irq_measure_if_def kernel_exit_A_if_def split: if_splits) apply(drule state_unchanged[OF kernel_exit_if_inv], simp) apply(clarsimp simp: irq_measure_if_def kernel_exit_A_if_def split: if_splits) apply(drule state_unchanged[OF kernel_exit_if_inv], simp) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) apply(clarsimp simp: kernel_exit_A_if_def) apply((erule use_valid, wp | simp)+)[1] apply(clarsimp simp: kernel_exit_A_if_def split: if_splits) done lemma invs_if_domain_sep_invs[intro]: "invs_if ((a,s),b) \ domain_sep_inv False s0_internal s" apply (simp add: invs_if_def Invs_def) done lemma invs_if_invs[intro]: "invs_if ((a,s),b) \ invs s" apply (simp add: invs_if_def Invs_def) done lemma kernel_exit_irq_masks[wp]: "\\s. P (irq_masks_of_state s)\ kernel_exit_if uc \\r s. P (irq_masks_of_state s)\" apply (simp add: kernel_exit_if_def) apply wp done lemma ADT_A_if_Step_irq_masks: "\(s,s') \ data_type.Step (ADT_A_if utf) x; invs_if s\ \ irq_masks_of_state (internal_state_if s') = irq_masks_of_state (internal_state_if s)" apply(case_tac s, clarsimp) apply(rename_tac uc i_s mode) apply(case_tac mode) apply(simp_all add: rah_simp system.Step_def execution_def steps_def ADT_A_if_def global_automaton_if_def check_active_irq_A_if_def do_user_op_A_if_def check_active_irq_if_def in_monad measuref_if_def kernel_call_A_if_def kernel_handle_preemption_if_def kernel_schedule_if_def kernel_exit_A_if_def | safe | split if_splits)+ apply (erule use_valid[OF _ do_user_op_if_irq_masks_of_state] | erule use_valid[OF _ dmo_getActiveIRQ_irq_masks] | erule use_valid[OF _ kernel_entry_if_irq_masks] | rule refl)+ apply (fastforce intro!: invs_if_domain_sep_invs) apply (subgoal_tac "irq_masks_of_state b = irq_masks_of_state i_s",simp) apply (erule use_valid[OF _ kernel_entry_if_irq_masks]) apply (fastforce intro!: invs_if_domain_sep_invs) apply (erule use_valid[OF _ handle_preemption_if_irq_masks]) apply (fastforce intro!: invs_if_domain_sep_invs) apply (erule use_valid[OF _ schedule_if_irq_masks]) apply (fastforce intro!: invs_if_domain_sep_invs) apply (erule use_valid[OF _ kernel_exit_irq_masks]) apply simp done lemma steps_preserves_equivalence: "\(s', as) \ sub_big_steps A R s1; \t t' as a. (t, as) \ sub_big_steps A R s1 \ (t, t') \ data_type.Step A a \ \ R s1 t' \ f t = f t'\ \ f s1 = f s'" apply (erule sub_big_steps.induct) apply simp apply fastforce done lemma step_out_equivalent: "\ (s', as) \ sub_big_steps A R s1; (s', s2)\ data_type.Step A a; g s2 = f (g s'); \t t' as a. (t, as) \ sub_big_steps A R s1 \ (t, t') \ data_type.Step A a \ \ R s1 t' \ f (g t) = f (g t')\ \ f (g s1) = g s2" apply simp apply (erule steps_preserves_equivalence) apply simp+ done (*Clagged from Noninterference*) lemma irq_state_back: "P (irq_state_of_state (internal_state_if ((a,b),c))) (irq_masks_of_state (internal_state_if ((a,b),c))) \ P (irq_state_of_state b) (irq_masks_of_state b)" apply simp done lemma sub_big_steps_not_related: "(s,a) \ sub_big_steps A R s1 \ \ R s1 s" apply (erule sub_big_steps.cases,simp+) done lemma invs_if_sub_big_steps_ADT_A_if: "\(s', evs) \ sub_big_steps (ADT_A_if utf) big_step_R s; invs_if s\ \ invs_if s'" apply (erule sub_big_steps.induct) apply simp apply (simp add: invs_if_Step_ADT_A_if) done lemma small_step_irq_state_next_irq: "\invs_if s1; (s',evs) \ sub_big_steps (ADT_A_if utf) big_step_R s1; (s', s2) \ data_type.Step (ADT_A_if utf) a; big_step_R\<^sup>*\<^sup>* s0 s1; snd s1 = KernelExit; interrupted_modes (snd s2)\ \ next_irq_state_of_state (internal_state_if s1) = irq_state_of_state (internal_state_if s2)" apply (subgoal_tac "invs_if s'") apply (rule step_out_equivalent[where f="\(states,mask). (next_irq_state (Suc states) mask,mask)" and g="\s. (irq_state_of_state (internal_state_if s),irq_masks_of_state (internal_state_if s))",simplified, THEN conjunct1]) apply assumption apply assumption apply (rule conjI) apply (rule ADT_A_if_Step_measure_if''[THEN conjunct2,rule_format],assumption+) apply (rule ADT_A_if_sub_big_steps_measuref_if,assumption+) apply (frule sub_big_steps_not_related) apply (simp add: big_step_R_def) apply simp apply (rule ADT_A_if_Step_irq_masks,assumption+) apply clarsimp apply (subgoal_tac "invs_if ((a,b),ba)") apply (rule_tac b=b and a=a and c=ba in irq_state_back) apply (rule_tac b=bb and a=aa and c=bc in irq_state_back) apply (rule conjI) apply (rule sym) apply (rule ADT_A_if_Step_measure_if'[THEN conjunct2,rule_format],assumption+) apply (rule ADT_A_if_sub_big_steps_measuref_if,assumption+) apply (drule sub_big_steps_not_related)+ apply (simp add: big_step_R_def) apply (simp add: big_step_R_def) apply (rule sym) apply (rule ADT_A_if_Step_irq_masks,assumption+) apply (simp add: invs_if_sub_big_steps_ADT_A_if)+ done (*Can probably be generalized*) lemma small_step_to_big_step: assumes a: "(\s' evs. \ (s',evs) \ sub_big_steps (ADT_A_if utf) big_step_R s1; (s', s2) \ data_type.Step (ADT_A_if utf) a; big_step_R s1 s2\ \ S)" assumes b: "(s1, s2) \ data_type.Step (big_step_ADT_A_if utf) a" shows "S" apply (insert b) apply (simp add: big_step_ADT_A_if_def big_step_adt_def) apply (erule big_steps.cases) apply (rule_tac s'=s' and evs=as in a) apply simp+ done lemma big_step_irq_state_next_irq: "\invs_if s1; big_step_R\<^sup>*\<^sup>* s0 s1; (s1, s2) \ data_type.Step (big_step_ADT_A_if utf) a; snd s1 = KernelExit; i_s1 = internal_state_if s1; i_s2 = internal_state_if s2\ \ next_irq_state_of_state i_s1 = irq_state_of_state i_s2" apply simp apply (rule small_step_to_big_step) apply (rule small_step_irq_state_next_irq,(simp add: big_step_R_def)+) done lemmas ADT_A_if_Step_measure_if = ADT_A_if_Step_measure_if'[THEN conjunct1] lemmas ADT_A_if_Step_next_irq_state_of_state = ADT_A_if_Step_measure_if'[THEN conjunct2, rule_format] lemma Step_ADT_A_if_def_global_automaton_if: "Step (ADT_A_if uop) = (\u. global_automaton_if check_active_irq_A_if (do_user_op_A_if uop) kernel_call_A_if kernel_handle_preemption_if kernel_schedule_if kernel_exit_A_if \ {(s, y). step_restrict y})" apply(clarsimp simp: ADT_A_if_def) done lemma ADT_A_if_big_step_R_terminate: "rel_terminate (ADT_A_if utf) s0 big_step_R {s. invs_if s} measuref_if" apply(clarsimp simp: rel_terminate_def) apply(rule conjI) apply(rename_tac uc s mode as uc' s' mode' uc'' s'' mode'') apply(rule ADT_A_if_Step_measure_if) apply assumption apply (simp add: invs_if_sub_big_steps_ADT_A_if) apply(rule ADT_A_if_sub_big_steps_measuref_if) apply simp apply (simp add: ADT_A_if_def) apply (simp add: ADT_A_if_def) apply(drule tranclp_s0) apply(fastforce simp: measuref_if_def split: if_splits simp: big_step_R_def Step_ADT_A_if Step_ADT_A_if_def_global_automaton_if global_automaton_if_def) done lemma ADT_A_if_reachable_step_restrict: "system.reachable (ADT_A_if utf) s0 s \ step_restrict s" apply(clarsimp simp: system.reachable_def) apply (erule execution_restrict) done lemma ADT_A_if_Init_inv_Fin: "Init_inv_Fin_system (ADT_A_if utf) s0" apply unfold_locales apply (simp add: ADT_A_if_def invs_if_full_invs_if extras_s0) apply (frule ADT_A_if_reachable_invs_if) apply (drule ADT_A_if_reachable_step_restrict) apply (simp add: ADT_A_if_def invs_if_full_invs_if) apply (simp add: ADT_A_if_def) done lemma invs_if_inv_holds_ADT_A_if: "ADT_A_if utf [> Collect invs_if" by (force intro: inv_holdsI invs_if_Step_ADT_A_if) lemma step_restrict_inv_holds_ADT_A_if: "ADT_A_if utf [> {s. step_restrict s}" apply (rule inv_holdsI) apply (clarsimp simp: Image_def ADT_A_if_def) done lemma ADT_A_if_Init_Fin_serial_weak: "Init_Fin_serial_weak (ADT_A_if utf) s0 ({s. invs_if s} \ {s. step_restrict s})" apply (rule Init_Fin_serial_weak_strengthen) apply (rule Init_Fin_serial.serial_to_weak[OF ADT_A_if_Init_Fin_serial]) apply (intro inv_holds_conjI invs_if_inv_holds_ADT_A_if step_restrict_inv_holds_ADT_A_if) apply (clarsimp simp: invs_if_full_invs_if) apply (simp add: ADT_A_if_def) apply (insert invs_if_s0 extras_s0) apply blast done lemma big_step_ADT_A_if_enabled_Step_system: "enabled_Step_system (big_step_ADT_A_if utf) s0" apply(simp add: big_step_ADT_A_if_def) apply(rule big_step_adt_enabled_Step_system) apply simp apply(fastforce simp: big_step_R_def) apply (rule ADT_A_if_Init_Fin_serial_weak) apply (rule ADT_A_if_Init_inv_Fin) apply (rule rel_terminate_weaken) apply (rule ADT_A_if_big_step_R_terminate) apply simp done end context begin interpretation Arch . (*FIXME: arch_split*) definition internal_R where "internal_R A R s s' \ R (Fin A s) (Fin A s')" lemma invariant_holds_inv_holds: "A \ I \ A [> I" by (simp add: invariant_holds_def inv_holds_def) lemma inv_holdsE: assumes I: "A [> I" and step: "(s, t) \ Step A e" and s_I: "s \ I" and t_I: "t \ I \ P" shows "P" apply (rule t_I) apply (insert step I s_I) apply (force simp: inv_holds_def) done lemma LI_sub_big_steps: "\(s',as) \ sub_big_steps C (internal_R C R) s; LI A C S (Ia \ Ic); A \ Ia; C \ Ic; (t, s) \ S; s \ Ic; t \ Ia\ \ \t'. (t',as) \ sub_big_steps A (internal_R A R) t \ (t', s') \ S \ t' \ Ia" apply (induct rule: sub_big_steps.induct) apply(clarsimp simp: LI_def) apply (rule_tac x=t in exI) apply clarsimp apply (rule sub_big_steps.nil, simp_all)[1] apply (force simp: internal_R_def) apply (clarsimp simp: LI_def) apply (erule_tac x=e in allE) apply (clarsimp simp: rel_semi_def) apply (drule_tac x="(t', ta)" in set_mp) apply (rule_tac b=s' in relcompI) apply simp apply (rule sub_big_steps_I_holds) apply (rule invariant_holds_inv_holds, assumption+) apply clarsimp apply (rule_tac x=y in exI) apply clarsimp apply (subst conj_commute) apply (rule context_conjI) apply (erule inv_holdsE[OF invariant_holds_inv_holds]) apply assumption+ apply (rule sub_big_steps.step[OF refl]) apply assumption+ apply (subgoal_tac "z \ Ic") prefer 2 apply (rule_tac I=Ic in inv_holdsE[OF invariant_holds_inv_holds]) apply assumption+ apply (erule sub_big_steps_I_holds[OF invariant_holds_inv_holds]) apply assumption+ apply (subgoal_tac "Fin A t = Fin C s") apply (subgoal_tac "Fin A y = Fin C z") apply (simp(no_asm_use) add: internal_R_def) apply metis apply force+ done lemma LI_big_steps: "\(s, s') \ big_steps C (internal_R C R) exmap ev; LI A C S (Ia \ Ic); A \ Ia; C \ Ic; (t, s) \ S; s \ Ic; t \ Ia\ \ \t'. (t, t') \ big_steps A (internal_R A R) exmap ev \ (t', s') \ S \ t' \ Ia" apply (drule big_stepsD) apply clarsimp apply (frule(2) sub_big_steps_I_holds[OF invariant_holds_inv_holds]) apply (drule (6) LI_sub_big_steps) apply clarsimp apply (clarsimp simp: LI_def) apply (erule_tac x=a in allE) apply (clarsimp simp: rel_semi_def) apply (drule_tac x="(t', s')" in set_mp) apply (rule_tac b="s'a" in relcompI) apply simp apply simp apply clarsimp apply (rule_tac x=y in exI) apply simp apply (subst conj_commute) apply (rule context_conjI) apply (clarsimp simp: invariant_holds_def, blast) apply (rule big_steps.cstep) apply assumption+ apply (simp add: internal_R_def) apply (subgoal_tac "Fin A t = Fin C s") apply (subgoal_tac "s' \ Ic") apply (subgoal_tac "Fin A y = Fin C s'") apply metis apply metis apply (simp(no_asm_use) add: invariant_holds_def, blast) apply force apply simp done lemma inv_holds_Run_big_steps: "\A [> I; s \ I; (s, t) \ Run (big_steps A R exmap) js\ \ t \ I" apply (induct js arbitrary: t rule: rev_induct) apply force apply (force intro: big_steps_I_holds dest: Run_mid) done lemma refines_Run_big_steps: "\(s, s') \ Run (big_steps C (internal_R C R) exmap) js; LI A C S (Ia \ Ic); A \ Ia; C \ Ic; (t, s) \ S; s \ Ic; t \ Ia\ \ \t'. (t, t') \ Run (big_steps A (internal_R A R) exmap) js \ (t', s') \ S \ t' \ Ia" apply (induct js arbitrary: s' rule: rev_induct) apply force apply (frule Run_mid) apply clarsimp apply atomize apply (erule_tac x=ta in allE) apply clarsimp apply (drule(4) LI_big_steps) apply (erule(2) inv_holds_Run_big_steps[OF invariant_holds_inv_holds]) apply assumption apply clarsimp apply (rule_tac x="t'a" in exI) apply (force intro: Run_trans) done text{* TODO: with some more work we can probably change both @{term "refines"} to be @{term "refines'"} (see below). *} lemma big_step_adt_refines: "\LI A C S (Ia \ Ic); A \ Ia; C \ Ic\ \ refines (big_step_adt C (internal_R C R) exmap) (big_step_adt A (internal_R A R) exmap)" apply (subst refines_def) apply (clarsimp simp: execution_def steps_eq_Run) apply (clarsimp simp: image_def) apply (subst Bex_def, subst steps_eq_Run) apply (clarsimp simp: big_step_adt_def) apply (subgoal_tac "\a0'\ Init A s. (a0', s0') \ S") prefer 2 apply (force simp: LI_def) apply clarsimp apply (frule(4) refines_Run_big_steps) apply (force simp: invariant_holds_def) apply (force simp: invariant_holds_def) apply clarsimp apply (rule_tac x="t'" in exI) apply (clarsimp simp: LI_def) apply (rule conjI) apply blast apply (subgoal_tac "xa \ Ic") apply simp apply (rule_tac s="s0'" in inv_holds_Run_big_steps[OF invariant_holds_inv_holds], assumption+) apply (force simp: invariant_holds_def) apply simp done text {* A start at making the change mentioned above to @{thm big_step_adt_refines}. *} text {* Refinement restricted to states reachable from a common initial state *} definition refines' where "refines' C A s0 \ \js s. system.reachable C s0 s \ execution C s js \ execution A s js" lemma refines_refines': "refines C A \ refines' C A s" apply(auto simp: refines_def refines'_def) done text {* Two validity requirements on the user operation (uop) of the infoflow adt. These definitions are mostly only needed in ADT_A_if_Refine. *} text {* uop_nonempty is required to prove corres between do_user_op_if and doUserOp_if *} definition uop_nonempty :: "user_transition_if \ bool" where "uop_nonempty uop \ \t pl pr pxn tc um es. uop t pl pr pxn (tc, um, es) \ {}" text {* uop_sane is required to prove that the infoflow adt describes an enabled system *} definition uop_sane :: "user_transition_if \ bool" where "uop_sane f \ \t pl pr pxn tcu. (f t pl pr pxn tcu) \ {} \ (\tc um es. (Some Interrupt, tc, um, es) \ (f t pl pr pxn tcu))" end end