(*
 * Copyright 2014, General Dynamics C4 Systems
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *)

theory ArchCNodeInv_AI
imports CNodeInv_AI
begin

context Arch begin global_naming X64

named_theorems CNodeInv_AI_assms

lemma valid_cnode_capI:
  "\<lbrakk>cap_table_at n w s; valid_objs s; pspace_aligned s; n > 0; length g \<le> 64\<rbrakk>
   \<Longrightarrow> s \<turnstile> cap.CNodeCap w n g"
  apply (simp add: valid_cap_def cap_aligned_def)
  apply (rule conjI)
   apply (clarsimp simp add: pspace_aligned_def obj_at_def)
   apply (drule bspec, fastforce)
   apply (clarsimp simp: is_obj_defs wf_obj_bits)
  apply (clarsimp simp add: obj_at_def is_obj_defs valid_objs_def dom_def)
  apply (erule allE, erule impE, blast)
  apply (simp add: valid_obj_def valid_cs_def valid_cs_size_def)
  apply (simp add: word_bits_def cte_level_bits_def)
  done

(* unused *)
lemma derive_cap_objrefs [CNodeInv_AI_assms]:
  "\<lbrace>\<lambda>s. P (obj_refs cap)\<rbrace> derive_cap slot cap \<lbrace>\<lambda>rv s. rv \<noteq> NullCap \<longrightarrow> P (obj_refs rv)\<rbrace>,-"
  apply (cases cap, simp_all add: derive_cap_def is_zombie_def)
          apply ((wp ensure_no_children_inv | simp add: o_def | rule hoare_pre)+)[11]
  apply (rename_tac arch_cap)
  apply (case_tac arch_cap, simp_all add: arch_derive_cap_def)
         by (wp | wpc | simp add: o_def)+

lemma derive_cap_zobjrefs [CNodeInv_AI_assms]:
  "\<lbrace>\<lambda>s. P (zobj_refs cap)\<rbrace> derive_cap slot cap \<lbrace>\<lambda>rv s. rv \<noteq> NullCap \<longrightarrow> P (zobj_refs rv)\<rbrace>,-"
  apply (cases cap, simp_all add: derive_cap_def is_zombie_def)
          apply ((wp ensure_no_children_inv | simp add: o_def | rule hoare_pre)+)[11]
  apply (rename_tac arch_cap)
  apply (case_tac arch_cap, simp_all add: arch_derive_cap_def)
         by (wp | wpc |simp add: o_def)+

lemma update_cap_objrefs [CNodeInv_AI_assms]:
  "\<lbrakk> update_cap_data P dt cap \<noteq> NullCap \<rbrakk> \<Longrightarrow>
     obj_refs (update_cap_data P dt cap) = obj_refs cap"
  by (case_tac cap,
      simp_all add: update_cap_data_closedform arch_update_cap_data_def Let_def
             split: if_split_asm arch_cap.splits)


lemma update_cap_zobjrefs [CNodeInv_AI_assms]:
  "\<lbrakk> update_cap_data P dt cap \<noteq> cap.NullCap \<rbrakk> \<Longrightarrow>
     zobj_refs (update_cap_data P dt cap) = zobj_refs cap"
  apply (case_tac cap,
      simp_all add: update_cap_data_closedform arch_update_cap_data_def Let_def
             split: if_split_asm arch_cap.splits)
  done


lemma copy_mask [simp, CNodeInv_AI_assms]:
  "copy_of (mask_cap R c) = copy_of c"
  apply (rule ext)
  apply (auto simp: copy_of_def is_cap_simps mask_cap_def
                    cap_rights_update_def same_object_as_def
                    bits_of_def acap_rights_update_def
         split: cap.splits arch_cap.splits bool.splits)
  done

lemma update_cap_data_mask_Null [simp, CNodeInv_AI_assms]:
  "(update_cap_data P x (mask_cap m c) = NullCap) = (update_cap_data P x c = NullCap)"
  unfolding update_cap_data_def mask_cap_def
  apply (cases c)
  apply (clarsimp simp: is_cap_simps cap_rights_update_def badge_update_def split: if_splits)+
  apply (rename_tac arch_cap)
  apply (case_tac arch_cap; clarsimp simp: arch_update_cap_data_def acap_rights_update_def split: if_splits)
  done

lemma cap_master_update_cap_data [CNodeInv_AI_assms]:
  "\<lbrakk> update_cap_data P x c \<noteq> NullCap \<rbrakk>
        \<Longrightarrow> cap_master_cap (update_cap_data P x c) = cap_master_cap c"
  apply (simp add: update_cap_data_def split del: if_split split: if_split_asm)
  apply (auto simp: is_cap_simps Let_def the_cnode_cap_def cap_master_cap_def
                    badge_update_def arch_update_cap_data_def
             split: arch_cap.split)
  done

lemma same_object_as_def2:
  "same_object_as cp cp' = (cap_master_cap cp = cap_master_cap cp'
                                \<and> \<not> cp = NullCap \<and> \<not> is_untyped_cap cp
                                \<and> \<not> is_zombie cp
                                \<and> (is_arch_cap cp \<longrightarrow>
                                     (case the_arch_cap cp of
                                         PageCap d x rs tp sz v \<Rightarrow> x \<le> x + 2 ^ pageBitsForSize sz - 1
                                       | _ \<Rightarrow> True)))"
  apply (simp add: same_object_as_def is_cap_simps split: cap.split)
  apply (auto simp: cap_master_cap_def bits_of_def is_cap_simps
             split: arch_cap.splits)
  done

lemma same_object_as_cap_master [CNodeInv_AI_assms]:
  "same_object_as cap cap' \<Longrightarrow> cap_master_cap cap = cap_master_cap cap'"
  by (simp add: same_object_as_def2)

lemma weak_derived_cap_is_device[CNodeInv_AI_assms]:
  "\<lbrakk>weak_derived c' c\<rbrakk> \<Longrightarrow>  cap_is_device c = cap_is_device c'"
  apply (auto simp: weak_derived_def copy_of_def is_cap_simps
                    same_object_as_def2
             split: if_split_asm
             dest!: master_cap_eq_is_device_cap_eq)
  done

lemma cap_asid_update_cap_data [CNodeInv_AI_assms]:
  "update_cap_data P x c \<noteq> NullCap
         \<Longrightarrow> cap_asid (update_cap_data P x c) = cap_asid c"
  apply (simp add: update_cap_data_def split del: if_split split: if_split_asm)
  apply (auto simp: is_cap_simps Let_def the_cnode_cap_def cap_master_cap_def
                    badge_update_def arch_update_cap_data_def
             split: arch_cap.split)
  done

lemma cap_vptr_update_cap_data [CNodeInv_AI_assms]:
  "update_cap_data P x c \<noteq> NullCap
         \<Longrightarrow> cap_vptr (update_cap_data P x c) = cap_vptr c"
  apply (simp add: update_cap_data_def split del: if_split split: if_split_asm)
  apply (auto simp: is_cap_simps Let_def the_cnode_cap_def cap_master_cap_def
                    badge_update_def arch_update_cap_data_def
             split: arch_cap.split)
  done

