2206 lines
97 KiB
Plaintext
2206 lines
97 KiB
Plaintext
(*
|
|
* 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 Intent_DR
|
|
imports Corres_D
|
|
begin
|
|
|
|
context begin interpretation Arch . (*FIXME: arch_split*)
|
|
|
|
definition not_idle_thread:: "obj_ref \<Rightarrow> 'z::state_ext state \<Rightarrow> bool"
|
|
where "not_idle_thread x \<equiv> (\<lambda>s. x \<noteq> idle_thread s)"
|
|
|
|
(*Some trivial lemmas rule out irq_node and idle_thread*)
|
|
|
|
lemma ep_not_idle:
|
|
"\<lbrakk>valid_idle s;obj_at is_ep epptr s\<rbrakk> \<Longrightarrow> not_idle_thread epptr s"
|
|
by (clarsimp simp:valid_idle_def obj_at_def is_cap_table_def pred_tcb_at_def is_ep_def not_idle_thread_def)
|
|
|
|
lemma ntfn_not_idle:
|
|
"\<lbrakk>valid_idle s;obj_at is_ntfn epptr s\<rbrakk> \<Longrightarrow> not_idle_thread epptr s"
|
|
by (clarsimp simp:valid_idle_def obj_at_def is_cap_table_def pred_tcb_at_def is_ntfn_def not_idle_thread_def)
|
|
|
|
lemma cte_wp_at_zombie_not_idle:
|
|
"\<lbrakk>cte_wp_at (op = (cap.Zombie ptr' zbits n)) ptr s; invs s\<rbrakk> \<Longrightarrow> not_idle_thread (fst ptr) s"
|
|
"\<lbrakk>cte_wp_at (op = (cap.Zombie ptr' zbits n)) ptr s; invs s\<rbrakk> \<Longrightarrow> not_idle_thread ptr' s"
|
|
by (auto dest!: zombie_cap_two_nonidles simp: cte_wp_at_caps_of_state not_idle_thread_def)
|
|
|
|
lemmas tcb_slots = Types_D.tcb_caller_slot_def Types_D.tcb_cspace_slot_def Types_D.tcb_ipcbuffer_slot_def
|
|
Types_D.tcb_pending_op_slot_def Types_D.tcb_replycap_slot_def Types_D.tcb_vspace_slot_def Types_D.tcb_boundntfn_slot_def
|
|
|
|
lemma tcb_cap_casesE:
|
|
assumes cs: "tcb_cap_cases p = Some (gf, sf, restr)"
|
|
and rules: "\<lbrakk> p = tcb_cnode_index 0; gf = tcb_ctable; sf = tcb_ctable_update; restr = (\<lambda>_ _. \<top>) \<rbrakk> \<Longrightarrow> R"
|
|
"\<lbrakk> p = tcb_cnode_index 1; gf = tcb_vtable; sf = tcb_vtable_update; restr = (\<lambda>_ _. \<top>) \<rbrakk> \<Longrightarrow> R"
|
|
"\<lbrakk> p = tcb_cnode_index 2; gf = tcb_reply; sf = tcb_reply_update; restr =
|
|
(\<lambda>t st c.
|
|
(is_master_reply_cap c \<and> obj_ref_of c = t)
|
|
\<or> (halted st \<and> (c = cap.NullCap))) \<rbrakk> \<Longrightarrow> R"
|
|
"\<lbrakk> p = tcb_cnode_index 3; gf = tcb_caller; sf = tcb_caller_update; restr =
|
|
(\<lambda>_ st. case st of
|
|
Structures_A.BlockedOnReceive e \<Rightarrow>
|
|
(op = cap.NullCap)
|
|
| _ \<Rightarrow> is_reply_cap or (op = cap.NullCap)) \<rbrakk> \<Longrightarrow> R"
|
|
"\<lbrakk> p = tcb_cnode_index 4; gf = tcb_ipcframe; sf = tcb_ipcframe_update; restr =
|
|
(\<lambda>_ _. is_nondevice_page_cap or (op = cap.NullCap)) \<rbrakk> \<Longrightarrow> R"
|
|
shows "R"
|
|
using cs
|
|
unfolding tcb_cap_cases_def
|
|
apply (simp split: split_if_asm del: One_nat_def)
|
|
apply (erule rules, fastforce+)+
|
|
done
|
|
|
|
lemma tcb_cnode_index_def2:
|
|
"n < 8 \<Longrightarrow> tcb_cnode_index n = bin_to_bl 3 (int n)"
|
|
unfolding tcb_cnode_index_def to_bl_def
|
|
by (simp add: uint_nat unat_of_nat)
|
|
|
|
lemma bl_to_bin_tcb_cnode_index:
|
|
"n < 8 \<Longrightarrow> nat (bl_to_bin (tcb_cnode_index n)) = n"
|
|
unfolding tcb_cnode_index_def
|
|
apply simp
|
|
apply (fold unat_def)
|
|
apply (simp add: unat_of_nat)
|
|
done
|
|
|
|
(* LIFT LEMMAS:
|
|
Lift the property from abstract spec to capdl model
|
|
*)
|
|
|
|
lemma transform_objects_kheap:
|
|
"\<lbrakk> kheap s p = Some ko; p \<noteq> idle_thread s \<rbrakk>
|
|
\<Longrightarrow> transform_objects s p = Some (transform_object (machine_state s) p (ekheap s p) ko)"
|
|
unfolding transform_objects_def
|
|
by (simp)
|
|
|
|
lemma transform_objects_tcb:
|
|
"\<lbrakk> get_tcb ptr s = Some tcb; get_etcb ptr s = Some etcb; ptr \<noteq> idle_thread s\<rbrakk>
|
|
\<Longrightarrow> transform_objects s ptr = Some (transform_tcb (machine_state s) ptr tcb etcb)"
|
|
by (clarsimp dest!: get_tcb_SomeD get_etcb_SomeD
|
|
simp: transform_objects_def)
|
|
|
|
lemma opt_object_tcb:
|
|
"\<lbrakk> get_tcb ptr s = Some tcb; get_etcb ptr s = Some etcb; ptr \<noteq> idle_thread s \<rbrakk> \<Longrightarrow>
|
|
opt_object ptr (transform s) = Some (transform_tcb (machine_state s) ptr tcb etcb)"
|
|
by (clarsimp simp: opt_object_def transform_def transform_objects_tcb dest!: get_tcb_SomeD)
|
|
|
|
abbreviation
|
|
"tcb_abstract_slots \<equiv> {tcb_caller_slot, tcb_cspace_slot, tcb_ipcbuffer_slot, tcb_replycap_slot, tcb_vspace_slot}"
|
|
|
|
lemma tcb_cap_cases_slot_simps[simp]:
|
|
"tcb_cap_cases (tcb_cnode_index tcb_cspace_slot) = Some (tcb_ctable, tcb_ctable_update, (\<lambda>_ _. \<top>))"
|
|
"tcb_cap_cases (tcb_cnode_index tcb_vspace_slot) = Some (tcb_vtable, tcb_vtable_update, (\<lambda>_ _. \<top>))"
|
|
"tcb_cap_cases (tcb_cnode_index tcb_replycap_slot) = Some (tcb_reply, tcb_reply_update,
|
|
(\<lambda>t st c.
|
|
(is_master_reply_cap c \<and> obj_ref_of c = t)
|
|
\<or> (halted st \<and> (c = cap.NullCap))))"
|
|
"tcb_cap_cases (tcb_cnode_index tcb_caller_slot) = Some (tcb_caller, tcb_caller_update,
|
|
(\<lambda>_ st. case st of
|
|
Structures_A.BlockedOnReceive e \<Rightarrow>
|
|
(op = cap.NullCap)
|
|
| _ \<Rightarrow> is_reply_cap or (op = cap.NullCap)))"
|
|
"tcb_cap_cases (tcb_cnode_index tcb_ipcbuffer_slot) = Some (tcb_ipcframe, tcb_ipcframe_update,
|
|
(\<lambda>_ _. is_nondevice_page_cap or (op = cap.NullCap)))"
|
|
by (simp add: tcb_slots)+
|
|
|
|
lemma opt_cap_tcb:
|
|
"\<lbrakk> get_tcb y s = Some tcb; (\<exists>etcb. get_etcb y s = Some etcb); y \<noteq> idle_thread s \<rbrakk> \<Longrightarrow>
|
|
opt_cap (y, sl) (transform s) =
|
|
(if sl \<in> tcb_abstract_slots then (option_map (\<lambda>(getF, _, _). transform_cap (getF tcb)) (tcb_cap_cases (tcb_cnode_index sl)))
|
|
else (if sl = tcb_pending_op_slot then (Some (infer_tcb_pending_op y (tcb_state tcb)))
|
|
else (if sl = tcb_boundntfn_slot then (Some (infer_tcb_bound_notification (tcb_bound_notification tcb))) else None)))"
|
|
by (fastforce simp add: opt_cap_def KHeap_D.slots_of_def opt_object_tcb object_slots_def transform_tcb_def tcb_slots)
|
|
|
|
lemma cdl_objects_cnode:
|
|
"\<lbrakk> kheap s' y = Some (CNode sz obj'); valid_idle s' ; sz \<noteq> 0\<rbrakk>
|
|
\<Longrightarrow> cdl_objects (transform s') y =
|
|
Some (cdl_object.CNode \<lparr>cdl_cnode_caps = transform_cnode_contents sz obj', cdl_cnode_size_bits = sz\<rparr>)"
|
|
apply (subgoal_tac "y \<noteq> idle_thread s'")
|
|
apply (auto simp:obj_at_def is_cap_table_def valid_idle_def pred_tcb_at_def
|
|
transform_def transform_objects_def
|
|
split:nat.split)
|
|
done
|
|
|
|
lemma cdl_objects_irq_node:
|
|
"\<lbrakk> kheap s' y = Some (CNode 0 obj'); valid_idle s' \<rbrakk>
|
|
\<Longrightarrow> cdl_objects (transform s') y =
|
|
Some (cdl_object.IRQNode \<lparr>cdl_irq_node_caps = transform_cnode_contents 0 obj'\<rparr>)"
|
|
apply (subgoal_tac "y \<noteq> idle_thread s'")
|
|
apply (auto simp:obj_at_def is_cap_table_def valid_idle_def pred_tcb_at_def
|
|
transform_def transform_objects_def)
|
|
done
|
|
|
|
lemma transform_objects_cnode:
|
|
"\<lbrakk> kheap s' y = Some (CNode sz obj'); valid_idle s'; sz \<noteq> 0\<rbrakk> \<Longrightarrow> transform_objects s' y =
|
|
Some (cdl_object.CNode \<lparr>cdl_cnode_caps = transform_cnode_contents sz obj', cdl_cnode_size_bits = sz\<rparr>)"
|
|
apply (subgoal_tac "y \<noteq> idle_thread s'")
|
|
apply (simp add: transform_objects_def)
|
|
apply (clarsimp simp add: valid_idle_def obj_at_def pred_tcb_at_def split:nat.split)+
|
|
done
|
|
|
|
lemma transform_objects_irq_node:
|
|
"\<lbrakk> kheap s' y = Some (CNode 0 obj'); valid_idle s'\<rbrakk> \<Longrightarrow> transform_objects s' y =
|
|
Some (cdl_object.IRQNode \<lparr>cdl_irq_node_caps = transform_cnode_contents 0 obj'\<rparr>)"
|
|
apply (subgoal_tac "y \<noteq> idle_thread s'")
|
|
apply (simp add: transform_objects_def)
|
|
apply (clarsimp simp add: valid_idle_def obj_at_def pred_tcb_at_def split:nat.split)+
|
|
done
|
|
|
|
lemmas lift_simp =
|
|
transform_objects_tcb transform_objects_cnode transform_objects_kheap cdl_objects_cnode
|
|
opt_cap_tcb opt_object_tcb
|
|
|
|
lemma transform_objects_update_other:
|
|
"\<lbrakk> kh ptr = Some ko; caps_of_object ko = caps_of_object ko'; a_type ko = a_type ko'; ref \<noteq> ptr \<rbrakk>
|
|
\<Longrightarrow> transform_objects (update_kheap (kh(ptr \<mapsto> ko')) s) ref = transform_objects (update_kheap kh s) ref"
|
|
unfolding transform_objects_def
|
|
by (cases ref, simp_all add: restrict_map_def caps_of_state_update_same_caps
|
|
cap_installed_at_irq_def map_add_def)
|
|
|
|
lemma caps_of_object_update_state [simp]:
|
|
"(\<lambda>n. map_option (\<lambda>(f, _). f (tcb_state_update stf tcb)) (tcb_cap_cases n)) =
|
|
(\<lambda>n. map_option (\<lambda>(f, _). f tcb) (tcb_cap_cases n))"
|
|
apply (rule ext)
|
|
apply (simp add: tcb_cap_cases_def split: split_if)
|
|
done
|
|
|
|
lemma caps_of_object_update_boundntfn [simp]:
|
|
"(\<lambda>n. map_option (\<lambda>(f, _). f (tcb_bound_notification_update stf tcb)) (tcb_cap_cases n)) =
|
|
(\<lambda>n. map_option (\<lambda>(f, _). f tcb) (tcb_cap_cases n))"
|
|
apply (rule ext)
|
|
apply (simp add: tcb_cap_cases_def split: split_if)
|
|
done
|
|
|
|
lemma caps_of_object_update_context [simp]:
|
|
"(\<lambda>n. map_option (\<lambda>(f, _). f (tcb_context_update stf tcb)) (tcb_cap_cases n)) =
|
|
(\<lambda>n. map_option (\<lambda>(f, _). f tcb) (tcb_cap_cases n))"
|
|
apply (rule ext)
|
|
apply (simp add: tcb_cap_cases_def split: split_if)
|
|
done
|
|
|
|
definition
|
|
generates_pending :: "Structures_A.thread_state \<Rightarrow> bool"
|
|
where
|
|
"generates_pending st \<equiv> case st of
|
|
Structures_A.BlockedOnReceive ptr \<Rightarrow> True
|
|
| Structures_A.BlockedOnSend ptr payload \<Rightarrow> True
|
|
| Structures_A.BlockedOnReply \<Rightarrow> True
|
|
| Structures_A.BlockedOnNotification ptr \<Rightarrow> True
|
|
| Structures_A.Restart \<Rightarrow> True
|
|
| Structures_A.Running \<Rightarrow> True
|
|
| _ \<Rightarrow> False"
|
|
|
|
lemmas generates_pending_simps [simp] = generates_pending_def [split_simps Structures_A.thread_state.split]
|
|
|
|
lemmas infer_tcb_pending_op_simps [simp] = infer_tcb_pending_op_def [split_simps Structures_A.thread_state.split]
|
|
|
|
(* Is actually iff *)
|
|
lemma not_generates_pending_is_null:
|
|
"\<not> generates_pending st \<Longrightarrow> (infer_tcb_pending_op ptr st = Types_D.NullCap)"
|
|
unfolding generates_pending_def infer_tcb_pending_op_def
|
|
by (simp split: Structures_A.thread_state.splits)
|
|
|
|
lemma transform_tcb_upd_state_no_pending:
|
|
"\<lbrakk> \<not> generates_pending (tcb_state tcb); \<not> generates_pending (f (tcb_state tcb)) \<rbrakk>
|
|
\<Longrightarrow> transform_tcb ms ptr (tcb_state_update f tcb) etcb = transform_tcb ms ptr tcb etcb"
|
|
unfolding transform_tcb_def
|
|
by (simp add: not_generates_pending_is_null cong: transform_full_intent_cong)
|
|
|
|
lemmas transform_objects_tcb_state =
|
|
transform_objects_update_kheap_same_caps transform_objects_update_same
|
|
transform_tcb_upd_state_no_pending
|
|
|
|
lemma transform_objects_dummy_set_original_cap [simp]:
|
|
"transform_objects (b\<lparr>is_original_cap := x\<rparr>) = transform_objects b"
|
|
by (clarsimp simp: cap_installed_at_irq_def transform_objects_def)
|
|
|
|
lemma transform_objects_dummy_update_cdt [simp]:
|
|
"transform_objects (b\<lparr>cdt := x\<rparr>) = transform_objects b"
|
|
by (clarsimp simp: cap_installed_at_irq_def transform_objects_def)
|
|
|
|
lemma update_tcb_cxt_eq_dupdate_tcb_intent:
|
|
"\<lbrakk>
|
|
cdl_objects (transform b) y = Some (Tcb t);
|
|
kheap b y = Some (TCB obj);
|
|
\<exists>etcb'. ekheap b y = Some etcb';
|
|
obj' = obj\<lparr>tcb_context:=cxt\<rparr>;
|
|
not_idle_thread y b;
|
|
intent = transform_full_intent (machine_state (update_kheap ((kheap b)(y\<mapsto>(TCB obj'))) b)) y obj'
|
|
\<rbrakk>
|
|
\<Longrightarrow> dupdate_cdl_object y (Tcb (dupdate_tcb_intent intent t)) (transform b)
|
|
= transform (update_kheap ((kheap b)(y\<mapsto> (TCB obj'))) b)"
|
|
apply (clarsimp simp:transform_def transform_current_thread_def
|
|
not_idle_thread_def transform_objects_def)
|
|
apply (rule ext, clarsimp)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp:restrict_map_Some_iff)
|
|
apply (clarsimp simp:transform_tcb_def restrict_map_def map_add_def)
|
|
apply (clarsimp simp:transform_tcb_def restrict_map_def map_add_def)
|
|
done
|
|
|
|
lemma duplicate_corrupt_tcb_intent:
|
|
"do corrupt_tcb_intent epptr; corrupt_tcb_intent epptr od = corrupt_tcb_intent epptr"
|
|
apply (clarsimp simp:bind_def)
|
|
apply (rule ext)
|
|
apply (clarsimp simp:split_def)
|
|
apply (rule prod_eqI)
|
|
apply (rule set_eqI)
|
|
apply clarsimp
|
|
apply (auto simp:corrupt_tcb_intent_def update_thread_def select_def gets_the_def
|
|
return_def fail_def gets_def get_def assert_opt_def bind_def
|
|
put_def modify_def KHeap_D.set_object_def opt_object_def split_def
|
|
split:option.splits cdl_object.splits)[1]
|
|
apply clarsimp
|
|
apply (rule iffI)
|
|
apply (auto simp:corrupt_tcb_intent_def update_thread_def select_def gets_the_def
|
|
return_def fail_def gets_def get_def assert_opt_def bind_def
|
|
put_def modify_def KHeap_D.set_object_def opt_object_def split_def
|
|
split:option.splits cdl_object.splits)
|
|
done
|
|
|
|
(* Corrupting a register several times is the same as corrupting it once. *)
|
|
lemma corres_corrupt_tcb_intent_dupl:
|
|
"\<lbrakk> dcorres dc P P' (do corrupt_tcb_intent x; corrupt_tcb_intent x od) g \<rbrakk> \<Longrightarrow>
|
|
dcorres dc P P' (corrupt_tcb_intent x) g"
|
|
by (subst duplicate_corrupt_tcb_intent[symmetric], simp)
|
|
|
|
(*
|
|
* Doing nothing at the abstract level corresponds to corrupting a TCB intent.
|
|
* (In particular, it is the "null" corruption.)
|
|
*)
|
|
lemma corres_corrupt_tcb_intent_return:
|
|
"dcorres dc \<top> (tcb_at ptr and not_idle_thread ptr and valid_etcbs) (corrupt_tcb_intent ptr) (return x)"
|
|
apply (clarsimp simp: corres_underlying_def)
|
|
apply (clarsimp simp: return_def corrupt_tcb_intent_def)
|
|
apply (clarsimp simp:corrupt_tcb_intent_def update_thread_def select_def gets_the_def
|
|
return_def fail_def gets_def get_def assert_opt_def bind_def
|
|
put_def modify_def KHeap_D.set_object_def opt_object_def)
|
|
apply (clarsimp split:option.splits
|
|
simp:transform_def tcb_at_def is_tcb_def
|
|
transform_objects_def not_idle_thread_def
|
|
dest!: get_tcb_SomeD)
|
|
apply (drule(1) valid_etcbs_tcb_etcb)
|
|
apply (clarsimp, clarsimp)
|
|
apply (rule exI)
|
|
apply (auto simp: transform_def transform_tcb_def
|
|
transform_objects_def not_idle_thread_def is_tcb_def
|
|
tcb_at_def obj_at_def split:cdl_object.splits)
|
|
done
|
|
|
|
lemma dcorres_set_object_tcb:
|
|
"\<lbrakk> \<exists>etcb'. (transform_tcb (machine_state s') p' tcb' etcb' = Tcb tcb \<and> ekheap s' p' = Some etcb');
|
|
p' \<noteq> idle_thread s'; kheap s' p' \<noteq> None; ekheap s' p' \<noteq> None \<rbrakk> \<Longrightarrow>
|
|
dcorres dc (op = (transform s')) (op = s')
|
|
(KHeap_D.set_object p' (Tcb tcb ))
|
|
(KHeap_A.set_object p' (TCB tcb'))"
|
|
apply (clarsimp simp: corres_underlying_def set_object_def in_monad)
|
|
apply (clarsimp simp: KHeap_D.set_object_def simpler_modify_def)
|
|
apply (clarsimp simp: transform_def transform_current_thread_def)
|
|
apply (clarsimp simp: transform_objects_def)
|
|
apply (rule ext)
|
|
apply clarsimp
|
|
apply (clarsimp simp: option_map_def restrict_map_def map_add_def)
|
|
done
|
|
|
|
lemma set_cxt_none_det_intent_corres:
|
|
"\<lbrakk>kheap s' y = Some (TCB obj'); ekheap s' y \<noteq> None; valid_idle s';not_idle_thread y s'\<rbrakk>
|
|
\<Longrightarrow> dcorres dc (op = (transform s')) (op = s')
|
|
(corrupt_tcb_intent y)
|
|
(KHeap_A.set_object y (TCB (obj'\<lparr>tcb_context := cxt\<rparr>)))"
|
|
apply (clarsimp simp:bind_assoc opt_object_def corrupt_tcb_intent_def get_thread_def gets_def gets_the_def)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule_tac P="op=(transform s')" and Q="op=s'"
|
|
and x="transform_full_intent (machine_state (update_kheap ((kheap s')(y\<mapsto>(TCB (obj'\<lparr>tcb_context:=cxt\<rparr>)))) s'))
|
|
y (obj'\<lparr>tcb_context:=cxt\<rparr>)"
|
|
in select_pick_corres)
|
|
apply (clarsimp simp:update_thread_def get_object_def
|
|
gets_the_def gets_def bind_assoc)
|
|
apply (rule dcorres_absorb_get_l)
|
|
apply (subgoal_tac "\<exists>t f. cdl_objects (transform s') y = Some (Tcb t)")
|
|
apply (clarsimp simp:assert_opt_def opt_object_def)
|
|
apply (rule dcorres_set_object_tcb)
|
|
apply (clarsimp simp:transform_tcb_def
|
|
transform_def transform_objects_def not_idle_thread_def)
|
|
apply (clarsimp simp:not_idle_thread_def)
|
|
apply simp
|
|
apply simp
|
|
apply (clarsimp simp:transform_def not_idle_thread_def
|
|
transform_objects_def transform_tcb_def)
|
|
apply clarsimp
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma set_message_info_corres:
|
|
"dcorres dc \<top> (valid_idle and not_idle_thread y and valid_etcbs) (corrupt_tcb_intent y)
|
|
(set_message_info y m)"
|
|
apply (clarsimp simp:set_message_info_def)
|
|
apply (clarsimp simp:as_user_def set_register_def)
|
|
apply (rule dcorres_absorb_gets_the)
|
|
apply (clarsimp simp:get_tcb_def opt_object_def split:option.splits Structures_A.kernel_object.splits)
|
|
apply (subst modify_def[unfolded bind_def]|clarsimp simp:get_def put_def)+
|
|
apply (frule_tac ptr=y and tcb=obj' in valid_etcbs_tcb_etcb, clarsimp, clarsimp)
|
|
apply (clarsimp simp:select_f_def bind_def)
|
|
apply (rule corres_guard_imp)
|
|
apply (erule set_cxt_none_det_intent_corres)
|
|
apply (clarsimp simp :opt_object_def valid_def get_tcb_def lift_simp not_idle_thread_def transform_tcb_def
|
|
split:option.splits Structures_A.kernel_object.splits)+
|
|
done
|
|
|
|
lemma corrupt_tcb_intent_as_user_corres:
|
|
"dcorres dc \<top> (valid_idle and not_idle_thread y and valid_etcbs) (corrupt_tcb_intent y)
|
|
(as_user y t)"
|
|
apply (clarsimp simp:as_user_def)
|
|
apply (rule dcorres_absorb_gets_the)
|
|
apply (clarsimp simp:get_tcb_def opt_object_def split:option.splits Structures_A.kernel_object.splits)
|
|
apply (rule corres_symb_exec_r)
|
|
apply clarsimp
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_underlying_split)
|
|
apply (drule(1) valid_etcbs_tcb_etcb)
|
|
apply (rule corres_guard_imp,erule set_cxt_none_det_intent_corres)
|
|
apply simp+
|
|
prefer 3
|
|
apply clarify
|
|
apply (rule corres_free_return[where P=\<top> and P'=\<top>])
|
|
apply (wp | simp)+
|
|
done
|
|
|
|
lemma set_register_corres:
|
|
"dcorres dc \<top> (valid_idle and not_idle_thread y and valid_etcbs) (corrupt_tcb_intent y)
|
|
(as_user y (set_register r v))"
|
|
apply (clarsimp simp:as_user_def set_register_def)
|
|
apply (rule dcorres_absorb_gets_the)
|
|
apply (clarsimp simp:get_tcb_def opt_object_def split:option.splits Structures_A.kernel_object.splits)
|
|
apply (subst modify_def[unfolded bind_def]|clarsimp simp:get_def put_def)+
|
|
apply (clarsimp simp:select_f_def bind_def)
|
|
apply (drule(1) valid_etcbs_tcb_etcb)
|
|
apply (rule corres_guard_imp,erule set_cxt_none_det_intent_corres)
|
|
apply (clarsimp simp :opt_object_def valid_def get_tcb_def not_idle_thread_def lift_simp transform_tcb_def
|
|
split:option.splits Structures_A.kernel_object.splits)+
|
|
done
|
|
|
|
lemma dummy_corrupt_tcb_intent_corres:
|
|
"dcorres dc \<top> (tcb_at y and valid_idle and not_idle_thread y and valid_etcbs)
|
|
(corrupt_tcb_intent y) (return a)"
|
|
apply (simp add:corrupt_tcb_intent_def not_idle_thread_def)
|
|
apply (rule dcorres_expand_pfx, clarsimp)
|
|
apply (clarsimp simp:tcb_at_def)
|
|
apply (drule(1) valid_etcbs_get_tcb_get_etcb, clarsimp)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule_tac P="op=(transform s')" and Q="op=s'"
|
|
and x = "transform_full_intent (machine_state s') y tcb" in select_pick_corres)
|
|
apply (clarsimp simp:update_thread_def gets_the_def gets_def bind_assoc)
|
|
apply (rule dcorres_absorb_get_l)
|
|
apply (clarsimp simp:opt_object_tcb assert_opt_def transform_tcb_def)
|
|
apply (clarsimp simp:KHeap_D.set_object_def get_def put_def modify_def assert_def bind_def return_def)
|
|
apply (subst corres_singleton)
|
|
apply (clarsimp simp:dc_def)
|
|
apply (clarsimp simp:transform_def)
|
|
apply (rule ext)
|
|
apply (clarsimp simp: restrict_map_Some_iff
|
|
transform_objects_def
|
|
split:option.splits dest!:get_tcb_SomeD get_etcb_SomeD)
|
|
apply (clarsimp simp: transform_tcb_def)
|
|
apply (clarsimp simp:transform_def)+
|
|
done
|
|
|
|
lemma neq_Nil_conv':
|
|
"(a\<noteq> []) = (\<exists>h x. a = h@[x])"
|
|
apply (auto | drule append_butlast_last_id)+
|
|
done
|
|
|
|
lemma not_idle_thread_as_usr[wp]:
|
|
"\<lbrace>not_idle_thread y\<rbrace> as_user p q \<lbrace>\<lambda>rv. not_idle_thread y\<rbrace>"
|
|
by (simp add:not_idle_thread_def,wp)
|
|
|
|
lemma not_idle_thread[wp]:
|
|
"\<lbrace>not_idle_thread y\<rbrace> as_user y (set_register a v) \<lbrace>\<lambda>rv. not_idle_thread y\<rbrace>"
|
|
by (simp add:not_idle_thread_def,wp)
|
|
|
|
|
|
lemma set_registers_corres:
|
|
"dcorres dc \<top> (tcb_at y and valid_idle and not_idle_thread y and valid_etcbs)
|
|
(corrupt_tcb_intent y)
|
|
(mapM (%r. do v \<leftarrow> as_user thread (get_register r);
|
|
as_user y (set_register r v)
|
|
od) (x)
|
|
)"
|
|
apply (induct_tac "x")
|
|
apply (clarsimp simp:bind_assoc mapM_def sequence_def)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule dummy_corrupt_tcb_intent_corres[unfolded dc_def])
|
|
apply simp+
|
|
apply (clarsimp simp:mapM_def)
|
|
apply (subst duplicate_corrupt_tcb_intent[symmetric])
|
|
apply (clarsimp simp:sequence_def)
|
|
apply (rule_tac P'="%r. tcb_at y and valid_idle and not_idle_thread y and valid_etcbs"
|
|
in corres_underlying_split [where P="%r. \<top>"])
|
|
apply (rule corres_symb_exec_r)
|
|
apply (rule set_register_corres)
|
|
apply (wp|simp)+
|
|
apply (simp add:bind_assoc dc_def[symmetric])
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_underlying_split [where r'="dc" and P="%x. \<top>" and P'="%x. \<top>"])
|
|
apply (rule corres_guard_imp)
|
|
apply simp+
|
|
done
|
|
|
|
lemma set_mrs_corres_no_recv_buffer:
|
|
"dcorres dc \<top> (valid_idle and not_idle_thread y and valid_etcbs) (corrupt_tcb_intent y) (set_mrs y None msg)"
|
|
apply (clarsimp simp:set_mrs_def get_thread_def)
|
|
apply (rule dcorres_absorb_gets_the, clarsimp)
|
|
apply (drule(1) valid_etcbs_get_tcb_get_etcb)
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_underlying_split [where P'="%x. \<top>" and P="%x. \<top>"])
|
|
apply (rule set_cxt_none_det_intent_corres)
|
|
apply (simp add:get_tcb_def opt_object_def get_etcb_def
|
|
split:option.splits Structures_A.kernel_object.splits
|
|
| wp)+
|
|
done
|
|
|
|
lemma corrupt_intents_dup: "corrupt_intents f bufp (corrupt_intents g bufp s) = corrupt_intents f bufp s"
|
|
apply (clarsimp simp:corrupt_intents_def)
|
|
apply (cases s)
|
|
apply clarsimp
|
|
apply (rule ext)
|
|
apply (case_tac "cdl_objects x")
|
|
apply (clarsimp simp:map_add_def)+
|
|
apply (clarsimp simp: tcb_ipcframe_id_def split:cdl_object.splits)
|
|
done
|
|
|
|
lemma corrupt_frame_duplicate: "(do _ \<leftarrow> corrupt_frame bufp; corrupt_frame bufp od) = (corrupt_frame bufp)"
|
|
apply (rule ext)
|
|
apply (clarsimp simp:corrupt_frame_def simpler_modify_def bind_assoc)
|
|
apply (clarsimp simp:bind_def select_def)
|
|
apply (force simp: corrupt_intents_dup)
|
|
done
|
|
|
|
lemma dcorres_dummy_corrupt_frame: "dcorres dc \<top> valid_etcbs
|
|
(corrupt_frame buf) (return a)"
|
|
apply (simp add:corrupt_frame_def)
|
|
apply (rule dcorres_expand_pfx)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule_tac P="op=(transform s')" and Q="op=s'"
|
|
and x = "\<lambda>x. transform_full_intent (machine_state s') x (the (get_tcb x s'))" in select_pick_corres)
|
|
apply (clarsimp simp:get_def put_def modify_def assert_def bind_def return_def)
|
|
apply (subst corres_singleton)
|
|
apply (clarsimp simp:corrupt_intents_def Let_def transform_def transform_objects_def)
|
|
apply (rule ext)
|
|
apply (clarsimp split:option.splits simp:restrict_map_def map_add_def)
|
|
apply (clarsimp simp:map_add_def split:option.splits cdl_object.split_asm if_splits)
|
|
apply (clarsimp simp:transform_object_def split:Structures_A.kernel_object.splits arch_kernel_obj.splits nat.splits)
|
|
apply (drule(1) valid_etcbs_tcb_etcb)
|
|
apply (clarsimp simp:get_tcb_rev get_etcb_rev transform_tcb_def)
|
|
apply (clarsimp split:option.splits simp:map_add_def)+
|
|
done
|
|
|
|
definition empty_when_fail :: "('s,'a) nondet_monad \<Rightarrow> bool"
|
|
where "empty_when_fail m \<equiv> \<forall>s. snd (m s)\<longrightarrow> fst (m s) = {}"
|
|
|
|
lemma empty_when_fail_return:
|
|
"empty_when_fail (return x)"
|
|
by (clarsimp simp:return_def empty_when_fail_def)
|
|
|
|
lemma wp_no_fail_spec:
|
|
"\<lbrakk>empty_when_fail f ; no_fail (op = s) f \<longrightarrow> \<lbrace>op = s\<rbrace> f \<lbrace>Q\<rbrace>\<rbrakk>\<Longrightarrow>\<lbrace>op = s\<rbrace> f \<lbrace>Q\<rbrace>"
|
|
apply (case_tac "no_fail (op = s) f")
|
|
apply simp
|
|
apply clarsimp
|
|
apply (simp add:no_fail_def valid_def empty_when_fail_def)
|
|
done
|
|
|
|
definition det_spec :: "('s \<Rightarrow> bool) \<Rightarrow> ('s\<Rightarrow>('b\<times>'s) set\<times> bool) \<Rightarrow> bool"
|
|
where "det_spec P f \<equiv> \<forall>s. P s \<longrightarrow> (\<exists>r. f s = ({r},False))"
|
|
|
|
definition weak_det_spec :: "('s \<Rightarrow> bool) \<Rightarrow> ('s\<Rightarrow>('b\<times>'s) set\<times> bool) \<Rightarrow> bool"
|
|
where "weak_det_spec P f \<equiv> no_fail P f \<longrightarrow> det_spec P f"
|
|
|
|
lemma empty_when_fail_compose:
|
|
assumes Q:"\<And>r. empty_when_fail (b r)"
|
|
assumes P:"empty_when_fail a"
|
|
shows "(\<And>P. weak_det_spec P a) \<Longrightarrow> empty_when_fail (a>>=b)"
|
|
apply (clarsimp simp:empty_when_fail_def)
|
|
apply (case_tac "snd (a s)")
|
|
apply (clarsimp simp:bind_def)
|
|
using P
|
|
apply (clarsimp simp:empty_when_fail_def)
|
|
apply (clarsimp simp:bind_def)
|
|
apply (clarsimp simp:weak_det_spec_def no_fail_def)
|
|
apply (drule_tac x = "op = s" in meta_spec)
|
|
apply (clarsimp simp:det_spec_def)
|
|
using Q
|
|
apply (simp add: empty_when_fail_def)
|
|
done
|
|
|
|
(*
|
|
The following lemma allows use to talking about the return value of a weak_det_spec function in wp
|
|
*)
|
|
|
|
lemma weak_det_spec_ret:
|
|
assumes no_fail_det: "weak_det_spec (op = s) f"
|
|
assumes op_eq: "g s = f s"
|
|
shows "\<lbrakk> x = the (evalMonad g s); empty_when_fail f\<rbrakk> \<Longrightarrow> \<lbrace>op = s\<rbrace> f \<lbrace>\<lambda>r s. r = x\<rbrace>"
|
|
apply (rule wp_no_fail_spec)
|
|
apply clarsimp+
|
|
apply (clarsimp simp:op_eq evalMonad_def weak_det_spec_def empty_when_fail_def)+
|
|
apply (drule_tac x = s in spec)
|
|
apply (clarsimp simp:|rule conjI)+
|
|
apply (clarsimp simp:valid_def)
|
|
apply (clarsimp)
|
|
using no_fail_det[unfolded weak_det_spec_def]
|
|
apply (clarsimp simp:det_spec_def valid_def)
|
|
done
|
|
|
|
lemma wp_spec:
|
|
assumes "P s \<Longrightarrow> \<lbrace>op = s\<rbrace> f \<lbrace>Q\<rbrace>"
|
|
shows "\<lbrace>op = s and P\<rbrace> f \<lbrace>Q\<rbrace>"
|
|
using assms
|
|
by (clarsimp simp:valid_def)
|
|
|
|
lemma det_compose:
|
|
"\<lbrakk>det_spec P a;\<And>r. det_spec (Q r) (b r); \<lbrace>P\<rbrace>a\<lbrace>Q\<rbrace>\<rbrakk>\<Longrightarrow> det_spec P (a>>=b)"
|
|
by (fastforce simp: det_spec_def bind_def valid_def)
|
|
|
|
lemma no_fail_compose_imp:
|
|
"\<lbrakk>no_fail P (a>>= b)\<rbrakk> \<Longrightarrow> no_fail P a \<and> (\<exists>Q. (\<lbrace>P\<rbrace>a\<lbrace>Q\<rbrace> \<and> (\<forall>r. no_fail (Q r) (b r))))"
|
|
apply (clarsimp simp: bind_def no_fail_def)
|
|
apply (rule_tac x = "\<lambda>rv s. \<exists>s'. P s'\<and> (rv,s) \<in> fst (a s')" in exI)
|
|
apply (auto simp:valid_def)
|
|
done
|
|
|
|
lemma mapM_load_word_offs_do_machine_op:
|
|
"mapM (load_word_offs ptr) list
|
|
= do_machine_op (mapM loadWord (map (\<lambda>offs. ptr + of_nat (offs * word_size)) list))"
|
|
apply (subst submonad_mapM[OF submonad_do_machine_op submonad_do_machine_op])
|
|
apply (simp add: loadWord_def)
|
|
apply (simp add: load_word_offs_def[abs_def] mapM_map_simp o_def)
|
|
done
|
|
|
|
lemma and_assoc:
|
|
"(A and B and C) = (A and (B and C))"
|
|
apply (rule ext)
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma det_spec_return:
|
|
"det_spec P (return x)"
|
|
by (clarsimp simp:return_def det_spec_def)
|
|
|
|
lemma det_spec_get:
|
|
"det_spec P (get)"
|
|
by (clarsimp simp:get_def det_spec_def)
|
|
|
|
lemma det_spec_put:
|
|
"det_spec P (put t)"
|
|
by (clarsimp simp:put_def det_spec_def)
|
|
|
|
lemma det_spec_modify:
|
|
"det_spec P (modify f)"
|
|
by (clarsimp simp:simpler_modify_def det_spec_def)
|
|
|
|
lemma det_spec_gets:
|
|
"det_spec P (gets f)"
|
|
apply (clarsimp simp:gets_def)
|
|
apply (rule det_compose)
|
|
apply (rule det_spec_get)
|
|
apply (rule det_spec_return)
|
|
apply (fastforce simp:get_def valid_def)
|
|
done
|
|
|
|
lemma det_spec_select_f:
|
|
"\<lbrakk>P a; det_spec P f\<rbrakk> \<Longrightarrow> det_spec Q (select_f (f a))"
|
|
by (fastforce simp: select_f_def det_spec_def)
|
|
|
|
lemma det_imply_weak_det:
|
|
"det_spec P a \<Longrightarrow> weak_det_spec P a"
|
|
by (simp add:weak_det_spec_def)
|
|
|
|
lemma weak_det_specD:
|
|
"\<lbrakk>weak_det_spec P a;no_fail P a\<rbrakk> \<Longrightarrow> det_spec P a"
|
|
by (clarsimp simp:weak_det_spec_def)
|
|
|
|
lemma weak_det_spec_mapM:
|
|
assumes single:
|
|
"\<And>r P. weak_det_spec P (g r)"
|
|
shows
|
|
"weak_det_spec Q (mapM g ls)"
|
|
proof (induct ls arbitrary:Q)
|
|
case Nil
|
|
show ?case
|
|
apply (clarsimp simp:mapM_def sequence_def det_spec_return)
|
|
apply (rule det_imply_weak_det[OF det_spec_return])
|
|
done
|
|
next
|
|
case (Cons x xs)
|
|
show ?case
|
|
using Cons.hyps
|
|
apply (clarsimp simp:mapM_Cons weak_det_spec_def)
|
|
apply (drule no_fail_compose_imp)
|
|
apply clarsimp
|
|
apply (rule det_compose)
|
|
apply (rule weak_det_specD)
|
|
apply (simp add: assms)+
|
|
apply (drule_tac x = r in spec)
|
|
apply (drule meta_spec)
|
|
apply (drule no_fail_compose_imp)
|
|
apply clarsimp
|
|
apply (rule det_compose)
|
|
apply fastforce
|
|
apply (rule det_spec_return)
|
|
apply simp
|
|
apply simp
|
|
done
|
|
qed
|
|
|
|
lemma empty_when_fail_mapM:
|
|
"(\<And>P l. weak_det_spec P (x l) \<and> empty_when_fail (x l))
|
|
\<Longrightarrow> empty_when_fail (mapM x ls)"
|
|
proof (induct ls)
|
|
case Nil
|
|
show ?case
|
|
by (clarsimp simp:mapM_def sequence_def empty_when_fail_return)
|
|
next
|
|
case (Cons x xs)
|
|
show ?case
|
|
apply (clarsimp simp:mapM_Cons)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (simp add: empty_when_fail_return)
|
|
apply (rule Cons)+
|
|
apply (rule weak_det_spec_mapM)
|
|
apply (simp add: Cons)+
|
|
done
|
|
qed
|
|
|
|
lemma weak_det_spec_compose:
|
|
assumes Q:"\<And>Q r. weak_det_spec (Q r) (b r)"
|
|
assumes P:"\<And>P. weak_det_spec P a"
|
|
shows "\<And>P. weak_det_spec P (a>>=b)"
|
|
apply (clarsimp simp:weak_det_spec_def)
|
|
apply (frule no_fail_compose_imp)
|
|
apply clarsimp
|
|
apply (rule det_compose)
|
|
apply (simp add: P[THEN weak_det_specD])
|
|
apply (drule_tac x = r in spec)
|
|
apply (erule Q[THEN weak_det_specD])
|
|
apply simp
|
|
done
|
|
|
|
lemma weak_det_spec_select_f:
|
|
"\<lbrakk>\<And>P. weak_det_spec P f\<rbrakk> \<Longrightarrow> weak_det_spec Q (select_f (f a))"
|
|
apply (case_tac "\<forall>s. \<not>Q s")
|
|
apply (simp add:weak_det_spec_def no_fail_def det_spec_def)
|
|
apply (clarsimp simp:weak_det_spec_def)
|
|
apply (rule det_spec_select_f[where P = "op = a"])
|
|
apply simp
|
|
apply (drule_tac x = "op = a" in meta_spec)
|
|
apply (clarsimp simp: no_fail_def select_f_def)
|
|
done
|
|
|
|
lemma weak_det_spec_fail:
|
|
"weak_det_spec P fail"
|
|
by (auto simp: weak_det_spec_def no_fail_def fail_def det_spec_def)
|
|
|
|
lemma weak_det_spec_assert:
|
|
"weak_det_spec P (assert x)"
|
|
by (auto simp:weak_det_spec_fail assert_def det_imply_weak_det[OF det_spec_return])
|
|
|
|
lemma weak_det_spec_assert_opt:
|
|
"weak_det_spec P (assert_opt x)"
|
|
by (auto simp: weak_det_spec_fail det_imply_weak_det[OF det_spec_return] assert_opt_def split:option.splits)
|
|
|
|
lemma weak_det_spec_gets_the:
|
|
"weak_det_spec P (gets_the f)"
|
|
apply (simp add:gets_the_def)
|
|
apply (rule weak_det_spec_compose[OF weak_det_spec_assert_opt det_imply_weak_det[OF det_spec_gets]])
|
|
done
|
|
|
|
|
|
lemma weak_det_spec_loadWord:
|
|
"weak_det_spec P (loadWord x)"
|
|
apply (clarsimp simp:loadWord_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (rule det_imply_weak_det[OF det_spec_return])
|
|
apply (rule weak_det_spec_assert)
|
|
apply (rule det_imply_weak_det[OF det_spec_gets])
|
|
done
|
|
|
|
lemmas weak_det_spec_simps = weak_det_spec_fail weak_det_spec_assert weak_det_spec_assert_opt weak_det_spec_gets_the
|
|
det_imply_weak_det[OF det_spec_return] det_imply_weak_det[OF det_spec_get]
|
|
det_imply_weak_det[OF det_spec_gets] det_imply_weak_det[OF det_spec_modify]
|
|
|
|
lemma weak_det_spec_storeWord:
|
|
"weak_det_spec P (storeWord a b)"
|
|
apply (simp add:storeWord_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (simp_all add:weak_det_spec_simps)
|
|
done
|
|
|
|
|
|
lemma weak_det_spec_thread_get:
|
|
"weak_det_spec P (thread_get f x)"
|
|
apply (simp add:thread_get_def)
|
|
apply (rule weak_det_spec_compose)
|
|
apply (clarsimp simp:weak_det_spec_simps)+
|
|
done
|
|
|
|
lemma weak_det_spec_load_word_offs:
|
|
"weak_det_spec P (load_word_offs buf r)"
|
|
apply (clarsimp simp:load_word_offs_def)
|
|
apply (clarsimp simp:do_machine_op_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply clarsimp
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (rule det_imply_weak_det[OF det_spec_return])
|
|
apply (rule det_imply_weak_det[OF det_spec_modify])
|
|
apply (rule weak_det_spec_select_f)
|
|
apply (rule weak_det_spec_loadWord)
|
|
apply (rule det_imply_weak_det[OF det_spec_gets])
|
|
done
|
|
|
|
lemma empty_when_fail_fail:
|
|
"empty_when_fail fail"
|
|
by (clarsimp simp:empty_when_fail_def fail_def)
|
|
|
|
lemma empty_when_fail_get:
|
|
"empty_when_fail get"
|
|
by (clarsimp simp:empty_when_fail_def get_def return_def)
|
|
|
|
lemma empty_when_fail_gets:
|
|
"empty_when_fail (gets x)"
|
|
by (clarsimp simp:empty_when_fail_def get_def return_def gets_def bind_def)
|
|
|
|
lemma empty_when_fail_assert:
|
|
"empty_when_fail (assert x)"
|
|
by(clarsimp simp:empty_when_fail_def assert_def fail_def return_def bind_def)
|
|
|
|
lemma empty_when_fail_assert_opt:
|
|
"empty_when_fail (assert_opt x)"
|
|
by (auto simp:assert_opt_def fail_def return_def empty_when_fail_def split:option.splits)
|
|
|
|
lemma empty_when_fail_gets_the:
|
|
"empty_when_fail (gets_the f)"
|
|
apply (clarsimp simp:gets_the_def)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (rule empty_when_fail_assert_opt)
|
|
apply (rule empty_when_fail_gets)+
|
|
apply (rule det_imply_weak_det[OF det_spec_gets])
|
|
done
|
|
|
|
lemma empty_when_fail_modify:
|
|
"empty_when_fail (modify x)"
|
|
by (clarsimp simp:empty_when_fail_def simpler_modify_def)
|
|
|
|
|
|
lemmas empty_when_fail_simps = empty_when_fail_fail empty_when_fail_return empty_when_fail_get empty_when_fail_gets
|
|
empty_when_fail_gets_the empty_when_fail_assert empty_when_fail_assert_opt empty_when_fail_modify
|
|
|
|
lemma empty_when_fail_loadWord:
|
|
"empty_when_fail (loadWord x)"
|
|
apply (simp add:loadWord_def)
|
|
apply (rule empty_when_fail_compose[OF _ empty_when_fail_gets])
|
|
apply (rule empty_when_fail_compose[OF empty_when_fail_return])
|
|
apply (simp_all add: weak_det_spec_simps empty_when_fail_simps)+
|
|
done
|
|
|
|
lemma empty_when_fail_storeWord:
|
|
"empty_when_fail (storeWord a b)"
|
|
apply (simp add:storeWord_def)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (simp_all add:empty_when_fail_simps weak_det_spec_simps)
|
|
done
|
|
|
|
lemma empty_when_fail_select_f:
|
|
"\<lbrakk>empty_when_fail f\<rbrakk> \<Longrightarrow> empty_when_fail (select_f (f a))"
|
|
by (clarsimp simp:empty_when_fail_def select_f_def)
|
|
|
|
lemma empty_when_fail_thread_get:
|
|
"empty_when_fail (thread_get f x)"
|
|
apply (clarsimp simp:thread_get_def)
|
|
apply (rule empty_when_fail_compose)
|
|
apply (clarsimp simp:empty_when_fail_simps weak_det_spec_simps)+
|
|
done
|
|
|
|
lemma empty_when_fail_load_word_offs:
|
|
"empty_when_fail (load_word_offs buf r)"
|
|
apply (clarsimp simp:load_word_offs_def)
|
|
apply (clarsimp simp:do_machine_op_def)
|
|
apply (rule empty_when_fail_compose[OF _ empty_when_fail_gets])
|
|
apply (rule empty_when_fail_compose[OF _ empty_when_fail_select_f])
|
|
apply clarsimp
|
|
apply (rule empty_when_fail_compose[OF empty_when_fail_return])
|
|
apply (simp_all add:empty_when_fail_simps weak_det_spec_simps empty_when_fail_loadWord)
|
|
apply (rule weak_det_spec_select_f[OF weak_det_spec_loadWord])
|
|
done
|
|
|
|
lemma empty_when_fail_get_object:
|
|
"empty_when_fail (get_object x)"
|
|
apply (simp add:get_object_def)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (simp add:empty_when_fail_simps weak_det_spec_simps)+
|
|
done
|
|
|
|
lemma weak_det_spec_get_object:
|
|
"weak_det_spec P (get_object x)"
|
|
apply (simp add:get_object_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (simp add:weak_det_spec_simps)+
|
|
done
|
|
|
|
lemma weak_det_spec_get_cap:
|
|
"weak_det_spec P (get_cap slot)"
|
|
apply (case_tac slot)
|
|
apply (simp add:get_cap_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (simp_all add:weak_det_spec_simps weak_det_spec_get_object)
|
|
apply (case_tac r)
|
|
apply (simp_all add:weak_det_spec_simps weak_det_spec_get_object)
|
|
apply (rule weak_det_spec_compose)
|
|
apply (simp_all add:weak_det_spec_simps weak_det_spec_get_object)
|
|
done
|
|
|
|
lemma empty_when_fail_get_cap:
|
|
"empty_when_fail (get_cap slot)"
|
|
apply (case_tac slot)
|
|
apply (clarsimp simp:get_cap_def)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (simp_all add:empty_when_fail_simps empty_when_fail_get_object weak_det_spec_get_object)
|
|
apply (case_tac r)
|
|
apply (simp_all add:empty_when_fail_simps empty_when_fail_get_object weak_det_spec_get_object)
|
|
apply (rule empty_when_fail_compose)
|
|
apply (simp_all add:empty_when_fail_simps weak_det_spec_simps empty_when_fail_get_object)
|
|
apply (case_tac r)
|
|
apply (simp_all add:empty_when_fail_simps weak_det_spec_simps empty_when_fail_get_object)
|
|
apply (rule weak_det_spec_compose)
|
|
apply (simp_all add:empty_when_fail_simps weak_det_spec_simps empty_when_fail_get_object)
|
|
done
|
|
|
|
lemma not_emptyI: "a\<noteq>{} \<Longrightarrow>\<exists>x. x\<in> a"
|
|
by auto
|
|
|
|
lemma evalMonad_do_machine_op:
|
|
assumes "weak_det_spec (op = (machine_state sa)) f"
|
|
assumes "empty_when_fail f"
|
|
shows "evalMonad (f) (machine_state sa) =
|
|
evalMonad (do_machine_op (f)) sa"
|
|
apply (clarsimp simp:evalMonad_def do_machine_op_def gets_def get_def bind_def return_def simpler_modify_def)
|
|
apply (clarsimp simp:select_f_def | rule conjI)+
|
|
apply (drule not_emptyI)
|
|
apply clarsimp
|
|
apply (rule_tac x = "(a,b)" in bexI)
|
|
apply clarsimp+
|
|
apply (rule arg_cong[where f = "(\<lambda>A. (SOME x. x\<in> A))"])
|
|
apply (rule set_eqI)
|
|
apply (clarsimp simp:image_def)
|
|
apply (rule iffI)
|
|
apply clarsimp
|
|
apply (rule_tac x = "(a,b)" in bexI)
|
|
using assms
|
|
apply (clarsimp simp:empty_when_fail_def weak_det_spec_def no_fail_def)
|
|
apply (drule_tac x = "machine_state sa" in spec)
|
|
apply (clarsimp simp:det_spec_def)
|
|
using assms
|
|
apply (clarsimp simp:empty_when_fail_def weak_det_spec_def no_fail_def)
|
|
apply force
|
|
done
|
|
|
|
lemma evalMonad_wp:
|
|
"\<lbrakk>empty_when_fail f; weak_det_spec (op = pres) f\<rbrakk> \<Longrightarrow> \<lbrace>op = pres \<rbrace>f\<lbrace>\<lambda>rv s. evalMonad f pres = Some rv\<rbrace>"
|
|
apply (clarsimp simp:valid_def weak_det_spec_def no_fail_def empty_when_fail_def)
|
|
apply (drule_tac x = pres in spec)
|
|
apply (clarsimp simp:evalMonad_def notemptyI det_spec_def)
|
|
done
|
|
|
|
|
|
|
|
lemma evalMonad_compose:
|
|
"\<lbrakk>empty_when_fail a;weak_det_spec (op = s) a;\<And>s. \<lbrace>op = s\<rbrace> a \<lbrace>\<lambda>r. op = s\<rbrace>\<rbrakk>
|
|
\<Longrightarrow> evalMonad (a>>=b) s = (case (evalMonad a s) of Some r \<Rightarrow> evalMonad (b r) s | _ \<Rightarrow> None)"
|
|
apply (clarsimp simp:evalMonad_def weak_det_spec_def)
|
|
apply (clarsimp simp:no_fail_def det_spec_def empty_when_fail_def)
|
|
apply (drule_tac x = s in spec)+
|
|
apply (case_tac "snd (a s)")
|
|
apply (simp_all)
|
|
apply (fastforce simp:bind_def valid_def)
|
|
apply (clarsimp simp:valid_def)
|
|
apply (drule_tac x = s in meta_spec)
|
|
apply (clarsimp simp:bind_def)
|
|
done
|
|
|
|
lemma evalMonad_thread_get:
|
|
"evalMonad (thread_get f thread) sa = Some x \<Longrightarrow> \<exists>tcb. get_tcb thread sa = Some tcb \<and> f tcb = x"
|
|
by (clarsimp simp:thread_get_def evalMonad_def gets_def gets_the_def
|
|
assert_opt_def bind_def get_def return_def get_tcb_def fail_def
|
|
split:option.splits Structures_A.kernel_object.splits)
|
|
|
|
lemma evalMonad_get_cap:
|
|
"evalMonad (get_cap slot) s = caps_of_state s slot"
|
|
using weak_det_spec_get_cap[where P ="op = s" and slot = slot]
|
|
using empty_when_fail_get_cap[where slot = slot]
|
|
apply (clarsimp simp:evalMonad_def caps_of_state_def empty_when_fail_def
|
|
weak_det_spec_def no_fail_def det_spec_def)
|
|
apply (drule_tac x = s in spec)
|
|
apply clarsimp
|
|
apply (subgoal_tac "\<lbrace>op = s\<rbrace>get_cap slot \<lbrace>\<lambda>r. op = s\<rbrace>")
|
|
apply (clarsimp simp:valid_def)
|
|
apply wp
|
|
done
|
|
|
|
lemma evalMonad_loadWord:
|
|
"evalMonad (loadWord x) ms =
|
|
(if x && mask 2 = 0 then
|
|
Some (word_rcat [underlying_memory ms (x + 3), underlying_memory ms (x + 2), underlying_memory ms (x + 1), underlying_memory ms x])
|
|
else None)"
|
|
by (clarsimp simp: loadWord_def gets_def get_def return_def bind_def assert_def fail_def evalMonad_def)
|
|
|
|
lemma weak_det_spec_lookup_ipc_buffer:
|
|
"weak_det_spec P (lookup_ipc_buffer a b)"
|
|
apply (simp add:lookup_ipc_buffer_def)
|
|
apply (rule weak_det_spec_compose)+
|
|
apply (simp_all add: empty_when_fail_simps empty_when_fail_get_cap empty_when_fail_thread_get
|
|
weak_det_spec_simps weak_det_spec_thread_get weak_det_spec_get_cap)
|
|
apply (case_tac ra; simp add:weak_det_spec_simps)
|
|
apply (rename_tac arch_cap)
|
|
apply (case_tac arch_cap; simp add:weak_det_spec_simps)
|
|
done
|
|
|
|
lemma empty_when_fail_lookup_ipc_buffer:
|
|
"empty_when_fail (lookup_ipc_buffer a b)"
|
|
apply (simp add:lookup_ipc_buffer_def)
|
|
apply (rule empty_when_fail_compose)+
|
|
apply (simp_all add: empty_when_fail_simps empty_when_fail_get_cap empty_when_fail_thread_get
|
|
weak_det_spec_simps weak_det_spec_thread_get weak_det_spec_get_cap)
|
|
apply (case_tac ra; simp add:empty_when_fail_simps)
|
|
apply (rename_tac arch_cap)
|
|
apply (case_tac arch_cap; simp add:empty_when_fail_simps)
|
|
done
|
|
|
|
abbreviation
|
|
"\<lambda>s. ipc_frame_cte_at thread buf rights sz s \<equiv>
|
|
\<lambda>s. (\<exists>mapdata dev. cte_wp_at (op = (cap.ArchObjectCap (arch_cap.PageCap dev buf rights sz mapdata))) (thread,tcb_cnode_index 4) s)"
|
|
|
|
lemma lookup_ipc_buffer_SomeB_evalMonad:
|
|
"evalMonad (lookup_ipc_buffer in_receive thread) sa = Some (Some buf)
|
|
\<Longrightarrow> \<exists>b rs sz obj. AllowRead \<in> rs \<and> (\<not> in_receive \<or> (AllowWrite \<in> rs))
|
|
\<and> ipc_frame_cte_at thread b rs sz sa \<and> ko_at (TCB obj) thread sa
|
|
\<and> (buf = b + (tcb_ipc_buffer obj && mask (pageBitsForSize sz)))"
|
|
apply (simp add:lookup_ipc_buffer_def)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_thread_get weak_det_spec_thread_get)+
|
|
apply wp
|
|
apply (clarsimp split:option.splits dest!:evalMonad_thread_get)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_get_cap weak_det_spec_get_cap)+
|
|
apply wp
|
|
apply (clarsimp simp:evalMonad_get_cap split:option.splits)
|
|
apply (clarsimp dest!:caps_of_state_cteD get_tcb_SomeD simp:obj_at_def split:cap.splits arch_cap.splits if_splits)
|
|
apply (clarsimp simp:cte_wp_at_cases)
|
|
apply (fastforce simp:obj_at_def vm_read_only_def vm_read_write_def)
|
|
done
|
|
|
|
lemma lookup_ipc_buffer_None_evalMonad:
|
|
"evalMonad (lookup_ipc_buffer in_receive thread) sa = Some None
|
|
\<Longrightarrow> \<exists>obj. ko_at (TCB obj) thread sa \<and> (\<forall>b rs sz. ipc_frame_cte_at thread b rs sz sa
|
|
\<longrightarrow> ((AllowRead \<notin> rs \<and> \<not> in_receive) \<or> (in_receive \<and> (AllowWrite \<notin> rs \<or> AllowRead\<notin> rs)))) "
|
|
apply (simp add:lookup_ipc_buffer_def)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_thread_get weak_det_spec_thread_get)+
|
|
apply wp
|
|
apply (clarsimp split:option.splits dest!:evalMonad_thread_get)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_get_cap weak_det_spec_get_cap)+
|
|
apply wp
|
|
apply (clarsimp simp:evalMonad_get_cap split:option.splits)
|
|
apply (clarsimp dest!:caps_of_state_cteD get_tcb_SomeD)
|
|
apply (simp add:obj_at_def cte_wp_at_cases split:cap.splits arch_cap.splits if_splits)
|
|
apply (clarsimp simp:vm_read_only_def vm_read_write_def)
|
|
done
|
|
|
|
lemma cdl_get_ipc_buffer_None:
|
|
"\<lbrakk> valid_etcbs s'; not_idle_thread thread s';evalMonad(lookup_ipc_buffer in_receive thread) s' = Some None\<rbrakk> \<Longrightarrow>
|
|
\<lbrace>op = (transform s')\<rbrace> get_ipc_buffer thread in_receive \<lbrace>\<lambda>r s. r = None\<rbrace>"
|
|
apply (drule lookup_ipc_buffer_None_evalMonad)
|
|
apply (clarsimp simp:valid_def get_ipc_buffer_def gets_the_def gets_def bind_def get_def return_def)
|
|
apply (subst (asm) opt_cap_tcb)
|
|
apply (simp add:obj_at_def get_tcb_rev not_idle_thread_def | drule(1) valid_etcbs_tcb_etcb | fastforce simp: get_etcb_rev)+
|
|
apply (clarsimp simp: assert_opt_def return_def split: cdl_cap.splits)
|
|
apply (clarsimp simp:transform_cap_def split:cap.splits arch_cap.splits)
|
|
apply (auto simp:cte_wp_at_cases split:split_if_asm)
|
|
done
|
|
|
|
lemma cdl_get_ipc_buffer_Some:
|
|
"\<lbrakk>ipc_frame_cte_at thread b rs sz s';valid_etcbs s';tcb_at thread s';not_idle_thread thread s';AllowRead \<in> rs \<and> (\<not> in_receive \<or> (AllowWrite \<in> rs))\<rbrakk> \<Longrightarrow>
|
|
\<lbrace>op = (transform s')\<rbrace> get_ipc_buffer thread in_receive \<lbrace>\<lambda>r s. r = Some b\<rbrace>"
|
|
apply (clarsimp simp:is_tcb_def tcb_at_def not_idle_thread_def)
|
|
apply (drule(1) valid_etcbs_get_tcb_get_etcb)
|
|
apply (clarsimp simp:get_ipc_buffer_def gets_the_def gets_def bind_assoc valid_def)
|
|
apply (clarsimp simp:get_def bind_def assert_opt_def)
|
|
apply (subst (asm) opt_cap_tcb,simp +)
|
|
apply (clarsimp simp:return_def cte_wp_at_cases dest!:get_tcb_SomeD get_etcb_SomeD)
|
|
apply (drule sym)
|
|
apply (clarsimp simp:transform_cap_def return_def split:if_splits)
|
|
done
|
|
|
|
lemma get_ipc_buffer_words_empty:
|
|
"\<lbrakk>ko_at (TCB obj) thread sa;evalMonad (lookup_ipc_buffer False thread) sa = Some None\<rbrakk> \<Longrightarrow>
|
|
get_ipc_buffer_words (machine_state sa) obj x = []"
|
|
apply (simp add:lookup_ipc_buffer_def)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_thread_get weak_det_spec_thread_get)+
|
|
apply wp
|
|
apply (clarsimp split:option.splits dest!:evalMonad_thread_get)
|
|
apply (subst (asm) evalMonad_compose)
|
|
apply (clarsimp simp:empty_when_fail_get_cap weak_det_spec_get_cap)+
|
|
apply wp
|
|
apply (clarsimp simp:evalMonad_get_cap split:option.splits)
|
|
apply (clarsimp dest!:caps_of_state_cteD get_tcb_SomeD simp:obj_at_def split:cap.splits arch_cap.splits if_splits)
|
|
apply (clarsimp simp:cte_wp_at_cases get_ipc_buffer_words_def dest!:sym[where t = "tcb_ipcframe obj"])+
|
|
apply (clarsimp simp:evalMonad_def split:if_splits)
|
|
apply (clarsimp simp:obj_at_def vm_read_only_def return_def vm_read_write_def)+
|
|
apply (clarsimp simp:cte_wp_at_cases get_ipc_buffer_words_def dest!:sym[where t = "tcb_ipcframe obj"])+
|
|
done
|
|
|
|
lemma get_ipc_buffer_words:
|
|
"\<lbrace>op = sa and ko_at (TCB obj) thread and K_bind (evalMonad (lookup_ipc_buffer in_receive thread) sa = Some (Some buf))\<rbrace>
|
|
mapM (load_word_offs (buf)) (ls)
|
|
\<lbrace>\<lambda>buf_mrs s. buf_mrs = get_ipc_buffer_words (machine_state sa) obj (ls)\<rbrace>"
|
|
apply (simp add:and_assoc get_ipc_buffer_words_def)
|
|
apply (rule wp_spec)
|
|
apply clarsimp
|
|
apply (drule lookup_ipc_buffer_SomeB_evalMonad)
|
|
apply (clarsimp simp:obj_at_def cte_wp_at_cases)
|
|
apply (drule sym[where t = "tcb_ipcframe obj"])
|
|
apply clarsimp
|
|
apply (rule weak_det_spec_ret)
|
|
apply (rule weak_det_spec_mapM)
|
|
apply (rule weak_det_spec_load_word_offs)
|
|
apply simp
|
|
apply (clarsimp simp: mapM_load_word_offs_do_machine_op mapM_map_simp)
|
|
apply (rule arg_cong[where f = the])
|
|
apply (rule evalMonad_do_machine_op)
|
|
apply (rule weak_det_spec_mapM)
|
|
apply clarsimp
|
|
apply (rule weak_det_spec_loadWord)
|
|
apply (rule empty_when_fail_mapM)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp: weak_det_spec_loadWord empty_when_fail_loadWord)+
|
|
apply (rule empty_when_fail_mapM)
|
|
apply (clarsimp simp:weak_det_spec_load_word_offs empty_when_fail_load_word_offs)
|
|
done
|
|
|
|
lemma get_tcb_mrs_wp:
|
|
"\<lbrace>op = sa and ko_at (TCB obj) thread and K_bind (evalMonad (lookup_ipc_buffer False thread) sa = Some (op_buf))\<rbrace>
|
|
get_mrs thread (op_buf) (data_to_message_info (tcb_context obj msg_info_register))
|
|
\<lbrace>\<lambda>rv s. rv = get_tcb_mrs (machine_state sa) obj\<rbrace>"
|
|
apply (case_tac op_buf)
|
|
apply (clarsimp simp:get_mrs_def thread_get_def gets_the_def)
|
|
apply (wp|wpc)+
|
|
apply (clarsimp simp:get_tcb_mrs_def Let_def)
|
|
apply (clarsimp simp:Suc_leI[OF msg_registers_lt_msg_max_length] split del:split_if)
|
|
apply (clarsimp simp:get_tcb_message_info_def get_ipc_buffer_words_empty)
|
|
apply (clarsimp dest!:get_tcb_SomeD simp:obj_at_def)
|
|
apply (clarsimp simp:get_mrs_def thread_get_def gets_the_def)
|
|
apply (clarsimp simp:Suc_leI[OF msg_registers_lt_msg_max_length] split del:split_if)
|
|
apply (wp|wpc)+
|
|
apply (rule_tac P = "tcb = obj" in hoare_gen_asm)
|
|
apply (clarsimp simp: get_tcb_mrs_def Let_def get_tcb_message_info_def Suc_leI[OF msg_registers_lt_msg_max_length]
|
|
split del:split_if)
|
|
apply (rule_tac Q="\<lambda>buf_mrs s. buf_mrs =
|
|
(get_ipc_buffer_words (machine_state sa) obj ([Suc (length msg_registers)..<msg_max_length] @ [msg_max_length]))"
|
|
in hoare_strengthen_post)
|
|
apply (rule get_ipc_buffer_words[where thread=thread ])
|
|
apply simp
|
|
apply wp
|
|
apply (fastforce simp:get_tcb_SomeD obj_at_def)
|
|
done
|
|
|
|
|
|
(* Following is the proof of set_mrs *)
|
|
|
|
declare pbfs_less_wb' [simp]
|
|
|
|
lemma mab_le_pbfs [simp]:
|
|
"msg_align_bits \<le> pageBitsForSize sz"
|
|
by (cases sz, simp_all add: msg_align_bits)
|
|
|
|
lemma two_le_pbfs[simp]:
|
|
"2 \<le> pageBitsForSize sz"
|
|
by (cases sz,simp_all)
|
|
|
|
lemma two_le_msg_align_bits[simp]:
|
|
"2 \<le> msg_align_bits"
|
|
by(simp add:msg_align_bits)
|
|
|
|
lemma is_aligned_word_size[simp]:
|
|
"is_aligned (of_nat r * of_nat word_size) 2"
|
|
apply (simp add:word_size_def)
|
|
apply (rule is_aligned_mult_triv2[where n = 2,simplified])
|
|
done
|
|
|
|
definition
|
|
ipc_frame_wp_at :: "(word32 \<Rightarrow> rights set \<Rightarrow> vmpage_size \<Rightarrow> (word32 \<times> word32) option \<Rightarrow> bool) \<Rightarrow> obj_ref \<Rightarrow> 'z::state_ext state \<Rightarrow> bool"
|
|
where
|
|
"ipc_frame_wp_at P \<equiv> obj_at (%ko. \<exists>tcb. ko = TCB tcb \<and>
|
|
(case (tcb_ipcframe tcb) of
|
|
cap.ArchObjectCap (arch_cap.PageCap dev ptr rights sz mapdata) \<Rightarrow> P ptr rights sz mapdata
|
|
| _ \<Rightarrow> False))"
|
|
|
|
definition
|
|
ipc_buffer_wp_at :: "word32 \<Rightarrow> obj_ref \<Rightarrow>'z::state_ext state \<Rightarrow> bool"
|
|
where
|
|
"ipc_buffer_wp_at w \<equiv> obj_at (%ko. \<exists>tcb. ko = TCB tcb \<and>
|
|
tcb_ipc_buffer tcb = w)"
|
|
|
|
|
|
lemma ipc_frame_wp_at_cte_at:
|
|
"ipc_frame_wp_at P a s\<Longrightarrow> \<exists>buf sz rs. ipc_frame_cte_at a buf sz rs s"
|
|
by (clarsimp simp:ipc_frame_wp_at_def obj_at_def cte_wp_at_cases
|
|
,simp add: split:cap.splits arch_cap.splits)
|
|
|
|
abbreviation
|
|
"ipc_frame_ptr_at ptr \<equiv> ipc_frame_wp_at (\<lambda>ptr' _ _ _. ptr = ptr')"
|
|
|
|
abbreviation
|
|
"ipc_frame_sz_at sz \<equiv> ipc_frame_wp_at (\<lambda>_ _ sz' _. sz = sz')"
|
|
|
|
definition storeWord_ms :: "word32 \<Rightarrow> word32 \<Rightarrow> machine_state \<Rightarrow> machine_state"
|
|
where "storeWord_ms ptr b ms \<equiv> (underlying_memory_update
|
|
(\<lambda>m. m(ptr := word_rsplit b ! 3, ptr + 1 := word_rsplit b ! 2, ptr + 2 := word_rsplit b ! Suc 0, ptr + 3 := word_rsplit b ! 0))
|
|
ms)"
|
|
|
|
definition
|
|
is_arch_page_cap :: "cap \<Rightarrow> bool"
|
|
where
|
|
"is_arch_page_cap cap = (case cap of
|
|
cap.ArchObjectCap (arch_cap.PageCap dev buf rights sz mapdata) \<Rightarrow> True
|
|
| _ \<Rightarrow> False)"
|
|
|
|
lemmas is_arch_page_cap_simps [simp] = is_arch_page_cap_def [split_simps cap.split arch_cap.split]
|
|
|
|
|
|
lemma get_ipc_frame_words_no_ipc_buffer:
|
|
"\<not> (is_arch_page_cap (tcb_ipcframe tcb)) \<Longrightarrow> get_ipc_buffer_words ms tcb ns = []"
|
|
unfolding get_ipc_buffer_words_def
|
|
by (clarsimp simp: evalMonad_def Let_def return_def
|
|
split:if_splits cap.splits arch_cap.splits)
|
|
|
|
lemma transform_full_intent_no_ipc_buffer:
|
|
"\<not> (is_arch_page_cap (tcb_ipcframe tcb)) \<Longrightarrow> transform_full_intent ms ptr tcb = transform_full_intent ms' ptr tcb"
|
|
unfolding transform_full_intent_def
|
|
apply (clarsimp simp: evalMonad_def Let_def return_def get_tcb_mrs_def
|
|
split:if_splits cap.splits arch_cap.splits)
|
|
apply (simp add: get_ipc_frame_words_no_ipc_buffer)
|
|
done
|
|
|
|
lemma get_ipc_buffer_words_empty_list[simp]:
|
|
"get_ipc_buffer_words x tcb_type [] = [] "
|
|
by (clarsimp simp:get_ipc_buffer_words_def split:cap.splits arch_cap.splits
|
|
simp:mapM_def sequence_def)
|
|
|
|
|
|
lemma evalMonad_mapM:
|
|
"\<lbrakk>\<forall>r\<in>(set ls). evalMonad (f r) sa = evalMonad (g r) sb;
|
|
\<And>s r. \<lbrace>op=s\<rbrace>f r\<lbrace>\<lambda>r. op = s\<rbrace>;
|
|
\<And>s r. \<lbrace>op=s\<rbrace>g r\<lbrace>\<lambda>r. op = s\<rbrace>;
|
|
\<And>r. empty_when_fail (f r);
|
|
\<And>r. empty_when_fail (g r);
|
|
\<And>r P. weak_det_spec P (f r);
|
|
\<And>r P. weak_det_spec P (g r)\<rbrakk>
|
|
\<Longrightarrow> evalMonad (mapM f ls) sa= evalMonad (mapM g ls) sb"
|
|
proof(induct ls)
|
|
case Nil
|
|
show ?case by (clarsimp simp:mapM_def sequence_def)
|
|
next
|
|
case (Cons x ls)
|
|
show ?case
|
|
apply (clarsimp simp:mapM_Cons)
|
|
apply (subst evalMonad_compose)
|
|
apply (simp add:Cons)+
|
|
apply (subst evalMonad_compose)
|
|
apply (simp add:Cons)
|
|
apply (rule empty_when_fail_mapM)
|
|
apply (simp add:Cons)
|
|
apply (rule weak_det_spec_mapM)
|
|
apply (simp add:Cons)
|
|
apply (rule mapM_wp_inv)
|
|
apply (simp add:Cons)
|
|
apply (subst evalMonad_compose)
|
|
apply (simp add:Cons)+
|
|
apply (subst evalMonad_compose)
|
|
apply (rule empty_when_fail_mapM)
|
|
apply (simp add:Cons)
|
|
apply (rule weak_det_spec_mapM)
|
|
apply (simp add:Cons)
|
|
apply (rule mapM_wp_inv)
|
|
apply (simp add:Cons)
|
|
apply (subgoal_tac "evalMonad (mapM f ls) sa = evalMonad (mapM g ls) sb")
|
|
apply (clarsimp split:option.splits)
|
|
apply (rule Cons.hyps)
|
|
apply (simp add:Cons)+
|
|
done
|
|
qed
|
|
|
|
lemma underlying_memory_storeWord:
|
|
"\<lbrakk> is_aligned ptr 2;is_aligned x 2;x \<noteq> ptr;n\<le> 3 \<rbrakk>
|
|
\<Longrightarrow>underlying_memory (storeWord_ms ptr b ms) (x + n) =
|
|
underlying_memory ms (x + n)"
|
|
apply (simp add:storeWord_ms_def)
|
|
using iffD2[OF and_mask_eq_iff_le_mask[where n = 2 and w = n]]
|
|
apply (intro conjI)
|
|
apply (clarsimp simp:is_aligned_mask mask_add_aligned)
|
|
apply (simp add:mask_2pm1)
|
|
apply (clarsimp simp:|rule conjI)+
|
|
apply (case_tac "n=1")
|
|
apply simp
|
|
apply (drule arg_cong[where f = "\<lambda>x. x && mask 2"])
|
|
apply (clarsimp simp:mask_add_aligned)
|
|
using iffD2[OF and_mask_eq_iff_le_mask[where n = 2 and w = n]]
|
|
apply (simp add:mask_2pm1)
|
|
apply (clarsimp simp:|rule conjI)+
|
|
apply (case_tac "n=2")
|
|
apply simp
|
|
apply (drule arg_cong[where f = "\<lambda>x. x && mask 2"])
|
|
apply (clarsimp simp:mask_add_aligned)
|
|
using iffD2[OF and_mask_eq_iff_le_mask[where n = 2 and w = n]]
|
|
apply (simp add:mask_2pm1)
|
|
apply clarsimp
|
|
apply (case_tac "n=3")
|
|
apply simp
|
|
apply (drule arg_cong[where f = "\<lambda>x. x && mask 2"])
|
|
apply (clarsimp simp:mask_add_aligned)
|
|
using iffD2[OF and_mask_eq_iff_le_mask[where n = 2 and w = n]]
|
|
apply (simp add:mask_2pm1)
|
|
done
|
|
thm data_at_def
|
|
lemma ipc_frame_ptr_at_frame_at:
|
|
"\<lbrakk>valid_objs s;ipc_frame_ptr_at buf thread s;ipc_frame_sz_at sz thread s\<rbrakk> \<Longrightarrow>ko_at (ArchObj (DataPage False sz)) buf s"
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply (clarsimp split:cap.splits arch_cap.splits)
|
|
apply (drule valid_tcb_objs)
|
|
apply (erule get_tcb_rev)
|
|
apply (simp add:valid_tcb_def)
|
|
apply (clarsimp simp:valid_ipc_buffer_cap_def tcb_cap_cases_def is_nondevice_page_cap_def
|
|
split:bool.split_asm)
|
|
apply (clarsimp simp:valid_cap_def obj_at_def a_type_def is_nondevice_page_cap_def)
|
|
apply (clarsimp split:Structures_A.kernel_object.splits if_splits arch_kernel_obj.splits)
|
|
done
|
|
|
|
lemma ipc_buffer_within_frame:
|
|
"\<lbrakk>
|
|
pspace_aligned s;
|
|
pspace_distinct s;
|
|
ko_at (ArchObj (DataPage dev sz)) buf s;
|
|
ko_at (ArchObj (DataPage dev' sz')) buf' s;
|
|
ptr && ~~ mask (pageBitsForSize sz) = buf;
|
|
ptr' && ~~ mask (pageBitsForSize sz') = buf';
|
|
buf\<noteq>buf'\<rbrakk>
|
|
\<Longrightarrow> ptr \<noteq> ptr'"
|
|
apply (simp add:pspace_aligned_def obj_at_def)
|
|
apply (frule_tac x = buf in bspec)
|
|
apply (simp add:domI obj_at_def)
|
|
apply (drule_tac x = buf' in bspec)
|
|
apply (clarsimp simp:domI obj_at_def)
|
|
apply (unfold pspace_distinct_def)
|
|
apply (drule_tac x = buf in spec)
|
|
apply (drule_tac x = buf' in spec)
|
|
apply (drule_tac x = "ArchObj (DataPage dev sz)" in spec)
|
|
apply (drule_tac x = "ArchObj (DataPage dev' sz')" in spec)
|
|
apply (rule distinct_element)
|
|
apply (rule mp)
|
|
apply (assumption)
|
|
apply simp
|
|
apply (clarsimp simp:is_aligned_def word_and_le2 word_neg_and_le)
|
|
apply (clarsimp simp:word_and_le2 word_neg_and_le)
|
|
done
|
|
|
|
definition
|
|
within_page :: "word32 \<Rightarrow> word32 \<Rightarrow> vmpage_size \<Rightarrow> bool"
|
|
where "within_page buf ptr sz \<equiv> (ptr && ~~ mask (pageBitsForSize sz) = buf)"
|
|
|
|
lemma valid_tcb_obj_ipc_align_etc:
|
|
"\<lbrakk>valid_objs s;pspace_aligned s;ipc_frame_ptr_at buf thread s;ipc_frame_sz_at pgsz thread s;
|
|
get_tcb thread s = Some tcb\<rbrakk>
|
|
\<Longrightarrow> is_aligned (tcb_ipc_buffer tcb) msg_align_bits \<and> is_aligned (tcb_ipc_buffer tcb) 2
|
|
\<and> is_aligned buf (pageBitsForSize pgsz) \<and> is_aligned buf 2"
|
|
apply (frule ipc_frame_ptr_at_frame_at)
|
|
apply simp+
|
|
apply (drule(1) valid_tcb_objs)
|
|
apply (clarsimp dest!:get_tcb_SomeD simp:valid_tcb_def valid_ipc_buffer_cap_def
|
|
ipc_frame_wp_at_def obj_at_def)
|
|
apply (clarsimp split:cap.splits arch_cap.splits bool.split_asm)
|
|
apply (rule conjI)
|
|
apply (rule is_aligned_weaken,simp+)
|
|
apply (simp add:msg_align_bits_def)
|
|
apply (simp add:pspace_aligned_def obj_at_def ipc_frame_wp_at_def)
|
|
apply (drule_tac x = buf in bspec)
|
|
apply (clarsimp simp:)
|
|
apply (clarsimp simp:obj_at_def)
|
|
apply (rule is_aligned_weaken)
|
|
apply simp+
|
|
done
|
|
|
|
lemma mask_neg_mask_cancel:
|
|
"a&& mask n && ~~ mask n = 0 "
|
|
by (simp add:mask_out_sub_mask)
|
|
|
|
lemma get_ipc_buffer_words_helper:
|
|
"\<lbrakk>valid_objs s;
|
|
get_tcb thread s = Some tcb_type;
|
|
ipc_frame_ptr_at obuf thread s;ipc_frame_sz_at osz thread s;
|
|
ko_at (ArchObj (DataPage dev sz)) buf s;
|
|
is_aligned ptr 2;
|
|
pspace_aligned s; pspace_distinct s;
|
|
within_page buf ptr sz;
|
|
\<forall>x \<in> set xs. within_page obuf (obuf + (tcb_ipc_buffer tcb_type && mask (pageBitsForSize osz)) +of_nat x* of_nat word_size) osz;
|
|
obuf \<noteq> buf\<rbrakk> \<Longrightarrow>
|
|
get_ipc_buffer_words (storeWord_ms ptr b ms) tcb_type xs= get_ipc_buffer_words ms tcb_type xs"
|
|
apply (clarsimp dest!:get_tcb_SomeD simp:get_ipc_buffer_words_def split:cap.splits arch_cap.splits)
|
|
apply (frule ipc_frame_ptr_at_frame_at[where buf = obuf],simp+)
|
|
apply (frule valid_tcb_obj_ipc_align_etc[where buf = obuf],simp+)
|
|
apply (erule get_tcb_rev)
|
|
apply (rule arg_cong[where f = the])
|
|
apply (rule evalMonad_mapM)
|
|
defer
|
|
apply (simp_all add:empty_when_fail_loadWord weak_det_spec_loadWord)
|
|
apply (wp loadWord_inv)
|
|
apply (clarsimp simp:obj_at_def ipc_frame_wp_at_def)
|
|
apply (drule_tac x = r in bspec,simp)
|
|
apply (clarsimp simp:evalMonad_loadWord get_tcb_SomeD | rule conjI)+
|
|
apply (rule arg_cong[where f = word_rcat])
|
|
apply clarsimp
|
|
apply (clarsimp simp:|rule conjI)
|
|
apply (rule underlying_memory_storeWord)
|
|
apply simp_all
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (rule is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf =obuf and buf'=buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (rule conjI)
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord)
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (rule conjI)
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord)
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord[where n = 0,simplified])
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply ((simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+)[7]
|
|
done
|
|
|
|
lemma get_ipc_buffer_words_separate_frame:
|
|
"\<lbrakk>valid_objs s;
|
|
get_tcb thread s = Some tcb_type;
|
|
ipc_frame_ptr_at obuf thread s;ipc_frame_sz_at osz thread s;
|
|
ipc_frame_ptr_at buf s_id s;ipc_frame_sz_at sz s_id s;
|
|
is_aligned ptr 2;
|
|
pspace_aligned s; pspace_distinct s;
|
|
within_page buf ptr sz;
|
|
\<forall>x \<in> set xs. within_page obuf (obuf + (tcb_ipc_buffer tcb_type && mask (pageBitsForSize osz)) +of_nat x* of_nat word_size) osz;
|
|
obuf \<noteq> buf\<rbrakk> \<Longrightarrow>
|
|
get_ipc_buffer_words (storeWord_ms ptr b ms) tcb_type xs= get_ipc_buffer_words ms tcb_type xs"
|
|
apply (clarsimp dest!:get_tcb_SomeD simp:get_ipc_buffer_words_def split:cap.splits arch_cap.splits)
|
|
apply (frule ipc_frame_ptr_at_frame_at[where buf = buf],simp+)
|
|
apply (frule ipc_frame_ptr_at_frame_at[where buf = obuf],simp+)
|
|
apply (frule valid_tcb_obj_ipc_align_etc[where buf = obuf],simp+)
|
|
apply (erule get_tcb_rev)
|
|
apply (subgoal_tac "\<exists>tcb. get_tcb s_id s = Some tcb")
|
|
prefer 2
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply (rule exI)
|
|
apply (erule get_tcb_rev)
|
|
apply clarify
|
|
apply (frule valid_tcb_obj_ipc_align_etc[where buf = buf],simp+)
|
|
apply (rule arg_cong[where f = the])
|
|
apply (rule evalMonad_mapM)
|
|
defer
|
|
apply (simp_all add:empty_when_fail_loadWord weak_det_spec_loadWord)
|
|
apply (wp loadWord_inv)
|
|
apply (clarsimp simp:obj_at_def ipc_frame_wp_at_def)
|
|
apply (drule_tac x = r in bspec,simp)
|
|
apply (clarsimp split:cap.split_asm arch_cap.split_asm)
|
|
apply (clarsimp simp:evalMonad_loadWord get_tcb_SomeD | rule conjI)+
|
|
apply (rule arg_cong[where f = word_rcat])
|
|
apply clarsimp
|
|
apply (clarsimp simp:|rule conjI)
|
|
apply (rule underlying_memory_storeWord)
|
|
apply simp_all
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (rule is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf =obuf and buf'=buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (rule conjI)
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord)
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (rule conjI)
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord)
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply (simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+
|
|
apply (subst add.assoc[symmetric])+
|
|
apply (rule underlying_memory_storeWord[where n = 0,simplified])
|
|
apply (simp_all)
|
|
apply (rule aligned_add_aligned)+
|
|
apply simp+
|
|
apply (subst is_aligned_after_mask)
|
|
apply simp+
|
|
apply (rule ipc_buffer_within_frame[where buf = obuf and buf' = buf])
|
|
apply ((simp add:obj_at_def get_tcb_SomeD within_page_def add.assoc)+)[7]
|
|
done
|
|
|
|
lemma mask_inj_if:
|
|
"\<lbrakk>a && mask n = a; b && mask n = b; a && mask n = b && mask n\<rbrakk>\<Longrightarrow> a = b"
|
|
by (rule box_equals)
|
|
|
|
lemma less_less_trans:
|
|
"\<lbrakk>(a::word32)\<le> b;b\<le> c\<rbrakk> \<Longrightarrow> a\<le> c"
|
|
by auto
|
|
|
|
lemma bound_preserve_mask:
|
|
"\<lbrakk>is_aligned (x::word32) n; x\<le> mask k; (z::word32)\<le> mask n;
|
|
n < 32;k<32;n\<le> k\<rbrakk> \<Longrightarrow> x+z \<le> mask k"
|
|
apply (rule less_less_trans[where b = "(mask k && ~~ mask n) + mask n"])
|
|
apply (rule less_less_trans[where b = "x + mask n"])
|
|
apply (erule word_plus_mono_right)
|
|
apply (rule is_aligned_no_wrap')
|
|
apply simp
|
|
apply (rule mask_lt_2pn)
|
|
apply (simp add:word_size)
|
|
apply (rule word_plus_mono_left)
|
|
apply (rule less_less_trans[where b = "x && ~~ mask n"])
|
|
apply (simp add:mask_out_sub_mask is_aligned_mask)
|
|
apply (erule neg_mask_mono_le)
|
|
apply (simp add:mask_out_sub_mask mask_and_mask min_def)
|
|
apply (rule word_leI)
|
|
apply (clarsimp simp:word_size)
|
|
apply (simp add:mask_out_sub_mask mask_and_mask min_def)
|
|
done
|
|
|
|
lemma nat_less_le:
|
|
"(a::nat) < b \<Longrightarrow> a \<le> b - 1"
|
|
by auto
|
|
|
|
lemma within_page_ipc_buf:
|
|
"\<lbrakk>valid_objs s; pspace_aligned s; pspace_distinct s; ipc_frame_ptr_at buf y s; ipc_frame_sz_at sz y s;
|
|
ipc_buffer_wp_at bptr y s; x < 2 ^ (msg_align_bits - 2) \<rbrakk>
|
|
\<Longrightarrow> within_page buf (buf + (bptr && mask (pageBitsForSize sz)) + of_nat x * of_nat word_size) sz"
|
|
apply (clarsimp simp:ipc_buffer_wp_at_def obj_at_def)
|
|
apply (frule valid_tcb_obj_ipc_align_etc,simp+)
|
|
apply (erule get_tcb_rev)
|
|
apply (clarsimp simp: ipc_frame_wp_at_def obj_at_def within_page_def)
|
|
apply (clarsimp split: cap.split_asm arch_cap.split_asm)
|
|
apply (frule valid_tcb_objs, erule get_tcb_rev)
|
|
apply (clarsimp simp: valid_tcb_def valid_ipc_buffer_cap_def)
|
|
apply (subst add.assoc)
|
|
apply (erule is_aligned_add_helper[THEN conjunct2])
|
|
apply (rule iffD1[OF le_mask_iff_lt_2n[where n = "pageBitsForSize sz"],THEN iffD1])
|
|
apply (simp add:word_size)
|
|
apply (case_tac sz,simp_all)
|
|
apply (rule bound_preserve_mask[where n = msg_align_bits])
|
|
apply (rule is_aligned_after_mask)
|
|
apply (simp add:word_and_le1)+
|
|
apply (simp add:msg_align_bits mask_2pm1)
|
|
apply (rule div_le_mult)
|
|
apply (simp add:word_size_def)
|
|
apply (rule word_of_nat_le)
|
|
apply (simp add:word_size_def msg_align_bits)+
|
|
apply (cases sz,auto)
|
|
done
|
|
|
|
lemma eq_sym_helper: "(A = B) \<Longrightarrow> (B = A)"
|
|
by auto
|
|
|
|
lemma store_word_corres_helper:
|
|
"\<lbrakk>pspace_aligned s; pspace_distinct s; valid_objs s; valid_etcbs s; ipc_frame_ptr_at buf s_id s;
|
|
ipc_frame_sz_at sz s_id s; is_aligned ptr 2 ; within_page buf ptr sz\<rbrakk>
|
|
\<Longrightarrow> \<exists>f. corrupt_intents (f) buf (transform s) =
|
|
transform (update_machine (storeWord_ms ptr b (machine_state s)) s)"
|
|
unfolding transform_def corrupt_intents_def
|
|
apply (clarsimp simp: transform_current_thread_def transform_objects_def Let_def)
|
|
apply (rule exI)
|
|
apply (rule ext)
|
|
apply (rename_tac thread)
|
|
apply (clarsimp simp: map_add_def split: option.splits simp del: Option.case_map_option)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp:restrict_map_def map_add_def)
|
|
apply clarsimp
|
|
apply (rule conjI)
|
|
apply (clarsimp simp:restrict_map_def transform_object_def transform_tcb_def
|
|
split:cdl_object.split_asm Structures_A.kernel_object.split_asm split_if_asm)
|
|
apply (drule(1) valid_etcbs_tcb_etcb,
|
|
clarsimp simp:restrict_map_def transform_object_def transform_tcb_def
|
|
split:cdl_object.split_asm Structures_A.kernel_object.split_asm split_if_asm)+
|
|
defer
|
|
apply (drule(1) valid_etcbs_tcb_etcb,
|
|
clarsimp simp:restrict_map_def transform_object_def transform_tcb_def
|
|
split:cdl_object.split_asm Structures_A.kernel_object.split_asm split_if_asm)+
|
|
defer
|
|
apply (simp add:tcb_ipcframe_id_def tcb_boundntfn_slot_def tcb_ipcbuffer_slot_def split:split_if_asm)
|
|
apply (simp add:tcb_ipcbuffer_slot_def tcb_pending_op_slot_def)
|
|
apply (frule_tac thread = thread in valid_tcb_objs)
|
|
apply (simp add: get_tcb_rev)
|
|
apply (clarsimp simp:valid_tcb_def tcb_cap_cases_def)
|
|
apply (rename_tac tcb etcb)
|
|
apply (case_tac "\<not> is_arch_page_cap (tcb_ipcframe tcb)")
|
|
apply (simp add:transform_full_intent_no_ipc_buffer)
|
|
apply (clarsimp simp del:upt.simps simp:transform_full_intent_def Let_def get_tcb_mrs_def is_arch_page_cap_def
|
|
split:cap.split_asm arch_cap.split_asm split del:split_if)
|
|
apply (rename_tac word cap_rights vmpage_size option)
|
|
apply (clarsimp simp:transform_cap_def arch_cap.split_asm simp del:upt.simps)
|
|
apply (frule_tac thread = thread and ptr = ptr and sz = sz
|
|
and ms = "machine_state s" and tcb_type = tcb and b = b and s_id = s_id
|
|
and xs = "[Suc (length msg_registers)..<Suc msg_max_length]"
|
|
in get_ipc_buffer_words_separate_frame)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def obj_at_def)+)[8]
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule_tac y = thread in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (simp add:msg_max_length_def msg_align_bits)
|
|
apply simp
|
|
apply (clarsimp simp:transform_cap_def split:cap.splits arch_cap.splits)
|
|
apply (rule conjI)
|
|
apply (frule_tac thread = thread and ptr = ptr and sz = sz and ms = "machine_state s" and
|
|
tcb_type = tcb and b = b and s_id = s_id
|
|
and xs = "[buffer_cptr_index..<buffer_cptr_index + unat (mi_extra_caps (get_tcb_message_info tcb))]"
|
|
in get_ipc_buffer_words_separate_frame)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def obj_at_def)+)[8]
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule_tac sz = vmpage_size and y = thread in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (simp add:msg_max_length_def msg_align_bits buffer_cptr_index_def)
|
|
apply (case_tac "(get_tcb_message_info tcb)")
|
|
apply (clarsimp simp add: get_tcb_message_info_def data_to_message_info_def)
|
|
apply (erule order_less_le_trans)
|
|
apply simp
|
|
apply (rule iffD1[OF word_le_nat_alt[where b = "0x6::word32",simplified]])
|
|
apply (rule less_less_trans)
|
|
apply (rule word_and_le1[where a = 3])
|
|
apply ((clarsimp simp:ipc_frame_wp_at_def obj_at_def)+)[4]
|
|
apply (frule_tac thread = thread and ptr = ptr and sz = sz and ms = "machine_state s" and
|
|
tcb_type = tcb and b = b and s_id = s_id
|
|
and xs = "[Suc (Suc (msg_max_length + msg_max_extra_caps))..<5 + (msg_max_length + msg_max_extra_caps)]"
|
|
in get_ipc_buffer_words_separate_frame)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def obj_at_def)+)[8]
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule_tac y = thread and sz = vmpage_size in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (clarsimp simp:msg_align_bits msg_max_length_def msg_max_extra_caps_def)
|
|
apply simp+
|
|
apply (clarsimp simp: tcb_ipcframe_id_def split: cdl_object.splits option.split_asm cdl_cap.split_asm)
|
|
apply (clarsimp simp: transform_object_def split:Structures_A.kernel_object.split_asm arch_kernel_obj.split_asm nat.splits)
|
|
apply (rename_tac tcb)
|
|
apply (simp add:transform_tcb_def)
|
|
apply (drule sym)
|
|
apply (clarsimp simp:tcb_pending_op_slot_def restrict_map_def tcb_ipcbuffer_slot_def split:if_splits)
|
|
apply (frule(1) valid_etcbs_tcb_etcb[OF _ eq_sym_helper])
|
|
apply clarsimp
|
|
apply (subgoal_tac "(get_tcb thread s) = Some tcb")
|
|
apply (clarsimp dest!:get_tcb_SomeD)
|
|
apply (subgoal_tac "tcb = the (get_tcb thread s)")
|
|
apply (subgoal_tac "etcb = the (get_etcb thread s)")
|
|
apply simp
|
|
apply (simp add: get_etcb_rev)
|
|
apply (simp add:get_tcb_rev)+
|
|
done
|
|
|
|
lemma select_f_store_word:
|
|
"(select_f (storeWord p w ms)) = (do assert (p && mask 2 = 0);
|
|
return ((),storeWord_ms p w ms) od)"
|
|
apply (clarsimp simp: assert_def select_f_def storeWord_def bind_def fail_def simpler_modify_def
|
|
storeWord_ms_def return_def)
|
|
done
|
|
|
|
lemma select_f_get_register:
|
|
"(as_user thread (get_register register)) =
|
|
(do tcb\<leftarrow>gets_the (get_tcb thread);return (tcb_context tcb register) od)"
|
|
apply (simp add: assert_opt_def as_user_def set_object_def gets_the_def
|
|
put_def select_f_def get_register_def gets_def get_def return_def bind_def)
|
|
apply (rule ext)
|
|
apply (case_tac "get_tcb thread s")
|
|
apply (clarsimp simp:fail_def return_def)+
|
|
apply (clarsimp simp:get_tcb_def split:option.splits Structures_A.kernel_object.splits)
|
|
done
|
|
|
|
lemma select_f_evalMonad:
|
|
"\<lbrakk>empty_fail g; empty_when_fail g; \<And>P. weak_det_spec P g; \<And>ms. \<lbrace>op = ms\<rbrace>g\<lbrace>\<lambda>r. op = ms\<rbrace>\<rbrakk>
|
|
\<Longrightarrow> (select_f (g ms)) = (case (evalMonad g ms) of Some a \<Rightarrow> return (a,ms) | None \<Rightarrow> fail)"
|
|
apply (rule ext)
|
|
apply (clarsimp simp: return_def select_f_def fail_def empty_fail_def split:option.splits)
|
|
apply (drule_tac x = ms in spec)
|
|
apply (rule conjI)
|
|
apply (clarsimp simp:evalMonad_def valid_def weak_det_spec_def)+
|
|
apply (drule_tac x = "op = ms" in meta_spec)+
|
|
apply (clarsimp simp:no_fail_def empty_when_fail_def)
|
|
apply (drule_tac x = ms in meta_spec)
|
|
apply (clarsimp simp:det_spec_def)
|
|
apply (drule_tac x = ms in spec)
|
|
apply clarsimp
|
|
done
|
|
|
|
|
|
lemma dcorres_store_word_safe:
|
|
"within_page obuf ptr sz \<Longrightarrow>
|
|
dcorres dc \<top>
|
|
(ko_at (ArchObj (DataPage dev sz)) obuf and (\<lambda>s. \<forall>buf thread. ipc_frame_ptr_at buf thread s \<longrightarrow> buf\<noteq> obuf) and
|
|
valid_objs and pspace_distinct and pspace_aligned and valid_etcbs)
|
|
(return a)
|
|
(do_machine_op (storeWord ptr b))"
|
|
apply (rule dcorres_expand_pfx)
|
|
apply (clarsimp simp: do_machine_op_def valid_def get_def gets_def bind_def return_def
|
|
simpler_modify_def corres_underlying_def)
|
|
apply (clarsimp simp: select_f_store_word assert_def bind_def fail_def return_def
|
|
split: if_splits)
|
|
apply (clarsimp simp: transform_def transform_current_thread_def)
|
|
apply (rule ext)
|
|
apply (rename_tac thread)
|
|
apply (clarsimp simp:transform_objects_def restrict_map_def option_map_def map_add_def split:option.splits)
|
|
apply (clarsimp simp:transform_object_def split:Structures_A.kernel_object.splits)
|
|
apply (clarsimp simp:transform_tcb_def transform_full_intent_def Let_def)
|
|
apply (clarsimp simp del:upt.simps
|
|
simp: Let_def get_tcb_mrs_def is_arch_page_cap_def
|
|
split:cap.split_asm arch_cap.split_asm
|
|
split del: split_if)
|
|
apply (frule valid_tcb_objs, erule get_tcb_rev)
|
|
apply (clarsimp simp: valid_tcb_def tcb_cap_cases_def valid_ipc_buffer_cap_def
|
|
simp del: upt.simps)
|
|
apply (erule disjE)
|
|
apply (clarsimp simp:is_nondevice_page_cap_def split:cap.split_asm simp del:upt.simps)
|
|
apply (rename_tac tcb arch_cap)
|
|
apply (case_tac arch_cap)
|
|
apply ((simp add:get_ipc_buffer_words_def)+)[2]
|
|
apply (rename_tac word rights vmpage_size option)
|
|
apply (simp add:Suc_leI[OF msg_registers_lt_msg_max_length] del:upt.simps)
|
|
apply (frule_tac thread = thread and ptr = ptr and ms = "machine_state s'"
|
|
and tcb_type = tcb and b = b
|
|
and xs = "[Suc (length msg_registers)..<Suc msg_max_length]"
|
|
in get_ipc_buffer_words_helper)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def obj_at_def)+)[2]
|
|
apply (simp add:obj_at_def)
|
|
apply (clarsimp simp:is_aligned_mask split:bool.split_asm simp del:upt.simps)+
|
|
apply (rule_tac y = thread in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (simp add:msg_max_length_def msg_align_bits)
|
|
apply (subgoal_tac "ipc_frame_ptr_at word thread s'")
|
|
apply (drule_tac x = word in spec)
|
|
apply clarsimp
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
|
|
apply (frule(1) valid_etcbs_tcb_etcb, clarsimp)
|
|
|
|
apply (rule conjI)
|
|
apply (frule_tac thread = thread and ptr = ptr and ms = "machine_state s'"
|
|
and tcb_type = tcb and b = b
|
|
and xs = "[buffer_cptr_index..<buffer_cptr_index +
|
|
unat (mi_extra_caps (get_tcb_message_info tcb))]"
|
|
in get_ipc_buffer_words_helper)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def obj_at_def is_aligned_mask)+)[7]
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule_tac sz = vmpage_size and y = thread in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (simp add:msg_max_length_def msg_align_bits buffer_cptr_index_def)
|
|
apply (case_tac "get_tcb_message_info tcb")
|
|
apply (clarsimp simp add: get_tcb_message_info_def data_to_message_info_def)
|
|
apply (erule order_less_le_trans)
|
|
apply simp
|
|
apply (rule iffD1[OF word_le_nat_alt[where b = "0x6::word32",simplified]])
|
|
apply (rule less_less_trans)
|
|
apply (rule word_and_le1[where a = 3])
|
|
apply simp
|
|
apply (subgoal_tac "ipc_frame_ptr_at word thread s'")
|
|
apply (drule_tac x = word in spec)
|
|
apply clarsimp
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply simp
|
|
apply (frule_tac thread = thread and ptr = ptr and sz = sz and ms = "machine_state s'"
|
|
and tcb_type = tcb and b = b
|
|
and xs = "[Suc (Suc (msg_max_length + msg_max_extra_caps))..<
|
|
5 + (msg_max_length + msg_max_extra_caps)]"
|
|
in get_ipc_buffer_words_helper)
|
|
apply (erule get_tcb_rev)
|
|
apply ((simp add:ipc_frame_wp_at_def is_aligned_mask obj_at_def)+)[7]
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule_tac y = thread and sz = vmpage_size in within_page_ipc_buf)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def ipc_buffer_wp_at_def)+
|
|
apply (clarsimp simp:msg_align_bits msg_max_length_def msg_max_extra_caps_def)
|
|
apply (subgoal_tac "ipc_frame_ptr_at word thread s'")
|
|
apply (drule_tac x = word in spec)
|
|
apply clarsimp
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply simp
|
|
apply (clarsimp simp:get_ipc_buffer_words_def)+
|
|
done
|
|
|
|
lemma store_word_corres:
|
|
"within_page buf ptr sz \<Longrightarrow>
|
|
dcorres dc \<top>
|
|
(pspace_aligned and pspace_distinct and valid_objs and
|
|
(ipc_frame_ptr_at buf s_id) and (ipc_frame_sz_at sz s_id) and valid_etcbs)
|
|
(corrupt_frame buf) (do_machine_op (storeWord ptr b))"
|
|
apply (case_tac "is_aligned ptr 2")
|
|
apply (simp add: corrupt_frame_def)
|
|
apply (simp add: do_machine_op_def gets_def)
|
|
apply (rule dcorres_absorb_get_r)
|
|
apply clarsimp
|
|
apply (drule store_word_corres_helper[where s_id = s_id],simp+)
|
|
apply (simp add:ipc_frame_wp_at_def obj_at_def)+
|
|
apply clarsimp
|
|
apply (rule corres_guard_imp)
|
|
apply (rule_tac Q="op = s'" and P =\<top> in select_pick_corres)
|
|
apply (simp add: select_f_store_word bind_assoc)
|
|
apply (clarsimp simp:assert_def corres_free_fail)
|
|
apply (rule corres_modify, simp)
|
|
apply (rule sym)
|
|
apply simp+
|
|
apply (clarsimp simp: do_machine_op_def gets_def)
|
|
apply (rule dcorres_absorb_get_r)
|
|
apply (rule corres_guard_imp)
|
|
apply (clarsimp simp:select_f_def fail_def storeWord_def
|
|
is_aligned_mask assert_def
|
|
|rule conjI)+
|
|
apply (simp add:bind_def simpler_modify_def corres_free_fail[unfolded fail_def])+
|
|
done
|
|
|
|
lemma store_word_offs_ipc_frame_wp:
|
|
"\<lbrace>ipc_frame_wp_at P s_id\<rbrace> store_word_offs base a aa \<lbrace>\<lambda>rv. ipc_frame_wp_at P s_id\<rbrace>"
|
|
by (wp | simp add: ipc_frame_wp_at_def store_word_offs_def)+
|
|
|
|
lemma zip_cpy_word_corres:
|
|
"\<forall>x\<in> set xs. within_page buf (base + of_nat(x*word_size)) sz
|
|
\<Longrightarrow> dcorres dc \<top>
|
|
(pspace_aligned and pspace_distinct and valid_objs
|
|
and (ipc_frame_ptr_at buf s_id) and (ipc_frame_sz_at sz s_id) and valid_etcbs)
|
|
(corrupt_frame buf)
|
|
(mapM (\<lambda>x. load_word_offs src_a x >>= store_word_offs base x)
|
|
xs)"
|
|
proof (induct xs)
|
|
case Nil
|
|
show ?case
|
|
apply (rule corres_guard_imp)
|
|
apply (clarsimp simp:mapM_def sequence_def)
|
|
apply (rule dcorres_dummy_corrupt_frame[THEN corres_guard_imp,unfolded dc_def])
|
|
apply simp+
|
|
done
|
|
next
|
|
case (Cons x xs)
|
|
show ?case
|
|
apply (subst corrupt_frame_duplicate[symmetric])
|
|
apply (rule corres_guard_imp)
|
|
apply (clarsimp simp:mapM_Cons)
|
|
apply (rule corres_split)
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_split)
|
|
apply (rule corres_free_return[where P = \<top> and P'=\<top> ])
|
|
apply (rule Cons.hyps)
|
|
using Cons
|
|
apply clarsimp
|
|
apply wp
|
|
apply (rule corres_symb_exec_r)
|
|
apply (simp add: store_word_offs_def bind_assoc[symmetric]
|
|
state_assert_def[symmetric])
|
|
apply (rule corres_state_assert)
|
|
apply (rule_tac s_id = s_id and sz = sz in store_word_corres)
|
|
using Cons.prems
|
|
apply simp
|
|
using Cons.prems
|
|
apply (clarsimp simp: within_page_def in_user_frame_def)
|
|
apply (thin_tac "Ball S P" for S P)
|
|
apply (rule_tac x=sz in exI)
|
|
apply (frule (2) ipc_frame_ptr_at_frame_at)
|
|
apply (simp add: obj_at_def a_type_simps)
|
|
apply wp
|
|
apply clarsimp+
|
|
apply (wp store_word_offs_ipc_frame_wp)
|
|
apply (fastforce simp:ipc_frame_wp_at_def)+
|
|
done
|
|
qed
|
|
|
|
lemma zip_store_word_corres:
|
|
"\<forall>x\<in> set xs. within_page buf (base + of_nat (x * word_size)) sz \<Longrightarrow>
|
|
dcorres dc \<top>
|
|
(pspace_aligned and pspace_distinct and valid_objs
|
|
and (ipc_frame_sz_at sz s_id) and (ipc_frame_ptr_at buf s_id) and valid_etcbs)
|
|
(corrupt_frame buf)
|
|
(zipWithM_x (store_word_offs base) xs ys)"
|
|
apply (clarsimp simp:zipWithM_x_mapM_x split del: split_if)
|
|
apply (induct xs arbitrary: ys)
|
|
apply (clarsimp simp: mapM_x_Cons)
|
|
apply (clarsimp simp: mapM_x_Nil)
|
|
apply (rule corres_guard_imp[OF dcorres_dummy_corrupt_frame])
|
|
apply (simp+)[2]
|
|
apply (case_tac ys)
|
|
apply (clarsimp simp: mapM_x_Cons mapM_x_Nil)
|
|
apply (rule corres_guard_imp[OF dcorres_dummy_corrupt_frame])
|
|
apply clarsimp+
|
|
apply (subst mapM_x_Cons)
|
|
apply clarify
|
|
apply (subst corrupt_frame_duplicate[symmetric])
|
|
apply (rule corres_guard_imp)
|
|
apply (rule corres_split [where P="\<top>" and r'="dc"])
|
|
apply clarsimp
|
|
apply (drule allI)
|
|
apply (drule_tac x = list in spec)
|
|
apply simp
|
|
apply (clarsimp simp:store_word_offs_def)
|
|
apply (simp add: store_word_offs_def bind_assoc[symmetric] state_assert_def[symmetric])
|
|
apply (rule corres_state_assert)
|
|
apply (rule_tac s_id = s_id and sz = sz in store_word_corres)
|
|
apply simp
|
|
apply (clarsimp simp: within_page_def in_user_frame_def)
|
|
apply (rule_tac x=sz in exI)
|
|
apply (frule (2) ipc_frame_ptr_at_frame_at)
|
|
apply (simp add: obj_at_def a_type_simps)
|
|
apply (wp store_word_offs_ipc_frame_wp)
|
|
apply clarsimp+
|
|
done
|
|
|
|
lemma ex_cte_cap_wp_to_not_idle:
|
|
"\<lbrakk> ex_cte_cap_wp_to P r s; valid_global_refs s; valid_objs s;
|
|
valid_idle s; valid_irq_node s\<rbrakk>
|
|
\<Longrightarrow> not_idle_thread (fst r) s"
|
|
apply (clarsimp simp:ex_cte_cap_wp_to_def)
|
|
apply (simp add:valid_global_refs_def valid_refs_def not_idle_thread_def)
|
|
apply (drule_tac x = a in spec, drule_tac x = b in spec)
|
|
apply (clarsimp simp:global_refs_def cte_wp_at_cases dest!:get_tcb_SomeD split:if_splits)
|
|
apply (erule disjE)
|
|
apply clarsimp
|
|
apply (case_tac cap)
|
|
apply (clarsimp simp:cap_range_def)+
|
|
apply (rename_tac word)
|
|
apply (clarsimp simp:valid_idle_def valid_irq_node_def)
|
|
apply (drule_tac x = word in spec)
|
|
apply (clarsimp simp:pred_tcb_at_def obj_at_def is_cap_table_def)
|
|
apply (clarsimp simp:cap_range_def)+
|
|
apply (case_tac "get tcb")
|
|
apply clarsimp+
|
|
apply (rename_tac word)
|
|
apply (clarsimp simp:valid_idle_def valid_irq_node_def)
|
|
apply (drule_tac x = word in spec)
|
|
apply (clarsimp simp:st_tcb_at_def pred_tcb_at_def obj_at_def is_cap_table_def)
|
|
apply clarsimp+
|
|
done
|
|
|
|
lemma pspace_aligned_set_cxt_mrs[wp]:
|
|
"\<lbrace>ko_at (TCB tcb) thread and pspace_aligned\<rbrace> KHeap_A.set_object thread (TCB (tcb\<lparr>tcb_context := t \<rparr>))\<lbrace>\<lambda>rv. pspace_aligned\<rbrace>"
|
|
apply (wp set_object_aligned)
|
|
apply (clarsimp simp:obj_at_def)
|
|
done
|
|
|
|
lemma pspace_distinct_set_cxt_mrs[wp]:
|
|
"\<lbrace>ko_at (TCB tcb) thread and pspace_distinct\<rbrace> KHeap_A.set_object thread (TCB (tcb\<lparr>tcb_context := t \<rparr>))
|
|
\<lbrace>\<lambda>rv. pspace_distinct\<rbrace>"
|
|
apply (wp set_object_distinct)
|
|
apply (clarsimp simp:obj_at_def)
|
|
done
|
|
|
|
|
|
lemma valid_objs_set_cxt_mrs[wp]:
|
|
"\<lbrace>ko_at (TCB tcb) thread and valid_objs\<rbrace> KHeap_A.set_object thread (TCB (tcb\<lparr>tcb_context := t \<rparr>))\<lbrace>\<lambda>rv. valid_objs\<rbrace>"
|
|
apply (wp set_object_valid_objs)
|
|
apply (clarsimp simp:obj_at_def)
|
|
apply (clarsimp simp:valid_objs_def)
|
|
apply (drule_tac x=thread in bspec)
|
|
apply (clarsimp simp:dom_def)
|
|
apply (clarsimp simp:valid_obj_def valid_tcb_def)
|
|
apply (drule_tac x="(a,aa,b)" in bspec)
|
|
apply simp
|
|
apply (clarsimp simp:tcb_cap_cases_def)
|
|
apply (erule disjE|clarsimp)+
|
|
done
|
|
|
|
lemma ipc_frame_set_cxt_mrs[wp]:
|
|
"\<lbrace>ko_at (TCB tcb) thread and ipc_frame_wp_at P a\<rbrace> KHeap_A.set_object thread (TCB (tcb\<lparr>tcb_context := t \<rparr>))\<lbrace>\<lambda>rv. ipc_frame_wp_at P a\<rbrace>"
|
|
by (clarsimp simp: KHeap_A.set_object_def get_def put_def bind_def valid_def
|
|
return_def obj_at_def ipc_frame_wp_at_def)
|
|
|
|
lemma ipc_buffer_set_cxt_mrs[wp]:
|
|
"\<lbrace>ko_at (TCB tcb) thread and ipc_buffer_wp_at P a\<rbrace> KHeap_A.set_object thread (TCB (tcb\<lparr>tcb_context := t \<rparr>))\<lbrace>\<lambda>rv. ipc_buffer_wp_at P a\<rbrace>"
|
|
by (clarsimp simp: KHeap_A.set_object_def get_def put_def bind_def valid_def
|
|
return_def obj_at_def ipc_buffer_wp_at_def)
|
|
|
|
lemmas [wp] = abs_typ_at_lifts[OF do_machine_op_typ_at]
|
|
|
|
lemma set_object_valid_etcbs: "\<lbrace>valid_etcbs and (\<lambda>s. kheap s ptr = Some (TCB tcba))\<rbrace>
|
|
KHeap_A.set_object ptr (TCB tcbb)
|
|
\<lbrace>\<lambda>rv. valid_etcbs\<rbrace>"
|
|
apply (clarsimp simp: set_object_def)
|
|
apply wp
|
|
apply (auto simp: valid_etcbs_def st_tcb_at_def obj_at_def is_etcb_at_def st_tcb_at_kh_def obj_at_kh_def)
|
|
done
|
|
|
|
lemma set_mrs_corres:
|
|
"dcorres dc \<top>
|
|
(valid_idle and valid_objs and pspace_aligned and pspace_distinct and not_idle_thread y
|
|
and ipc_frame_ptr_at buf y and ipc_frame_sz_at sz y and ipc_buffer_wp_at bptr y and valid_etcbs)
|
|
(do corrupt_tcb_intent y;corrupt_frame buf od)
|
|
(set_mrs y (Some (buf + (bptr && mask (pageBitsForSize sz)))) b)"
|
|
apply (simp add:set_mrs_def del:upt.simps)
|
|
apply (rule dcorres_absorb_gets_the)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule corres_split [where r'=dc])
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_split [where r'=dc and R'="%x. \<top>" and R="%x. \<top>"])
|
|
apply (rule corres_free_return)
|
|
apply (rule_tac s_id = y and sz = sz in zip_store_word_corres)
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule within_page_ipc_buf)
|
|
apply ((simp add:msg_align_bits msg_max_length_def)+)[7]
|
|
apply wp
|
|
apply (clarsimp, drule(1) valid_etcbs_get_tcb_get_etcb)
|
|
apply (rule_tac s'=s' in set_cxt_none_det_intent_corres)
|
|
apply (clarsimp dest!:get_tcb_SomeD get_etcb_SomeD)+
|
|
apply (wp set_object_valid_etcbs)
|
|
apply (simp del:upt.simps)
|
|
apply (auto dest!:get_tcb_SomeD simp:obj_at_def ipc_frame_wp_at_def)
|
|
done
|
|
|
|
lemma set_registers_ipc_frame_ptr_at[wp]:
|
|
"\<lbrace>ipc_frame_wp_at buf y\<rbrace>as_user thread (set_register r rv) \<lbrace>%x. ipc_frame_wp_at buf y\<rbrace>"
|
|
apply (clarsimp simp:as_user_def select_f_def set_register_def simpler_modify_def)
|
|
apply wp
|
|
apply clarsimp
|
|
apply wp
|
|
apply (clarsimp simp:valid_def)
|
|
apply (assumption)
|
|
apply wp
|
|
apply clarsimp
|
|
done
|
|
|
|
lemma set_registers_ipc_buffer_ptr_at[wp]:
|
|
"\<lbrace>ipc_buffer_wp_at buf y\<rbrace>as_user thread (set_register r rv) \<lbrace>%x. ipc_buffer_wp_at buf y\<rbrace>"
|
|
apply (clarsimp simp:as_user_def select_f_def set_register_def simpler_modify_def)
|
|
apply wp
|
|
apply clarsimp
|
|
apply wp
|
|
apply (clarsimp simp:valid_def)
|
|
apply (assumption)
|
|
apply wp
|
|
apply clarsimp
|
|
done
|
|
|
|
|
|
lemma copy_mrs_corres:
|
|
"valid_message_info mi \<Longrightarrow>
|
|
dcorres dc \<top> ((valid_idle and valid_objs and pspace_aligned and pspace_distinct and not_idle_thread y
|
|
and ipc_frame_ptr_at buf y and ipc_frame_sz_at sz y and ipc_buffer_wp_at bptr y and valid_etcbs))
|
|
(do corrupt_tcb_intent y;corrupt_frame buf od)
|
|
(copy_mrs thread rv y (Some (buf + (bptr && mask (pageBitsForSize sz))))
|
|
(mi_length mi))"
|
|
apply (simp add:copy_mrs_def del:upt.simps)
|
|
apply (rule dcorres_expand_pfx)
|
|
apply (rule corres_guard_imp)
|
|
apply (rule corres_split [where r'="dc"])
|
|
apply (wpc)
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_split [where r'="dc"])
|
|
apply (rule corres_free_return[where P="\<top>" and P'="\<top>"])
|
|
apply (rule dcorres_dummy_corrupt_frame)
|
|
apply wp
|
|
apply (clarify,simp del:upt.simps )
|
|
apply (rule corres_dummy_return_l)
|
|
apply (rule corres_split[where r'="dc"])
|
|
apply (rule corres_free_return[where P="\<top>" and P'="\<top>"])
|
|
apply (rule_tac s_id = y and sz = sz in zip_cpy_word_corres)
|
|
apply (clarsimp simp del:upt.simps)
|
|
apply (rule within_page_ipc_buf)
|
|
apply simp+
|
|
apply (clarsimp simp:msg_align_bits valid_message_info_def msg_max_length_def)
|
|
apply (erule less_trans)
|
|
apply (rule le_less_trans[where y = "Suc (unat (0x78))"])
|
|
apply (rule iffD2[OF Suc_le_mono])
|
|
apply (erule iffD1[OF word_le_nat_alt])
|
|
apply simp
|
|
apply wp
|
|
apply (rule set_registers_corres)
|
|
apply ((clarsimp|wp)+)[1]
|
|
apply (rule mapM_wp_inv)
|
|
apply (case_tac rv)
|
|
apply clarsimp
|
|
apply (wp_once+)[1]
|
|
apply (clarsimp|rule conjI)+
|
|
apply ((wp|clarsimp)+)[3]
|
|
apply (case_tac rv)
|
|
apply (clarsimp simp: ipc_buffer_wp_at_def obj_at_def tcb_at_def)+
|
|
done
|
|
|
|
lemmas transform_cap_simps [simp] = transform_cap_def [split_simps cap.split arch_cap.split]
|
|
|
|
lemma corrupt_frame_include_self:
|
|
assumes corres:"dcorres dc \<top> P (do corrupt_tcb_intent y;corrupt_frame buf od) g"
|
|
assumes imp:"\<And>s. P s\<Longrightarrow> ipc_frame_ptr_at buf y s \<and> not_idle_thread y s \<and> valid_etcbs s"
|
|
shows "dcorres dc \<top> P (corrupt_frame buf) g"
|
|
using corres
|
|
apply (clarsimp simp:corres_underlying_def)
|
|
apply (frule imp)
|
|
apply (erule allE, erule (1) impE)
|
|
apply (drule_tac x = "(a,ba)" in bspec)
|
|
apply simp+
|
|
apply (clarsimp simp:bind_def)
|
|
apply (rule_tac x = "((),transform ba)" in bexI)
|
|
apply simp
|
|
apply (clarsimp simp:corrupt_tcb_intent_def bind_def)
|
|
apply (clarsimp simp:update_thread_def gets_the_def gets_def get_def bind_def in_monad)
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply (clarsimp split:cap.splits arch_cap.splits)
|
|
apply (clarsimp simp:select_def KHeap_D.set_object_def simpler_modify_def)
|
|
apply (clarsimp simp:corrupt_frame_def bind_def select_def)
|
|
apply (clarsimp simp:simpler_modify_def corrupt_intents_def)
|
|
apply (drule(1) valid_etcbs_tcb_etcb, clarsimp)
|
|
apply (subst(asm) opt_object_tcb)
|
|
apply (erule get_tcb_rev)
|
|
apply (erule get_etcb_rev)
|
|
apply (simp add:not_idle_thread_def)
|
|
apply (clarsimp simp:transform_tcb_def in_monad set_object_def)
|
|
apply (rule_tac x = x in exI)
|
|
apply (clarsimp simp:transform_def KHeap_D.set_object_def simpler_modify_def)
|
|
apply (case_tac "transform b")
|
|
apply (clarsimp simp:transform_def map_add_def)
|
|
apply (rule ext)
|
|
apply (drule_tac x = xa in fun_cong)
|
|
apply (case_tac xa)
|
|
apply (clarsimp simp:not_idle_thread_def tcb_ipcframe_id_def restrict_map_def transform_objects_def
|
|
split: split_if)
|
|
apply (clarsimp dest!:get_tcb_rev simp: transform_objects_tcb tcb_ipcbuffer_slot_def
|
|
tcb_pending_op_slot_def tcb_boundntfn_slot_def)
|
|
apply (clarsimp simp: tcb_ipcbuffer_slot_def tcb_ipcframe_id_def | rule conjI)+
|
|
apply (clarsimp simp:transform_def transform_object_def transform_tcb_def tcb_ipcframe_id_def
|
|
tcb_ipcbuffer_slot_def tcb_pending_op_slot_def tcb_boundntfn_slot_def dest!:get_tcb_SomeD)
|
|
done
|
|
|
|
lemma corrupt_frame_include_self':
|
|
assumes corres:"dcorres dc \<top> P (do corrupt_frame buf; corrupt_tcb_intent y od) g"
|
|
assumes imp:"\<And>s. P s\<Longrightarrow> ipc_frame_ptr_at buf y s \<and> not_idle_thread y s \<and> valid_etcbs s"
|
|
shows "dcorres dc \<top> P (corrupt_frame buf) g"
|
|
using corres
|
|
apply (clarsimp simp:corres_underlying_def bind_def)
|
|
apply (frule imp)
|
|
apply (erule allE, erule (1) impE)
|
|
apply (drule_tac x = "(a,ba)" in bspec)
|
|
apply simp+
|
|
apply (clarsimp)
|
|
apply (rule_tac x = "((),transform ba)" in bexI)
|
|
apply simp+
|
|
apply (clarsimp simp:corrupt_frame_def select_def bind_def simpler_modify_def)
|
|
apply (clarsimp simp:corrupt_tcb_intent_def update_thread_def
|
|
select_def gets_the_def KHeap_D.set_object_def
|
|
bind_def gets_def get_def return_def assert_opt_def
|
|
fail_def simpler_modify_def split:option.splits)
|
|
apply (rule_tac x = "\<lambda>t. if t = y then T else x t" for T in exI)
|
|
apply (clarsimp simp:corrupt_intents_def transform_def not_idle_thread_def
|
|
restrict_map_def map_add_def opt_object_def ipc_frame_wp_at_def obj_at_def
|
|
split:option.split_asm cdl_object.split_asm)
|
|
apply (rule ext)
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def tcb_ipcframe_id_def tcb_pending_op_slot_def
|
|
transform_object_def not_idle_thread_def transform_tcb_def tcb_ipcbuffer_slot_def)
|
|
apply (clarsimp simp: transform_objects_def)
|
|
apply (clarsimp split:cap.splits arch_cap.splits)
|
|
apply (drule(1) valid_etcbs_tcb_etcb)
|
|
apply (fastforce simp:opt_object_def transform_tcb_def tcb_ipcframe_id_def tcb_pending_op_slot_def
|
|
tcb_ipcbuffer_slot_def tcb_boundntfn_slot_def)+
|
|
done
|
|
|
|
lemma dcorres_set_mrs:
|
|
"dcorres dc \<top>
|
|
(valid_idle and valid_objs and pspace_aligned and pspace_distinct and not_idle_thread y
|
|
and ipc_frame_ptr_at buf y and ipc_frame_sz_at sz y and ipc_buffer_wp_at bptr y and valid_etcbs)
|
|
(corrupt_frame buf)
|
|
(set_mrs y (Some (buf + (bptr && mask (pageBitsForSize sz)))) b)"
|
|
apply (rule corrupt_frame_include_self)
|
|
apply (rule corres_guard_imp[OF set_mrs_corres])
|
|
apply clarsimp+
|
|
done
|
|
|
|
lemma dcorres_copy_mrs:
|
|
"valid_message_info mi \<Longrightarrow>
|
|
dcorres dc \<top> ((valid_idle and valid_objs and pspace_aligned and pspace_distinct and not_idle_thread y
|
|
and ipc_frame_ptr_at buf y and ipc_frame_sz_at sz y and ipc_buffer_wp_at bptr y and valid_etcbs))
|
|
(corrupt_frame buf)
|
|
(copy_mrs thread rv y (Some (buf + (bptr && mask (pageBitsForSize sz))))
|
|
(mi_length mi))"
|
|
apply (rule corrupt_frame_include_self)
|
|
apply (rule corres_guard_imp[OF copy_mrs_corres])
|
|
apply auto
|
|
done
|
|
|
|
lemma ipc_frame_ptr_at_sz_at:
|
|
"\<lbrakk>ko_at (ArchObj (DataPage dev sz)) obuf s; valid_objs s;ipc_frame_ptr_at obuf thread s \<rbrakk> \<Longrightarrow> ipc_frame_sz_at sz thread s"
|
|
apply (clarsimp simp:ipc_frame_wp_at_def obj_at_def)
|
|
apply (clarsimp split:cap.splits arch_cap.splits)
|
|
apply (frule valid_tcb_objs)
|
|
apply (erule get_tcb_rev)
|
|
apply (subgoal_tac "valid_cap (tcb_ipcframe tcb) s")
|
|
apply (clarsimp simp:valid_cap_def obj_at_def a_type_def split:if_splits arch_kernel_obj.splits)
|
|
apply (clarsimp simp:valid_tcb_def tcb_cap_cases_def split:if_splits)
|
|
done
|
|
|
|
lemma dcorres_store_word_conservative:
|
|
" within_page obuf ptr sz \<Longrightarrow>
|
|
dcorres dc (\<lambda>_. True)
|
|
(ko_at (ArchObj (DataPage dev sz)) obuf and valid_objs and
|
|
pspace_distinct and
|
|
pspace_aligned and valid_etcbs)
|
|
(corrupt_frame obuf) (do_machine_op (storeWord ptr b))"
|
|
apply (rule dcorres_expand_pfx,clarsimp)
|
|
apply (case_tac "\<forall>buf. (\<exists>thread. ipc_frame_ptr_at buf thread s') \<longrightarrow> buf \<noteq> obuf")
|
|
apply (rule corres_dummy_return_pl)
|
|
apply (rule corres_dummy_return_r)
|
|
apply (rule corres_underlying_split)
|
|
apply (rule corres_guard_imp[OF dcorres_store_word_safe])
|
|
apply simp+
|
|
apply (rule hoare_TrueI)[1]
|
|
apply (wp do_machine_op_valid_etcbs, simp)
|
|
apply (clarsimp simp:dcorres_dummy_corrupt_frame)
|
|
apply (clarsimp)
|
|
apply (frule ipc_frame_ptr_at_sz_at,simp+)
|
|
apply (rule corres_guard_imp[OF store_word_corres])
|
|
apply simp+
|
|
done
|
|
|
|
end
|
|
|
|
end
|