Theory Separation_kernel_model
subsection ‹Separation kernel model \label{sect:separation_kernel_model}›
theory Separation_kernel_model
imports "../../step/Step"
"../../step/Step_invariants"
"../../step/Step_vpeq"
"../../step/Step_vpeq_locally_respects"
"../../step/Step_vpeq_weakly_step_consistent"
CISK
begin
text ‹
First (Section~\ref{sect:initial_state}) we instantiate the CISK generic model.
Functions that instantiate a generic function of the CISK model are prefixed with an `r',
`r' standing for ``Rushby';, as CISK is derived originally from a model
by Rushby~\<^cite>‹"Verbeek2013"›.
For example, `rifp' is the instantiation of the generic `ifp'.
Later (Section~\ref{sect:discharging}) all CISK proof obligations are discharged, e.g.,
weak step consistency, output consistency, etc. These will be used in
Section~\ref{sect:link_to_CISK}.
›
subsubsection ‹Initial state of separation kernel model\label{sect:initial_state}›
text ‹We assume that the initial state of threads and memory is given.
The initial state of threads is arbitrary, but the threads are not
executing the system call. The purpose of the following definitions
is to obtain the initial state without potentially dangerous axioms.
The only axioms we admit without proof are formulated using the
``consts'' syntax and thus safe.›
consts
initial_current :: "thread_id_t"
initial_obj :: "obj_id_t ⇒ obj_t"
definition s0 :: state_t where
"s0 ≡ ⦇ sp_impl_subj_subj = Policy.sp_spec_subj_subj,
sp_impl_subj_obj = Policy.sp_spec_subj_obj,
current = initial_current,
obj = initial_obj,
thread = λ _ . (| ev_counter = 0 |)
⦈"
lemma initial_invariant:
shows "atomic_step_invariant s0"
proof -
have "sp_subset s0"
unfolding sp_subset_def s0_def by auto
thus ?thesis
unfolding atomic_step_invariant_def by auto
qed
subsubsection ‹Types for instantiation of the generic model›
text ‹To simplify formulations, we include the state invariant
@{term "atomic_step_invariant"} in the state data type. The
initial state @{term s0} serves at witness that @{term rstate_t}
is non-empty.›
typedef (overloaded) rstate_t = "{ s . atomic_step_invariant s }"
using initial_invariant by auto
definition abs :: "state_t ⇒ rstate_t" ("↑ _") where "abs = Abs_rstate_t"
definition rep :: "rstate_t ⇒ state_t" ("↓ _") where "rep = Rep_rstate_t"
lemma rstate_invariant:
shows "atomic_step_invariant (↓s)"
unfolding rep_def by (metis Rep_rstate_t mem_Collect_eq)
lemma rstate_down_up[simp]:
shows "(↑↓s) = s"
unfolding rep_def abs_def using Rep_rstate_t_inverse by auto
lemma rstate_up_down[simp]:
assumes "atomic_step_invariant s"
shows "(↓↑s) = s"
using assms Abs_rstate_t_inverse unfolding rep_def abs_def by auto
text ‹A CISK action is identified with an interrupt point.›
type_synonym raction_t = int_point_t
definition rcurrent :: "rstate_t ⇒ thread_id_t" where
"rcurrent s = current ↓s"
definition rstep :: "rstate_t ⇒ raction_t ⇒ rstate_t" where
"rstep s a ≡ ↑(atomic_step (↓s) a)"
text ‹Each CISK domain is identified with a thread id.›
type_synonym rdom_t = "thread_id_t"
text ‹The output function returns the contents of all memory accessible
to the subject. The action argument of the output function is ignored.›
datatype visible_obj_t = VALUE obj_t | EXCEPTION
type_synonym routput_t = "page_t ⇒ visible_obj_t"
definition routput_f :: "rstate_t ⇒ raction_t ⇒ routput_t" where
"routput_f s a p ≡
if sp_impl_subj_obj (↓s) (partition (rcurrent s)) (PAGE p) READ then
VALUE (obj (↓s) (PAGE p))
else
EXCEPTION"
text ‹The precondition for the generic model. Note that @{term atomic_step_invariant}
is already part of the state.›
definition rprecondition :: "rstate_t ⇒ rdom_t ⇒ raction_t ⇒ bool" where
"rprecondition s d a ≡ atomic_step_precondition (↓s) d a"
abbreviation rinvariant
where "rinvariant s ≡ True"
text ‹Translate view-partitioning and interaction-allowed relations.›
definition rvpeq :: "rdom_t ⇒ rstate_t ⇒ rstate_t ⇒ bool" where
"rvpeq u s1 s2 ≡ vpeq (partition u) (↓s1) (↓s2)"
definition rifp :: "rdom_t ⇒ rdom_t ⇒ bool" where
"rifp u v = Policy.ifp (partition u) (partition v)"
text ‹Context Switches›
definition rcswitch :: "nat ⇒ rstate_t ⇒ rstate_t" where
"rcswitch n s ≡ ↑((↓s) ⦇ current := (SOME t . True) ⦈)"
subsubsection ‹Possible action sequences›
text ‹
An @{term SK_IPC} consists of three atomic actions @{term PREP}, @{term WAIT} and @{term BUF} with the same parameters.
›
definition is_SK_IPC :: "raction_t list ⇒ bool"
where "is_SK_IPC aseq ≡ ∃ dir partner page .
aseq = [SK_IPC dir PREP partner page,SK_IPC dir WAIT partner page,SK_IPC dir (BUF (SOME page' . True)) partner page]"
text ‹
An @{term SK_EV_WAIT} consists of three atomic actions, one for each of the stages @{term EV_PREP}, @{term EV_WAIT} and @{term EV_FINISH}
with the same parameters.
›
definition is_SK_EV_WAIT :: "raction_t list ⇒ bool"
where "is_SK_EV_WAIT aseq ≡ ∃ consume .
aseq = [SK_EV_WAIT EV_PREP consume ,
SK_EV_WAIT EV_WAIT consume ,
SK_EV_WAIT EV_FINISH consume ]"
text ‹
An @{term SK_EV_SIGNAL} consists of two atomic actions, one for each of the stages @{term EV_SIGNAL_PREP} and
@{term EV_SIGNAL_FINISH} with the same parameters.
›
definition is_SK_EV_SIGNAL :: "raction_t list ⇒ bool"
where "is_SK_EV_SIGNAL aseq ≡ ∃ partner .
aseq = [SK_EV_SIGNAL EV_SIGNAL_PREP partner,
SK_EV_SIGNAL EV_SIGNAL_FINISH partner]"
text ‹
The complete attack surface consists of IPC calls, events, and noops.
›
definition rAS_set :: "raction_t list set"
where "rAS_set ≡ { aseq . is_SK_IPC aseq ∨ is_SK_EV_WAIT aseq ∨ is_SK_EV_SIGNAL aseq } ∪ {[]}"
subsubsection ‹Control›
text ‹
When are actions aborting, and when are actions waiting.
We do not currently use the @{term set_error_code} function yet.
›
abbreviation raborting
where "raborting s ≡ aborting (↓s)"
abbreviation rwaiting
where "rwaiting s ≡ waiting (↓s)"
definition rset_error_code :: "rstate_t ⇒ raction_t ⇒ rstate_t"
where "rset_error_code s a ≡ s"
text ‹
Returns the set of threads that are involved in a certain action.
For example, for an IPC call, the @{term WAIT} stage synchronizes with the partner.
This partner is involved in that action.
›
definition rkinvolved :: "int_point_t ⇒ rdom_t set"
where "rkinvolved a ≡
case a of SK_IPC dir WAIT partner page ⇒ {partner}
| SK_EV_SIGNAL EV_SIGNAL_FINISH partner => {partner}
| _ ⇒ {}"
abbreviation rinvolved :: "int_point_t option ⇒ rdom_t set"
where "rinvolved ≡ Kernel.involved rkinvolved"
subsubsection ‹Discharging the proof obligations\label{sect:discharging}›
lemma inst_vpeq_rel:
shows rvpeq_refl: "rvpeq u s s"
and rvpeq_sym: "rvpeq u s1 s2 ⟹ rvpeq u s2 s1"
and rvpeq_trans: "⟦ rvpeq u s1 s2; rvpeq u s2 s3 ⟧ ⟹ rvpeq u s1 s3"
unfolding rvpeq_def using vpeq_rel by metis+
lemma inst_ifp_refl:
shows "∀ u . rifp u u"
unfolding rifp_def using Policy_properties.ifp_reflexive by fast
lemma inst_step_atomicity [simp]:
shows "∀ s a . rcurrent (rstep s a) = rcurrent s"
unfolding rstep_def rcurrent_def
using atomic_step_does_not_change_current_thread rstate_up_down rstate_invariant atomic_step_preserves_invariants
by auto
lemma inst_weakly_step_consistent:
assumes "rvpeq u s t"
and "rvpeq (rcurrent s) s t"
and "rcurrent s = rcurrent t"
and "rprecondition s (rcurrent s) a"
and "rprecondition t (rcurrent t) a"
shows "rvpeq u (rstep s a) (rstep t a)"
using assms atomic_step_weakly_step_consistent rstate_invariant atomic_step_preserves_invariants
unfolding rcurrent_def rstep_def rvpeq_def rprecondition_def
by auto
lemma inst_local_respect:
assumes not_ifp: "¬rifp (rcurrent s) u"
and prec: "rprecondition s (rcurrent s) a"
shows "rvpeq u s (rstep s a)"
using assms atomic_step_respects_policy rstate_invariant atomic_step_preserves_invariants
unfolding rifp_def rprecondition_def rvpeq_def rstep_def rcurrent_def
by auto
lemma inst_output_consistency:
assumes rvpeq: "rvpeq (rcurrent s) s t"
and current_eq: "rcurrent s = rcurrent t"
shows "routput_f s a = routput_f t a"
proof-
have "∀ a s t. rvpeq (rcurrent s) s t ∧ rcurrent s = rcurrent t ⟶ routput_f s a = routput_f t a"
proof-
{ fix a :: raction_t
fix s t :: rstate_t
fix p :: page_t
assume 1: "rvpeq (rcurrent s) s t"
and 2: "rcurrent s = rcurrent t"
let ?part = "partition (rcurrent s)"
have "routput_f s a p = routput_f t a p"
proof (cases "Policy.sp_spec_subj_obj ?part (PAGE p) READ"
rule: case_split [case_names Allowed Denied])
case Allowed
have 5: "obj (↓s) (PAGE p) = obj (↓t) (PAGE p)"
using 1 Allowed unfolding rvpeq_def vpeq_def vpeq_obj_def by auto
have 6: "sp_impl_subj_obj (↓s) ?part (PAGE p) READ = sp_impl_subj_obj (↓t) ?part (PAGE p) READ"
using 1 2 Allowed unfolding rvpeq_def vpeq_def vpeq_subj_obj_def by auto
show "routput_f s a p = routput_f t a p"
unfolding routput_f_def using 2 5 6 by auto
next case Denied
hence "sp_impl_subj_obj (↓s) ?part (PAGE p) READ = False"
and "sp_impl_subj_obj (↓t) ?part (PAGE p) READ = False"
using rstate_invariant unfolding atomic_step_invariant_def sp_subset_def
by auto
thus "routput_f s a p = routput_f t a p"
using 2 unfolding routput_f_def by simp
qed }
thus "∀ a s t. rvpeq (rcurrent s) s t ∧ rcurrent s = rcurrent t ⟶ routput_f s a = routput_f t a"
by auto
qed
thus ?thesis using assms by auto
qed
lemma inst_cswitch_independent_of_state:
assumes "rcurrent s = rcurrent t"
shows "rcurrent (rcswitch n s) = rcurrent (rcswitch n t)"
using rstate_invariant cswitch_preserves_invariants unfolding rcurrent_def rcswitch_def by simp
lemma inst_cswitch_consistency:
assumes "rvpeq u s t"
shows "rvpeq u (rcswitch n s) (rcswitch n t)"
proof-
have 1: "vpeq (partition u) (↓s) ↓(rcswitch n s)"
using rstate_invariant cswitch_consistency_and_respect cswitch_preserves_invariants
unfolding rcswitch_def
by auto
have 2: "vpeq (partition u) (↓t) ↓(rcswitch n t)"
using rstate_invariant cswitch_consistency_and_respect cswitch_preserves_invariants
unfolding rcswitch_def
by auto
from 1 2 assms show ?thesis unfolding rvpeq_def using vpeq_rel by metis
qed
text ‹
For the @{term PREP} stage (the first stage of the IPC action sequence) the precondition is True.
›
lemma prec_first_IPC_action:
assumes "is_SK_IPC aseq"
shows "rprecondition s d (hd aseq)"
using assms
unfolding is_SK_IPC_def rprecondition_def atomic_step_precondition_def
by auto
text ‹
For the the first stage of the @{term EV_WAIT} action sequence the precondition is True.
›
lemma prec_first_EV_WAIT_action:
assumes "is_SK_EV_WAIT aseq"
shows "rprecondition s d (hd aseq)"
using assms
unfolding is_SK_EV_WAIT_def rprecondition_def atomic_step_precondition_def
by auto
text ‹
For the first stage of the @{term EV_SIGNAL} action sequence the precondition is True.
›
lemma prec_first_EV_SIGNAL_action:
assumes "is_SK_EV_SIGNAL aseq"
shows "rprecondition s d (hd aseq)"
using assms
unfolding is_SK_EV_SIGNAL_def rprecondition_def atomic_step_precondition_def
ev_signal_precondition_def
by auto
text ‹
When not waiting or aborting, the precondition is ``1-step inductive'', that is at all times
the precondition holds initially (for the first step of an action sequence) and after doing
one step.
›
lemma prec_after_IPC_step:
assumes prec: "rprecondition s (rcurrent s) (aseq ! n)"
and n_bound: "Suc n < length aseq"
and IPC: "is_SK_IPC aseq"
and not_aborting: "¬raborting s (rcurrent s) (aseq ! n)"
and not_waiting: "¬rwaiting s (rcurrent s) (aseq ! n)"
shows "rprecondition (rstep s (aseq ! n)) (rcurrent s) (aseq ! Suc n)"
proof-
{
fix dir partner page
let ?page' = "(SOME page' . True)"
assume IPC: "aseq = [SK_IPC dir PREP partner page,SK_IPC dir WAIT partner page,SK_IPC dir (BUF ?page') partner page]"
{
assume 0: "n=0"
from 0 IPC prec not_aborting
have ?thesis
unfolding rprecondition_def atomic_step_precondition_def rstep_def rcurrent_def atomic_step_def atomic_step_ipc_def aborting_def
by(auto)
}
moreover
{
assume 1: "n=1"
from 1 IPC prec not_waiting
have ?thesis
unfolding rprecondition_def atomic_step_precondition_def rstep_def rcurrent_def atomic_step_def atomic_step_ipc_def waiting_def
by(auto)
}
moreover
from IPC
have "length aseq = 3"
by auto
ultimately
have ?thesis
using n_bound
by arith
}
thus ?thesis
using IPC
unfolding is_SK_IPC_def
by(auto)
qed
text ‹
When not waiting or aborting, the precondition is 1-step inductive.
›
lemma prec_after_EV_WAIT_step:
assumes prec: "rprecondition s (rcurrent s) (aseq ! n)"
and n_bound: "Suc n < length aseq"
and IPC: "is_SK_EV_WAIT aseq"
and not_aborting: "¬raborting s (rcurrent s) (aseq ! n)"
and not_waiting: "¬rwaiting s (rcurrent s) (aseq ! n)"
shows "rprecondition (rstep s (aseq ! n)) (rcurrent s) (aseq ! Suc n)"
proof-
{
fix consume
assume WAIT: "aseq = [SK_EV_WAIT EV_PREP consume,
SK_EV_WAIT EV_WAIT consume,
SK_EV_WAIT EV_FINISH consume]"
{
assume 0: "n=0"
from 0 WAIT prec not_aborting
have ?thesis
unfolding rprecondition_def atomic_step_precondition_def
by(auto)
}
moreover
{
assume 1: "n=1"
from 1 WAIT prec not_waiting
have ?thesis
unfolding rprecondition_def atomic_step_precondition_def
by(auto)
}
moreover
from WAIT
have "length aseq = 3"
by auto
ultimately
have ?thesis
using n_bound
by arith
}
thus ?thesis
using assms
unfolding is_SK_EV_WAIT_def
by auto
qed
text ‹
When not waiting or aborting, the precondition is 1-step inductive.
›
lemma prec_after_EV_SIGNAL_step:
assumes prec: "rprecondition s (rcurrent s) (aseq ! n)"
and n_bound: "Suc n < length aseq"
and SIGNAL: "is_SK_EV_SIGNAL aseq"
and not_aborting: "¬raborting s (rcurrent s) (aseq ! n)"
and not_waiting: "¬rwaiting s (rcurrent s) (aseq ! n)"
shows "rprecondition (rstep s (aseq ! n)) (rcurrent s) (aseq ! Suc n)"
proof-
{ fix partner
assume SIGNAL1: "aseq = [SK_EV_SIGNAL EV_SIGNAL_PREP partner,
SK_EV_SIGNAL EV_SIGNAL_FINISH partner]"
{
assume 0: "n=0"
from 0 SIGNAL1 prec not_aborting
have ?thesis
unfolding rprecondition_def atomic_step_precondition_def ev_signal_precondition_def
aborting_def rstep_def atomic_step_def
by auto
}
moreover
from SIGNAL1
have "length aseq = 2"
by auto
ultimately
have ?thesis
using n_bound
by arith
}
thus ?thesis
using assms
unfolding is_SK_EV_SIGNAL_def
by auto
qed
lemma on_set_object_value:
shows "sp_impl_subj_subj (set_object_value ob val s) = sp_impl_subj_subj s"
and "sp_impl_subj_obj (set_object_value ob val s) = sp_impl_subj_obj s"
unfolding set_object_value_def apply simp+ done
lemma prec_IPC_dom_independent:
assumes "current s ≠ d"
and "atomic_step_invariant s"
and "atomic_step_precondition s d a"
shows "atomic_step_precondition (atomic_step_ipc (current s) dir stage partner page s) d a"
using assms on_set_object_value
unfolding atomic_step_precondition_def atomic_step_ipc_def ipc_precondition_def
ev_signal_precondition_def set_object_value_def
by (auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_consume_t.splits ev_wait_stage_t.splits ev_signal_stage_t.splits)
lemma prec_ev_signal_dom_independent:
assumes "current s ≠ d"
and "atomic_step_invariant s"
and "atomic_step_precondition s d a"
shows "atomic_step_precondition (atomic_step_ev_signal (current s) partner s) d a"
using assms on_set_object_value
unfolding atomic_step_precondition_def atomic_step_ev_signal_def ipc_precondition_def
ev_signal_precondition_def set_object_value_def
by (auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_consume_t.splits ev_wait_stage_t.splits ev_signal_stage_t.splits)
lemma prec_ev_wait_one_dom_independent:
assumes "current s ≠ d"
and "atomic_step_invariant s"
and "atomic_step_precondition s d a"
shows "atomic_step_precondition (atomic_step_ev_wait_one (current s) s) d a"
using assms on_set_object_value
unfolding atomic_step_precondition_def atomic_step_ev_wait_one_def ipc_precondition_def
ev_signal_precondition_def set_object_value_def
by (auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_consume_t.splits ev_wait_stage_t.splits ev_signal_stage_t.splits)
lemma prec_ev_wait_all_dom_independent:
assumes "current s ≠ d"
and "atomic_step_invariant s"
and "atomic_step_precondition s d a"
shows "atomic_step_precondition (atomic_step_ev_wait_all (current s) s) d a"
using assms on_set_object_value
unfolding atomic_step_precondition_def atomic_step_ev_wait_all_def ipc_precondition_def
ev_signal_precondition_def set_object_value_def
by (auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_consume_t.splits ev_wait_stage_t.splits ev_signal_stage_t.splits)
lemma prec_dom_independent:
shows "∀ s d a a' . rcurrent s ≠ d ∧ rprecondition s d a ⟶ rprecondition (rstep s a') d a"
using atomic_step_preserves_invariants
rstate_invariant prec_IPC_dom_independent prec_ev_signal_dom_independent
prec_ev_wait_all_dom_independent prec_ev_wait_one_dom_independent
unfolding rcurrent_def rprecondition_def rstep_def atomic_step_def
by(auto split: int_point_t.splits ev_consume_t.splits ev_wait_stage_t.splits ev_signal_stage_t.splits)
lemma ipc_precondition_after_cswitch[simp]:
shows "ipc_precondition d dir partner page ((↓ s)⦇current := new_current⦈)
= ipc_precondition d dir partner page (↓ s)"
unfolding ipc_precondition_def
by(auto split: ipc_direction_t.splits)
lemma precondition_after_cswitch:
shows "∀s d n a. rprecondition s d a ⟶ rprecondition (rcswitch n s) d a"
using cswitch_preserves_invariants rstate_invariant
unfolding rprecondition_def rcswitch_def atomic_step_precondition_def
ev_signal_precondition_def
by (auto split: int_point_t.splits ipc_stage_t.splits ev_signal_stage_t.splits)
lemma aborting_switch_independent:
shows "∀n s. raborting (rcswitch n s) = raborting s"
proof-
{
fix n s
{
fix tid a
have "raborting (rcswitch n s) tid a = raborting s tid a"
using rstate_invariant cswitch_preserves_invariants ev_signal_precondition_weakly_step_consistent
cswitch_consistency_and_respect
unfolding aborting_def rcswitch_def
apply (auto split: int_point_t.splits ipc_stage_t.splits
ev_wait_stage_t.splits ev_signal_stage_t.splits)
apply (metis (full_types))
by blast
}
hence "raborting (rcswitch n s) = raborting s" by auto
}
thus ?thesis by auto
qed
lemma waiting_switch_independent:
shows "∀n s. rwaiting (rcswitch n s) = rwaiting s"
proof-
{
fix n s
{
fix tid a
have "rwaiting (rcswitch n s) tid a = rwaiting s tid a"
using rstate_invariant cswitch_preserves_invariants
unfolding waiting_def rcswitch_def
by(auto split: int_point_t.splits ipc_stage_t.splits ev_wait_stage_t.splits)
}
hence "rwaiting (rcswitch n s) = rwaiting s" by auto
}
thus ?thesis by auto
qed
lemma aborting_after_IPC_step:
assumes "d1 ≠ d2"
shows "aborting (atomic_step_ipc d1 dir stage partner page s) d2 a = aborting s d2 a"
unfolding atomic_step_ipc_def aborting_def set_object_value_def ipc_precondition_def
ev_signal_precondition_def
by(auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_signal_stage_t.splits)
lemma waiting_after_IPC_step:
assumes "d1 ≠ d2"
shows "waiting (atomic_step_ipc d1 dir stage partner page s) d2 a = waiting s d2 a"
unfolding atomic_step_ipc_def waiting_def set_object_value_def ipc_precondition_def
by(auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_wait_stage_t.splits)
lemma raborting_consistent:
shows "∀s t u. rvpeq u s t ⟶ raborting s u = raborting t u"
proof-
{
fix s t u
assume vpeq: "rvpeq u s t"
{
fix a
from vpeq ipc_precondition_weakly_step_consistent rstate_invariant
have "⋀ tid dir partner page . ipc_precondition u dir partner page (↓s)
= ipc_precondition u dir partner page (↓t)"
unfolding rvpeq_def
by auto
with vpeq rstate_invariant have "raborting s u a = raborting t u a"
unfolding aborting_def rvpeq_def vpeq_def vpeq_local_def ev_signal_precondition_def
vpeq_subj_subj_def atomic_step_invariant_def sp_subset_def rep_def
apply (auto split: int_point_t.splits ipc_stage_t.splits ev_signal_stage_t.splits)
by blast
}
hence "raborting s u = raborting t u" by auto
}
thus ?thesis by auto
qed
lemma aborting_dom_independent:
assumes "rcurrent s ≠ d"
shows "raborting (rstep s a) d a' = raborting s d a'"
proof -
have "⋀ tid dir partner page s . ipc_precondition tid dir partner page s = ipc_precondition tid dir partner page (atomic_step s a)
∧ ev_signal_precondition tid partner s = ev_signal_precondition tid partner (atomic_step s a)
"
proof -
fix tid dir partner page s
let ?s = "atomic_step s a"
have "(∀ p q . sp_impl_subj_subj s p q = sp_impl_subj_subj ?s p q)
∧ (∀ p x m . sp_impl_subj_obj s p x m = sp_impl_subj_obj ?s p x m)"
unfolding atomic_step_def atomic_step_ipc_def
atomic_step_ev_wait_all_def atomic_step_ev_wait_one_def
atomic_step_ev_signal_def set_object_value_def
by (auto split: int_point_t.splits ipc_stage_t.splits ipc_direction_t.splits
ev_wait_stage_t.splits ev_consume_t.splits ev_signal_stage_t.splits)
thus "ipc_precondition tid dir partner page s = ipc_precondition tid dir partner page (atomic_step s a)
∧ ev_signal_precondition tid partner s = ev_signal_precondition tid partner (atomic_step s a)"
unfolding ipc_precondition_def ev_signal_precondition_def by simp
qed
moreover have "⋀ b . (↓(↑(atomic_step (↓s) b))) = atomic_step (↓s) b"
using rstate_invariant atomic_step_preserves_invariants rstate_up_down by auto
ultimately show ?thesis
unfolding aborting_def rstep_def ev_signal_precondition_def
by (simp split: int_point_t.splits ipc_stage_t.splits ev_wait_stage_t.splits
ev_signal_stage_t.splits)
qed
lemma ipc_precondition_of_partner_consistent:
assumes vpeq: "∀ d ∈ rkinvolved (SK_IPC dir WAIT partner page) . rvpeq d s t"
shows "ipc_precondition partner dir' u page' (↓ s) = ipc_precondition partner dir' u page' ↓ t"
proof-
from assms ipc_precondition_weakly_step_consistent rstate_invariant
show ?thesis
unfolding rvpeq_def rkinvolved_def
by auto
qed
lemma ev_signal_precondition_of_partner_consistent:
assumes vpeq: "∀ d ∈ rkinvolved (SK_EV_SIGNAL EV_SIGNAL_FINISH partner) . rvpeq d s t"
shows "ev_signal_precondition partner u (↓ s) = ev_signal_precondition partner u (↓ t)"
proof-
from assms ev_signal_precondition_weakly_step_consistent rstate_invariant
show ?thesis
unfolding rvpeq_def rkinvolved_def
by auto
qed
lemma waiting_consistent:
shows "∀s t u a . rvpeq (rcurrent s) s t ∧ (∀ d ∈ rkinvolved a . rvpeq d s t)
∧ rvpeq u s t
⟶ rwaiting s u a = rwaiting t u a"
proof-
{
fix s t u a
assume vpeq: "rvpeq (rcurrent s) s t"
assume vpeq_involved: "∀ d ∈ rkinvolved a . rvpeq d s t"
assume vpeq_u: "rvpeq u s t"
have "rwaiting s u a = rwaiting t u a" proof (cases a)
case SK_IPC
thus "rwaiting s u a = rwaiting t u a"
using ipc_precondition_of_partner_consistent vpeq_involved
unfolding waiting_def by (auto split: ipc_stage_t.splits)
next case SK_EV_WAIT
thus "rwaiting s u a = rwaiting t u a"
using ev_signal_precondition_of_partner_consistent
vpeq_involved vpeq vpeq_u
unfolding waiting_def rkinvolved_def ev_signal_precondition_def
rvpeq_def vpeq_def vpeq_local_def
by (auto split: ipc_stage_t.splits ev_wait_stage_t.splits ev_consume_t.splits)
qed (simp add: waiting_def, simp add: waiting_def)
}
thus ?thesis by auto
qed
lemma ipc_precondition_ensures_ifp:
assumes "ipc_precondition (current s) dir partner page s"
and "atomic_step_invariant s"
shows "rifp partner (current s)"
proof -
let ?sp = "λ t1 t2 . Policy.sp_spec_subj_subj (partition t1) (partition t2)"
have "?sp (current s) partner ∨ ?sp partner (current s)"
using assms unfolding ipc_precondition_def atomic_step_invariant_def sp_subset_def
by (cases dir, auto)
thus ?thesis
unfolding rifp_def using Policy_properties.ifp_compatible_with_sp_spec by auto
qed
lemma ev_signal_precondition_ensures_ifp:
assumes "ev_signal_precondition (current s) partner s"
and "atomic_step_invariant s"
shows "rifp partner (current s)"
proof -
let ?sp = "λ t1 t2 . Policy.sp_spec_subj_subj (partition t1) (partition t2)"
have "?sp (current s) partner ∨ ?sp partner (current s)"
using assms unfolding ev_signal_precondition_def atomic_step_invariant_def sp_subset_def
by (auto)
thus ?thesis
unfolding rifp_def using Policy_properties.ifp_compatible_with_sp_spec by auto
qed
lemma involved_ifp:
shows "∀ s a . ∀ d ∈ rkinvolved a . rprecondition s (rcurrent s) a ⟶ rifp d (rcurrent s)"
proof-
{
fix s a d
assume d_involved: "d ∈ rkinvolved a"
assume prec: "rprecondition s (rcurrent s) a"
from d_involved prec have "rifp d (rcurrent s)"
using ipc_precondition_ensures_ifp ev_signal_precondition_ensures_ifp rstate_invariant
unfolding rkinvolved_def rprecondition_def atomic_step_precondition_def rcurrent_def Kernel.involved_def
by(cases a,simp,auto split: int_point_t.splits ipc_stage_t.splits ev_signal_stage_t.splits)
}
thus ?thesis by auto
qed
lemma spec_of_waiting_ev:
shows "∀s a. rwaiting s (rcurrent s) (SK_EV_WAIT EV_FINISH EV_CONSUME_ALL)
⟶ rstep s a = s"
unfolding waiting_def
by auto
lemma spec_of_waiting_ev_w:
shows "∀s a. rwaiting s (rcurrent s) (SK_EV_WAIT EV_WAIT EV_CONSUME_ALL)
⟶ rstep s (SK_EV_WAIT EV_WAIT EV_CONSUME_ALL) = s"
unfolding rstep_def atomic_step_def
by (auto split: int_point_t.splits ipc_stage_t.splits ev_wait_stage_t.splits)
lemma spec_of_waiting:
shows "∀s a. rwaiting s (rcurrent s) a ⟶ rstep s a = s"
unfolding waiting_def rstep_def atomic_step_def atomic_step_ipc_def
atomic_step_ev_signal_def atomic_step_ev_wait_all_def
atomic_step_ev_wait_one_def
by(auto split: int_point_t.splits ipc_stage_t.splits ev_wait_stage_t.splits)
end