lemma cap_asid_base_update_cap_data [CNodeInv_AI_assms]:
  "update_cap_data P x c \<noteq> NullCap
         \<Longrightarrow> cap_asid_base (update_cap_data P x c) = cap_asid_base c"
  apply (simp add: update_cap_data_def split del: if_split split: if_split_asm)
  apply (auto simp: is_cap_simps Let_def the_cnode_cap_def cap_master_cap_def
                    badge_update_def arch_update_cap_data_def
             split: arch_cap.split)
  done

lemma same_object_as_update_cap_data [CNodeInv_AI_assms]:
  "\<lbrakk> update_cap_data P x c \<noteq> NullCap; same_object_as c' c \<rbrakk> \<Longrightarrow>
  same_object_as c' (update_cap_data P x c)"
  apply (clarsimp simp: same_object_as_def is_cap_simps
                  split: cap.split_asm arch_cap.splits if_split_asm)
  apply (auto simp: update_cap_data_def badge_update_def cap_rights_update_def is_cap_simps
                   arch_update_cap_data_def
                   Let_def split_def the_cnode_cap_def bits_of_def
              split: if_split_asm cap.splits)
  done

lemma is_reply_update_cap_data[simp]:
  "is_reply_cap (update_cap_data P x c) = is_reply_cap c"
  by (simp add:is_reply_cap_def update_cap_data_def arch_update_cap_data_def the_cnode_cap_def
               is_arch_cap_def badge_update_def split:cap.split)

lemma is_master_reply_update_cap_data[simp]:
  "is_master_reply_cap (update_cap_data P x c) = is_master_reply_cap c"
  by (simp add:is_master_reply_cap_def update_cap_data_def arch_update_cap_data_def
               the_cnode_cap_def is_arch_cap_def badge_update_def split:cap.split)

lemma weak_derived_update_cap_data [CNodeInv_AI_assms]:
  "\<lbrakk>update_cap_data P x c \<noteq> NullCap; weak_derived c c'\<rbrakk>
  \<Longrightarrow> weak_derived (update_cap_data P x c) c'"
  apply (simp add: weak_derived_def copy_of_def
                   cap_master_update_cap_data cap_asid_update_cap_data
                   cap_asid_base_update_cap_data
                   cap_vptr_update_cap_data
              split del: if_split cong: if_cong)
  apply (erule disjE)
   apply (clarsimp split: if_split_asm)
     apply (clarsimp simp: is_cap_simps)
     apply (simp add: update_cap_data_def arch_update_cap_data_def is_cap_simps)
   apply (erule (1) same_object_as_update_cap_data)
  apply clarsimp
  apply (rule conjI, clarsimp simp: is_cap_simps update_cap_data_def split del: if_split)+
  apply clarsimp
  apply (clarsimp simp: same_object_as_def is_cap_simps
                 split: cap.split_asm arch_cap.splits if_split_asm)
  apply (auto simp: update_cap_data_def badge_update_def cap_rights_update_def is_cap_simps
                    arch_update_cap_data_def
                    Let_def split_def the_cnode_cap_def bits_of_def
             split: if_split_asm cap.splits arch_cap.splits)
  done

lemma cap_badge_update_cap_data [CNodeInv_AI_assms]:
  "update_cap_data False x c \<noteq> NullCap \<and> (bdg, cap_badge c) \<in> capBadge_ordering False
       \<longrightarrow> (bdg, cap_badge (update_cap_data False x c)) \<in> capBadge_ordering False"
  apply clarsimp
  apply (erule capBadge_ordering_trans)
  apply (simp add: update_cap_data_def split del: if_split split: if_split_asm)
  apply (auto simp: is_cap_simps Let_def the_cnode_cap_def cap_master_cap_def
                    badge_update_def arch_update_cap_data_def
             split: arch_cap.split)
  done


lemma cap_vptr_rights_update[simp, CNodeInv_AI_assms]:
  "cap_vptr (cap_rights_update f c) = cap_vptr c"
  by (simp add: cap_vptr_def cap_rights_update_def acap_rights_update_def
           split: cap.splits arch_cap.splits bool.splits)

lemma cap_vptr_mask[simp, CNodeInv_AI_assms]:
  "cap_vptr (mask_cap m c) = cap_vptr c"
  by (simp add: mask_cap_def)

lemma cap_asid_base_rights [simp, CNodeInv_AI_assms]:
  "cap_asid_base (cap_rights_update R c) = cap_asid_base c"
  by (auto simp add: cap_rights_update_def acap_rights_update_def
           split: cap.splits arch_cap.splits bool.splits)

lemma cap_asid_base_mask[simp, CNodeInv_AI_assms]:
  "cap_asid_base (mask_cap m c) = cap_asid_base c"
  by (simp add: mask_cap_def)

lemma weak_derived_mask [CNodeInv_AI_assms]:
  "\<lbrakk> weak_derived c c'; cap_aligned c \<rbrakk> \<Longrightarrow> weak_derived (mask_cap m c) c'"
  unfolding weak_derived_def
  apply simp
  apply (erule disjE)
   apply simp
  apply (simp add: mask_cap_def cap_rights_update_def
                   copy_of_def same_object_as_def bits_of_def
                   is_cap_simps acap_rights_update_def
            split: cap.split arch_cap.split)+
  apply (clarsimp simp: cap_aligned_def
                        is_aligned_no_overflow)
  done


lemma vs_cap_ref_update_cap_data[simp, CNodeInv_AI_assms]:
  "vs_cap_ref (update_cap_data P d cap) = vs_cap_ref cap"
  by (simp add: vs_cap_ref_def update_cap_data_closedform
                arch_update_cap_data_def Let_def
         split: arch_cap.splits cap.split if_splits)


lemma invs_irq_state_independent[intro!, simp, CNodeInv_AI_assms]:
  "invs (s\<lparr>machine_state := machine_state s\<lparr>irq_state := f (irq_state (machine_state s))\<rparr>\<rparr>)
   = invs s"
  by (clarsimp simp: irq_state_independent_A_def invs_def
      valid_state_def valid_pspace_def valid_mdb_def valid_ioc_def valid_idle_def
      only_idle_def if_unsafe_then_cap_def valid_reply_caps_def
      valid_reply_masters_def valid_global_refs_def valid_arch_state_def
      valid_irq_node_def valid_irq_handlers_def valid_machine_state_def
      valid_arch_caps_def valid_global_objs_def
      valid_kernel_mappings_def equal_kernel_mappings_def
      valid_asid_map_def valid_global_vspace_mappings_def
      pspace_in_kernel_window_def cap_refs_in_kernel_window_def
      cur_tcb_def sym_refs_def state_refs_of_def vspace_at_asid_def
      swp_def valid_irq_states_def)


