(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *)

theory Retype_AC
imports CNode_AC
begin

context begin interpretation Arch . (*FIXME: arch_split*)

(* put in here that we own the region mentioned in the invocation *)
definition
  authorised_untyped_inv :: "'a PAS \<Rightarrow> Invocations_A.untyped_invocation \<Rightarrow> bool"
where
 "authorised_untyped_inv aag ui \<equiv> case ui of
     Invocations_A.untyped_invocation.Retype src_slot reset base aligned_free_ref new_type obj_sz slots dev \<Rightarrow>
       is_subject aag (fst src_slot) \<and> (0::word32) < of_nat (length slots) \<and>
       (\<forall>x\<in>set (retype_addrs aligned_free_ref new_type (length slots) obj_sz). is_subject aag x) \<and>
       (\<forall>x\<in>{aligned_free_ref..aligned_free_ref + of_nat (length slots)*2^(obj_bits_api new_type obj_sz) - 1}. is_subject aag x) \<and>
       new_type \<noteq> ArchObject ASIDPoolObj \<and>
       (\<forall>x\<in>set slots. is_subject aag (fst x))"

subsection\<open>invoke\<close>

lemma create_cap_integrity:
  "\<lbrace>integrity aag X st and K (is_subject aag (fst (fst ref)))\<rbrace>
     create_cap typ sz untyped_ptr is_device ref
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply (simp add: create_cap_def split_def)
  apply (wp set_cap_integrity_autarch[unfolded pred_conj_def K_def]
            create_cap_extended.list_integ_lift
            create_cap_list_integrity
            set_original_integrity_autarch
              | simp add: set_cdt_def)+
  by (auto simp: integrity_def)

crunch inv[wp]: reserve_region P

lemma mol_respects:
  "\<lbrace>\<lambda>ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>)\<rbrace>
     machine_op_lift mop
   \<lbrace>\<lambda>a b. integrity aag X st (s\<lparr>machine_state := b\<rparr>)\<rbrace>"
  unfolding machine_op_lift_def
  apply (simp add: machine_rest_lift_def split_def)
  apply wp
  apply (clarsimp simp: integrity_def)
  done

lemma ptr_range_memI:
  "is_aligned p n \<Longrightarrow> p \<in> ptr_range p n"
  unfolding ptr_range_def
  apply (erule is_aligned_get_word_bits)
  apply (drule (1) base_member_set)
  apply (simp add: field_simps)
  apply simp
  done

