lh-l4v/proof/invariant-abstract/Schedule_AI.thy

220 lines
8.8 KiB
Plaintext

(*
* Copyright 2014, General Dynamics C4 Systems
*
* SPDX-License-Identifier: GPL-2.0-only
*)
theory Schedule_AI
imports VSpace_AI
begin
abbreviation
"activatable \<equiv> \<lambda>st. runnable st \<or> idle st"
locale Schedule_AI =
fixes state_ext :: "('a::state_ext) itself"
assumes dmo_mapM_storeWord_0_invs[wp]:
"\<And>S. valid invs (do_machine_op (mapM (\<lambda>p. storeWord p 0) S)) (\<lambda>_. (invs :: 'a state \<Rightarrow> bool))"
assumes arch_stt_invs [wp]:
"\<And>t'. \<lbrace>invs\<rbrace> arch_switch_to_thread t' \<lbrace>\<lambda>_. (invs :: 'a state \<Rightarrow> bool)\<rbrace>"
assumes arch_stt_tcb [wp]:
"\<And>t'. \<lbrace>tcb_at t'\<rbrace> arch_switch_to_thread t' \<lbrace>\<lambda>_. (tcb_at t' :: 'a state \<Rightarrow> bool)\<rbrace>"
assumes arch_stt_runnable:
"\<And>t. \<lbrace>st_tcb_at runnable t\<rbrace> arch_switch_to_thread t \<lbrace>\<lambda>r . (st_tcb_at runnable t :: 'a state \<Rightarrow> bool)\<rbrace>"
assumes stit_invs [wp]:
"\<lbrace>invs\<rbrace> switch_to_idle_thread \<lbrace>\<lambda>rv. (invs :: 'a state \<Rightarrow> bool)\<rbrace>"
assumes stit_activatable:
"\<lbrace>invs\<rbrace> switch_to_idle_thread \<lbrace>\<lambda>rv . (ct_in_state activatable :: 'a state \<Rightarrow> bool)\<rbrace>"
context begin interpretation Arch .
(* FIXME arch_split: some of these could be moved to generic theories
so they don't need to be unqualified. *)
requalify_facts
no_irq
no_irq_storeWord
end
crunch inv[wp]: schedule_switch_thread_fastfail P
lemma findM_inv'':
assumes p: "suffix xs xs'"
assumes x: "\<And>x xs. suffix (x # xs) xs' \<Longrightarrow> \<lbrace>P (x # xs)\<rbrace> m x \<lbrace>\<lambda>rv s. (rv \<longrightarrow> Q s) \<and> (\<not> rv \<longrightarrow> P xs s)\<rbrace>"
assumes y: "\<And>s. P [] s \<Longrightarrow> Q s"
shows "\<lbrace>P xs\<rbrace> findM m xs \<lbrace>\<lambda>rv. Q\<rbrace>"
using p
apply (induct xs)
apply simp
apply wp
apply (erule y)
apply (frule suffix_ConsD)
apply simp
apply wp
apply (erule x)
apply simp
done
lemmas findM_inv' = findM_inv''[OF suffix_order.refl]
lemma findM_inv:
assumes x: "\<And>x. \<lbrace>P\<rbrace> m x \<lbrace>\<lambda>rv. P\<rbrace>"
shows "\<lbrace>P\<rbrace> findM m xs \<lbrace>\<lambda>rv. P\<rbrace>"
by (rule findM_inv', simp_all add: x)
lemma allActiveTCBs_gets:
"allActiveTCBs = gets (\<lambda>state. {x. getActiveTCB x state \<noteq> None})"
by (simp add: allActiveTCBs_def gets_def)
lemma postfix_tails:
"\<lbrakk> suffix (xs # ys) (tails zs) \<rbrakk>
\<Longrightarrow> suffix xs zs \<and> (xs # ys) = tails xs"
apply (induct zs arbitrary: xs ys)
apply (clarsimp elim!: suffixE)
apply (case_tac zs, simp_all)[1]
apply (clarsimp elim!: suffixE)
apply (case_tac zsa, simp_all)
apply clarsimp
apply clarsimp
apply (erule meta_allE, erule meta_allE, drule meta_mp,
rule suffix_appendI[OF suffix_order.refl])
apply clarsimp
apply (erule suffix_ConsI)
done
lemma valid_irq_states_cur_thread_update[simp]:
"valid_irq_states (cur_thread_update f s) = valid_irq_states s"
by(simp add: valid_irq_states_def)
lemma sct_invs:
"\<lbrace>invs and tcb_at t\<rbrace> modify (cur_thread_update (%_. t)) \<lbrace>\<lambda>rv. invs\<rbrace>"
by wp (clarsimp simp add: invs_def cur_tcb_def valid_state_def valid_idle_def
valid_irq_node_def valid_machine_state_def)
lemma storeWord_valid_irq_states:
"\<lbrace>\<lambda>m. valid_irq_states (s\<lparr>machine_state := m\<rparr>)\<rbrace> storeWord x y
\<lbrace>\<lambda>a b. valid_irq_states (s\<lparr>machine_state := b\<rparr>)\<rbrace>"
apply (simp add: valid_irq_states_def | wp no_irq | simp add: no_irq_storeWord)+
done
lemma dmo_storeWord_valid_irq_states[wp]:
"\<lbrace>valid_irq_states\<rbrace> do_machine_op (storeWord x y) \<lbrace>\<lambda>_. valid_irq_states\<rbrace>"
apply (simp add: do_machine_op_def | wp | wpc)+
apply clarsimp
apply(erule use_valid[OF _ storeWord_valid_irq_states])
by simp
lemma dmo_kheap_arch_state[wp]:
"\<lbrace>\<lambda>s. P (kheap s) (arch_state s)\<rbrace>
do_machine_op a
\<lbrace>\<lambda>_ s. P (kheap s) (arch_state s)\<rbrace>"
by (clarsimp simp: do_machine_op_def simpler_gets_def select_f_def
simpler_modify_def return_def bind_def valid_def)
lemmas do_machine_op_tcb[wp] =
do_machine_op_obj_at[where P=id and Q=is_tcb, simplified]
lemma (in Schedule_AI) stt_tcb [wp]:
"\<lbrace>tcb_at t\<rbrace> switch_to_thread t \<lbrace>\<lambda>_. (tcb_at t :: 'a state \<Rightarrow> bool)\<rbrace>"
apply (simp add: switch_to_thread_def)
apply (wp | simp)+
done
(* FIXME - Move Invariants_AI *)
lemma invs_exst [iff]:
"invs (trans_state f s) = invs s"
by (simp add: invs_def valid_state_def)
lemma (in Schedule_AI) stt_invs [wp]:
"\<lbrace>invs :: 'a state \<Rightarrow> bool\<rbrace> switch_to_thread t' \<lbrace>\<lambda>_. invs\<rbrace>"
apply (simp add: switch_to_thread_def)
apply wp
apply (simp add: trans_state_update[symmetric] del: trans_state_update)
apply (rule_tac Q="\<lambda>_. invs and tcb_at t'" in hoare_strengthen_post, wp)
apply (clarsimp simp: invs_def valid_state_def valid_idle_def
valid_irq_node_def valid_machine_state_def)
apply (fastforce simp: cur_tcb_def obj_at_def
elim: valid_pspace_eqI ifunsafe_pspaceI)
apply wp+
apply clarsimp
apply (simp add: is_tcb_def)
done
lemma (in Schedule_AI) stt_activatable:
"\<lbrace>st_tcb_at runnable t\<rbrace> switch_to_thread t \<lbrace>\<lambda>rv . (ct_in_state activatable :: 'a state \<Rightarrow> bool) \<rbrace>"
apply (simp add: switch_to_thread_def)
apply (wp | simp add: ct_in_state_def)+
apply (rule hoare_post_imp [OF _ arch_stt_runnable])
apply (clarsimp elim!: pred_tcb_weakenE)
apply (rule assert_inv)
apply wp
apply assumption
done
lemma invs_upd_cur_valid:
"\<lbrakk>\<lbrace>P\<rbrace> f \<lbrace>\<lambda>rv. invs\<rbrace>; \<lbrace>Q\<rbrace> f \<lbrace>\<lambda>rv. tcb_at thread\<rbrace>\<rbrakk>
\<Longrightarrow> \<lbrace>P and Q\<rbrace> f \<lbrace>\<lambda>rv s. invs (s\<lparr>cur_thread := thread\<rparr>)\<rbrace>"
by (fastforce simp: valid_def invs_def valid_state_def cur_tcb_def valid_machine_state_def)
(* FIXME move *)
lemma pred_tcb_weaken_strongerE:
"\<lbrakk> pred_tcb_at proj P t s; \<And>tcb . P (proj tcb) \<Longrightarrow> P' (proj' tcb) \<rbrakk> \<Longrightarrow> pred_tcb_at proj' P' t s"
by (auto simp: pred_tcb_at_def elim: obj_at_weakenE)
lemma OR_choice_weak_wp:
"\<lbrace>P\<rbrace> f \<sqinter> g \<lbrace>Q\<rbrace> \<Longrightarrow> \<lbrace>P\<rbrace> OR_choice b f g \<lbrace>Q\<rbrace>"
apply (fastforce simp add: OR_choice_def alternative_def valid_def bind_def
select_f_def gets_def return_def get_def
split: option.splits if_split_asm)
done
locale Schedule_AI_U = Schedule_AI "TYPE(unit)"
lemma (in Schedule_AI_U) schedule_invs[wp]:
"\<lbrace>invs\<rbrace> (Schedule_A.schedule :: (unit,unit) s_monad) \<lbrace>\<lambda>rv. invs\<rbrace>"
apply (simp add: Schedule_A.schedule_def allActiveTCBs_def)
apply (wp OR_choice_weak_wp dmo_invs thread_get_inv
do_machine_op_tcb select_ext_weak_wp when_def
| clarsimp simp: getActiveTCB_def get_tcb_def)+
done
(* FIXME - move *)
lemma get_tcb_exst_update:
"get_tcb p (trans_state f s) = get_tcb p s"
by (simp add: get_tcb_def)
lemma ct_in_state_trans_update[simp]: "ct_in_state st (trans_state f s) = ct_in_state st s"
apply (simp add: ct_in_state_def)
done
lemma (in Schedule_AI_U) schedule_ct_activateable[wp]:
"\<lbrace>invs\<rbrace> (Schedule_A.schedule :: (unit,unit) s_monad) \<lbrace>\<lambda>rv. ct_in_state activatable \<rbrace>"
proof -
have P: "\<And>t s. ct_in_state activatable (cur_thread_update (\<lambda>_. t) s) = st_tcb_at activatable t s"
by (fastforce simp: ct_in_state_def pred_tcb_at_def intro: obj_at_pspaceI)
have Q: "\<And>s. invs s \<longrightarrow> idle_thread s = cur_thread s \<longrightarrow> ct_in_state activatable s"
apply (clarsimp simp: ct_in_state_def dest!: invs_valid_idle)
apply (clarsimp simp: valid_idle_def pred_tcb_def2)
done
show ?thesis
apply (simp add: Schedule_A.schedule_def allActiveTCBs_def)
apply (wp select_ext_weak_wp stt_activatable stit_activatable
| simp add: P Q)+
apply (clarsimp simp: getActiveTCB_def ct_in_state_def)
apply (rule conjI)
apply clarsimp
apply (case_tac "get_tcb (cur_thread s) s", simp_all add: ct_in_state_def)
apply (drule get_tcb_SomeD)
apply (clarsimp simp: pred_tcb_at_def obj_at_def split: if_split_asm)
apply (case_tac "get_tcb x s", simp_all)
apply (drule get_tcb_SomeD)
apply (clarsimp simp: pred_tcb_at_def obj_at_def split: if_split_asm)
done
qed
end