lemma cte_at_nat_to_cref_zbits [CNodeInv_AI_assms]:
  "\<lbrakk> s \<turnstile> Zombie oref zb n; m < n \<rbrakk>
     \<Longrightarrow> cte_at (oref, nat_to_cref (zombie_cte_bits zb) m) s"
  apply (subst(asm) valid_cap_def)
  apply (cases zb, simp_all add: valid_cap_def)
   apply (clarsimp simp: obj_at_def is_tcb)
   apply (drule(1) tcb_cap_cases_lt [OF order_less_le_trans])
   apply clarsimp
   apply (rule cte_wp_at_tcbI, fastforce+)
  apply (clarsimp elim!: cap_table_at_cte_at simp: cap_aligned_def)
  apply (simp add: nat_to_cref_def word_bits_conv)
  done


lemma copy_of_cap_range [CNodeInv_AI_assms]:
  "copy_of cap cap' \<Longrightarrow> cap_range cap = cap_range cap'"
  apply (clarsimp simp: copy_of_def split: if_split_asm)
  apply (cases cap', simp_all add: same_object_as_def)
       apply (clarsimp simp: is_cap_simps bits_of_def cap_range_def
                      split: cap.split_asm)+
  apply (rename_tac acap' acap)
   apply (case_tac acap, simp_all)
       apply (clarsimp split: arch_cap.split_asm cap.split_asm)+
  done


lemma copy_of_zobj_refs [CNodeInv_AI_assms]:
  "copy_of cap cap' \<Longrightarrow> zobj_refs cap = zobj_refs cap'"
  apply (clarsimp simp: copy_of_def split: if_split_asm)
  apply (cases cap', simp_all add: same_object_as_def)
       apply (clarsimp simp: is_cap_simps bits_of_def
                      split: cap.split_asm)+
  apply (rename_tac acap' acap)
   apply (case_tac acap, simp_all)
       apply (clarsimp split: arch_cap.split_asm cap.split_asm)+
  done


lemma vs_cap_ref_master [CNodeInv_AI_assms]:
  "\<lbrakk> cap_master_cap cap = cap_master_cap cap';
           cap_asid cap = cap_asid cap';
           cap_asid_base cap = cap_asid_base cap';
           cap_vptr cap = cap_vptr cap' \<rbrakk>
        \<Longrightarrow> vs_cap_ref cap = vs_cap_ref cap'"
  apply (rule ccontr)
  apply (clarsimp simp: vs_cap_ref_def cap_master_cap_def
                 split: cap.split_asm)
  apply (clarsimp simp: cap_asid_def split: arch_cap.split_asm option.split_asm)
  done

lemma weak_derived_vs_cap_ref [CNodeInv_AI_assms]:
  "weak_derived c c' \<Longrightarrow> vs_cap_ref c = vs_cap_ref c'"
  by (auto simp: weak_derived_def copy_of_def
                 same_object_as_def2
          split: if_split_asm elim: vs_cap_ref_master[OF sym])

lemma weak_derived_table_cap_ref [CNodeInv_AI_assms]:
  "weak_derived c c' \<Longrightarrow> table_cap_ref c = table_cap_ref c'"
  apply (clarsimp simp: weak_derived_def copy_of_def
                 same_object_as_def2
          split: if_split_asm)
   apply (elim disjE,simp_all add:is_cap_simps)
  apply (elim disjE,simp_all)
  apply clarsimp
  apply (frule vs_cap_ref_master[OF sym],simp+)
  apply (drule vs_cap_ref_eq_imp_table_cap_ref_eq')
   apply simp
  apply simp
  done


lemma weak_derived_vspace_asid:
  "weak_derived c c' \<Longrightarrow> cap_asid c = cap_asid c'
                       \<and> is_pt_cap c = is_pt_cap c'
                       \<and> is_pd_cap c = is_pd_cap c'
                       \<and> is_pdpt_cap c = is_pdpt_cap c'
                       \<and> is_pml4_cap c = is_pml4_cap c'"
  by (auto simp: weak_derived_def copy_of_def is_cap_simps
                 same_object_as_def2 is_pt_cap_def
                 cap_master_cap_simps
          split: if_split_asm
          dest!: cap_master_cap_eqDs)

lemma weak_derived_ASIDPool1:
  "weak_derived (cap.ArchObjectCap (ASIDPoolCap ap asid)) cap =
  (cap = cap.ArchObjectCap (ASIDPoolCap ap asid))"
  apply (rule iffI)
   prefer 2
   apply simp
  apply (clarsimp simp: weak_derived_def copy_of_def split: if_split_asm)
  apply (clarsimp simp: same_object_as_def2 cap_master_cap_simps dest!: cap_master_cap_eqDs)
  done

lemma weak_derived_ASIDPool2:
  "weak_derived cap (ArchObjectCap (ASIDPoolCap ap asid)) =
  (cap = ArchObjectCap (ASIDPoolCap ap asid))"
  apply (rule iffI)
   prefer 2
   apply simp
  apply (clarsimp simp: weak_derived_def copy_of_def split: if_split_asm)
  apply (auto simp: same_object_as_def2 cap_master_cap_simps dest!: cap_master_cap_eqDs)
  done

lemmas weak_derived_ASIDPool [simp] =
  weak_derived_ASIDPool1 weak_derived_ASIDPool2


lemma swap_of_caps_valid_arch_caps [CNodeInv_AI_assms]:
  "\<lbrace>valid_arch_caps and
    cte_wp_at (weak_derived c) a and
    cte_wp_at (weak_derived c') b\<rbrace>
   do
     y \<leftarrow> set_cap c b;
     set_cap c' a
   od
   \<lbrace>\<lambda>rv. valid_arch_caps\<rbrace>"
  apply (rule hoare_pre)
   apply (simp add: valid_arch_caps_def
                    valid_vs_lookup_def valid_table_caps_def pred_conj_def
               del: split_paired_Ex split_paired_All imp_disjL)
   apply (wp hoare_vcg_all_lift hoare_convert_imp[OF set_cap.vs_lookup_pages]
             hoare_vcg_disj_lift hoare_convert_imp[OF set_cap_caps_of_state]
             hoare_use_eq[OF set_cap_arch set_cap_obj_at_impossible[where P="\<lambda>x. x"]])
  apply (clarsimp simp: valid_arch_caps_def cte_wp_at_caps_of_state
              simp del: split_paired_Ex split_paired_All imp_disjL)
  apply (frule weak_derived_obj_refs[where dcap=c])
  apply (frule weak_derived_obj_refs[where dcap=c'])
  apply (frule weak_derived_vspace_asid[where c=c])
  apply (frule weak_derived_vspace_asid[where c=c'])
  apply (intro conjI)
     apply (simp add: valid_vs_lookup_def del: split_paired_Ex split_paired_All)
     apply (elim allEI)
     apply (intro impI disjCI2)
     apply (simp del: split_paired_Ex split_paired_All)
     apply (elim conjE)
     apply (erule exfEI[where f="id (a := b, b := a)"])
     subgoal by (clarsimp dest!: weak_derived_vs_cap_ref, intro conjI; clarsimp)
    apply (simp add: valid_table_caps_def empty_table_caps_of
                del: split_paired_Ex split_paired_All imp_disjL)
   apply (simp add: unique_table_caps_def
               del: split_paired_Ex split_paired_All imp_disjL
                    split del: if_split)
   apply (erule allfEI[where f="id (a := b, b := a)"])
   apply (erule allfEI[where f="id (a := b, b := a)"])
   apply (clarsimp split del: if_split split: if_split_asm)
  apply (simp add: unique_table_refs_def
              del: split_paired_All split del: if_split)
  apply (erule allfEI[where f="id (a := b, b := a)"])
  apply (erule allfEI[where f="id (a := b, b := a)"])
  apply (clarsimp split del: if_split split: if_split_asm dest!:vs_cap_ref_to_table_cap_ref
                      dest!: weak_derived_table_cap_ref)
  done


lemma cap_swap_asid_map[wp, CNodeInv_AI_assms]:
  "\<lbrace>valid_asid_map and
    cte_wp_at (weak_derived c) a and
    cte_wp_at (weak_derived c') b\<rbrace>
     cap_swap c a c' b \<lbrace>\<lambda>rv. valid_asid_map\<rbrace>"
  apply (simp add: cap_swap_def set_cdt_def valid_asid_map_def vspace_at_asid_def)
  apply (rule hoare_pre)
   apply (wp set_cap.vs_lookup|simp
          |rule hoare_lift_Pf [where f=arch_state])+
  done


lemma cap_swap_cap_refs_in_kernel_window[wp, CNodeInv_AI_assms]:
  "\<lbrace>cap_refs_in_kernel_window and
    cte_wp_at (weak_derived c) a and
    cte_wp_at (weak_derived c') b\<rbrace>
     cap_swap c a c' b \<lbrace>\<lambda>rv. cap_refs_in_kernel_window\<rbrace>"
  apply (simp add: cap_swap_def)
  apply (rule hoare_pre)
   apply (wp | simp split del: if_split)+
  apply (auto dest!: cap_refs_in_kernel_windowD
               simp: cte_wp_at_caps_of_state weak_derived_cap_range)
  done


lemma cap_swap_ioports[wp, CNodeInv_AI_assms]:
  "\<lbrace>valid_ioports and cte_wp_at (weak_derived c) a and cte_wp_at (weak_derived c') b\<rbrace>
     cap_swap c a c' b
   \<lbrace>\<lambda>rv. valid_ioports\<rbrace>"
  apply (simp add: valid_ioports_def all_ioports_issued_def ioports_no_overlap_def issued_ioports_def)
  apply (rule hoare_pre)
   apply (wp hoare_use_eq [where f=arch_state,
                           OF cap_swap_arch cap_swap_caps_of_state])
  apply (clarsimp simp: cte_wp_at_caps_of_state
                 elim!: ranE split: if_split_asm
                 dest!: weak_derived_cap_ioports)
  by (fastforce elim!: ranE split: if_split_asm)

lemma cap_swap_vms[wp, CNodeInv_AI_assms]:
  "\<lbrace>valid_machine_state\<rbrace>  cap_swap c a c' b \<lbrace>\<lambda>rv. valid_machine_state\<rbrace>"
  apply (simp add: valid_machine_state_def in_user_frame_def)
  apply (wp cap_swap_typ_at
            hoare_vcg_all_lift hoare_vcg_ex_lift hoare_vcg_disj_lift)
  done

(* FIXME x64: this could probably be generic *)
lemma unat_of_bl_nat_to_cref[CNodeInv_AI_assms]:
  "\<lbrakk> n < 2 ^ len; len < word_bits \<rbrakk>
    \<Longrightarrow> unat (of_bl (nat_to_cref len n) :: machine_word) = n"
  apply (simp add: nat_to_cref_def word_bits_conv of_drop_to_bl
                   word_size)
  apply (subst less_mask_eq)
   apply (rule order_less_le_trans)
    apply (erule of_nat_mono_maybe[rotated])
    apply (rule power_strict_increasing)
     apply simp
    apply simp
   apply simp
  apply (rule unat_of_nat_eq[where 'a=machine_word_len, unfolded word_bits_len_of])
  apply (erule order_less_trans)
  apply (rule power_strict_increasing)
   apply (simp add: word_bits_conv)
  apply simp
  done

lemma zombie_is_cap_toE_pre[CNodeInv_AI_assms]:
  "\<lbrakk> s \<turnstile> Zombie ptr zbits n; invs s; m < n \<rbrakk>
     \<Longrightarrow> (ptr, nat_to_cref (zombie_cte_bits zbits) m) \<in> cte_refs (Zombie ptr zbits n) irqn"
  apply (clarsimp simp add: valid_cap_def cap_aligned_def)
  apply (clarsimp split: option.split_asm)
   apply (simp add: unat_of_bl_nat_to_cref)
   apply (simp add: nat_to_cref_def word_bits_conv)
  apply (simp add: unat_of_bl_nat_to_cref)
  apply (simp add: nat_to_cref_def word_bits_conv)
  done

crunch st_tcb_at_halted[wp]: prepare_thread_delete "st_tcb_at halted t"

lemma finalise_cap_makes_halted_proof[CNodeInv_AI_assms]:
  "\<lbrace>invs and valid_cap cap and (\<lambda>s. ex = is_final_cap' cap s)
         and cte_wp_at ((=) cap) slot\<rbrace>
    finalise_cap cap ex
   \<lbrace>\<lambda>rv s. \<forall>t \<in> obj_refs (fst rv). halted_if_tcb t s\<rbrace>"
  apply (case_tac cap, simp_all)
            apply (wp unbind_notification_valid_objs
                   | clarsimp simp: o_def valid_cap_def cap_table_at_typ
                                    is_tcb obj_at_def
                   | clarsimp simp: halted_if_tcb_def
                             split: option.split
                   | intro impI conjI
                   | rule hoare_drop_imp)+
  apply (drule_tac final_zombie_not_live; (assumption | simp add: invs_iflive)?)
   apply (clarsimp simp: pred_tcb_at_def is_tcb obj_at_def live_def, elim disjE)
    apply (clarsimp; case_tac "tcb_state tcb"; simp)+
  apply (rename_tac arch_cap)
  apply (case_tac arch_cap, simp_all add: arch_finalise_cap_def)
      apply (wp
             | clarsimp simp: valid_cap_def obj_at_def is_tcb_def is_cap_table_def
                        split: option.splits bool.split
             | intro impI conjI)+
  done

lemmas finalise_cap_makes_halted = finalise_cap_makes_halted_proof

crunch emptyable[wp,CNodeInv_AI_assms]: finalise_cap "\<lambda>s. emptyable sl s"
  (simp: crunch_simps rule: emptyable_lift
     wp: crunch_wps suspend_emptyable unbind_notification_invs unbind_maybe_notification_invs)


lemma finalise_cap_not_reply_master_unlifted [CNodeInv_AI_assms]:
  "(rv, s') \<in> fst (finalise_cap cap sl s) \<Longrightarrow>
   \<not> is_master_reply_cap (fst rv)"
  by (case_tac cap, auto simp: is_cap_simps in_monad liftM_def
                               arch_finalise_cap_def
                        split: if_split_asm arch_cap.split_asm bool.split_asm option.split_asm)


lemma nat_to_cref_0_replicate [CNodeInv_AI_assms]:
  "\<And>n. n < word_bits \<Longrightarrow> nat_to_cref n 0 = replicate n False"
  apply (subgoal_tac "nat_to_cref n (unat (of_bl (replicate n False))) = replicate n False")
   apply simp
  apply (rule nat_to_cref_unat_of_bl')
   apply (simp add: word_bits_def)
  apply simp
  done

lemma prepare_thread_delete_thread_cap [CNodeInv_AI_assms]:
  "\<lbrace>\<lambda>s. caps_of_state s x = Some (cap.ThreadCap p)\<rbrace>
    prepare_thread_delete t
   \<lbrace>\<lambda>rv s. caps_of_state s x = Some (cap.ThreadCap p)\<rbrace>"
  by (wpsimp simp: prepare_thread_delete_def)

end


global_interpretation CNodeInv_AI?: CNodeInv_AI
  proof goal_cases
  interpret Arch .
  case 1 show ?case by (unfold_locales; (fact CNodeInv_AI_assms)?)
  qed


termination rec_del by (rule rec_del_termination)


context Arch begin global_naming X64

lemma post_cap_delete_pre_is_final_cap':
  "\<And>rv s'' rva s''a s.
       \<lbrakk>valid_ioports s; caps_of_state s slot = Some cap; is_final_cap' cap s; cap_cleanup_opt cap \<noteq> NullCap\<rbrakk>
       \<Longrightarrow> post_cap_delete_pre (cap_cleanup_opt cap) ((caps_of_state s)(slot \<mapsto> NullCap))"
  apply (clarsimp simp: cap_cleanup_opt_def cte_wp_at_def post_cap_delete_pre_def
                      split: cap.split_asm if_split_asm
                      elim!: ranE dest!: caps_of_state_cteD)
   (* IRQHandlerCap case *)
   apply (drule(2) final_cap_duplicate_irq)
     apply simp+
   (* IOPort case *)
  apply (clarsimp simp: arch_cap_cleanup_opt_def arch_post_cap_delete_pre_def
                        clearable_ioport_range_def get_cap_caps_of_state
                 elim!: ranE
                 split: arch_cap.split_asm if_split_asm)
  apply (drule_tac s="Some c" for c in sym)
  apply (rule ccontr)
  apply (frule_tac p=slot and cap="ArchObjectCap (IOPortCap x31 x32)" and cap'=cap'
                  in valid_ioportsD; (fastforce simp: ran_def)?)
  apply (case_tac cap'; clarsimp)
  apply (case_tac x12; clarsimp)
  apply (frule_tac p=slot and p'="(a,b)" and cap''=cap and cap'=cap
                         in is_final_cap_caps_of_state_2D; auto simp: gen_obj_refs_def)
  done

lemma rec_del_invs'':
  notes Inr_in_liftE_simp[simp del]
  assumes set_cap_Q[wp]: "\<And>cap p. \<lbrace>Q and invs\<rbrace> set_cap cap p \<lbrace>\<lambda>_.Q\<rbrace>"
  assumes empty_slot_Q[wp]: "\<And>slot free_irq. \<lbrace>Q and invs\<rbrace> empty_slot slot free_irq\<lbrace>\<lambda>_.Q\<rbrace>"
  assumes finalise_cap_Q[wp]: "\<And>cap final. \<lbrace>Q and invs\<rbrace> finalise_cap cap final \<lbrace>\<lambda>_.Q\<rbrace>"
  assumes cap_swap_for_delete_Q[wp]: "\<And>a b. \<lbrace>Q and invs and cte_at a and cte_at b and K (a \<noteq> b)\<rbrace>
                                              cap_swap_for_delete a b
                                             \<lbrace>\<lambda>_.Q\<rbrace>"
  assumes preemption_point_Q: "\<And>cap final. \<lbrace>Q and invs\<rbrace> preemption_point \<lbrace>\<lambda>_.Q\<rbrace>"
  shows
  "s \<turnstile> \<lbrace>Q and invs and valid_rec_del_call call
           and (\<lambda>s. \<not> exposed_rdcall call
                       \<longrightarrow> ex_cte_cap_wp_to (\<lambda>cp. cap_irqs cp = {})
                                (slot_rdcall call) s)
           and emptyable (slot_rdcall call)
           and (\<lambda>s. case call of ReduceZombieCall cap sl ex \<Rightarrow>
                               \<not> cap_removeable cap sl
                               \<and> (\<forall>t\<in>obj_refs cap. halted_if_tcb t s)
                        | _ \<Rightarrow> True)\<rbrace>
         rec_del call
       \<lbrace>\<lambda>rv s. Q s \<and> invs s \<and>
               (case call of FinaliseSlotCall sl x \<Rightarrow>
                             ((fst rv \<or> x) \<longrightarrow> cte_wp_at (replaceable s sl cap.NullCap) sl s)
                             \<and> (snd rv \<noteq> NullCap \<longrightarrow>
                                   post_cap_delete_pre (snd rv) ((caps_of_state s) (sl \<mapsto> cap.NullCap)))
                          | ReduceZombieCall cap sl x \<Rightarrow>
                             (\<not> x \<longrightarrow> ex_cte_cap_wp_to (\<lambda>cp. cap_irqs cp = {}) sl s)
                          | _ \<Rightarrow> True) \<and>
               emptyable (slot_rdcall call) s\<rbrace>,
       \<lbrace>\<lambda>rv. Q and invs\<rbrace>"
proof (induct rule: rec_del.induct,
       simp_all only: rec_del_fails)
  case (1 slot exposed s)
  show ?case
    apply (subst rec_del.simps)
    apply (simp only: split_def)
    apply wp
     apply (simp(no_asm))
     apply (wp empty_slot_invs empty_slot_emptyable)[1]
    apply (rule hoare_pre_spec_validE)
     apply (rule spec_strengthen_postE, unfold slot_rdcall.simps)
      apply (rule "1.hyps"[simplified rec_del_call.simps slot_rdcall.simps])
     apply clarsimp
     apply (auto simp: cte_wp_at_caps_of_state)
    done
next
  case (2 slot exposed s)
  show ?case
    apply (subst rec_del.simps)
    apply (simp only: split_def)
    apply (rule split_spec_bindE[rotated])
     apply (rule drop_spec_validE, simp)
     apply (rule get_cap_sp)
    apply (rule hoare_pre_spec_validE)
     apply (wp replace_cap_invs | simp)+
        apply (erule finalise_cap_not_reply_master)
       apply (wp "2.hyps")
         apply (wp preemption_point_Q | simp)+
         apply (wp preemption_point_inv, simp+)
         apply (wp preemption_point_Q)
         apply ((wp preemption_point_inv irq_state_independent_A_conjI irq_state_independent_AI
                    emptyable_irq_state_independent invs_irq_state_independent
               | simp add: valid_rec_del_call_def irq_state_independent_A_def)+)[1]
        apply (simp(no_asm))
        apply (rule spec_strengthen_postE)
        apply (rule "2.hyps"[simplified rec_del_call.simps slot_rdcall.simps conj_assoc], assumption+)
       apply (simp add: cte_wp_at_eq_simp
                | wp replace_cap_invs set_cap_sets final_cap_same_objrefs
                     set_cap_cte_cap_wp_to hoare_weak_lift_imp
                | erule finalise_cap_not_reply_master)+
       apply (wp hoare_vcg_const_Ball_lift)+
      apply (rule hoare_strengthen_post)
       apply (rule_tac Q="\<lambda>fin s. Q s \<and> invs s \<and> replaceable s slot (fst fin) rv
                                 \<and> cte_wp_at ((=) rv) slot s \<and> s \<turnstile> (fst fin)
                                 \<and> ex_cte_cap_wp_to (appropriate_cte_cap rv) slot s
                                 \<and> emptyable slot s
                                 \<and> (\<forall>t\<in>obj_refs (fst fin). halted_if_tcb t s)"
                  in hoare_vcg_conj_lift)
        apply (wp finalise_cap_invs[where slot=slot]
                  finalise_cap_replaceable[where sl=slot]
                  finalise_cap_makes_halted[where slot=slot])[1]
       apply (rule finalise_cap_cases[where slot=slot])
      apply (clarsimp simp: cte_wp_at_caps_of_state)
      apply (erule disjE)
       apply clarsimp
       apply (rule post_cap_delete_pre_is_final_cap', clarsimp+)
      apply (rule conjI)
       apply clarsimp
       apply (subst replaceable_def)
       apply (clarsimp simp: is_cap_simps tcb_cap_valid_NullCapD
                             no_cap_to_obj_with_diff_ref_Null gen_obj_refs_eq
                        del: disjCI)
       apply (thin_tac "appropriate_cte_cap a = appropriate_cte_cap b" for a b)
       apply (rule conjI)
        apply (clarsimp simp: replaceable_def)
        apply (erule disjE)
         apply (simp only: zobj_refs.simps mem_simps)
        apply clarsimp+
       subgoal
         apply (drule sym, simp)
         apply (drule sym, simp)
         apply clarsimp
         apply (simp add: unat_eq_0)
         apply (drule of_bl_eq_0)
          apply (drule zombie_cte_bits_less, simp add: word_bits_def)
         by (clarsimp simp: cte_wp_at_caps_of_state)
      apply (drule_tac s="appropriate_cte_cap c" for c in sym)
      apply (clarsimp simp: is_cap_simps appropriate_Zombie gen_obj_refs_eq)
     apply (simp add: is_final_cap_def)
     apply wp
    apply (clarsimp simp: cte_wp_at_eq_simp)
    apply (rule conjI)
     apply (clarsimp simp: cte_wp_at_caps_of_state replaceable_def)
    apply (frule cte_wp_at_valid_objs_valid_cap, clarsimp+)
    apply (frule invs_valid_asid_table)
    apply (frule invs_sym_refs)
    apply (clarsimp simp: invs_def valid_state_def
                          invs_valid_objs invs_psp_aligned)
    apply (drule(1) if_unsafe_then_capD, clarsimp+)
    done
next
  have replicate_helper:
    "\<And>x n. True \<in> set x \<Longrightarrow> replicate n False \<noteq> x"
   by (clarsimp simp: replicate_not_True)
  case (3 ptr bits n slot s)
  show ?case
    apply simp
    apply wp+
    apply clarsimp
    apply (rule context_conjI')
     apply (rule context_conjI')
      apply (rule conjI)
       apply (erule zombie_is_cap_toE2)
        apply simp+
      apply (clarsimp simp: halted_emptyable)
      apply (rule conjI, clarsimp simp: cte_wp_at_caps_of_state)
       apply (erule tcb_valid_nonspecial_cap)
         apply fastforce
        apply (clarsimp simp: ran_tcb_cap_cases is_cap_simps
                       split: Structures_A.thread_state.splits)
       apply (clarsimp simp: is_cap_simps)
      apply (rule conjI)
       apply (drule cte_wp_valid_cap, clarsimp)
       apply (frule cte_at_nat_to_cref_zbits [where m=0], simp)
       apply (rule cte_wp_at_not_reply_master)
          apply (simp add: replicate_helper tcb_cnode_index_def)
         apply (subst(asm) nat_to_cref_0_replicate)
          apply (simp add: zombie_cte_bits_less)
         apply assumption
        apply clarsimp
       apply (simp add: invs_def valid_state_def)
      apply (clarsimp simp: cte_wp_at_caps_of_state is_cap_simps)
     apply (erule cte_wp_at_weakenE | clarsimp)+
    done
next
  have nat_helper:
    "\<And>x n. \<lbrakk> x < Suc n; x \<noteq> n \<rbrakk> \<Longrightarrow> x < n"
    by (simp add: le_simps)
  case (4 ptr bits n slot s)
  show ?case
    apply simp
    apply (rule hoare_pre_spec_validE)
     apply (wp replace_cap_invs | simp add: is_cap_simps)+
      apply (rule_tac Q="\<lambda>rv s. Q s \<and> invs s \<and> cte_wp_at (\<lambda>cap. cap = rv) slot s
                             \<and> cte_wp_at (\<lambda>cap. cap = cap.NullCap
                                        \<or> \<not> False \<and> is_zombie cap
                                            \<and> (ptr, nat_to_cref (zombie_cte_bits bits) n)
                                                 \<in> fst_cte_ptrs cap)
                                    (ptr, nat_to_cref (zombie_cte_bits bits) n) s
                             \<and> \<not> cap_removeable (cap.Zombie ptr bits (Suc n)) slot"
                  in hoare_post_imp)
       apply (thin_tac "(a, b) \<in> fst c" for a b c)
       apply clarsimp
       apply (frule cte_wp_at_emptyableD, clarsimp, assumption)
       apply (rule conjI[rotated], (clarsimp simp: is_cap_simps)+)
       apply (frule cte_wp_at_valid_objs_valid_cap, clarsimp+)
       apply (frule if_unsafe_then_capD, clarsimp+)
       apply (rule conjI)
        apply (frule zombies_finalD, (clarsimp simp: is_cap_simps)+)
        apply (clarsimp simp: cte_wp_at_caps_of_state)
        apply (erule disjE[where P="val = cap.NullCap" for val])
         apply (clarsimp simp: replaceable_def cap_range_def is_cap_simps
                               gen_obj_refs_subset vs_cap_ref_def)
         apply (rule conjI[rotated])
          apply (rule conjI)
           apply (rule mp [OF tcb_cap_valid_imp'])
           apply (fastforce simp: ran_tcb_cap_cases is_cap_simps
                                 is_pt_cap_def vs_cap_ref_def
                                 valid_ipc_buffer_cap_def
                          split: Structures_A.thread_state.splits)
          apply (drule unique_table_refs_no_cap_asidD)
           apply (simp add: invs_def valid_state_def valid_arch_caps_def)
          apply (simp add: no_cap_to_obj_with_diff_ref_def Ball_def
                           table_cap_ref_def)
         apply clarsimp
         apply (rule ccontr, erule notE, erule nat_helper)
         apply clarsimp
         apply (erule disjE[where Q="val = slot" for val])
          apply (clarsimp simp: cte_wp_at_caps_of_state)
          apply (erule notE[rotated, where P="val = Some cap.NullCap" for val])
          apply (drule sym, simp, subst nat_to_cref_unat_of_bl)
           apply (drule zombie_cte_bits_less, simp add: word_bits_def)
          apply assumption
         apply clarsimp
         apply (drule sym, simp)
         apply (subst(asm) nat_to_cref_unat_of_bl)
          apply (drule zombie_cte_bits_less, simp add: word_bits_conv)
         apply simp
        apply (clarsimp simp: is_final_cap'_def3 simp del: split_paired_All)
        apply (frule_tac x=slot in spec)
        apply (drule_tac x="(ptr, nat_to_cref (zombie_cte_bits bits) n)" in spec)
        apply (clarsimp simp: cte_wp_at_caps_of_state fst_cte_ptrs_def
                              gen_obj_refs_Int)
        apply (drule(1) nat_to_cref_replicate_Zombie[OF sym])
         apply simp
        apply simp
       apply (clarsimp simp: valid_cap_def cap_aligned_def is_cap_simps
                             cte_wp_at_cte_at appropriate_Zombie
                      split: option.split_asm)
      apply (wp get_cap_cte_wp_at)[1]
     apply simp
     apply (subst conj_assoc[symmetric])
     apply (rule spec_valid_conj_liftE2)
      apply (wp rec_del_delete_cases[where ex=False, simplified])[1]
     apply (rule spec_strengthen_postE)
      apply (rule "4.hyps"[simplified rec_del_call.simps slot_rdcall.simps simp_thms pred_conj_def])
      apply (simp add: in_monad)
     apply simp
    apply (clarsimp simp: halted_emptyable)
    apply (erule(1) zombie_is_cap_toE)
     apply simp
    apply simp
    done
qed


lemmas rec_del_invs'[CNodeInv_AI_assms] = rec_del_invs'' [where Q=\<top>,
  simplified hoare_post_taut pred_conj_def simp_thms, OF TrueI TrueI TrueI TrueI, simplified]

end


global_interpretation CNodeInv_AI_2?: CNodeInv_AI_2
  proof goal_cases
  interpret Arch .
  case 1 show ?case by (unfold_locales; (fact CNodeInv_AI_assms)?)
  qed


context Arch begin global_naming X64

lemma finalise_cap_rvk_prog [CNodeInv_AI_assms]:
   "\<lbrace>\<lambda>s. revoke_progress_ord m (\<lambda>x. map_option cap_to_rpo (caps_of_state s x))\<rbrace>
   finalise_cap a b
   \<lbrace>\<lambda>_ s. revoke_progress_ord m (\<lambda>x. map_option cap_to_rpo (caps_of_state s x))\<rbrace>"
  apply (case_tac a,simp_all add:liftM_def)
    apply (wp suspend_rvk_prog deleting_irq_handler_rvk_prog
      | clarsimp simp:is_final_cap_def comp_def)+
  done


lemma rec_del_rvk_prog [CNodeInv_AI_assms]:
  "st \<turnstile> \<lbrace>\<lambda>s. revoke_progress_ord m (option_map cap_to_rpo \<circ> caps_of_state s)
          \<and> (case args of ReduceZombieCall cap sl ex \<Rightarrow>
               cte_wp_at (\<lambda>c. c = cap) sl s \<and> is_final_cap' cap s
             | _ \<Rightarrow> True)\<rbrace>
     rec_del args
   \<lbrace>\<lambda>rv s. revoke_progress_ord m (option_map cap_to_rpo \<circ> caps_of_state s)\<rbrace>,\<lbrace>\<top>\<top>\<rbrace>"
proof (induct rule: rec_del.induct,
       simp_all only: rec_del_fails)
  case (1 slot exposed s)
  note wp = "1.hyps"[simplified rdcall_simps simp_thms]
  show ?case
    apply (subst rec_del.simps)
    apply (simp only: rdcall_simps simp_thms split_def)
    apply wp
     apply (simp(no_asm) del: o_apply)
     apply (wp empty_slot_rvk_prog)[1]
    apply (simp del: o_apply)
    apply (rule wp)
    done
next
  case (2 sl exp s)
  note wp = "2.hyps" [simplified rdcall_simps simp_thms]
  show ?case
    apply (subst rec_del.simps)
    apply (simp only: rdcall_simps simp_thms split_def)
    apply (rule hoare_pre_spec_validE)
     apply wp
         apply ((wp | simp)+)[1]
        apply (wp wp)
          apply ((wp preemption_point_inv | simp)+)[1]
         apply (simp(no_asm))
         apply (rule wp, assumption+)
        apply (wp final_cap_same_objrefs
                  set_cap_cte_wp_at_cases
                   | simp)+
       apply (rule hoare_strengthen_post)
        apply (rule_tac Q="\<lambda>fc s. cte_wp_at ((=) rv) sl s
                              \<and> revoke_progress_ord m (option_map cap_to_rpo \<circ> caps_of_state s)"
                 in hoare_vcg_conj_lift)
         apply (wp finalise_cap_rvk_prog[folded o_def])[1]
        apply (rule finalise_cap_cases[where slot=sl])
       apply (clarsimp simp: o_def)
       apply (strengthen rvk_prog_update_strg[unfolded fun_upd_def o_def])
       apply (clarsimp simp: cte_wp_at_caps_of_state)
       apply (erule disjE)
        apply clarsimp
       apply (clarsimp simp: is_cap_simps)
       apply (case_tac "is_zombie rv")
        apply (clarsimp simp: cap_to_rpo_def is_cap_simps fst_cte_ptrs_def)
        apply (simp add: is_final_cap'_def)
       apply (case_tac rv, simp_all add: cap_to_rpo_def is_cap_simps gen_obj_refs_eq)[1]
       apply (rename_tac arch_cap)
       apply (case_tac arch_cap, simp_all)[1]
      apply (simp add: is_final_cap_def, wp)
     apply (simp, wp get_cap_wp)
    apply (clarsimp simp: o_def)
    done
next
  case (3 ptr bits n slot s)
  show ?case
    apply simp
    apply (fold o_def)
    apply (rule hoare_pre_spec_validE)
     apply (simp del: o_apply | wp (once) cap_swap_fd_rvk_prog)+
    apply (clarsimp simp: cte_wp_at_caps_of_state cap_to_rpo_def)
    done
next
  case (4 ptr zb znum sl s)
  note wp = "4.hyps"[simplified rdcall_simps]
  show ?case
    apply (subst rec_del.simps)
    apply wp
        apply (wp | simp)+
      apply (wp get_cap_wp)[1]
     apply (rule spec_strengthen_postE)
      apply (rule wp, assumption+)
     apply (clarsimp simp: cte_wp_at_caps_of_state is_cap_defs)
     apply (strengthen rvk_prog_update_strg[unfolded fun_upd_def o_def])
     apply (clarsimp simp: cte_wp_at_caps_of_state cap_to_rpo_def)
    apply (wp | simp add: o_def)+
    done
qed

end


global_interpretation CNodeInv_AI_3?: CNodeInv_AI_3
  proof goal_cases
  interpret Arch .
  case 1 show ?case by (unfold_locales; (fact CNodeInv_AI_assms)?)
  qed


termination cap_revoke by (rule cap_revoke_termination)

declare cap_revoke.simps[simp del]


context Arch begin global_naming X64

crunch typ_at[wp, CNodeInv_AI_assms]: finalise_slot "\<lambda>s. P (typ_at T p s)"
  (wp: crunch_wps simp: crunch_simps filterM_mapM unless_def
   ignore: without_preemption filterM set_object clearMemory)


lemma weak_derived_appropriate [CNodeInv_AI_assms]:
  "weak_derived cap cap' \<Longrightarrow> appropriate_cte_cap cap = appropriate_cte_cap cap'"
  by (auto simp: weak_derived_def copy_of_def same_object_as_def2
                 appropriate_cte_master
          split: if_split_asm
          dest!: arg_cong[where f=appropriate_cte_cap])

end


global_interpretation CNodeInv_AI_4?: CNodeInv_AI_4
  proof goal_cases
  interpret Arch .
  case 1 show ?case by (unfold_locales; (fact CNodeInv_AI_assms)?)
  qed


context Arch begin global_naming X64

lemma cap_move_ioports:
  "\<lbrace>valid_ioports and cte_wp_at ((=) cap.NullCap) ptr'
         and cte_wp_at (weak_derived cap) ptr
         and cte_wp_at (\<lambda>c. c \<noteq> cap.NullCap) ptr and K (ptr \<noteq> ptr')\<rbrace>
     cap_move cap ptr ptr'
   \<lbrace>\<lambda>rv. valid_ioports\<rbrace>"
  apply (simp add: valid_ioports_def all_ioports_issued_def ioports_no_overlap_def issued_ioports_def)
  apply (rule hoare_pre)
   apply (wp hoare_use_eq [where f=arch_state,
                           OF cap_move_arch cap_move_caps_of_state])
  apply (clarsimp simp: cte_wp_at_caps_of_state
                 elim!: ranE split: if_split_asm
                 dest!: weak_derived_cap_ioports)
  by (fastforce elim!: ranE split: if_split_asm)

lemma cap_move_invs[wp, CNodeInv_AI_assms]:
  "\<lbrace>invs and valid_cap cap and cte_wp_at ((=) cap.NullCap) ptr'
         and tcb_cap_valid cap ptr'
         and cte_wp_at (weak_derived cap) ptr
         and cte_wp_at (\<lambda>c. c \<noteq> cap.NullCap) ptr
         and ex_cte_cap_wp_to (appropriate_cte_cap cap) ptr' and K (ptr \<noteq> ptr')
         and K (\<not> is_master_reply_cap cap)\<rbrace>
     cap_move cap ptr ptr'
   \<lbrace>\<lambda>rv. invs\<rbrace>"
  unfolding invs_def valid_state_def valid_pspace_def
  apply (simp add: pred_conj_def conj_comms [where Q = "valid_mdb S" for S])
  apply wp
   apply (wpe cap_move_zombies_final)
   apply (wpe cap_move_if_live)
   apply (wpe cap_move_if_unsafe)
   apply (wpe cap_move_irq_handlers)
   apply (wpe cap_move_replies)
   apply (wpe cap_move_valid_arch_caps)
   apply (wpe cap_move_valid_ioc)
   apply (wpe cap_move_ioports)
   apply (simp add: cap_move_def set_cdt_def)
   apply (rule hoare_pre)
    apply (wp set_cap_valid_objs set_cap_idle set_cap_typ_at
              cap_table_at_lift_irq tcb_at_typ_at
              hoare_vcg_disj_lift hoare_vcg_all_lift
              set_cap_cap_refs_respects_device_region_NullCap
            | wp set_cap_cap_refs_respects_device_region_spec[where ptr=ptr]
            | simp del: split_paired_Ex split_paired_All
            | simp add: valid_irq_node_def valid_machine_state_def
                   del: split_paired_All split_paired_Ex)+
   apply (clarsimp simp: tcb_cap_valid_def cte_wp_at_caps_of_state)
   apply (frule(1) valid_global_refsD2[where ptr=ptr])
   apply (frule(1) cap_refs_in_kernel_windowD[where ptr=ptr])
   apply (frule weak_derived_cap_range)
   apply (frule weak_derived_is_reply_master)
   apply (simp add: cap_range_NullCap valid_ipc_buffer_cap_def[where c=cap.NullCap])
   apply (simp add: is_cap_simps)
   apply (subgoal_tac "tcb_cap_valid cap.NullCap ptr s")
    apply (simp add: tcb_cap_valid_def weak_derived_cap_is_device)
   apply (rule tcb_cap_valid_NullCapD)
    apply (erule(1) tcb_cap_valid_caps_of_stateD)
   apply (simp add: is_cap_simps)
   done

lemma arch_derive_is_arch:
  "\<lbrace>\<top>\<rbrace> arch_derive_cap c \<lbrace>\<lambda>rv s. rv \<noteq> NullCap \<longrightarrow> is_arch_cap rv\<rbrace>,-"
  by (wpsimp simp: is_arch_cap_def arch_derive_cap_def)

end


global_interpretation CNodeInv_AI_5?: CNodeInv_AI_5
  proof goal_cases
  interpret Arch .
  case 1 show ?case by (unfold_locales; (fact CNodeInv_AI_assms)?)
  qed


end