lemma ptr_range_add_memI:
  "\<lbrakk> is_aligned (p :: 'a :: len word) n; k < 2 ^ n \<rbrakk> \<Longrightarrow> (p + k) \<in> ptr_range p n"
  unfolding ptr_range_def
  apply (erule is_aligned_get_word_bits)
  apply clarsimp
  apply (rule conjI)
   apply (erule (1) is_aligned_no_wrap')
  apply (subst p_assoc_help, rule word_plus_mono_right)
  apply simp
  apply (erule is_aligned_no_overflow')
  apply (subgoal_tac "2 ^ n = (0 :: 'a word)")
   apply simp
  apply (simp add: word_bits_conv)
  done

lemma storeWord_integrity_autarch:
  "\<lbrace>\<lambda>ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>) \<and> (is_aligned p 2 \<longrightarrow> (\<forall>p' \<in> ptr_range p 2. is_subject aag p'))\<rbrace> storeWord p v \<lbrace>\<lambda>a b. integrity aag X st (s\<lparr>machine_state := b\<rparr>)\<rbrace>"
  unfolding storeWord_def
  apply wp
  apply (auto simp: integrity_def is_aligned_mask [symmetric] intro!: trm_lrefl ptr_range_memI ptr_range_add_memI)
  done

lemma word_minus_1:
  "x + (0xFFFFFFFF::word32) = x - 1"
  by simp

lemma Suc_0_lt_cases:
  "\<lbrakk>(x = 0 \<Longrightarrow> False); (x = 1 \<Longrightarrow> False)\<rbrakk> \<Longrightarrow> Suc 0 < x"
  apply (rule classical)
  apply (auto simp add: not_less le_Suc_eq)
  done

lemmas upto_enum_step_shift_red =
   upto_enum_step_shift_red[where 'a=32, simplified, simplified word_bits_def[symmetric, simplified]]

lemma clearMemory_respects:
  "\<lbrace>\<lambda> a. integrity aag X st (s\<lparr>machine_state := a\<rparr>) \<and>
         is_aligned ptr sz \<and> sz < word_bits \<and> 2 \<le> sz \<and>
         (\<forall> y\<in>ptr_range ptr sz. is_subject aag y)\<rbrace>
    clearMemory ptr (2 ^ sz)
   \<lbrace>\<lambda>rv a. integrity aag X st (s\<lparr>machine_state := a\<rparr>)\<rbrace>"
  unfolding clearMemory_def
  apply (rule hoare_pre)
   apply (simp add: split_def cleanCacheRange_PoU_def)
   apply wp
   apply (simp add: cleanByVA_PoU_def)
   apply (wp mol_respects)
   apply (rule_tac Q="\<lambda> x ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>) \<and> (\<forall> y\<in> set [ptr , ptr + 4 .e. ptr + of_nat (2 ^ sz) - 1]. (is_aligned y 2 \<longrightarrow> (\<forall> z \<in> ptr_range y 2. is_subject aag z)))" in  hoare_strengthen_post)
    apply(wp mapM_x_wp' storeWord_integrity_autarch | simp add: no_irq_storeWord word_size_def)+
  apply(clarsimp simp: upto_enum_step_shift_red[where us=2, simplified] word_bits_def)
  apply(erule bspec)
  apply(erule subsetD[rotated])
  apply(rule ptr_range_subset)
     apply assumption
    apply(rule is_aligned_mult_triv2[where n=2, simplified])
   apply assumption
  apply (auto simp: word_bits_def
             intro: word_less_power_trans_ofnat[where k=2, simplified])
  done

crunch integrity_autarch: set_pd "integrity aag X st"
  (wp: crunch_wps simp: crunch_simps)

lemma store_pde_integrity:
  "\<lbrace>integrity aag X st and K (is_subject aag (p && ~~ mask pd_bits))\<rbrace>
     store_pde p pde
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply(simp add: store_pde_def)
  apply(wp set_pd_integrity_autarch)
  apply(auto)
  done

(* Borrowed from part of copy_global_mappings_nonempty_table in Untyped_R.thy *)
lemma copy_global_mappings_index_subset:
  "set [kernel_base >> 20.e.2 ^ (pd_bits - 2) - 1] \<subseteq> {x. \<exists>y. x = y >> 20}"
  apply clarsimp
  apply (rule_tac x="x << 20" in exI)
  apply (subst shiftl_shiftr1, simp)
  apply (simp add: word_size)
  apply (rule sym, rule less_mask_eq)
  apply (simp add: word_leq_minus_one_le pd_bits_def pageBits_def)
  done

lemma copy_global_mappings_integrity:
  "is_aligned x pd_bits \<Longrightarrow>
   \<lbrace>integrity aag X st and K (is_subject aag x)\<rbrace>
     copy_global_mappings x
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply (rule hoare_gen_asm)
  apply (simp add: copy_global_mappings_def)
  apply (wp mapM_x_wp[OF _ subset_refl] store_pde_integrity)
    apply (drule subsetD[OF copy_global_mappings_index_subset])
    apply (fastforce simp: pd_shifting')
   apply wpsimp+
  done

lemma dmo_mol_respects:
  "\<lbrace>integrity aag X st\<rbrace> do_machine_op (machine_op_lift mop) \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  unfolding do_machine_op_def
  apply (simp add: split_def)
  apply wp
  apply clarsimp
  apply (erule use_valid)
   apply (wp mol_respects)
  apply simp
  done

lemma dmo_bind_valid:
  "\<lbrace>P\<rbrace> do_machine_op (a >>= b) \<lbrace>Q\<rbrace> = \<lbrace>P\<rbrace> do_machine_op a >>= (\<lambda>rv. do_machine_op (b rv)) \<lbrace>Q\<rbrace>"
  by (fastforce simp: do_machine_op_def gets_def get_def select_f_def modify_def put_def return_def bind_def valid_def)

lemma dmo_bind_valid':
  "\<lbrace>P\<rbrace> a >>= (\<lambda>rv. do_machine_op (b rv >>= c rv)) \<lbrace>Q\<rbrace>
    = \<lbrace>P\<rbrace> a >>= (\<lambda>rv. do_machine_op (b rv) >>= (\<lambda>rv'. do_machine_op (c rv rv'))) \<lbrace>Q\<rbrace>"
  by (fastforce simp: do_machine_op_def gets_def get_def select_f_def modify_def put_def return_def bind_def valid_def)

lemma dmo_mapM_wp:
  assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> do_machine_op (f x) \<lbrace>\<lambda>rv. P\<rbrace>"
  shows      "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> do_machine_op (mapM f xs) \<lbrace>\<lambda>rv. P\<rbrace>"
  apply (induct xs)
   apply (simp add: mapM_def sequence_def)
  apply (simp add: mapM_Cons dmo_bind_valid dmo_bind_valid')
  apply (wpsimp | rule x)+
  done

lemma dmo_mapM_x_wp:
  assumes x: "\<And>x. x \<in> S \<Longrightarrow> \<lbrace>P\<rbrace> do_machine_op (f x) \<lbrace>\<lambda>rv. P\<rbrace>"
  shows      "set xs \<subseteq> S \<Longrightarrow> \<lbrace>P\<rbrace> do_machine_op (mapM_x f xs) \<lbrace>\<lambda>rv. P\<rbrace>"
  apply (subst mapM_x_mapM)
  apply (simp add: do_machine_op_return_foo)
  apply wp
  apply (rule dmo_mapM_wp)
   apply (rule x)
   apply assumption+
  done

lemmas dmo_mapM_x_wp_inv = dmo_mapM_x_wp[where S=UNIV, simplified]

lemma dmo_cacheRangeOp_lift:
  "(\<And>a b. \<lbrace>P\<rbrace> do_machine_op (oper a b) \<lbrace>\<lambda>_. P\<rbrace>)
    \<Longrightarrow> \<lbrace>P\<rbrace> do_machine_op (cacheRangeOp oper x y z) \<lbrace>\<lambda>_. P\<rbrace>"
  apply (simp add: cacheRangeOp_def)
  apply (wp dmo_mapM_x_wp_inv)
   apply (simp add: split_def)+
  done

lemma dmo_cleanCacheRange_PoU_respects [wp]:
  "\<lbrace>integrity aag X st\<rbrace> do_machine_op (cleanCacheRange_PoU vstart vend pstart) \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  by (simp add: cleanCacheRange_PoU_def cleanByVA_PoU_def | wp dmo_cacheRangeOp_lift dmo_mol_respects)+

lemma dmo_mapM_x_cleanCacheRange_PoU_integrity:
     "\<lbrace>integrity aag X st\<rbrace>
      do_machine_op
           (mapM_x (\<lambda>x. cleanCacheRange_PoU (f x) (g x) (h x)) refs)
       \<lbrace>\<lambda>_. integrity aag X st\<rbrace>"
  by (wp dmo_mapM_x_wp_inv)

definition word_object_size :: "apiobject_type \<Rightarrow> nat" where
  "word_object_size aobject_type \<equiv>
    (case aobject_type of
         (ArchObject SmallPageObj) \<Rightarrow> 12 |
         (ArchObject LargePageObj) \<Rightarrow> 16 |
         (ArchObject SectionObj) \<Rightarrow> 20 |
         (ArchObject SuperSectionObj) \<Rightarrow> 24)"

lemma init_arch_objects_integrity:
  "\<lbrace>integrity aag X st and
    K (\<forall> x\<in>set refs. is_subject aag x) and
    K (\<forall>ref \<in> set refs. is_aligned ref (obj_bits_api new_type obj_sz))\<rbrace>
     init_arch_objects new_type ptr num_objects obj_sz refs
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply(rule hoare_gen_asm)+
  apply(cases new_type)
  apply(simp_all add: init_arch_objects_def split del: if_split)
  apply(rule hoare_pre)
   apply(wpc
        | wp  mapM_x_wp[OF _ subset_refl]
             copy_global_mappings_integrity dmo_mapM_x_cleanCacheRange_PoU_integrity
        | simp add: obj_bits_api_def default_arch_object_def pd_bits_def pageBits_def)+
  done

lemma foldr_upd_app_if': "foldr (\<lambda>p ps. ps(p := f p)) as g = (\<lambda>x. if x \<in> set as then (f x) else g x)"
  apply (induct as)
   apply simp
  apply simp
  apply (rule ext)
  apply simp
  done

lemma retype_region_integrity:
  "\<lbrace>integrity aag X st and
       K (range_cover ptr sz (obj_bits_api type o_bits) num_objects \<and>
          (\<forall>x\<in>{ptr..(ptr && ~~ mask sz) + (2 ^ sz - 1)}. is_subject aag x))\<rbrace>
     retype_region ptr num_objects o_bits type dev
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply (rule hoare_gen_asm)+
  apply (simp only: retype_region_def retype_region_ext_extended.dxo_eq)
  apply (simp only: retype_addrs_def  retype_region_ext_def
                    foldr_upd_app_if' fun_app_def K_bind_def)
  apply wp
  apply (clarsimp simp: not_less)
  apply (erule integrity_trans)
  apply (clarsimp simp add: integrity_def)
  apply(fastforce intro: tro_lrefl tre_lrefl
                   dest: retype_addrs_subset_ptr_bits[simplified retype_addrs_def]
                   simp: image_def p_assoc_help power_sub integrity_def)
  done

lemma retype_region_ret_is_subject:
  "\<lbrace>K (range_cover ptr sz (obj_bits_api tp us) num_objects \<and>
       (\<forall>x\<in>{ptr..(ptr && ~~ mask sz) + (2 ^ sz - 1)}. is_subject aag x))\<rbrace>
   retype_region ptr num_objects us tp dev
   \<lbrace>\<lambda>rv. K (\<forall> ref \<in> set rv. is_subject aag ref)\<rbrace>"
  apply(rule hoare_gen_asm2 | rule hoare_gen_asm)+
  apply(rule hoare_strengthen_post)
   apply(rule retype_region_ret)
  apply(simp only: K_def)
  apply(rule ballI)
  apply(elim conjE)
  apply(erule bspec)
  apply(rule rev_subsetD, assumption)
  apply(simp add: p_assoc_help del: set_map)
  apply(rule retype_addrs_subset_ptr_bits[simplified retype_addrs_def])
  apply simp
  done

lemma retype_region_ret_pd_aligned:
  "\<lbrace>K (range_cover ptr sz (obj_bits_api tp us) num_objects)\<rbrace>
   retype_region ptr num_objects us tp dev
   \<lbrace>\<lambda>rv. K (\<forall> ref \<in> set rv. tp = ArchObject PageDirectoryObj \<longrightarrow> is_aligned ref pd_bits)\<rbrace>"
  apply(rule hoare_strengthen_post)
  apply(rule hoare_weaken_pre)
  apply(rule retype_region_aligned_for_init)
   apply simp
  apply (clarsimp simp: obj_bits_api_def default_arch_object_def pd_bits_def pageBits_def)
  done

declare wrap_ext_det_ext_ext_def[simp]

lemma detype_integrity:
  "\<lbrakk>integrity aag X st s; (\<forall> r\<in>refs. is_subject aag r)\<rbrakk> \<Longrightarrow>
    integrity aag X st (detype refs s)"
  apply (erule integrity_trans)
  by (auto simp: detype_def detype_ext_def integrity_def)

lemma state_vrefs_detype [simp]:
  "state_vrefs (detype R s) = (\<lambda>x. if x \<in> R then {} else state_vrefs s x)"
  unfolding state_vrefs_def
  apply (rule ext)
  apply (clarsimp simp: detype_def)
  done

lemma global_refs_detype [simp]:
  "global_refs (detype R s) = global_refs s"
  by(simp add: detype_def)

lemma thread_states_detype[simp]:
  "thread_states (detype S s) = (\<lambda>x. if x \<in> S then {} else thread_states s x)"
  by (rule ext, simp add: thread_states_def get_tcb_def  o_def detype_def tcb_states_of_state_def)

lemma thread_bound_ntfns_detype[simp]:
  "thread_bound_ntfns (detype S s) = (\<lambda>x. if x \<in> S then None else thread_bound_ntfns s x)"
  by (rule ext, simp add: thread_bound_ntfns_def get_tcb_def  o_def detype_def tcb_states_of_state_def)

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)
  done

lemma sita_detype:
  "state_irqs_to_policy aag (detype R s) \<subseteq> state_irqs_to_policy aag s"
  apply (clarsimp)
  apply (erule state_irqs_to_policy_aux.induct)
  apply (auto simp: detype_def  intro: state_irqs_to_policy_aux.intros split: if_split_asm)
  done

lemma sata_detype:
  "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

(* FIXME: move *)
lemmas pas_refined_by_subsets = pas_refined_state_objs_to_policy_subset

lemma detype_irqs [simp]:
  "interrupt_irq_node (detype R s) = interrupt_irq_node s"
  unfolding detype_def by simp

lemma dtsa_detype: "domains_of_state (detype R s) \<subseteq> domains_of_state s"
by (auto simp: detype_def detype_ext_def
        intro: domtcbs
        elim!: domains_of_state_aux.cases
        split: if_splits)

lemma pas_refined_detype:
  "pas_refined aag s \<Longrightarrow> pas_refined aag (detype R s)"
  apply (rule pas_refined_by_subsets)
  apply (blast intro!: sta_detype sata_detype sita_detype detype_irqs dtsa_detype)+
  done

(* TODO: proof has mainly been copied from dmo_clearMemory_respects *)
lemma dmo_freeMemory_respects:
  "\<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>
   do_machine_op (freeMemory ptr bits) \<lbrace>\<lambda>rv. 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_bits_def upto_enum_step_shift_red [where us=2, 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 = 2, simplified])
    apply assumption
   apply (erule word_less_power_trans_ofnat [where k = 2, simplified])
    apply assumption
   apply simp
  apply simp
  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>
   delete_objects ptr bits
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
   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)

lemma storeWord_respects:
  "\<lbrace>\<lambda>ms. integrity aag X st (s\<lparr>machine_state := ms\<rparr>)
    \<and> (\<forall>p' \<in> ptr_range p 2. aag_has_auth_to aag Write p')\<rbrace>
     storeWord p v
   \<lbrace>\<lambda>a b. integrity aag X st (s\<lparr>machine_state := b\<rparr>)\<rbrace>"
  unfolding storeWord_def
  apply wp
  apply (auto simp: integrity_def is_aligned_mask [symmetric]
            intro!: trm_write ptr_range_memI ptr_range_add_memI)
  done

lemma dmo_clearMemory_respects':
  "\<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. aag_has_auth_to aag Write p))\<rbrace>
  do_machine_op (clearMemory ptr (2 ^ bits))
  \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  unfolding do_machine_op_def clearMemory_def
  apply (simp add: split_def cleanCacheRange_PoU_def)
  apply wp
  apply clarsimp
  apply (erule use_valid)
   apply wp
    apply (simp add: cleanByVA_PoU_def)
    apply (wp mol_respects mapM_x_wp' storeWord_respects)+
   apply simp
   apply (clarsimp simp add: word_size_def word_bits_def upto_enum_step_shift_red[where us=2, 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 = 2, simplified])
    apply assumption
   apply (erule word_less_power_trans_ofnat [where k = 2, simplified])
    apply assumption
   apply simp
  apply simp
  done

lemma integrity_work_units_completed_update[simp]:
  "integrity aag X st (work_units_completed_update f s) = integrity aag X st s"
  by (simp add: integrity_def)

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
      and K (is_subject aag (fst slot))\<rbrace>
     reset_untyped_cap slot
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply (rule hoare_gen_asm)
  apply (simp add: reset_untyped_cap_def)
  apply (rule hoare_pre)
   apply (wp set_cap_integrity_autarch dmo_clearMemory_respects'
         | simp add: unless_def)+
     apply (rule valid_validE, rule_tac P="cap_aligned cap \<and> is_untyped_cap cap
           \<and> (\<forall>r \<in> cap_range cap. aag_has_auth_to aag Write r)" in hoare_gen_asm)
     apply (rule validE_valid, rule mapME_x_wp')
     apply (rule hoare_pre)
      apply (wp mapME_x_inv_wp[OF hoare_pre(2)]  preemption_point_inv'
                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 (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',
        simp_all add: is_aligned_shiftl)[1]
      apply (rule shiftl_less_t2n)
       apply (rule word_of_nat_less)
       apply simp
      apply (simp add: word_bits_def)
     apply clarsimp
    apply (simp add: if_apply_def2)
    apply (wp hoare_vcg_const_imp_lift get_cap_wp)+
  apply (clarsimp simp: cte_wp_at_caps_of_state)
  apply (frule caps_of_state_valid_cap, clarsimp+)
  apply (clarsimp simp: cap_aligned_def is_cap_simps valid_cap_simps bits_of_def
                        untyped_min_bits_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)
  done

lemma bool_enum[simp]: "(\<forall>x. d = (\<not> x)) = False" "(\<forall>x. d = x) = False"
  by blast+

lemma invoke_untyped_integrity:
  "\<lbrace>integrity aag X st and pas_refined aag
        and valid_objs
        and valid_untyped_inv ui and K (authorised_untyped_inv aag ui)\<rbrace>
     invoke_untyped ui
   \<lbrace>\<lambda>rv. integrity aag X st\<rbrace>"
  apply (rule hoare_name_pre_state)
  apply (clarsimp simp only: valid_untyped_inv_wcap)
  apply (cases ui)
  apply (simp add: mapM_x_def[symmetric] authorised_untyped_inv_def
                   invoke_untyped_def)
  apply (rule hoare_pre)
   apply (wp mapM_x_wp[OF _ subset_refl] create_cap_integrity
             init_arch_objects_integrity retype_region_integrity
             retype_region_ret_is_subject retype_region_ret_pd_aligned
             set_cap_integrity_autarch hoare_vcg_if_lift
             hoare_whenE_wp reset_untyped_cap_integrity
         | clarsimp simp: split_paired_Ball
         | erule in_set_zipE
         | blast)+
  apply (clarsimp simp: is_aligned_neg_mask_eq
                        ptr_range_def p_assoc_help bits_of_def
                        cte_wp_at_caps_of_state)
  apply (frule(1) cap_cur_auth_caps_of_state, simp+)
  apply (clarsimp simp: aag_cap_auth_def pas_refined_all_auth_is_owns)
  apply (simp add: word_and_le2 field_simps
        | erule ball_subset[where A="{a && c .. b}" for a b c]
        | rule conjI impI)+
  done

lemma clas_default_cap:
  "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:
  "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 obj_refs_default_nut:
  "\<lbrakk> tp \<noteq> Untyped; \<forall>atp. tp \<noteq> ArchObject atp \<rbrakk> \<Longrightarrow>
  obj_refs (default_cap tp oref sz dev) = {oref}"
  by (cases tp, simp_all add: arch_default_cap_def  split: aobject_type.splits)

lemma obj_refs_default':
  "is_aligned oref (obj_bits_api tp sz) \<Longrightarrow> obj_refs (default_cap tp oref sz dev) \<subseteq> ptr_range oref (obj_bits_api tp sz)"
  by (cases tp, simp_all add: arch_default_cap_def ptr_range_memI obj_bits_api_def default_arch_object_def split: aobject_type.splits)

lemma create_cap_pas_refined:
  "\<lbrace>pas_refined aag 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>
     create_cap tp sz p dev ref
   \<lbrace>\<lambda>rv. pas_refined aag\<rbrace>"
  apply (simp add: create_cap_def split_def)
  apply (wps | wp set_cdt_pas_refined set_cap_pas_refined set_original_wp | clarsimp)+
  apply (rule conjI)
   apply (cases "fst ref", clarsimp simp: pas_refined_refl)
  apply (cases "tp = Untyped")
   apply (simp add: cap_links_asid_slot_def pas_refined_refl cap_links_irq_def aag_cap_auth_def ptr_range_def obj_bits_api_def)
  apply (clarsimp simp add:  obj_refs_default_nut clas_default_cap pas_refined_refl cli_default_cap aag_cap_auth_def)
  apply (drule obj_refs_default')
  apply (case_tac tp, simp_all)
  apply (auto intro: pas_refined_refl dest!: subsetD)
  done

lemma pd_shifting_dual':
  "is_aligned (pd::word32) pd_bits \<Longrightarrow>
  pd + (vptr >> 20 << 2) && mask pd_bits = vptr >> 20 << 2"
  apply (subst (asm) pd_bits_def)
  apply (subst (asm) pageBits_def)
  apply (simp add: pd_shifting_dual)
  done

lemma empty_table_update_from_arm_global_pts:
  "\<lbrakk>valid_global_objs s;
    kernel_base >> 20 \<le> y >> 20; y >> 20 \<le> 2 ^ (pd_bits - 2) - 1;
    is_aligned pd pd_bits;
    kheap s (arm_global_pd (arch_state s)) = Some (ArchObj (PageDirectory pda));
    obj_at (empty_table (set (second_level_tables (arch_state s)))) pd s\<rbrakk>
   \<Longrightarrow>
   (\<forall>pdb. ko_at (ArchObj (PageDirectory pdb)) pd s \<longrightarrow>
       empty_table (set (second_level_tables (arch_state s)))
                   (ArchObj
                     (PageDirectory
                       (pdb(ucast (y >> 20) := pda (ucast (y >> 20)))))))"
  apply(clarsimp simp: empty_table_def obj_at_def)
  apply(clarsimp simp: valid_global_objs_def obj_at_def empty_table_def)
  done

lemma copy_global_mappings_pas_refined:
  "is_aligned pd pd_bits \<Longrightarrow>
   \<lbrace>pas_refined aag and valid_kernel_mappings and
     valid_arch_state and valid_global_objs and valid_global_refs and
     pspace_aligned\<rbrace>
     copy_global_mappings pd
   \<lbrace>\<lambda>rv. pas_refined aag\<rbrace>"
  apply(simp add: copy_global_mappings_def)
  apply(rule hoare_weaken_pre)
  apply(wp)
  (* Use \<circ> to avoid wp filtering out the global_pd condition here
     TODO: see if we can clean this up *)
  apply(rule_tac Q="\<lambda> rv s. is_aligned global_pd pd_bits \<and> (global_pd = (arm_global_pd \<circ> arch_state) s \<and> valid_kernel_mappings s \<and> valid_arch_state s \<and> valid_global_objs s \<and> valid_global_refs s \<and> pas_refined aag s)" in hoare_strengthen_post)
  apply(rule mapM_x_wp[OF _ subset_refl])
    apply (rule hoare_seq_ext)
     apply(unfold o_def)
     (* Use [1] so wp doesn't filter out the global_pd condition *)
     apply(wp store_pde_pas_refined store_pde_valid_kernel_mappings_map_global)[1]
     apply(frule subsetD[OF copy_global_mappings_index_subset])
     apply(rule hoare_gen_asm[simplified K_def pred_conj_def conj_commute])
     apply(simp add: get_pde_def)
     apply(subst kernel_vsrefs_kernel_mapping_slots[symmetric])
     apply(wp)
     apply(clarsimp simp: get_pde_def pd_shifting' pd_shifting_dual' triple_shift_fun)
     apply(subst (asm) obj_at_def, erule exE, erule conjE)
     apply(rotate_tac -1, drule sym, simp)
     apply(frule (1) valid_kernel_mappingsD[folded obj_at_def])
     apply(clarsimp simp: kernel_mapping_slots_def shiftr_20_less
                          empty_table_update_from_arm_global_pts
                          global_refs_def pde_ref_def)
     apply(fastforce)
    apply fastforce
   apply(rule gets_wp)
  apply(simp, blast intro: invs_aligned_pdD)
  done

lemma copy_global_invs_mappings_restricted':
  "pd \<in> S \<Longrightarrow>
   \<lbrace>all_invs_but_equal_kernel_mappings_restricted S
    and (\<lambda>s. S \<inter> global_refs s = {})
    and K (is_aligned pd pd_bits)\<rbrace>
    copy_global_mappings pd
   \<lbrace>\<lambda>rv. all_invs_but_equal_kernel_mappings_restricted S\<rbrace>"
  apply(rule hoare_weaken_pre)
  apply(rule copy_global_invs_mappings_restricted)
  apply(simp add: insert_absorb)
  done

lemma init_arch_objects_pas_refined:
  "\<lbrace>pas_refined aag and
    post_retype_invs tp refs and
    (\<lambda> s. \<forall> x\<in>set refs. x \<notin> global_refs s) and
    K (\<forall>ref \<in> set refs. is_aligned ref (obj_bits_api tp obj_sz))\<rbrace>
     init_arch_objects tp ptr bits obj_sz refs
   \<lbrace>\<lambda>rv. pas_refined aag\<rbrace>"
  apply(rule hoare_gen_asm)
  apply(cases tp)
       apply(simp_all add: init_arch_objects_def)
       apply(wp | simp)+
  apply(rename_tac aobject_type)
  apply(case_tac aobject_type, simp_all)
        apply((simp | wp)+)[5]
   apply(wp)
    apply(rule_tac Q="\<lambda> rv. pas_refined aag and all_invs_but_equal_kernel_mappings_restricted (set refs) and (\<lambda> s. \<forall> x\<in>set refs. x \<notin> global_refs s)" in hoare_strengthen_post)
     apply(wp mapM_x_wp[OF _ subset_refl])
     apply((wp copy_global_mappings_pas_refined
               copy_global_invs_mappings_restricted'
               copy_global_mappings_global_refs_inv
               copy_global_invs_mappings_restricted' |
            fastforce simp: obj_bits_api_def default_arch_object_def
                            pd_bits_def pageBits_def)+)[2]
   apply(wp dmo_invs hoare_vcg_const_Ball_lift
            valid_irq_node_typ |
         fastforce simp: post_retype_invs_def)+
  done

end

locale retype_region_proofs' = retype_region_proofs + constrains s ::"det_ext state" and s' :: "det_ext state"

context retype_region_proofs
begin

interpretation Arch . (*FIXME; arch_split*)

lemma vs_refs_no_global_pts_default [simp]:
  "vs_refs_no_global_pts (default_object ty dev us) = {}"
  by (simp add: default_object_def default_arch_object_def tyunt
                vs_refs_no_global_pts_def pde_ref2_def pte_ref_def
                o_def
           split: Structures_A.apiobject_type.splits aobject_type.splits)

lemma vrefs_eq: "state_vrefs s' = state_vrefs s"
  apply(rule ext)
  apply(simp add: s'_def state_vrefs_def ps_def orthr split: option.split)
  done

lemma ts_eq[simp]: "thread_states s' = thread_states s"
  apply (rule ext)
  apply (simp add: s'_def ps_def thread_states_def get_tcb_def orthr tcb_states_of_state_def
            split: option.split Structures_A.kernel_object.split)
  apply (simp add: default_object_def default_tcb_def tyunt
            split: Structures_A.apiobject_type.split)
  done

lemma bas_eq[simp]: "thread_bound_ntfns s' = thread_bound_ntfns s"
  apply (rule ext)
  apply (simp add: s'_def ps_def thread_bound_ntfns_def get_tcb_def orthr tcb_states_of_state_def
            split: option.split Structures_A.kernel_object.split)
  apply (simp add: default_object_def default_tcb_def tyunt
            split: Structures_A.apiobject_type.split)
  done
end

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 . (*FIXME; arch_split*)

lemma domains_of_state: "domains_of_state s' \<subseteq> domains_of_state s"
  unfolding s'_def by simp

(* FIXME MOVE next to cte_at_pres *)
lemma cte_wp_at_pres:
  "cte_wp_at P p s \<Longrightarrow> cte_wp_at P p s'"
  unfolding cte_wp_at_cases s'_def ps_def
  apply (erule disjE)
   apply (clarsimp simp: well_formed_cnode_n_def orthr)+
  done

(* FIXME MOVE next to cte_at_pres *)
lemma caps_of_state_pres:
  "caps_of_state s p = Some cap \<Longrightarrow> caps_of_state s' p = Some cap"
  using cte_wp_at_pres by (simp add: F)

lemma pas_refined: "invs s \<Longrightarrow> pas_refined aag s \<Longrightarrow> pas_refined aag s'"
  apply(erule pas_refined_state_objs_to_policy_subset)
     apply(simp add: state_objs_to_policy_def refs_eq vrefs_eq mdb_and_revokable)
     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 (simp add: vrefs_eq)
      apply (blast intro: state_bits_to_policy.intros)
     apply (simp add: vrefs_eq)
     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 begin interpretation Arch . (*FIXME: arch_split*)

lemma retype_region_ext_kheap_update:
  "\<lbrace>Q xs and R xs\<rbrace> retype_region_ext xs ty \<lbrace>\<lambda>_. Q xs\<rbrace>
  \<Longrightarrow> \<lbrace>\<lambda>s. Q xs (kheap_update f s) \<and> R xs (kheap_update f s)\<rbrace> retype_region_ext xs ty \<lbrace>\<lambda>_ s. Q xs (kheap_update f s)\<rbrace>"
  apply (clarsimp simp: valid_def retype_region_ext_def)
  apply (erule_tac x="kheap_update f s" in allE)
  apply (clarsimp simp: split_def bind_def gets_def get_def return_def modify_def put_def)
  done

lemma use_retype_region_proofs_ext':
  assumes x: "\<And>(s::det_ext state). \<lbrakk> retype_region_proofs s ty us ptr sz n dev; P s \<rbrakk>
   \<Longrightarrow> Q (retype_addrs ptr ty n us) (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>)"
  assumes y: "\<And>xs. \<lbrace>Q xs and R xs\<rbrace> retype_region_ext xs ty \<lbrace>\<lambda>_. Q xs\<rbrace>"
  assumes z: "\<And>f xs s. R xs (kheap_update f s) = R xs s"
  shows
    "\<lbrakk> ty = CapTableObject \<Longrightarrow> 0 < us;
         \<And>s. P s \<Longrightarrow> Q (retype_addrs ptr ty n us) s \<rbrakk> \<Longrightarrow>
    \<lbrace>\<lambda>s. valid_pspace s \<and> valid_mdb s \<and> range_cover ptr sz (obj_bits_api ty us) n
        \<and> caps_overlap_reserved {ptr..ptr + of_nat n * 2 ^ obj_bits_api ty 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>
        P s \<and> R (retype_addrs ptr ty n us) s\<rbrace> retype_region ptr n us ty dev \<lbrace>Q\<rbrace>"
  apply (simp add: retype_region_def split del: if_split)
  apply (rule hoare_pre, (wp|simp)+)
    apply (rule retype_region_ext_kheap_update[OF y])
   apply (wp|simp)+
  apply (clarsimp simp: retype_addrs_fold
                        foldr_upd_app_if fun_upd_def[symmetric])
  apply safe
  apply (rule x)
   apply (rule retype_region_proofs.intro, simp_all)[1]
   apply (fastforce simp add: range_cover_def obj_bits_api_def z
     slot_bits_def word_bits_def cte_level_bits_def)+
   done

lemmas use_retype_region_proofs_ext
    = use_retype_region_proofs_ext'[where Q="\<lambda>_. Q" and P=Q, simplified] for Q

end

lemma (in is_extended) pas_refined_tcb_domain_map_wellformed':
  assumes tdmw: "\<lbrace>tcb_domain_map_wellformed aag and P\<rbrace> f \<lbrace>\<lambda>_. tcb_domain_map_wellformed aag\<rbrace>"
  shows "\<lbrace>pas_refined aag and P\<rbrace> f \<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
apply (simp add: pas_refined_def)
apply (wp tdmw)
apply (wp lift_inv)
apply simp+
done

context begin interpretation Arch . (*FIXME: arch_split*)

lemma retype_region_ext_pas_refined:
  "\<lbrace>pas_refined aag and pas_cur_domain aag and K (\<forall>x\<in> set xs. is_subject aag x)\<rbrace> retype_region_ext xs ty \<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
  including no_pre
  apply (subst and_assoc[symmetric])
  apply (wp retype_region_ext_extended.pas_refined_tcb_domain_map_wellformed')
  apply (simp add: retype_region_ext_def, wp)
  apply (clarsimp simp: tcb_domain_map_wellformed_aux_def)
  apply (erule domains_of_state_aux.cases)
  apply (clarsimp simp: foldr_upd_app_if' fun_upd_def[symmetric] split: if_split_asm)
   apply (clarsimp simp: default_ext_def default_etcb_def split: apiobject_type.splits)
   defer
  apply (force intro: domtcbs)
  done

lemma retype_region_pas_refined:
  "\<lbrace>pas_refined aag and invs and pas_cur_domain aag and
    caps_overlap_reserved
            {ptr..ptr + of_nat num_objects * 2 ^ obj_bits_api type o_bits -
                  1} and
    caps_no_overlap ptr sz and pspace_no_overlap_range_cover ptr sz and
    (\<lambda>s. \<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
    K (range_cover ptr sz (obj_bits_api type o_bits) num_objects) and
    K (\<forall>x\<in>set (retype_addrs ptr type num_objects o_bits). is_subject aag x) and
    K ((type = CapTableObject \<longrightarrow> 0 < o_bits))\<rbrace>
     retype_region ptr num_objects o_bits type dev
   \<lbrace>\<lambda>rv. pas_refined aag\<rbrace>"
  apply (rule hoare_gen_asm)
  apply (rule hoare_pre)
   apply (rule use_retype_region_proofs_ext'[where P = "invs and pas_refined aag"])
       apply clarsimp
       apply (erule (2) retype_region_proofs'.pas_refined[OF retype_region_proofs'.intro])
      apply (wp retype_region_ext_pas_refined)
      apply simp
     apply auto
  done

(* FIXME MOVE *)
lemma retype_region_aag_bits:
  "\<lbrace>\<lambda>s. 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

lemma retype_region_ranges'':
  "\<lbrace>K (range_cover ptr sz (obj_bits_api tp us) num_objects \<and> num_objects \<noteq> 0)\<rbrace>
  retype_region ptr num_objects us tp dev
   \<lbrace>\<lambda>rv s. \<forall>y\<in>set rv. ptr_range y (obj_bits_api tp us) \<subseteq> {ptr..ptr + of_nat num_objects * 2 ^ (obj_bits_api tp us) - 1}\<rbrace>"
  apply simp
  apply (rule hoare_gen_asm[where P'="\<top>", simplified])
  apply (rule hoare_strengthen_post [OF retype_region_ret])
  apply (clarsimp)
  apply (frule_tac p=y in range_cover_subset)
    apply assumption
   apply simp
  apply(rule conjI)
   apply (fastforce simp: ptr_range_def ptr_add_def)
  apply(clarsimp simp: ptr_range_def ptr_add_def intro: order_trans)
  apply(erule order_trans)
  apply(erule impE)
   apply(simp add: p_assoc_help)
   apply(rule is_aligned_no_wrap')
    apply(rule is_aligned_add)
     apply(fastforce simp: range_cover_def)
    apply(simp add: is_aligned_mult_triv2)
   apply(rule word_leq_le_minus_one, simp)
   apply(rule power_not_zero)
   apply(simp add: range_cover_def)
  apply simp
  done

lemma region_in_kernel_window_preserved:
  assumes "\<And> P. \<lbrace>\<lambda> s. P (arch_state s) \<rbrace> f \<lbrace>\<lambda> rv s. P (arch_state s) \<rbrace>"
  shows "\<And> S. \<lbrace> region_in_kernel_window S \<rbrace> f \<lbrace> \<lambda>_. region_in_kernel_window S \<rbrace>"
  apply(clarsimp simp: valid_def region_in_kernel_window_def)
  apply(erule use_valid)
  apply(rule assms)
  apply simp
  done

lemma pspace_no_overlap_msu[simp]:
  "pspace_no_overlap S (machine_state_update f s) = pspace_no_overlap S s"
  apply(clarsimp simp: pspace_no_overlap_def)
  done

lemma descendants_range_in_msu[simp]:
  "descendants_range_in S slot (machine_state_update f s) = descendants_range_in S slot s"
  apply(clarsimp simp: descendants_range_in_def)
  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)+
  done

lemma dmo_freeMemory_vms:
  "\<lbrace>valid_machine_state\<rbrace>
     do_machine_op (freeMemory ptr bits)
   \<lbrace>\<lambda>_. 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:
  "\<lbrace>\<lambda>m. valid_irq_states (s\<lparr>machine_state := m\<rparr>) \<rbrace>
   freeMemory ptr bits
   \<lbrace>\<lambda>a b. valid_irq_states (s\<lparr>machine_state := b\<rparr>)\<rbrace>"
  unfolding freeMemory_def
  apply(wp mapM_x_wp[OF _ subset_refl] storeWord_valid_irq_states)
  done

crunch pspace_respects_device_region[wp]: freeMemory "\<lambda>ms. P (device_state ms)"
 (wp: crunch_wps)

lemma dmo_freeMemory_invs:
  "\<lbrace> invs \<rbrace>
     do_machine_op (freeMemory ptr bits)
   \<lbrace>\<lambda>_. 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)
  by auto

lemma delete_objects_pas_refined:
  "\<lbrace>pas_refined aag\<rbrace> delete_objects ptr sz \<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
  apply(simp add: delete_objects_def do_machine_op_def)
  apply (wp modify_wp | simp add: split_def)+
  apply clarsimp
  apply(rule pas_refined_detype)
  apply simp
  done

lemma cte_wp_at_sym:
  "cte_wp_at (\<lambda> c. c = cap) slot s = cte_wp_at ((=) cap) slot s"
  apply(simp add: cte_wp_at_def)
  done

lemma untyped_slots_not_in_untyped_range:
  "\<lbrakk>invs s; descendants_range_in S slot s; cte_wp_at ((=) cap) slot s;
    is_untyped_cap cap; S = untyped_range cap; T \<subseteq> S\<rbrakk> \<Longrightarrow>
   fst slot \<notin> T"
  apply(erule contra_subsetD)
  proof -
  assume i: "invs s" and
         dr: "descendants_range_in S slot s" and
         ct: "cte_wp_at ((=) cap) slot s" and
         ut: "is_untyped_cap cap" and
          r: "S = untyped_range cap"
  hence dt: "detype_locale cap slot s"
   by(simp add: detype_locale_def descendants_range_def2 invs_untyped_children)
  show "fst slot \<notin> S"
  apply -
  apply (insert r)
  apply (simp, rule detype_locale.non_null_present[OF dt])
  apply (insert ct ut)
  apply (case_tac cap, simp_all)
  apply (auto simp: cte_wp_at_def)
  done
  qed

lemma descendants_range_in_detype:
  "\<lbrakk>invs s; descendants_range_in S slot s; cte_wp_at ((=) cap) slot s;
    is_untyped_cap cap; S = untyped_range cap; T \<subseteq> S\<rbrakk> \<Longrightarrow>
   descendants_range_in T slot (detype S s)"
  apply(erule descendants_range_in_subseteq[rotated])
  proof -
  assume i: "invs s" and
         dr: "descendants_range_in S slot s" and
         ct: "cte_wp_at ((=) cap) slot s" and
         ut: "is_untyped_cap cap" and
          r: "S = untyped_range cap"
  hence dt: "detype_locale cap slot s"
   by(simp add: detype_locale_def descendants_range_def2 invs_untyped_children)
  show "descendants_range_in S slot (detype S s)"
  apply -
  apply(insert i dr ct ut r)
  apply(simp add: valid_mdb_descendants_range_in[OF invs_mdb])
  apply(simp add: descendants_range_in_def)
  apply(rule ballI)
  apply(drule_tac x=p' in bspec, assumption)
  apply(clarsimp simp: null_filter_def split: if_split_asm)
  apply(rule conjI)
   apply(simp add: cte_wp_at_caps_of_state)
  apply(rule_tac t=a in ssubst[OF fst_conv[symmetric]])
  apply(rule_tac ptr=slot and s=s in detype_locale.non_null_present)
   apply(rule dt)
  apply(simp add: cte_wp_at_caps_of_state)
  apply fastforce
  done
  qed

lemma descendants_range_in_detype_ex:
  "\<lbrakk>invs s; descendants_range_in S slot s; \<exists> cap. cte_wp_at ((=) cap) slot s \<and>
    is_untyped_cap cap \<and> S = untyped_range cap; T \<subseteq> S\<rbrakk> \<Longrightarrow>
   descendants_range_in T slot (detype S s)"
  apply clarsimp
  apply(blast intro: descendants_range_in_detype)
  done

lemma descendants_range_in_detype_ex_strengthen:
  "(invs s \<and> descendants_range_in S slot s \<and> (\<exists> cap. cte_wp_at ((=) cap) slot s \<and>
    is_untyped_cap cap \<and> S = untyped_range cap) \<and> T \<subseteq> S) \<longrightarrow>
   descendants_range_in T slot (detype S s)"
  apply(blast intro: descendants_range_in_detype_ex)
  done

lemma delete_objects_descendants_range_in':
  notes modify_wp[wp del]
  shows
    "\<lbrace>invs and (\<lambda> s. \<exists> idx. cte_wp_at ((=) (UntypedCap dev word2 sz idx)) slot s) and
     descendants_range_in {word2..word2 + 2 ^ sz - 1} slot\<rbrace>
     (delete_objects word2 sz)
     \<lbrace>\<lambda>_. descendants_range_in {word2..word2 + 2 ^ sz - 1} slot\<rbrace>"
  apply(rule hoare_pre)
   unfolding delete_objects_def
   apply (wp modify_wp dmo_freeMemory_invs
         | strengthen descendants_range_in_detype_ex_strengthen)+
   apply (wp descendants_range_in_lift hoare_vcg_ex_lift | elim conjE | simp)+
  apply clarsimp
  apply(fastforce)
  done

lemma untyped_cap_aligned:
  "\<lbrakk>cte_wp_at ((=) (UntypedCap dev word sz idx)) slot s; valid_objs s\<rbrakk> \<Longrightarrow>
   is_aligned word sz"
  apply(fastforce dest: cte_wp_at_valid_objs_valid_cap simp: valid_cap_def cap_aligned_def)
  done

lemma delete_objects_descendants_range_in'':
  shows
    "\<lbrace>invs and (\<lambda> s. \<exists> idx. cte_wp_at ((=) (UntypedCap dev word2 sz idx)) slot s) and
     descendants_range_in {word2..word2 + 2 ^ sz - 1} slot\<rbrace>
     (delete_objects word2 sz)
     \<lbrace>\<lambda>_. descendants_range_in {word2..(word2 && ~~ mask sz) + 2 ^ sz - 1} slot\<rbrace>"
  apply(clarsimp simp: valid_def)
  apply(frule untyped_cap_aligned, fastforce)
  apply(clarsimp simp: is_aligned_neg_mask_eq)
  apply(erule use_valid)
   apply(wp delete_objects_descendants_range_in' | clarsimp | blast)+
  done

lemma delete_objects_descendants_range_in''':
  shows
    "\<lbrace>invs and (\<lambda> s. \<exists> idx. cte_wp_at ((=) (UntypedCap dev word2 sz idx)) slot s) and
     descendants_range_in {word2..word2 + 2 ^ sz - 1} slot\<rbrace>
     (delete_objects word2 sz)
     \<lbrace>\<lambda>_. descendants_range_in {word2 && ~~ mask sz..(word2 && ~~ mask sz) + 2 ^ sz - 1} slot\<rbrace>"
  apply(clarsimp simp: valid_def)
  apply(frule untyped_cap_aligned, fastforce)
  apply(clarsimp simp: is_aligned_neg_mask_eq)
  apply(erule use_valid)
   apply(wp delete_objects_descendants_range_in' | clarsimp | blast)+
  done

lemma range_cover_subset'':
  "\<lbrakk>range_cover ptr sz sbit n; n \<noteq> 0\<rbrakk>
  \<Longrightarrow> {ptr ..ptr + of_nat n * 2 ^ sbit - 1} \<subseteq> {ptr && ~~ mask sz..(ptr && ~~ mask sz) + 2^ sz - 1}"
  apply (rule order_trans, erule(1) range_cover_subset')
  apply (simp add: word_and_le2)
  done

lemma delete_objects_descendants_range_in'''':
  shows
   "\<lbrace>invs and (\<lambda> s. \<exists> idx. cte_wp_at ((=) (UntypedCap dev word2 sz idx)) slot s) and
    ct_active and descendants_range_in {word2..word2 + 2 ^ sz - 1} slot and
     K (range_cover word2 sz bits n \<and>
        n \<noteq> 0)\<rbrace>
          (delete_objects word2 sz)
    \<lbrace>\<lambda>_. descendants_range_in {word2..word2 + of_nat n * 2 ^ bits - 1} slot\<rbrace>"
  apply(clarsimp simp: valid_def)
  apply(rule descendants_range_in_subseteq)
  apply(erule use_valid)
   apply(wp delete_objects_descendants_range_in' | clarsimp | blast)+
  apply(drule range_cover_subset'', simp)
  apply(fastforce dest: untyped_cap_aligned simp: is_aligned_neg_mask_eq)
  done

lemmas delete_objects_descendants_range_in =
   delete_objects_descendants_range_in'
   delete_objects_descendants_range_in''
   delete_objects_descendants_range_in'''
   delete_objects_descendants_range_in''''

crunch global_refs[wp]: delete_objects "\<lambda> s. P (global_refs s)"
  (ignore: do_machine_op freeMemory)

crunch arch_state[wp]: delete_objects "\<lambda> s. P (arch_state s)"
  (ignore: do_machine_op freeMemory)

lemma  bits_of_UntypedCap:
  "bits_of (UntypedCap dev ptr sz free) = sz"
  apply(simp add: bits_of_def split: cap.splits)
  done

lemma mask_neg_mask_is_zero:
  "((x::word32) && ~~ a) && a = 0"
  apply(subst word_bw_assocs)
  apply simp
  done

(* clagged from Untyped_R.invoke_untyped_proofs.usable_range_disjoint *)
lemma usable_range_disjoint:
  assumes cte_wp_at: "cte_wp_at ((=) (cap.UntypedCap dev (ptr && ~~ mask sz) sz idx)) cref s"
  assumes  misc     : "distinct slots" "idx \<le> unat (ptr && mask sz) \<or> ptr = ptr && ~~ mask sz"
  "invs s" "slots \<noteq> []" "ct_active s"
  "\<forall>slot\<in>set slots. cte_wp_at ((=) cap.NullCap) slot s"
  "\<forall>x\<in>set slots. ex_cte_cap_wp_to (\<lambda>_. True) x s"
  assumes cover: "range_cover ptr sz (obj_bits_api tp us) (length slots)"
  notes blah[simp del] = untyped_range.simps usable_untyped_range.simps atLeastAtMost_iff atLeastatMost_subset_iff atLeastLessThan_iff
          Int_atLeastAtMost atLeastatMost_empty_iff split_paired_Ex
  shows
       "usable_untyped_range (cap.UntypedCap dev (ptr && ~~ mask sz) sz
       (unat ((ptr && mask sz) + of_nat (length slots) * 2 ^ obj_bits_api tp us))) \<inter>
       {ptr..ptr + of_nat (length slots) * 2 ^ obj_bits_api tp us - 1} = {}"
      proof -
      have not_0_ptr[simp]: "ptr\<noteq> 0"
      using misc cte_wp_at
      apply (clarsimp simp:cte_wp_at_caps_of_state)
      apply (drule(1) caps_of_state_valid)
      apply (clarsimp simp:valid_cap_def)
      done

      have idx_compare''[simp]:
       "unat ((ptr && mask sz) + (of_nat (length slots) * (2::word32) ^ obj_bits_api tp us)) < 2 ^ sz
        \<Longrightarrow> ptr + of_nat (length slots) * 2 ^ obj_bits_api tp us - 1
        < ptr + of_nat (length slots) * 2 ^ obj_bits_api tp us"
      apply (rule word_leq_le_minus_one,simp)
      apply (rule neq_0_no_wrap)
      apply (rule machine_word_plus_mono_right_split)
      apply (simp add:shiftl_t2n range_cover_unat[OF cover] field_simps)
      apply (simp add:range_cover.sz[where 'a=32, folded word_bits_def, OF cover])+
      done
      show ?thesis
       apply (clarsimp simp:mask_out_sub_mask blah)
       apply (drule idx_compare'')
       apply (simp add:not_le[symmetric])
       done
     qed

lemma set_free_index_invs':
  "\<lbrace> (\<lambda>s. invs s \<and>
         cte_wp_at ((=) cap) slot s \<and>
         (free_index_of cap \<le> idx' \<or>
          (descendants_range_in {word1..word1 + 2 ^ (bits_of cap) - 1} slot s \<and>
           pspace_no_overlap_range_cover word1 (bits_of cap) s)) \<and>
         idx' \<le> 2 ^ cap_bits cap \<and>
         is_untyped_cap cap) and K(word1 = obj_ref_of cap \<and> dev = (cap_is_device cap))\<rbrace>
       set_cap
           (UntypedCap dev word1 (bits_of cap) idx')
            slot
       \<lbrace>\<lambda>_. invs \<rbrace>"
  apply(rule hoare_gen_asm)
  apply(case_tac cap, simp_all add: bits_of_def)
  apply(case_tac "free_index_of cap \<le> idx'")
   apply simp
    apply(cut_tac cap=cap and cref=slot and idx="idx'" in set_free_index_invs)
    apply(simp add: free_index_update_def conj_comms is_cap_simps)
   apply simp
   apply(wp set_untyped_cap_invs_simple | simp)+
   apply(fastforce simp: cte_wp_at_def)
   done

lemma delete_objects_pspace_no_overlap:
  "\<lbrace> pspace_aligned and valid_objs and
     cte_wp_at ((=) (UntypedCap dev ptr sz idx)) slot\<rbrace>
    delete_objects ptr sz
   \<lbrace>\<lambda>rv. pspace_no_overlap_range_cover ptr sz\<rbrace>"
  unfolding delete_objects_def do_machine_op_def
  apply(wp | simp add: split_def detype_machine_state_update_comm)+
  apply clarsimp
  apply(rule pspace_no_overlap_detype)
   apply(auto dest: cte_wp_at_valid_objs_valid_cap)
  done

lemma delete_objects_pspace_no_overlap':
  "\<lbrace> pspace_aligned and valid_objs and
     cte_wp_at ((=) (UntypedCap dev ptr sz idx)) slot\<rbrace>
    delete_objects ptr sz
   \<lbrace>\<lambda>rv. pspace_no_overlap_range_cover (ptr && ~~ mask sz) sz\<rbrace>"
  apply(clarsimp simp: valid_def)
  apply(frule untyped_cap_aligned, simp)
  apply(clarsimp simp: is_aligned_neg_mask_eq)
  apply(frule(1) cte_wp_at_valid_objs_valid_cap)
  apply(erule use_valid, wp delete_objects_pspace_no_overlap, auto)
  done

(* FIXME: move *)
lemma valid_cap_range_untyped:
  "\<lbrakk> valid_objs s; cte_wp_at ((=) (UntypedCap dev (ptr && ~~ mask sz) sz idx)) slot s\<rbrakk>
  \<Longrightarrow> cte_wp_at (\<lambda>c. up_aligned_area ptr sz \<subseteq> cap_range c \<and> cap_is_device c = dev) slot s"
  apply (rule cte_wp_at_weakenE)
   apply simp
  apply (clarsimp simp: word_and_le2 p_assoc_help)
  done

lemma retype_region_pas_refined':
  "\<lbrace>pas_refined aag and pas_cur_domain aag and invs and
    caps_overlap_reserved
            {ptr..ptr + of_nat num_objects * 2 ^ obj_bits_api type o_bits -
                  1} and
    (\<lambda> s. \<exists> idx. cte_wp_at (\<lambda> c. c = (UntypedCap dev (ptr && ~~ mask sz) sz idx)) slot s \<and>
                 (idx \<le> unat (ptr && mask sz) \<or>
                  (descendants_range_in {ptr..(ptr && ~~ mask sz) + 2 ^ sz - 1} slot s) \<and>
                    pspace_no_overlap_range_cover ptr sz s)) and
    K (sz < word_bits) and
    K (range_cover ptr sz (obj_bits_api type o_bits) num_objects) and
    K (\<forall>x\<in>set (retype_addrs ptr type num_objects o_bits). is_subject aag x) and
    K ((type = CapTableObject \<longrightarrow> 0 < o_bits))\<rbrace>
     retype_region ptr num_objects o_bits type dev
   \<lbrace>\<lambda>rv. pas_refined aag\<rbrace>"
  apply (rule hoare_gen_asm)+
  apply (rule hoare_weaken_pre)
   apply (rule use_retype_region_proofs_ext'[where P="invs and pas_refined aag"])
       apply clarsimp
       apply (erule (2) retype_region_proofs'.pas_refined[OF retype_region_proofs'.intro])
      apply (wp retype_region_ext_pas_refined)
      apply simp
     apply fastforce
    apply fastforce
   apply clarsimp
  apply clarsimp
  apply (frule valid_cap_range_untyped[OF invs_valid_objs])
   apply (fastforce simp: cte_wp_at_caps_of_state)
  apply (cases slot)
  apply (auto intro: cte_wp_at_caps_no_overlapI descendants_range_caps_no_overlapI
                     cte_wp_at_pspace_no_overlapI
               simp: cte_wp_at_sym)
  done

lemma free_index_of_UntypedCap:
  "free_index_of (UntypedCap dev ptr sz idx) = idx"
  apply(simp add: free_index_of_def)
  done

fun slot_of_untyped_inv where "slot_of_untyped_inv (Retype slot _ _ _ _ _ _ _) = slot"

lemma region_in_kernel_window_subseteq:
  "\<lbrakk> region_in_kernel_window S s; T \<subseteq> S\<rbrakk> \<Longrightarrow>
     region_in_kernel_window T s"
  apply(fastforce simp: region_in_kernel_window_def)
  done

lemma aag_cap_auth_UntypedCap_idx_dev:
   "aag_cap_auth aag l (UntypedCap dev base sz idx) \<Longrightarrow>
    aag_cap_auth aag l (UntypedCap dev' base sz idx')"
  by (clarsimp simp: aag_cap_auth_def cap_links_asid_slot_def
                     cap_links_irq_def)

lemma cte_wp_at_pas_cap_cur_auth_UntypedCap_idx_dev:
  "\<lbrakk>cte_wp_at ((=) (UntypedCap dev base sz idx)) slot s; is_subject aag (fst slot);
    pas_refined aag s\<rbrakk> \<Longrightarrow>
  pas_cap_cur_auth aag (UntypedCap dev' base sz idx')"
  apply(rule aag_cap_auth_UntypedCap_idx_dev)
  apply(auto intro: cap_cur_auth_caps_of_state simp: cte_wp_at_caps_of_state)
  done

lemmas caps_pas_cap_cur_auth_UntypedCap_idx_dev
    = cte_wp_at_pas_cap_cur_auth_UntypedCap_idx_dev[OF caps_of_state_cteD]

lemma retype_addrs_aligned_range_cover:
  assumes xin: "x \<in> set (retype_addrs ptr ty n us)"
  and co: "range_cover ptr sz (obj_bits_api ty us) n"
  shows   "is_aligned x (obj_bits_api ty us)"
  using co
  apply (clarsimp simp: range_cover_def)
  apply (rule retype_addrs_aligned[OF xin, where sz=sz], simp_all)
  apply (simp add: word_bits_def)
  done

lemma pas_refined_work_units_complete[simp]:
  "pas_refined aag (work_units_completed_update f s) = pas_refined aag s"
  by (simp add: pas_refined_def)

(*FIXME MOVE *)
lemma set_cap_sets_direct:
  "P cap \<Longrightarrow>
   \<lbrace>\<top>\<rbrace>
     set_cap cap slot
   \<lbrace>\<lambda>rv. cte_wp_at P slot\<rbrace>"
  apply (rule hoare_strengthen_post)
   apply (rule set_cap_sets)
  apply (erule cte_wp_at_lift)
  by blast

(*FIXME MOVE *)
lemma set_cap_sets_wp:
  "\<lbrace>\<lambda>_. P cap\<rbrace>
     set_cap cap slot
   \<lbrace>\<lambda>rv. cte_wp_at P slot\<rbrace>"
  by (rule hoare_gen_asm2[simplified]) (erule set_cap_sets_direct)

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
      and K (is_subject aag (fst slot))\<rbrace>
    reset_untyped_cap slot
  \<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
  apply (rule hoare_gen_asm)
  apply (clarsimp simp: reset_untyped_cap_def)
  apply (rule hoare_pre)
   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"
                     in hoare_strengthen_post)
      apply (rule validE_valid, rule mapME_x_inv_wp)
      apply (rule hoare_pre)
       apply (wps
             | wp preemption_point_inv' set_cap_pas_refined_not_transferable set_cap_sets_direct
             | 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 (clarsimp simp: cte_wp_at_caps_of_state is_cap_simps bits_of_def)
  apply (auto elim: caps_pas_cap_cur_auth_UntypedCap_idx_dev)
  done

lemma retype_region_post_retype_invs_spec:
  "\<lbrace>invs and caps_no_overlap ptr sz and pspace_no_overlap_range_cover ptr sz
      and caps_overlap_reserved {ptr..ptr + of_nat n * 2 ^ obj_bits_api ty us - 1}
      and region_in_kernel_window {ptr .. (ptr && ~~ mask sz) + 2 ^ sz - 1}
      and (\<lambda>s. \<exists>idx. cte_wp_at ((=) (UntypedCap dev (ptr && ~~ mask sz) sz idx)) slot s)
      and K (ty = Structures_A.CapTableObject \<longrightarrow> 0 < us)
      and K (range_cover ptr sz (obj_bits_api ty us) n) \<rbrace>
      retype_region ptr n us ty dev\<lbrace>\<lambda>rv. post_retype_invs ty rv\<rbrace>"
  apply (rule hoare_pre)
  apply (wp retype_region_post_retype_invs)
  apply (clarsimp simp del: split_paired_Ex)
  apply (frule valid_cap_range_untyped[OF invs_valid_objs],simp)
  apply fastforce
  done

lemma invoke_untyped_pas_refined:
  notes modify_wp[wp del]
  notes usable_untyped_range.simps[simp del]
  shows
  "\<lbrace>pas_refined aag and pas_cur_domain aag and invs and valid_untyped_inv ui
      and ct_active and K (authorised_untyped_inv aag ui)\<rbrace>
     invoke_untyped ui
   \<lbrace>\<lambda>rv. 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 invoke_untyped_Q)
        apply (rule hoare_pre, wp create_cap_pas_refined)
        apply (clarsimp simp: authorised_untyped_inv_def
                              range_cover.aligned ptr_range_def[symmetric]
                              retype_addrs_aligned_range_cover)
        apply (clarsimp simp: cte_wp_at_caps_of_state
                              is_cap_simps ptr_range_def[symmetric])
        apply (frule cap_cur_auth_caps_of_state[where
            cap="cap.UntypedCap dev p sz idx" for dev p sz idx], simp+)
        apply (clarsimp simp add: aag_cap_auth_def ptr_range_def[symmetric]
                                  pas_refined_all_auth_is_owns)
        apply blast
       apply (rule hoare_pre, wp init_arch_objects_pas_refined)
       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 hoare_name_pre_state, clarsimp)
      apply (rule hoare_pre, wp retype_region_pas_refined)
      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 (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 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)+
  done

subsection\<open>decode\<close>

lemma data_to_obj_type_ret_not_asid_pool:
  "\<lbrace> \<top> \<rbrace> data_to_obj_type v \<lbrace> \<lambda>r s. r \<noteq> ArchObject ASIDPoolObj \<rbrace>,-"
  apply(clarsimp simp: validE_R_def validE_def valid_def)
  apply(auto simp: data_to_obj_type_def arch_data_to_obj_type_def throwError_def simp: returnOk_def bindE_def return_def bind_def lift_def split: if_split_asm)
  done

definition authorised_untyped_inv' where
 "authorised_untyped_inv' aag ui \<equiv> case ui of
     Invocations_A.untyped_invocation.Retype src_slot reset base aligned_free_ref new_type obj_sz slots dev \<Rightarrow>
       is_subject aag (fst src_slot) \<and> (0::word32) < of_nat (length slots) \<and>
       new_type \<noteq> ArchObject ASIDPoolObj \<and>
       (\<forall>x\<in>set slots. is_subject aag (fst x))"

lemma authorised_untyped_invI:
  notes blah[simp del] = atLeastAtMost_iff atLeastatMost_subset_iff atLeastLessThan_iff
          Int_atLeastAtMost atLeastatMost_empty_iff split_paired_Ex

  shows
  "\<lbrakk>valid_untyped_inv ui s; pas_refined aag s;
        authorised_untyped_inv' aag ui\<rbrakk> \<Longrightarrow>
   authorised_untyped_inv aag ui"
  apply(case_tac ui)
  apply(clarsimp simp: cte_wp_at_caps_of_state
                       authorised_untyped_inv_def authorised_untyped_inv'_def
                  del: ballI)
  apply (frule(1) cap_cur_auth_caps_of_state, simp)
  apply (simp add: aag_cap_auth_def aag_has_Control_iff_owns)
  apply (frule range_cover_subset'', simp)
  apply (frule retype_addrs_subset_ptr_bits)
  apply (subgoal_tac "case ui of Retype src r base aligned_free_ref new_type obj_sz slots dev \<Rightarrow>
    {aligned_free_ref .. base + 2 ^ sz - 1} \<subseteq> {base .. base + 2 ^ sz - 1}")
   apply (simp add: field_simps)
   apply blast
  apply (simp add: blah word_and_le2)
  done

lemma nonzero_unat_simp:
  "0 < unat (x::word32) \<Longrightarrow> 0 < x"
  apply(auto dest: word_of_nat_less)
  done

lemma decode_untyped_invocation_authorised:
   "\<lbrace>invs and pas_refined aag and valid_cap cap
        and cte_wp_at ((=) cap) slot
        and (\<lambda>s. \<forall>cap\<in>set excaps.
                  is_cnode_cap cap \<longrightarrow>
                   (\<forall>r\<in>cte_refs cap (interrupt_irq_node s).
                       ex_cte_cap_wp_to is_cnode_cap r s))
        and (\<lambda>s. \<forall>x\<in>set excaps. s \<turnstile> x)
        and K (cap = cap.UntypedCap dev base sz idx
               \<and> is_subject aag (fst slot)
               \<and> (\<forall>c \<in> set excaps. pas_cap_cur_auth aag c)
               \<and> (\<forall> ref \<in> untyped_range cap. is_subject aag ref))\<rbrace>
     decode_untyped_invocation label args slot cap excaps
   \<lbrace>\<lambda>rv s. authorised_untyped_inv aag rv\<rbrace>,-"
  apply(rule hoare_gen_asmE)
  apply(rule hoare_pre)
   apply (strengthen authorised_untyped_invI[mk_strg I])
   apply(wp dui_inv_wf | simp)+
  apply (clarsimp simp: decode_untyped_invocation_def split_def
                        authorised_untyped_inv'_def
                  split del: if_split split: untyped_invocation.splits)
  (* need to hoist the is_cnode_cap assumption into postcondition later on *)

  apply (simp add: unlessE_def[symmetric] whenE_def[symmetric] unlessE_whenE
           split del: if_split)
  apply (wp whenE_throwError_wp  hoare_vcg_all_lift mapME_x_inv_wp
        | simp split: untyped_invocation.splits
        | (auto)[1])+
           apply (rule_tac Q="\<lambda>node_cap s.
             (is_cnode_cap node_cap \<longrightarrow> is_subject aag (obj_ref_of node_cap)) \<and>
             is_subject aag (fst slot) \<and>
             new_type \<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))"
                       in hoare_strengthen_post)
            apply (wp get_cap_inv get_cap_ret_is_subject)
           apply (fastforce simp: nonzero_unat_simp)
          apply clarsimp
          apply(wp lookup_slot_for_cnode_op_authorised
                   lookup_slot_for_cnode_op_inv whenE_throwError_wp)+
     apply(rule hoare_drop_imps)+
     apply(clarsimp)
     apply(rule_tac Q'="\<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>
                          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)
      apply(wp data_to_obj_type_ret_not_asid_pool data_to_obj_type_inv2)
     apply(case_tac "excaps ! 0", simp_all, fastforce simp: nonzero_unat_simp)[1]
    apply(wp whenE_throwError_wp)+
  apply(auto dest!: bang_0_in_set
              simp: valid_cap_def cap_aligned_def obj_ref_of_def is_cap_simps
                    cap_auth_conferred_def pas_refined_all_auth_is_owns
                    aag_cap_auth_def ptr_range_def untyped_min_bits_def
             dest: cte_wp_at_eqD2 simp: bits_of_UntypedCap)
  done

end

end