riscv ainvs+access: add proofs for Retype_AC
Signed-off-by: Ryan Barry <ryan.barry@unsw.edu.au>
This commit is contained in:
parent
9478264f19
commit
cc5014240d
|
@ -0,0 +1,366 @@
|
|||
(*
|
||||
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only
|
||||
*)
|
||||
|
||||
theory ArchRetype_AC
|
||||
imports Retype_AC
|
||||
begin
|
||||
|
||||
|
||||
lemma invs_mdb_cte':
|
||||
"invs s \<Longrightarrow> mdb_cte_at (\<lambda>p. \<exists>c. caps_of_state s p = Some c \<and> NullCap \<noteq> c) (cdt s)"
|
||||
by (drule invs_mdb) (simp add: valid_mdb_def2)
|
||||
|
||||
|
||||
context retype_region_proofs begin interpretation Arch .
|
||||
|
||||
lemma state_vrefs_eq:
|
||||
"\<lbrakk> valid_vspace_objs s; valid_arch_state s \<rbrakk>
|
||||
\<Longrightarrow> state_vrefs s' = state_vrefs s"
|
||||
apply (insert dev vp)
|
||||
apply (intro ext subset_antisym subsetI)
|
||||
apply (clarsimp simp: state_vrefs_def)
|
||||
apply (frule vs_lookup_level)
|
||||
apply (simp add: vs_lookup_table')
|
||||
apply (prop_tac "kheap s x = kheap s' x")
|
||||
apply (clarsimp simp: s'_def ps_def split: if_splits)
|
||||
apply (case_tac "lvl > max_pt_level")
|
||||
apply (fastforce simp: valid_arch_state_def opt_map_def orthr
|
||||
dest: vs_lookup_asid_pool
|
||||
split: option.splits)
|
||||
apply (fastforce simp: valid_arch_state_def valid_pspace_def obj_at_def orthr
|
||||
dest!: vs_lookup_table_pt_at )
|
||||
apply (fastforce simp: opt_map_def)
|
||||
apply (clarsimp simp: state_vrefs_def)
|
||||
apply (frule vs_lookup_level)
|
||||
apply (prop_tac "kheap s x = kheap s' x")
|
||||
apply (clarsimp simp: s'_def ps_def split: if_splits)
|
||||
apply (case_tac "lvl > max_pt_level")
|
||||
apply (fastforce simp: valid_arch_state_def opt_map_def orthr
|
||||
dest: vs_lookup_asid_pool
|
||||
split: option.splits)
|
||||
apply (fastforce simp: valid_arch_state_def valid_pspace_def obj_at_def orthr
|
||||
dest!: vs_lookup_table_pt_at )
|
||||
apply (fastforce simp: opt_map_def vs_lookup_table'[symmetric])
|
||||
done
|
||||
|
||||
end
|
||||
|
||||
|
||||
context retype_region_proofs' begin interpretation Arch .
|
||||
|
||||
lemma pas_refined:
|
||||
"\<lbrakk> invs s; pas_refined aag s \<rbrakk> \<Longrightarrow> pas_refined aag s'"
|
||||
apply (erule pas_refined_state_objs_to_policy_subset)
|
||||
apply (simp add: state_objs_to_policy_def refs_eq mdb_and_revokable)
|
||||
apply (subst state_vrefs_eq; fastforce?)
|
||||
apply (rule subsetI, rename_tac x, case_tac x, simp)
|
||||
apply (erule state_bits_to_policy.cases)
|
||||
apply (solves \<open>auto intro!: sbta_caps intro: caps_retype split: cap.split\<close>)
|
||||
apply (solves \<open>auto intro!: sbta_untyped intro: caps_retype split: cap.split\<close>)
|
||||
apply (blast intro: state_bits_to_policy.intros)
|
||||
apply (blast intro: state_bits_to_policy.intros)
|
||||
apply (force intro!: sbta_cdt
|
||||
dest: caps_of_state_pres invs_mdb_cte'[THEN mdb_cte_atD[rotated]])
|
||||
apply (force intro!: sbta_cdt_transferable
|
||||
dest: caps_of_state_pres invs_mdb_cte'[THEN mdb_cte_atD[rotated]])
|
||||
apply (blast intro: state_bits_to_policy.intros)
|
||||
apply (subst state_vrefs_eq; fastforce?)
|
||||
apply (force elim!: state_asids_to_policy_aux.cases
|
||||
intro: state_asids_to_policy_aux.intros caps_retype
|
||||
split: cap.split
|
||||
dest: sata_asid[OF caps_retype, rotated])
|
||||
apply clarsimp
|
||||
apply (erule state_irqs_to_policy_aux.cases)
|
||||
apply (solves\<open>auto intro!: sita_controlled intro: caps_retype split: cap.split\<close>)
|
||||
apply (rule domains_of_state)
|
||||
apply simp
|
||||
done
|
||||
|
||||
end
|
||||
|
||||
context Arch begin
|
||||
|
||||
lemma aobjs_of_detype[simp]:
|
||||
"(aobjs_of (detype S s) p = Some aobj) = (p \<notin> S \<and> aobjs_of s p = Some aobj)"
|
||||
by (simp add: in_omonad detype_def)
|
||||
|
||||
lemma pts_of_detype[simp]:
|
||||
"(pts_of (detype S s) p = Some pt) = (p \<notin> S \<and> pts_of s p = Some pt)"
|
||||
by (simp add: in_omonad detype_def)
|
||||
|
||||
lemma ptes_of_detype_Some[simp]:
|
||||
"(ptes_of (detype S s) p = Some pte) = (table_base p \<notin> S \<and> ptes_of s p = Some pte)"
|
||||
by (simp add: in_omonad ptes_of_def detype_def)
|
||||
|
||||
lemma asid_pools_of_detype:
|
||||
"asid_pools_of (detype S s) = (\<lambda>p. if p\<in>S then None else asid_pools_of s p)"
|
||||
by (rule ext) (simp add: detype_def opt_map_def)
|
||||
|
||||
lemma asid_pools_of_detype_Some[simp]:
|
||||
"(asid_pools_of (detype S s) p = Some ap) = (p \<notin> S \<and> asid_pools_of s p = Some ap)"
|
||||
by (simp add: in_omonad detype_def)
|
||||
|
||||
lemma pool_for_asid_detype_Some[simp]:
|
||||
"(pool_for_asid asid (detype S s) = Some p) = (pool_for_asid asid s = Some p)"
|
||||
by (simp add: pool_for_asid_def)
|
||||
|
||||
lemma vspace_for_pool_detype_Some[simp]:
|
||||
"(vspace_for_pool ap asid (\<lambda>p. if p \<in> S then None else pools p) = Some p) =
|
||||
(ap \<notin> S \<and> vspace_for_pool ap asid pools = Some p)"
|
||||
by (simp add: vspace_for_pool_def obind_def split: option.splits)
|
||||
|
||||
lemma vspace_for_asid_detype_Some[simp]:
|
||||
"(vspace_for_asid asid (detype S s) = Some p) =
|
||||
((\<exists>ap. pool_for_asid asid s = Some ap \<and> ap \<notin> S) \<and> vspace_for_asid asid s = Some p)"
|
||||
apply (simp add: vspace_for_asid_def obind_def asid_pools_of_detype split: option.splits)
|
||||
apply (auto simp: pool_for_asid_def)
|
||||
done
|
||||
|
||||
lemma pt_walk_detype:
|
||||
"pt_walk level bot_level pt_ptr vref (ptes_of (detype S s)) = Some (bot_level, p) \<Longrightarrow>
|
||||
pt_walk level bot_level pt_ptr vref (ptes_of s) = Some (bot_level, p)"
|
||||
apply (induct level arbitrary: pt_ptr)
|
||||
apply (subst pt_walk.simps, simp)
|
||||
apply (subst pt_walk.simps)
|
||||
apply (subst (asm) (3) pt_walk.simps)
|
||||
apply (clarsimp simp: in_omonad split: if_split_asm)
|
||||
apply (erule disjE; clarsimp)
|
||||
apply (drule meta_spec, drule (1) meta_mp)
|
||||
apply fastforce
|
||||
done
|
||||
|
||||
lemma vs_lookup_table:
|
||||
"vs_lookup_table level asid vref (detype S s) = Some (level, p) \<Longrightarrow>
|
||||
vs_lookup_table level asid vref s = Some (level, p)"
|
||||
apply (clarsimp simp: vs_lookup_table_def in_omonad obind_def asid_pools_of_detype
|
||||
split: if_split_asm option.split_asm)
|
||||
apply (rule conjI)
|
||||
apply clarsimp
|
||||
apply (subst pt_walk_detype)
|
||||
apply simp
|
||||
apply simp
|
||||
done
|
||||
|
||||
end
|
||||
|
||||
context Arch begin global_naming RISCV64
|
||||
|
||||
named_theorems Retype_AC_assms
|
||||
|
||||
declare retype_region_proofs'.pas_refined[Retype_AC_assms]
|
||||
|
||||
lemma state_vrefs_detype[Retype_AC_assms, dest]:
|
||||
"x \<in> state_vrefs (detype R s) p \<Longrightarrow> x \<in> state_vrefs s p"
|
||||
apply (clarsimp simp: state_vrefs_def)
|
||||
apply (frule vs_lookup_level)
|
||||
apply (drule vs_lookup_table)
|
||||
apply fastforce
|
||||
done
|
||||
|
||||
lemma sata_detype[Retype_AC_assms]:
|
||||
"state_asids_to_policy aag (detype R s) \<subseteq> state_asids_to_policy aag s"
|
||||
apply (clarsimp)
|
||||
apply (erule state_asids_to_policy_aux.induct)
|
||||
apply (auto intro: state_asids_to_policy_aux.intros split: if_split_asm)
|
||||
done
|
||||
|
||||
lemma word_size_bits_untyped_min_bits[Retype_AC_assms]: "word_size_bits \<le> untyped_min_bits"
|
||||
by (simp add: word_size_bits_def untyped_min_bits_def)
|
||||
|
||||
lemma clas_default_cap[Retype_AC_assms]:
|
||||
"tp \<noteq> ArchObject ASIDPoolObj \<Longrightarrow> cap_links_asid_slot aag p (default_cap tp p' sz dev)"
|
||||
unfolding cap_links_asid_slot_def
|
||||
apply (cases tp, simp_all)
|
||||
apply (rename_tac aobject_type)
|
||||
apply (case_tac aobject_type, simp_all add: arch_default_cap_def)
|
||||
done
|
||||
|
||||
lemma cli_default_cap[Retype_AC_assms]:
|
||||
"tp \<noteq> ArchObject ASIDPoolObj \<Longrightarrow> cap_links_irq aag p (default_cap tp p' sz dev)"
|
||||
unfolding cap_links_irq_def
|
||||
apply (cases tp, simp_all)
|
||||
done
|
||||
|
||||
lemma aobj_refs'_default'[Retype_AC_assms]:
|
||||
"is_aligned oref (obj_bits_api (ArchObject tp) sz)
|
||||
\<Longrightarrow> aobj_ref' (arch_default_cap tp oref sz dev) \<subseteq> ptr_range oref (obj_bits_api (ArchObject tp) sz)"
|
||||
by (cases tp; simp add: arch_default_cap_def ptr_range_memI obj_bits_api_def default_arch_object_def)
|
||||
|
||||
crunches init_arch_objects
|
||||
for inv[wp]: P
|
||||
|
||||
lemma region_in_kernel_window_preserved:
|
||||
assumes "\<And>P. f \<lbrace>\<lambda>s. P (arch_state s)\<rbrace>"
|
||||
shows "\<And>S. f \<lbrace>region_in_kernel_window S\<rbrace>"
|
||||
apply (clarsimp simp: valid_def region_in_kernel_window_def)
|
||||
apply (erule use_valid)
|
||||
apply (rule assms)
|
||||
apply fastforce
|
||||
done
|
||||
|
||||
(* proof clagged from Retype_AI.clearMemory_vms *)
|
||||
lemma freeMemory_vms:
|
||||
"valid_machine_state s \<Longrightarrow>
|
||||
\<forall>x\<in>fst (freeMemory ptr bits (machine_state s)). valid_machine_state (s\<lparr>machine_state := snd x\<rparr>)"
|
||||
apply (clarsimp simp: valid_machine_state_def disj_commute[of "in_user_frame p s" for p s])
|
||||
apply (drule_tac x=p in spec, simp)
|
||||
apply (drule_tac P4="\<lambda>m'. underlying_memory m' p = 0"
|
||||
in use_valid[where P=P and Q="\<lambda>_. P" for P], simp_all)
|
||||
apply (simp add: freeMemory_def machine_op_lift_def machine_rest_lift_def split_def)
|
||||
apply (wp hoare_drop_imps | simp | wp mapM_x_wp_inv)+
|
||||
apply (simp add: storeWord_def | wp)+
|
||||
apply (simp add: word_rsplit_0 upto.simps)
|
||||
apply simp
|
||||
done
|
||||
|
||||
lemma dmo_freeMemory_vms:
|
||||
"do_machine_op (freeMemory ptr bits) \<lbrace>valid_machine_state\<rbrace>"
|
||||
apply (unfold do_machine_op_def)
|
||||
apply (wp modify_wp freeMemory_vms | simp add: split_def)+
|
||||
done
|
||||
|
||||
lemma freeMemory_valid_irq_states:
|
||||
"freeMemory ptr bits \<lbrace>\<lambda>ms. valid_irq_states (s\<lparr>machine_state := ms\<rparr>)\<rbrace>"
|
||||
unfolding freeMemory_def
|
||||
by (wp mapM_x_wp[OF _ subset_refl] storeWord_valid_irq_states)
|
||||
|
||||
crunch pspace_respects_device_region[wp]: freeMemory "\<lambda>ms. P (device_state ms)"
|
||||
(wp: crunch_wps)
|
||||
|
||||
lemma dmo_freeMemory_invs[Retype_AC_assms]:
|
||||
"do_machine_op (freeMemory ptr bits) \<lbrace>invs\<rbrace>"
|
||||
apply (simp add: do_machine_op_def invs_def valid_state_def cur_tcb_def | wp | wpc)+
|
||||
apply (clarsimp)
|
||||
apply (frule_tac P1="(=) (device_state (machine_state s))"
|
||||
in use_valid[OF _ freeMemory_pspace_respects_device_region])
|
||||
apply simp
|
||||
apply simp
|
||||
apply (rule conjI)
|
||||
apply (erule use_valid[OF _ freeMemory_valid_irq_states], simp)
|
||||
apply (drule freeMemory_vms)
|
||||
apply auto
|
||||
done
|
||||
|
||||
crunch global_refs[wp]: delete_objects "\<lambda>s. P (global_refs s)"
|
||||
(ignore: do_machine_op freeMemory)
|
||||
|
||||
lemma init_arch_objects_pas_cur_domain[Retype_AC_assms, wp]:
|
||||
"init_arch_objects tp ptr n us refs \<lbrace>pas_cur_domain aag\<rbrace>"
|
||||
by wp
|
||||
|
||||
lemma retype_region_pas_cur_domain[Retype_AC_assms, wp]:
|
||||
"retype_region ptr n us tp dev \<lbrace>pas_cur_domain aag\<rbrace>"
|
||||
by wp
|
||||
|
||||
lemma reset_untyped_cap_pas_cur_domain[Retype_AC_assms, wp]:
|
||||
"reset_untyped_cap src_slot \<lbrace>pas_cur_domain aag\<rbrace>"
|
||||
by wp
|
||||
|
||||
lemma arch_data_to_obj_type_not_ASIDPoolObj[Retype_AC_assms, simp]:
|
||||
"arch_data_to_obj_type v \<noteq> Some ASIDPoolObj"
|
||||
by (clarsimp simp: arch_data_to_obj_type_def)
|
||||
|
||||
lemma data_to_nat_of_nat[Retype_AC_assms, simp]:
|
||||
"of_nat (data_to_nat x) = x"
|
||||
by simp
|
||||
|
||||
lemma nonzero_data_to_nat_simp[Retype_AC_assms]:
|
||||
"0 < data_to_nat x \<Longrightarrow> 0 < x"
|
||||
by (auto dest: word_of_nat_less)
|
||||
|
||||
lemma storeWord_integrity_autarch:
|
||||
"\<lbrace>\<lambda>ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>) \<and>
|
||||
(is_aligned p word_size_bits \<longrightarrow> (\<forall>p' \<in> ptr_range p word_size_bits. is_subject aag p'))\<rbrace>
|
||||
storeWord p v
|
||||
\<lbrace>\<lambda>_ ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>)\<rbrace>"
|
||||
unfolding storeWord_def
|
||||
apply wp
|
||||
apply (auto simp: upto.simps integrity_def is_aligned_mask [symmetric] word_size_bits_def
|
||||
intro!: trm_lrefl ptr_range_memI ptr_range_add_memI)
|
||||
done
|
||||
|
||||
(* TODO: proof has mainly been copied from dmo_clearMemory_respects *)
|
||||
lemma dmo_freeMemory_respects[Retype_AC_assms]:
|
||||
"\<lbrace>integrity aag X st and K (is_aligned ptr bits \<and> bits < word_bits \<and> word_size_bits \<le> bits \<and>
|
||||
(\<forall>p \<in> ptr_range ptr bits. is_subject aag p))\<rbrace>
|
||||
do_machine_op (freeMemory ptr bits)
|
||||
\<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
|
||||
unfolding do_machine_op_def freeMemory_def
|
||||
apply (simp add: split_def)
|
||||
apply wp
|
||||
apply clarsimp
|
||||
apply (erule use_valid)
|
||||
apply (wp mol_respects mapM_x_wp' storeWord_integrity_autarch)
|
||||
apply simp
|
||||
apply (clarsimp simp: word_size_def word_size_bits_def word_bits_def
|
||||
upto_enum_step_shift_red[where us=3, simplified])
|
||||
apply (erule bspec)
|
||||
apply (erule set_mp [rotated])
|
||||
apply (rule ptr_range_subset)
|
||||
apply simp
|
||||
apply (simp add: is_aligned_mult_triv2 [where n = 3, simplified])
|
||||
apply assumption
|
||||
apply (erule word_less_power_trans_ofnat [where k = 3, simplified])
|
||||
apply assumption
|
||||
apply simp
|
||||
apply simp
|
||||
done
|
||||
|
||||
lemma storeWord_respects:
|
||||
"\<lbrace>\<lambda>ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>) \<and>
|
||||
(\<forall>p' \<in> ptr_range p word_size_bits. aag_has_auth_to aag Write p')\<rbrace>
|
||||
storeWord p v
|
||||
\<lbrace>\<lambda>_ ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>)\<rbrace>"
|
||||
unfolding storeWord_def word_size_bits_def
|
||||
apply wp
|
||||
apply (auto simp: upto.simps integrity_def is_aligned_mask [symmetric]
|
||||
intro!: trm_write ptr_range_memI ptr_range_add_memI)
|
||||
done
|
||||
|
||||
lemma dmo_clearMemory_respects'[Retype_AC_assms]:
|
||||
"\<lbrace>integrity aag X st and
|
||||
K (is_aligned ptr bits \<and> bits < word_bits \<and> word_size_bits \<le> bits \<and>
|
||||
(\<forall>p \<in> ptr_range ptr bits. aag_has_auth_to aag Write p))\<rbrace>
|
||||
do_machine_op (clearMemory ptr (2 ^ bits))
|
||||
\<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
|
||||
unfolding do_machine_op_def clearMemory_def
|
||||
apply (simp add: split_def )
|
||||
apply wp
|
||||
apply clarsimp
|
||||
apply (erule use_valid)
|
||||
apply (wp mol_respects mapM_x_wp' storeWord_respects)+
|
||||
apply (simp add: word_size_bits_def)
|
||||
apply (clarsimp simp: word_size_def word_bits_def upto_enum_step_shift_red[where us=3, simplified])
|
||||
apply (erule bspec)
|
||||
apply (erule set_mp [rotated])
|
||||
apply (rule ptr_range_subset)
|
||||
apply simp
|
||||
apply (simp add: is_aligned_mult_triv2 [where n = 3, simplified])
|
||||
apply assumption
|
||||
apply (erule word_less_power_trans_ofnat [where k = 3, simplified])
|
||||
apply assumption
|
||||
apply simp
|
||||
apply simp
|
||||
done
|
||||
|
||||
end
|
||||
|
||||
|
||||
global_interpretation Retype_AC_1?: Retype_AC_1
|
||||
proof goal_cases
|
||||
interpret Arch .
|
||||
case 1 show ?case
|
||||
by (unfold_locales; (fact Retype_AC_assms | wpsimp wp: init_arch_objects_inv)?)
|
||||
qed
|
||||
|
||||
|
||||
context begin interpretation Arch .
|
||||
|
||||
requalify_facts storeWord_respects
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -169,11 +169,11 @@ locale retype_region_proofs' = retype_region_proofs +
|
|||
locale Retype_AC_1 =
|
||||
fixes aag :: "'a PAS"
|
||||
assumes state_vrefs_detype[simp]:
|
||||
"state_vrefs (detype R s) = (\<lambda>x. if x \<in> R then {} else state_vrefs s x)"
|
||||
"x \<in> state_vrefs (detype R s) p \<Longrightarrow> x \<in> state_vrefs s p"
|
||||
and sata_detype:
|
||||
"state_asids_to_policy aag (detype R s) \<subseteq> state_asids_to_policy aag s"
|
||||
and untyped_min_bits_ge_2:
|
||||
"2 \<le> untyped_min_bits"
|
||||
and word_size_bits_untyped_min_bits:
|
||||
"word_size_bits \<le> untyped_min_bits"
|
||||
and clas_default_cap:
|
||||
"\<And>tp. tp \<noteq> ArchObject ASIDPoolObj \<Longrightarrow> cap_links_asid_slot aag l (default_cap tp p sz dev)"
|
||||
and cli_default_cap:
|
||||
|
@ -201,25 +201,19 @@ locale Retype_AC_1 =
|
|||
"\<And>x. of_nat (data_to_nat x) = x"
|
||||
and nonzero_data_to_nat_simp:
|
||||
"\<And>x. 0 < data_to_nat x \<Longrightarrow> 0 < x"
|
||||
and retype_region_proofs_vrefs_eq:
|
||||
"retype_region_proofs s ty us ptr sz n dev
|
||||
\<Longrightarrow> state_vrefs (s\<lparr>kheap := \<lambda>x. if x \<in> set (retype_addrs ptr ty n us)
|
||||
then Some (default_object ty dev us)
|
||||
else kheap s x\<rparr>) =
|
||||
state_vrefs s"
|
||||
and retype_region_proofs'_pas_refined:
|
||||
"\<lbrakk> retype_region_proofs' s ty us ptr sz n dev; invs s; pas_refined aag s \<rbrakk>
|
||||
\<Longrightarrow> pas_refined aag (s\<lparr>kheap := \<lambda>x. if x \<in> set (retype_addrs ptr ty n us)
|
||||
then Some (default_object ty dev us)
|
||||
else kheap s x\<rparr>)"
|
||||
and dmo_freeMemory_respects:
|
||||
"\<lbrace>integrity aag X st and K (is_aligned ptr bits \<and> bits < word_bits \<and> 2 \<le> bits
|
||||
assumes dmo_freeMemory_respects:
|
||||
"\<lbrace>integrity aag X st and K (is_aligned ptr bits \<and> bits < word_bits \<and> word_size_bits \<le> bits
|
||||
\<and> (\<forall>p \<in> ptr_range ptr bits. is_subject aag p))\<rbrace>
|
||||
do_machine_op (freeMemory ptr bits)
|
||||
\<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
|
||||
and dmo_clearMemory_respects':
|
||||
"\<lbrace>integrity aag X st and
|
||||
K (is_aligned ptr bits \<and> bits < word_bits \<and> 2 \<le> bits \<and>
|
||||
K (is_aligned ptr bits \<and> bits < word_bits \<and> word_size_bits \<le> bits \<and>
|
||||
(\<forall>p \<in> ptr_range ptr bits. aag_has_auth_to aag Write p))\<rbrace>
|
||||
do_machine_op (clearMemory ptr (2 ^ bits))
|
||||
\<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
|
||||
|
@ -242,7 +236,8 @@ lemma sta_detype:
|
|||
"state_objs_to_policy (detype R s) \<subseteq> state_objs_to_policy s"
|
||||
apply (clarsimp simp add: state_objs_to_policy_def state_refs_of_detype)
|
||||
apply (erule state_bits_to_policy.induct)
|
||||
apply (auto intro: state_bits_to_policy.intros split: if_split_asm)
|
||||
apply (auto intro: state_bits_to_policy.intros dest: state_vrefs_detype
|
||||
simp: state_objs_to_policy_def split: if_splits)
|
||||
done
|
||||
|
||||
lemma pas_refined_detype:
|
||||
|
@ -252,15 +247,15 @@ lemma pas_refined_detype:
|
|||
done
|
||||
|
||||
lemma delete_objects_respects[wp]:
|
||||
"\<lbrace>integrity aag X st and K (is_aligned ptr bits \<and> bits < word_bits \<and> 2 \<le> bits \<and>
|
||||
(\<forall>p\<in>ptr_range ptr bits. is_subject aag p))\<rbrace>
|
||||
"\<lbrace>\<lambda>s. integrity aag X st s \<and> is_aligned ptr bits \<and> bits < word_bits \<and>
|
||||
word_size_bits \<le> bits \<and> (\<forall>p\<in>ptr_range ptr bits. is_subject aag p)\<rbrace>
|
||||
delete_objects ptr bits
|
||||
\<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
|
||||
apply (simp add: delete_objects_def)
|
||||
apply (rule_tac seq_ext)
|
||||
apply (simp add: delete_objects_def)
|
||||
apply (rule_tac seq_ext)
|
||||
apply (rule hoare_triv[of P _ "%_. P" for P])
|
||||
apply (wp dmo_freeMemory_respects | simp)+
|
||||
by (fastforce simp: ptr_range_def intro!: detype_integrity)
|
||||
by (fastforce simp: ptr_range_def intro!: detype_integrity)
|
||||
|
||||
lemma integrity_work_units_completed_update[simp]:
|
||||
"integrity aag X st (work_units_completed_update f s) = integrity aag X st s"
|
||||
|
@ -272,6 +267,7 @@ lemma integrity_irq_state_independent[intro!, simp]:
|
|||
integrity x y z s"
|
||||
by (simp add: integrity_def)
|
||||
|
||||
(* FIXME AC: shouldn't use word-dependent definitions in a generic context *)
|
||||
lemma reset_untyped_cap_integrity:
|
||||
"\<lbrace>integrity aag X st and pas_refined aag and valid_objs
|
||||
and cte_wp_at is_untyped_cap slot
|
||||
|
@ -292,6 +288,7 @@ lemma reset_untyped_cap_integrity:
|
|||
set_cap_integrity_autarch dmo_clearMemory_respects' | simp)+
|
||||
apply (clarsimp simp: cap_aligned_def is_cap_simps bits_of_def)
|
||||
apply (subst aligned_add_aligned, assumption, rule is_aligned_shiftl, simp+)
|
||||
apply (simp add: word_size_bits_def reset_chunk_bits_def)
|
||||
apply (clarsimp simp: arg_cong2[where f="(\<le>)", OF refl reset_chunk_bits_def])
|
||||
apply (drule bspec, erule subsetD[rotated])
|
||||
apply (simp only: ptr_range_def, rule new_range_subset',
|
||||
|
@ -308,7 +305,7 @@ lemma reset_untyped_cap_integrity:
|
|||
apply (clarsimp simp: cap_aligned_def is_cap_simps valid_cap_simps bits_of_def)
|
||||
apply (frule(2) cap_cur_auth_caps_of_state)
|
||||
apply (clarsimp simp: aag_cap_auth_def ptr_range_def aag_has_Control_iff_owns
|
||||
pas_refined_refl le_trans[OF untyped_min_bits_ge_2])
|
||||
pas_refined_refl le_trans[OF word_size_bits_untyped_min_bits])
|
||||
done
|
||||
|
||||
lemma retype_region_integrity:
|
||||
|
@ -364,7 +361,7 @@ lemma obj_refs_default':
|
|||
by (cases tp; auto simp: ptr_range_memI obj_bits_api_def dest: rev_subsetD[OF _ aobj_refs'_default'])
|
||||
|
||||
lemma create_cap_pas_refined:
|
||||
"\<lbrace>pas_refined aag and
|
||||
"\<lbrace>pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state and
|
||||
K (tp \<noteq> ArchObject ASIDPoolObj \<and> is_subject aag (fst p) \<and> is_subject aag (fst (fst ref)) \<and>
|
||||
(\<forall>x \<in> ptr_range (snd ref) (obj_bits_api tp sz). is_subject aag x) \<and>
|
||||
is_aligned (snd ref) (obj_bits_api tp sz))\<rbrace>
|
||||
|
@ -461,7 +458,7 @@ lemma use_retype_region_proofs_ext':
|
|||
apply (clarsimp simp: retype_addrs_fold
|
||||
foldr_upd_app_if fun_upd_def[symmetric])
|
||||
apply safe
|
||||
apply (rule x)
|
||||
apply (rule x)
|
||||
apply (rule retype_region_proofs.intro, simp_all)[1]
|
||||
apply (fastforce simp: range_cover_def obj_bits_api_def z slot_bits_def2 word_bits_def)+
|
||||
done
|
||||
|
@ -523,31 +520,6 @@ lemma retype_region_pas_refined:
|
|||
apply auto
|
||||
done
|
||||
|
||||
(* FIXME MOVE *)
|
||||
lemma retype_region_aag_bits:
|
||||
"\<lbrace>\<lambda>s :: det_ext state. P (null_filter (caps_of_state s)) (state_refs_of s) (cdt s) (state_vrefs s)
|
||||
\<and> valid_pspace s \<and> valid_mdb s
|
||||
\<and> caps_overlap_reserved {ptr..ptr + of_nat num_objects * 2 ^ obj_bits_api tp us - 1} s
|
||||
\<and> caps_no_overlap ptr sz s \<and> pspace_no_overlap_range_cover ptr sz s
|
||||
\<and> (\<exists>slot. cte_wp_at (\<lambda>c. up_aligned_area ptr sz \<subseteq> cap_range c \<and> cap_is_device c = dev) slot s)
|
||||
\<and> ((tp = CapTableObject \<longrightarrow> 0 < us) \<and> range_cover ptr sz (obj_bits_api tp us) num_objects)\<rbrace>
|
||||
retype_region ptr num_objects us tp dev
|
||||
\<lbrace>\<lambda>_ s. P (null_filter (caps_of_state s)) (state_refs_of s) (cdt s) (state_vrefs s)\<rbrace>"
|
||||
apply (subst conj_assoc [symmetric])+
|
||||
apply (rule hoare_gen_asm [unfolded pred_conj_def K_def])+
|
||||
apply (rule hoare_pre)
|
||||
apply (rule use_retype_region_proofs)
|
||||
apply (frule retype_region_proofs.null_filter, erule ssubst)
|
||||
apply (frule retype_region_proofs.refs_eq, erule ssubst)
|
||||
apply (frule retype_region_proofs_vrefs_eq, erule ssubst)
|
||||
apply (frule retype_region_proofs.mdb_and_revokable, erule ssubst)
|
||||
apply assumption
|
||||
apply simp
|
||||
apply simp
|
||||
apply simp
|
||||
apply blast
|
||||
done
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -939,9 +911,101 @@ lemma delete_objects_pas_refined:
|
|||
apply simp
|
||||
done
|
||||
|
||||
lemma delete_objects_pspace_aligned[wp]:
|
||||
"delete_objects ptr sz \<lbrace>pspace_aligned\<rbrace>"
|
||||
unfolding delete_objects_def do_machine_op_def
|
||||
apply (wp | simp add: split_def detype_machine_state_update_comm)+
|
||||
apply clarsimp
|
||||
apply (auto simp add: detype_def pspace_aligned_def)
|
||||
done
|
||||
|
||||
lemma reset_untyped_cap_pspace_aligned[wp]:
|
||||
"reset_untyped_cap slot \<lbrace>pspace_aligned\<rbrace>"
|
||||
apply (clarsimp simp: reset_untyped_cap_def)
|
||||
apply (wpsimp wp: mapME_x_inv_wp )
|
||||
apply (rule valid_validE)
|
||||
apply (wpsimp wp: preemption_point_inv dxo_wp_weak hoare_drop_imps)+
|
||||
done
|
||||
|
||||
lemma valid_vspace_objs_detype:
|
||||
assumes "invs s"
|
||||
assumes "cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c ptr s
|
||||
\<and> untyped_range c = {p..p + 2 ^ sz - 1}) ptr s"
|
||||
shows "valid_vspace_objs (detype {p..p + 2 ^ sz - 1} s)"
|
||||
proof -
|
||||
obtain c where c_def: "cte_wp_at ((=) c) ptr s \<and> is_untyped_cap c \<and> descendants_range c ptr s
|
||||
\<and> untyped_range c = {p..p + 2 ^ sz - 1}"
|
||||
using assms by (fastforce dest: cte_wp_at_norm)
|
||||
have detype: "detype_locale_arch c ptr s"
|
||||
by unfold_locales (auto simp: assms c_def invs_untyped_children)
|
||||
thus ?thesis
|
||||
using detype_locale_arch.valid_vspace_obj_detype by (fastforce simp: c_def)
|
||||
qed
|
||||
|
||||
lemma delete_objects_valid_vspace_objs:
|
||||
"\<lbrace>\<lambda>s. invs s \<and> (\<exists>ptr. cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c ptr s \<and>
|
||||
untyped_range c = {p..p + 2 ^ sz - 1}) ptr s)\<rbrace>
|
||||
delete_objects p sz
|
||||
\<lbrace>\<lambda>_. valid_vspace_objs\<rbrace>"
|
||||
unfolding delete_objects_def do_machine_op_def
|
||||
apply (wp | simp add: split_def detype_machine_state_update_comm)+
|
||||
apply (auto simp: valid_vspace_objs_detype)
|
||||
done
|
||||
|
||||
lemma reset_untyped_cap_valid_vspace_objs:
|
||||
"\<lbrace>\<lambda>s. invs s \<and> cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c src_slot s) src_slot s\<rbrace>
|
||||
reset_untyped_cap src_slot
|
||||
\<lbrace>\<lambda>_. valid_vspace_objs\<rbrace>"
|
||||
unfolding reset_untyped_cap_def
|
||||
apply (wpsimp wp: mapME_x_inv_wp preemption_point_inv)
|
||||
apply (wp static_imp_wp delete_objects_valid_vspace_objs)
|
||||
apply (wpsimp wp: get_cap_wp)+
|
||||
apply (cases src_slot)
|
||||
apply (auto simp: cte_wp_at_caps_of_state)
|
||||
apply (fastforce simp: bits_of_def is_cap_simps)+
|
||||
done
|
||||
|
||||
lemma valid_arch_state_detype:
|
||||
assumes "invs s"
|
||||
assumes "cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c ptr s
|
||||
\<and> untyped_range c = {p..p + 2 ^ sz - 1}) ptr s"
|
||||
shows "valid_arch_state (detype {p..p + 2 ^ sz - 1} s)"
|
||||
proof -
|
||||
obtain c where c_def: "cte_wp_at ((=) c) ptr s \<and> is_untyped_cap c \<and> descendants_range c ptr s
|
||||
\<and> untyped_range c = {p..p + 2 ^ sz - 1}"
|
||||
using assms by (fastforce dest: cte_wp_at_norm)
|
||||
have detype: "detype_locale_arch c ptr s"
|
||||
by unfold_locales (auto simp: assms c_def invs_untyped_children)
|
||||
thus ?thesis
|
||||
using detype_locale_arch.valid_arch_state_detype by (fastforce simp: c_def)
|
||||
qed
|
||||
|
||||
lemma delete_objects_valid_arch_state:
|
||||
"\<lbrace>\<lambda>s. invs s \<and> (\<exists>ptr. cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c ptr s \<and>
|
||||
untyped_range c = {p..p + 2 ^ sz - 1}) ptr s)\<rbrace>
|
||||
delete_objects p sz
|
||||
\<lbrace>\<lambda>_. valid_arch_state\<rbrace>"
|
||||
unfolding delete_objects_def do_machine_op_def
|
||||
apply (wp | simp add: split_def detype_machine_state_update_comm)+
|
||||
apply (auto simp: valid_arch_state_detype)
|
||||
done
|
||||
|
||||
lemma reset_untyped_cap_valid_arch_state:
|
||||
"\<lbrace>\<lambda>s. invs s \<and> cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c src_slot s) src_slot s\<rbrace>
|
||||
reset_untyped_cap src_slot
|
||||
\<lbrace>\<lambda>_. valid_arch_state\<rbrace>"
|
||||
unfolding reset_untyped_cap_def
|
||||
apply (wpsimp wp: mapME_x_inv_wp preemption_point_inv)
|
||||
apply (wp static_imp_wp delete_objects_valid_arch_state)
|
||||
apply (wpsimp wp: get_cap_wp)+
|
||||
apply (cases src_slot)
|
||||
apply (auto simp: cte_wp_at_caps_of_state)
|
||||
apply (fastforce simp: bits_of_def is_cap_simps)+
|
||||
done
|
||||
|
||||
lemma reset_untyped_cap_pas_refined[wp]:
|
||||
"\<lbrace>pas_refined aag and cte_wp_at is_untyped_cap slot
|
||||
and cte_wp_at (\<lambda>c. fst slot \<notin> untyped_range c) slot
|
||||
"\<lbrace>pas_refined aag and invs and
|
||||
(\<lambda>s. cte_wp_at (\<lambda>c. is_untyped_cap c \<and> descendants_range c slot s) slot s)
|
||||
and K (is_subject aag (fst slot))\<rbrace>
|
||||
reset_untyped_cap slot
|
||||
\<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
|
||||
|
@ -951,7 +1015,8 @@ lemma reset_untyped_cap_pas_refined[wp]:
|
|||
apply (wps | wp set_cap_pas_refined_not_transferable | simp add: unless_def)+
|
||||
apply (rule valid_validE)
|
||||
apply (rule_tac P="is_untyped_cap cap \<and> pas_cap_cur_auth aag cap" in hoare_gen_asm)
|
||||
apply (rule_tac Q="\<lambda>_.cte_wp_at (\<lambda> c. \<not> is_transferable (Some c)) slot and pas_refined aag"
|
||||
apply (rule_tac Q="\<lambda>_. cte_wp_at (\<lambda> c. \<not> is_transferable (Some c)) slot and pas_refined aag and
|
||||
pspace_aligned and valid_vspace_objs and valid_arch_state"
|
||||
in hoare_strengthen_post)
|
||||
apply (rule validE_valid, rule mapME_x_inv_wp)
|
||||
apply (rule hoare_pre)
|
||||
|
@ -960,11 +1025,15 @@ lemma reset_untyped_cap_pas_refined[wp]:
|
|||
| simp)+
|
||||
apply (fastforce simp: is_cap_simps aag_cap_auth_UntypedCap_idx_dev bits_of_def)
|
||||
apply blast
|
||||
apply (wps
|
||||
| wp hoare_vcg_const_imp_lift get_cap_wp delete_objects_pas_refined hoare_drop_imp
|
||||
| simp)+
|
||||
apply (wps | wp hoare_vcg_const_imp_lift get_cap_wp delete_objects_pas_refined hoare_drop_imp
|
||||
delete_objects_valid_vspace_objs delete_objects_valid_arch_state
|
||||
| simp)+
|
||||
apply (clarsimp simp: cte_wp_at_caps_of_state is_cap_simps bits_of_def)
|
||||
apply (frule cte_map_not_null_outside'[rotated])
|
||||
apply (fastforce simp: cte_wp_at_caps_of_state)+
|
||||
apply (cases slot)
|
||||
apply (auto elim: caps_pas_cap_cur_auth_UntypedCap_idx_dev)
|
||||
apply (fastforce simp: bits_of_def is_cap_simps)+
|
||||
done
|
||||
|
||||
lemma invoke_untyped_pas_refined:
|
||||
|
@ -974,7 +1043,8 @@ lemma invoke_untyped_pas_refined:
|
|||
\<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
|
||||
apply (rule hoare_gen_asm)
|
||||
apply (rule hoare_pre)
|
||||
apply (rule_tac Q="\<lambda>_. pas_refined aag and pas_cur_domain aag" in hoare_strengthen_post)
|
||||
apply (rule_tac Q="\<lambda>_. pas_refined aag and pspace_aligned and valid_vspace_objs
|
||||
and valid_arch_state and pas_cur_domain aag" in hoare_strengthen_post)
|
||||
apply (rule invoke_untyped_Q)
|
||||
apply (rule hoare_pre, wp create_cap_pas_refined)
|
||||
apply (clarsimp simp: authorised_untyped_inv_def
|
||||
|
@ -987,40 +1057,43 @@ lemma invoke_untyped_pas_refined:
|
|||
apply (clarsimp simp add: aag_cap_auth_def ptr_range_def[symmetric]
|
||||
pas_refined_all_auth_is_owns)
|
||||
apply blast
|
||||
apply (wp init_arch_objects_pas_refined)
|
||||
apply (wpsimp wp: init_arch_objects_pas_refined init_arch_objects_invs_from_restricted
|
||||
| strengthen invs_psp_aligned invs_vspace_objs invs_arch_state)+
|
||||
apply (clarsimp simp: retype_addrs_aligned_range_cover
|
||||
cte_wp_at_caps_of_state)
|
||||
apply (drule valid_global_refsD[rotated 2])
|
||||
apply (clarsimp simp: post_retype_invs_def split: if_split_asm)
|
||||
apply (erule caps_of_state_cteD)
|
||||
apply (erule notE, erule subsetD[rotated])
|
||||
apply (rule order_trans, erule retype_addrs_subset_ptr_bits)
|
||||
apply (simp add: field_simps word_and_le2)
|
||||
apply (rule context_conjI, clarsimp)
|
||||
apply (drule valid_global_refsD[rotated 2])
|
||||
apply (clarsimp simp: post_retype_invs_def split: if_split_asm)
|
||||
apply (erule caps_of_state_cteD)
|
||||
apply (erule notE, erule subsetD[rotated])
|
||||
apply (rule order_trans, erule retype_addrs_subset_ptr_bits)
|
||||
apply (simp add: field_simps word_and_le2)
|
||||
apply blast
|
||||
apply (rule hoare_name_pre_state, clarsimp)
|
||||
apply (rule hoare_pre, wp retype_region_pas_refined)
|
||||
apply (rule_tac Q="\<lambda>rv. post_retype_invs tp rv and pas_cur_domain aag" in hoare_strengthen_post)
|
||||
apply (wp retype_region_post_retype_invs_spec)
|
||||
apply (clarsimp simp: post_retype_invs_def invs_def valid_state_def valid_pspace_def split: if_splits)
|
||||
apply (clarsimp simp: authorised_untyped_inv_def)
|
||||
apply (strengthen range_cover_le[mk_strg I E], simp)
|
||||
apply (intro conjI exI;
|
||||
(erule cte_wp_at_weakenE)?,
|
||||
clarsimp simp: field_simps word_and_le2)
|
||||
|
||||
apply (intro conjI)
|
||||
apply (intro conjI exI;
|
||||
(erule cte_wp_at_weakenE)?,
|
||||
clarsimp simp: field_simps word_and_le2)
|
||||
apply (clarsimp simp: cte_wp_at_caps_of_state)
|
||||
apply (erule caps_region_kernel_window_imp)
|
||||
apply clarsimp
|
||||
apply clarsimp
|
||||
apply (fastforce simp: word_and_le2)
|
||||
apply (fastforce simp: cte_wp_at_caps_of_state)
|
||||
apply (rule hoare_pre, wp set_cap_pas_refined)
|
||||
apply (clarsimp simp: cte_wp_at_caps_of_state is_cap_simps)
|
||||
apply (cases ui,
|
||||
clarsimp simp: authorised_untyped_inv_def caps_pas_cap_cur_auth_UntypedCap_idx_dev)
|
||||
apply wp
|
||||
apply (wp reset_untyped_cap_valid_vspace_objs reset_untyped_cap_valid_arch_state)
|
||||
apply clarsimp
|
||||
apply (cases ui, clarsimp)
|
||||
(* FIXME CLEAN UP ? *)
|
||||
apply (intro conjI)
|
||||
prefer 2
|
||||
apply (simp add: cte_wp_at_caps_of_state del: untyped_range.simps)
|
||||
apply (rule cte_map_not_null_outside'
|
||||
[where p="(a, b)" and p'="(a, b)" for a b,
|
||||
simplified fst_conv, OF caps_of_state_cteD],
|
||||
assumption)
|
||||
apply (force simp: descendants_range_def
|
||||
cte_wp_at_caps_of_state authorised_untyped_inv_def)+
|
||||
apply (force simp: descendants_range_def cte_wp_at_caps_of_state authorised_untyped_inv_def)
|
||||
done
|
||||
|
||||
end
|
||||
|
@ -1104,7 +1177,7 @@ lemma decode_untyped_invocation_authorised:
|
|||
"\<lambda>rv s. rv \<noteq> ArchObject ASIDPoolObj \<and>
|
||||
(\<forall>cap. cte_wp_at ((=) cap) slot s
|
||||
\<longrightarrow> (\<forall>ref \<in> ptr_range base (bits_of cap). is_subject aag ref)) \<and>
|
||||
is_subject aag (fst slot) \<and> pas_refined aag s \<and> 2 \<le> sz \<and>
|
||||
is_subject aag (fst slot) \<and> pas_refined aag s \<and> word_size_bits \<le> sz \<and>
|
||||
sz < word_bits \<and> is_aligned base sz \<and>
|
||||
(is_cnode_cap (excaps ! 0) \<longrightarrow> (\<forall>x\<in>obj_refs (excaps ! 0). is_subject aag x))"
|
||||
in hoare_post_imp_R)
|
||||
|
@ -1114,7 +1187,7 @@ lemma decode_untyped_invocation_authorised:
|
|||
apply (auto dest!: bang_0_in_set dest: cte_wp_at_eqD2
|
||||
simp: valid_cap_def cap_aligned_def obj_ref_of_def is_cap_simps
|
||||
cap_auth_conferred_def pas_refined_all_auth_is_owns bits_of_UntypedCap
|
||||
aag_cap_auth_def ptr_range_def le_trans[OF untyped_min_bits_ge_2])
|
||||
aag_cap_auth_def ptr_range_def le_trans[OF word_size_bits_untyped_min_bits])
|
||||
done
|
||||
|
||||
end
|
||||
|
|
|
@ -233,20 +233,20 @@ lemma pt_walk_detype:
|
|||
done
|
||||
|
||||
lemma vs_lookup_table:
|
||||
"vs_lookup_table level asid vref (detype (untyped_range cap) s) = Some (level, p) \<Longrightarrow>
|
||||
"vs_lookup_table level asid vref (detype S s) = Some (level, p) \<Longrightarrow>
|
||||
vs_lookup_table level asid vref s = Some (level, p)"
|
||||
by (fastforce simp: vs_lookup_table_def in_omonad asid_pools_of_detype pt_walk_detype
|
||||
split: if_split_asm)
|
||||
|
||||
lemma vs_lookup_slot:
|
||||
"(vs_lookup_slot level asid vref (detype (untyped_range cap) s) = Some (level, p)) ==>
|
||||
"(vs_lookup_slot level asid vref (detype S s) = Some (level, p)) \<Longrightarrow>
|
||||
(vs_lookup_slot level asid vref s = Some (level, p))"
|
||||
by (fastforce simp: vs_lookup_slot_def in_omonad asid_pools_of_detype
|
||||
split: if_split_asm
|
||||
dest!: vs_lookup_table)
|
||||
|
||||
lemma vs_lookup_target:
|
||||
"(vs_lookup_target level asid vref (detype (untyped_range cap) s) = Some (level, p)) ==>
|
||||
"(vs_lookup_target level asid vref (detype S s) = Some (level, p)) \<Longrightarrow>
|
||||
(vs_lookup_target level asid vref s = Some (level, p))"
|
||||
by (fastforce simp: vs_lookup_target_def in_omonad asid_pools_of_detype
|
||||
split: if_split_asm
|
||||
|
|
Loading…
Reference in New Issue