diff --git a/proof/refine/AARCH64/Refine.thy b/proof/refine/AARCH64/Refine.thy new file mode 100644 index 000000000..5a33212dc --- /dev/null +++ b/proof/refine/AARCH64/Refine.thy @@ -0,0 +1,1016 @@ +(* + * Copyright 2023, Proofcraft Pty Ltd + * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: GPL-2.0-only + *) + +(* + The main theorem +*) + +theory Refine +imports + KernelInit_R + ADT_H + InitLemmas + PageTableDuplicates +begin + +context begin interpretation Arch . (*FIXME: arch_split*) + +text \User memory content is the same on both levels\ +lemma typ_at_AUserDataI: + "\ typ_at (AArch (AUserData sz)) p s; pspace_relation (kheap s) (ksPSpace s'); + pspace_aligned' s'; pspace_distinct' s'; n < 2 ^ (pageBitsForSize sz - pageBits) \ + \ typ_at' UserDataT (p + n * 2 ^ pageBits) s'" + apply (clarsimp simp add: obj_at_def a_type_def ) + apply (simp split: Structures_A.kernel_object.split_asm + arch_kernel_obj.split_asm split: if_split_asm) + apply (drule(1) pspace_relation_absD) + apply (clarsimp) + apply (drule_tac x = "p + n * 2 ^ pageBits" in spec) + apply (drule_tac x = "\_ obj. obj = KOUserData" in spec) + apply (clarsimp simp: obj_at'_def typ_at'_def ko_wp_at'_def) + apply (rule exI [where x = KOUserData]) + apply (drule mp) + apply (rule exI [where x = n]) + apply (simp add: shiftl_t2n) + apply (clarsimp simp: pspace_aligned'_def) + apply (drule (1) bspec [OF _ domI]) + apply (clarsimp simp: objBits_simps) + apply (fastforce dest!: pspace_distinctD' simp: objBits_simps) + done + +lemma typ_at_ADeviceDataI: + "\ typ_at (AArch (ADeviceData sz)) p s; pspace_relation (kheap s) (ksPSpace s'); + pspace_aligned' s'; pspace_distinct' s'; n < 2 ^ (pageBitsForSize sz - pageBits) \ + \ typ_at' UserDataDeviceT (p + n * 2 ^ pageBits) s'" + apply (clarsimp simp add: obj_at_def a_type_def ) + apply (simp split: Structures_A.kernel_object.split_asm + arch_kernel_obj.split_asm split: if_split_asm) + apply (drule(1) pspace_relation_absD) + apply (clarsimp) + apply (drule_tac x = "p + n * 2 ^ pageBits" in spec) + apply (drule_tac x = "\_ obj. obj = KOUserDataDevice" in spec) + apply (clarsimp simp: obj_at'_def typ_at'_def ko_wp_at'_def) + apply (rule exI [where x = KOUserDataDevice]) + apply (drule mp) + apply (rule exI [where x = n]) + apply (simp add: shiftl_t2n) + apply (clarsimp simp: pspace_aligned'_def) + apply (drule (1) bspec [OF _ domI]) + apply (clarsimp simp: objBits_simps) + apply (fastforce dest!: pspace_distinctD' simp: objBits_simps) + done + +lemma typ_at_UserDataI: + "\ typ_at' UserDataT (p && ~~ mask pageBits) s'; + pspace_relation (kheap s) (ksPSpace s'); pspace_aligned s \ + \ \sz. typ_at (AArch (AUserData sz)) (p && ~~ mask (pageBitsForSize sz)) s" + apply (clarsimp simp: exists_disj obj_at'_def typ_at'_def ko_wp_at'_def) + apply (frule (1) in_related_pspace_dom) + apply (clarsimp simp: pspace_dom_def) + apply (clarsimp simp: pspace_relation_def dom_def) + apply (erule allE, erule impE, blast) + apply clarsimp + apply (drule (1) bspec) + apply clarsimp + apply (subst mask_lower_twice [where n = pageBits, OF pbfs_atleast_pageBits, symmetric]) + apply (clarsimp simp: obj_relation_cuts_def2 pte_relation_def + cte_relation_def other_obj_relation_def + split: Structures_A.kernel_object.split_asm + Structures_H.kernel_object.split_asm + if_split_asm arch_kernel_obj.split_asm) + apply (rename_tac vmpage_size n) + apply (rule_tac x = vmpage_size in exI) + apply (subst conjunct2 [OF is_aligned_add_helper]) + apply (drule (1) pspace_alignedD) + apply simp + apply (simp add: shiftl_t2n mult_ac) + apply (erule word_less_power_trans2 [OF _ pbfs_atleast_pageBits]) + apply (case_tac vmpage_size, simp_all add: word_bits_conv bit_simps)[1] + apply (simp add: obj_at_def a_type_def) + done + +lemma typ_at_DeviceDataI: + "\ typ_at' UserDataDeviceT (p && ~~ mask pageBits) s'; + pspace_relation (kheap s) (ksPSpace s'); pspace_aligned s \ + \ \sz. typ_at (AArch (ADeviceData sz)) (p && ~~ mask (pageBitsForSize sz)) s" + apply (clarsimp simp: exists_disj obj_at'_def typ_at'_def ko_wp_at'_def) + apply (frule (1) in_related_pspace_dom) + apply (clarsimp simp: pspace_dom_def) + apply (clarsimp simp: pspace_relation_def dom_def) + apply (erule allE, erule impE, blast) + apply clarsimp + apply (drule (1) bspec) + apply clarsimp + apply (subst mask_lower_twice [where n = pageBits, OF pbfs_atleast_pageBits, symmetric]) + apply (clarsimp simp: obj_relation_cuts_def2 pte_relation_def + cte_relation_def other_obj_relation_def + split: Structures_A.kernel_object.split_asm + Structures_H.kernel_object.split_asm + if_split_asm arch_kernel_obj.split_asm) + apply (rename_tac vmpage_size n) + apply (rule_tac x = vmpage_size in exI) + apply (subst conjunct2 [OF is_aligned_add_helper]) + apply (drule (1) pspace_alignedD) + apply simp + apply (simp add: shiftl_t2n mult_ac) + apply (erule word_less_power_trans2 [OF _ pbfs_atleast_pageBits]) + apply (case_tac vmpage_size, simp_all add: word_bits_conv bit_simps)[1] + apply (simp add: obj_at_def a_type_def) + done + +lemma pointerInUserData_relation: + "\ (s,s') \ state_relation; valid_state' s'; valid_state s\ + \ pointerInUserData p s' = in_user_frame p s" + apply (simp add: pointerInUserData_def in_user_frame_def) + apply (rule iffI) + apply (erule typ_at_UserDataI, (clarsimp simp: valid_state_def)+)[1] + apply clarsimp + apply (drule_tac sz = sz and + n = "(p && mask (pageBitsForSize sz)) >> pageBits" + in typ_at_AUserDataI [where s = s and s' = s']) + apply (fastforce simp: valid_state'_def)+ + apply (rule shiftr_less_t2n') + apply (simp add: pbfs_atleast_pageBits mask_twice) + apply (case_tac sz, simp_all add: bit_simps)[1] + apply (subgoal_tac "(p && ~~ mask (pageBitsForSize sz)) + (p && mask (pageBitsForSize sz) >> pageBits) * 2 ^ pageBits = (p && ~~ mask pageBits)") + apply simp + apply (subst mult.commute) + apply (subst shiftl_t2n [symmetric]) + apply (simp add: shiftr_shiftl1) + apply (subst mask_out_add_aligned) + apply (rule is_aligned_neg_mask) + apply (simp add: pbfs_atleast_pageBits) + apply (subst add.commute) + apply (simp add: word_plus_and_or_coroll2) + done + +lemma pointerInDeviceData_relation: + "\ (s,s') \ state_relation; valid_state' s'; valid_state s\ + \ pointerInDeviceData p s' = in_device_frame p s" + apply (simp add: pointerInDeviceData_def in_device_frame_def) + apply (rule iffI) + apply (erule typ_at_DeviceDataI, (clarsimp simp: valid_state_def)+)[1] + apply clarsimp + apply (drule_tac sz = sz and + n = "(p && mask (pageBitsForSize sz)) >> pageBits" + in typ_at_ADeviceDataI [where s = s and s' = s']) + apply (fastforce simp: valid_state'_def)+ + apply (rule shiftr_less_t2n') + apply (simp add: pbfs_atleast_pageBits mask_twice) + apply (case_tac sz, simp_all add: bit_simps)[1] + apply (subgoal_tac "(p && ~~ mask (pageBitsForSize sz)) + (p && mask (pageBitsForSize sz) >> pageBits) * 2 ^ pageBits = (p && ~~ mask pageBits)") + apply simp + apply (subst mult.commute) + apply (subst shiftl_t2n [symmetric]) + apply (simp add: shiftr_shiftl1) + apply (subst mask_out_add_aligned) + apply (rule is_aligned_neg_mask) + apply (simp add: pbfs_atleast_pageBits) + apply (subst add.commute) + apply (simp add: word_plus_and_or_coroll2) + done + +lemma user_mem_relation: + "\(s,s') \ state_relation; valid_state' s'; valid_state s\ + \ user_mem' s' = user_mem s" + apply (rule ext) + apply (clarsimp simp: user_mem_def user_mem'_def pointerInUserData_relation pointerInDeviceData_relation) + apply (simp add: state_relation_def) + done + +lemma device_mem_relation: + "\(s,s') \ state_relation; valid_state' s'; valid_state s\ + \ device_mem' s' = device_mem s" + apply (rule ext) + apply (clarsimp simp: device_mem_def device_mem'_def pointerInUserData_relation + pointerInDeviceData_relation) + done + +lemma absKState_correct: + assumes invs: "einvs (s :: det_ext state)" and invs': "invs' s'" + assumes rel: "(s,s') \ state_relation" + shows "absKState s' = abs_state s" + using assms + apply (intro state.equality, simp_all add: absKState_def abs_state_def) + apply (rule absHeap_correct, clarsimp+) + apply (clarsimp elim!: state_relationE) + apply (rule absCDT_correct, clarsimp+) + apply (rule absIsOriginalCap_correct, clarsimp+) + apply (simp add: state_relation_def) + apply (simp add: state_relation_def) + apply (clarsimp simp: user_mem_relation invs_def invs'_def) + apply (simp add: state_relation_def) + apply (rule absInterruptIRQNode_correct, simp add: state_relation_def) + apply (rule absInterruptStates_correct, simp add: state_relation_def) + apply (rule absArchState_correct, simp) + apply (rule absExst_correct, simp+) + done + +text \The top-level invariance\ + +lemma set_thread_state_sched_act: + "\(\s. runnable state) and (\s. P (scheduler_action s))\ + set_thread_state thread state + \\rs s. P (scheduler_action (s::det_state))\" + apply (simp add: set_thread_state_def) + apply wp + apply (simp add: set_thread_state_ext_def) + apply wp + apply (rule hoare_pre_cont) + apply (rule_tac Q="\rv. (\s. runnable ts) and (\s. P (scheduler_action s))" + in hoare_strengthen_post) + apply wp + apply force + apply (wp gts_st_tcb_at)+ + apply (rule_tac Q="\rv. st_tcb_at ((=) state) thread and (\s. runnable state) and (\s. P (scheduler_action s))" in hoare_strengthen_post) + apply (simp add: st_tcb_at_def) + apply (wp obj_set_prop_at)+ + apply (force simp: st_tcb_at_def obj_at_def) + apply wp + apply clarsimp + done + +lemma activate_thread_sched_act: + "\ct_in_state activatable and (\s. P (scheduler_action s))\ + activate_thread + \\rs s. P (scheduler_action (s::det_state))\" + by (simp add: activate_thread_def set_thread_state_def arch_activate_idle_thread_def + | (wp set_thread_state_sched_act gts_wp)+ | wpc)+ + +lemma schedule_sched_act_rct[wp]: + "\\\ Schedule_A.schedule + \\rs (s::det_state). scheduler_action s = resume_cur_thread\" + unfolding Schedule_A.schedule_def + by (wpsimp) + +lemma call_kernel_sched_act_rct[wp]: + "\einvs and (\s. e \ Interrupt \ ct_running s) + and (\s. scheduler_action s = resume_cur_thread)\ + call_kernel e + \\rs (s::det_state). scheduler_action s = resume_cur_thread\" + apply (simp add: call_kernel_def) + apply (wp activate_thread_sched_act | simp)+ + apply (clarsimp simp: active_from_running) + done + +lemma kernel_entry_invs: + "\einvs and (\s. e \ Interrupt \ ct_running s) + and (\s. 0 < domain_time s) and valid_domain_list and (ct_running or ct_idle) + and (\s. scheduler_action s = resume_cur_thread)\ + kernel_entry e us + \\rv. einvs and (\s. ct_running s \ ct_idle s) + and (\s. 0 < domain_time s) and valid_domain_list + and (\s. scheduler_action s = resume_cur_thread)\" + apply (rule_tac Q="\rv. invs and (\s. ct_running s \ ct_idle s) and valid_sched and + (\s. 0 < domain_time s) and valid_domain_list and + valid_list and (\s. scheduler_action s = resume_cur_thread)" + in hoare_post_imp) + apply clarsimp + apply (simp add: kernel_entry_def) + apply (wp akernel_invs_det_ext call_kernel_valid_sched thread_set_invs_trivial + thread_set_ct_running thread_set_not_state_valid_sched + hoare_vcg_disj_lift ct_in_state_thread_state_lift thread_set_no_change_tcb_state + call_kernel_domain_time_inv_det_ext call_kernel_domain_list_inv_det_ext + static_imp_wp + | clarsimp simp add: tcb_cap_cases_def active_from_running)+ + done + +definition + "full_invs \ {((tc, s :: det_ext state), m, e). einvs s \ + (ct_running s \ ct_idle s) \ + (m = KernelMode \ e \ None) \ + (m = UserMode \ ct_running s) \ + (m = IdleMode \ ct_idle s) \ + (e \ None \ e \ Some Interrupt \ ct_running s) \ + 0 < domain_time s \ valid_domain_list s \ + (scheduler_action s = resume_cur_thread)}" + +lemma do_user_op_valid_list:"\valid_list\ do_user_op f tc \\_. valid_list\" + unfolding do_user_op_def + apply (wp select_wp | simp add: split_def)+ + done + +lemma do_user_op_valid_sched:"\valid_sched\ do_user_op f tc \\_. valid_sched\" + unfolding do_user_op_def + apply (wp select_wp | simp add: split_def)+ + done + +lemma do_user_op_sched_act: + "\\s. P (scheduler_action s)\ do_user_op f tc \\_ s. P (scheduler_action s)\" + unfolding do_user_op_def + apply (wp select_wp | simp add: split_def)+ + done + +lemma do_user_op_invs2: + "\einvs and ct_running and (\s. scheduler_action s = resume_cur_thread) + and (\s. 0 < domain_time s) and valid_domain_list \ + do_user_op f tc + \\_. (einvs and ct_running and (\s. scheduler_action s = resume_cur_thread)) + and (\s. 0 < domain_time s) and valid_domain_list \" + apply (rule_tac Q="\_. valid_list and valid_sched and + (\s. scheduler_action s = resume_cur_thread) and (invs and ct_running) and + (\s. 0 < domain_time s) and valid_domain_list" + in hoare_strengthen_post) + apply (wp do_user_op_valid_list do_user_op_valid_sched do_user_op_sched_act + do_user_op_invs | simp | force)+ + done + +lemmas ext_init_def = ext_init_det_ext_ext_def ext_init_unit_def + +lemma valid_list_init[simp]: + "valid_list init_A_st" + by (simp add: valid_list_2_def init_A_st_def ext_init_def init_cdt_def) + +lemmas valid_list_inits[simp] = valid_list_init[simplified] + +lemma valid_sched_init[simp]: + "valid_sched init_A_st" + apply (simp add: valid_sched_def init_A_st_def ext_init_def) + apply (clarsimp simp: valid_etcbs_def init_kheap_def st_tcb_at_kh_def obj_at_kh_def + obj_at_def is_etcb_at_def idle_thread_ptr_def + valid_queues_2_def ct_not_in_q_def not_queued_def + valid_sched_action_def is_activatable_def init_irq_node_ptr_def + arm_global_pt_ptr_def + ct_in_cur_domain_2_def valid_blocked_2_def valid_idle_etcb_def + etcb_at'_def default_etcb_def) + done + +lemma valid_domain_list_init[simp]: + "valid_domain_list init_A_st" + by (simp add: init_A_st_def ext_init_def valid_domain_list_def) + +lemma akernel_invariant: + "ADT_A uop \ full_invs" + unfolding full_invs_def + apply (rule invariantI) + apply (clarsimp simp: ADT_A_def subset_iff) + apply (frule bspec[OF akernel_init_invs]) + apply (simp add: Let_def Init_A_def) + apply (simp add: init_A_st_def ext_init_def) + apply (clarsimp simp: ADT_A_def global_automaton_def) + + apply (rename_tac tc' s' mode' e' tc s mode e) + apply (elim disjE) + apply ((clarsimp simp: kernel_call_A_def + | drule use_valid[OF _ kernel_entry_invs])+)[2] + apply ((clarsimp simp: do_user_op_A_def monad_to_transition_def + check_active_irq_A_def + | drule use_valid[OF _ do_user_op_invs2] + | drule use_valid[OF _ check_active_irq_invs_just_running])+)[2] + apply ((clarsimp simp add: check_active_irq_A_def + | drule use_valid[OF _ check_active_irq_invs])+)[1] + apply (clarsimp simp: ct_in_state_def st_tcb_at_def obj_at_def) + apply ((clarsimp simp add: do_user_op_A_def check_active_irq_A_def + | drule use_valid[OF _ do_user_op_invs2] + | drule use_valid[OF _ check_active_irq_invs_just_running])+)[1] + apply (clarsimp simp: ct_in_state_def st_tcb_at_def obj_at_def) + apply (clarsimp simp: ct_in_state_def st_tcb_at_def obj_at_def) + apply ((clarsimp simp add: check_active_irq_A_def + | drule use_valid[OF _ check_active_irq_invs])+)[1] + apply ((clarsimp simp add: check_active_irq_A_def + | drule use_valid[OF _ check_active_irq_invs_just_idle])+)[1] + apply ((clarsimp simp add: check_active_irq_A_def + | drule use_valid[OF _ check_active_irq_invs])+)[1] + done + +(* FIXME AARCH64 originally in PageTableDuplicates *) +lemma dmo_getActiveIRQ_notin_non_kernel_IRQs[wp]: + "\\\ doMachineOp (getActiveIRQ True) \\irq _. irq \ Some ` non_kernel_IRQs\" + unfolding doMachineOp_def + by (wpsimp simp: getActiveIRQ_def in_monad split: if_split_asm) + +(* FIXME AARCH64 originally in PageTableDuplicates *) +lemma non_kernel_IRQs_strg: + "invs' s \ irq \ Some ` non_kernel_IRQs \ Q \ + (\y. irq = Some y) \ invs' s \ (the irq \ non_kernel_IRQs \ P) \ Q" + by auto + +lemma ckernel_invs: + "\invs' and + (\s. e \ Interrupt \ ct_running' s) and + (\s. ksSchedulerAction s = ResumeCurrentThread)\ + callKernel e + \\rs. (\s. ksSchedulerAction s = ResumeCurrentThread) + and (invs' and (ct_running' or ct_idle'))\" + apply (simp add: callKernel_def) + apply (rule hoare_pre) + apply (wp activate_invs' activate_sch_act schedule_sch + schedule_sch_act_simple he_invs' schedule_invs' hoare_vcg_if_lift3 + hoare_drop_imp[where R="\_. kernelExitAssertions"] + | simp add: no_irq_getActiveIRQ + | strengthen non_kernel_IRQs_strg[where Q=True, simplified], simp cong: conj_cong)+ + done + +(* abstract and haskell have identical domain list fields *) +abbreviation valid_domain_list' :: "'a kernel_state_scheme \ bool" where + "valid_domain_list' \ \s. valid_domain_list_2 (ksDomSchedule s)" + +lemmas valid_domain_list'_def = valid_domain_list_2_def + +defs kernelExitAssertions_def: + "kernelExitAssertions s \ 0 < ksDomainTime s \ valid_domain_list' s" + +lemma callKernel_domain_time_left: + "\ \ \ callKernel e \\_ s. 0 < ksDomainTime s \ valid_domain_list' s \" + unfolding callKernel_def kernelExitAssertions_def by wpsimp + +lemma doMachineOp_sch_act_simple: + "doMachineOp f \sch_act_simple\" + by (wp sch_act_simple_lift) + +lemma kernelEntry_invs': + "\ invs' and (\s. e \ Interrupt \ ct_running' s) and + (ct_running' or ct_idle') and + (\s. ksSchedulerAction s = ResumeCurrentThread) and + (\s. 0 < ksDomainTime s) and valid_domain_list' \ + kernelEntry e tc + \\rs. (\s. ksSchedulerAction s = ResumeCurrentThread) and + (invs' and (ct_running' or ct_idle')) and + (\s. 0 < ksDomainTime s) and valid_domain_list' \" + apply (simp add: kernelEntry_def) + apply (wp ckernel_invs callKernel_domain_time_left + threadSet_invs_trivial threadSet_ct_running' select_wp + TcbAcc_R.dmo_invs' static_imp_wp + doMachineOp_ct_in_state' doMachineOp_sch_act_simple + callKernel_domain_time_left + | clarsimp simp: user_memory_update_def no_irq_def tcb_at_invs' + valid_domain_list'_def)+ + done + +lemma absKState_correct': + "\einvs s; invs' s'; (s,s') \ state_relation\ + \ absKState s' = abs_state s" + apply (intro state.equality, simp_all add: absKState_def abs_state_def) + apply (rule absHeap_correct) + apply (clarsimp simp: valid_state_def valid_pspace_def)+ + apply (clarsimp dest!: state_relationD) + apply (rule absCDT_correct) + apply (clarsimp simp: valid_state_def valid_pspace_def + valid_state'_def valid_pspace'_def)+ + apply (rule absIsOriginalCap_correct, clarsimp+) + apply (simp add: state_relation_def) + apply (simp add: state_relation_def) + apply (clarsimp simp: user_mem_relation invs_def invs'_def) + apply (simp add: state_relation_def) + apply (rule absInterruptIRQNode_correct, simp add: state_relation_def) + apply (rule absInterruptStates_correct, simp add: state_relation_def) + apply (erule absArchState_correct) + apply (rule absExst_correct, simp, assumption+) + done + +lemma ptable_lift_abs_state[simp]: + "ptable_lift t (abs_state s) = ptable_lift t s" + by (simp add: ptable_lift_def abs_state_def) + +lemma ptable_rights_abs_state[simp]: + "ptable_rights t (abs_state s) = ptable_rights t s" + by (simp add: ptable_rights_def abs_state_def) + +lemma ptable_rights_imp_UserData: + assumes invs: "einvs s" and invs': "invs' s'" + assumes rel: "(s,s') : state_relation" + assumes rights: "ptable_rights t (absKState s') x \ {}" + assumes trans: + "ptable_lift t (absKState s') x = Some (AARCH64.addrFromPPtr y)" + shows "pointerInUserData y s' \ pointerInDeviceData y s'" +proof - + from invs invs' rel have [simp]: "absKState s' = abs_state s" + by - (rule absKState_correct', simp_all) + from invs have valid: "valid_state s" by auto + from invs' have valid': "valid_state' s'" by auto + have "in_user_frame y s \ in_device_frame y s " + by (rule ptable_rights_imp_frame[OF valid rights[simplified] + trans[simplified]]) + thus ?thesis + by (auto simp add: pointerInUserData_relation[OF rel valid' valid] + pointerInDeviceData_relation[OF rel valid' valid]) +qed + +definition + "ex_abs G \ \s'. \s. ((s :: (det_ext) state),s') \ state_relation \ G s" + +lemma device_update_invs': + "\invs'\doMachineOp (device_memory_update ds) + \\_. invs'\" + apply (simp add: doMachineOp_def device_memory_update_def simpler_modify_def select_f_def + gets_def get_def bind_def valid_def return_def) + by (clarsimp simp: invs'_def valid_state'_def valid_irq_states'_def valid_machine_state'_def) + +crunches doMachineOp + for ksDomainTime[wp]: "\s. P (ksDomainTime s)" + +lemma doUserOp_invs': + "\invs' and ex_abs einvs and + (\s. ksSchedulerAction s = ResumeCurrentThread) and ct_running' and + (\s. 0 < ksDomainTime s) and valid_domain_list'\ + doUserOp f tc + \\_. invs' and + (\s. ksSchedulerAction s = ResumeCurrentThread) and ct_running' and + (\s. 0 < ksDomainTime s) and valid_domain_list'\" + apply (simp add: doUserOp_def split_def ex_abs_def) + apply (wp device_update_invs' doMachineOp_ct_in_state' select_wp + | (wp (once) dmo_invs', wpsimp simp: no_irq_modify device_memory_update_def + user_memory_update_def))+ + apply (clarsimp simp: user_memory_update_def simpler_modify_def + restrict_map_def + split: option.splits) + apply (frule ptable_rights_imp_UserData[rotated 2], auto) + done + + +text \The top-level correspondence\ + +lemma None_drop: + "P \ x = None \ P" + by simp + +lemma Ex_Some_conv: + "((\y. x = Some y) \ P x) = (\y. x = Some y \ P (Some y))" + by auto + + +lemma kernel_corres': + "corres dc (einvs and (\s. event \ Interrupt \ ct_running s) and (ct_running or ct_idle) + and (\s. scheduler_action s = resume_cur_thread)) + (invs' and (\s. event \ Interrupt \ ct_running' s) and (ct_running' or ct_idle') and + (\s. ksSchedulerAction s = ResumeCurrentThread)) + (call_kernel event) + (do _ \ runExceptT $ + handleEvent event `~catchError~` + (\_. withoutPreemption $ do + irq <- doMachineOp (getActiveIRQ True); + when (isJust irq) $ handleInterrupt (fromJust irq) + od); + _ \ ThreadDecls_H.schedule; + activateThread + od)" + unfolding call_kernel_def callKernel_def + apply (simp add: call_kernel_def callKernel_def) + apply (rule corres_guard_imp) + apply (rule corres_split) + apply (rule corres_split_handle[OF handleEvent_corres]) + apply simp + apply (rule corres_split[OF corres_machine_op]) + apply (rule corres_underlying_trivial) + apply (rule no_fail_getActiveIRQ) + apply clarsimp + apply (rule_tac x=irq in option_corres) + apply (rule_tac P=\ and P'=\ in corres_inst) + apply (simp add: when_def) + apply (rule corres_when[simplified dc_def], simp) + apply simp + apply (rule handleInterrupt_corres[simplified dc_def]) + apply simp + apply (wp hoare_drop_imps hoare_vcg_all_lift)[1] + apply simp + apply (rule_tac Q="\irq s. invs' s \ + (\irq'. irq = Some irq' \ + intStateIRQTable (ksInterruptState s ) irq' \ + IRQInactive)" + in hoare_post_imp) + apply simp + apply (wp doMachineOp_getActiveIRQ_IRQ_active handle_event_valid_sched | simp)+ + apply (rule_tac Q="\_. \" and E="\_. invs'" in hoare_post_impErr) + apply wpsimp+ + apply (simp add: invs'_def valid_state'_def) + apply (rule corres_split[OF schedule_corres]) + apply (rule activateThread_corres) + apply (wp schedule_invs' hoare_vcg_if_lift2 dmo_getActiveIRQ_non_kernel + | simp cong: rev_conj_cong | strengthen None_drop | subst Ex_Some_conv)+ + apply (rule_tac Q="\_. valid_sched and invs and valid_list" and + E="\_. valid_sched and invs and valid_list" + in hoare_post_impErr) + apply (wp handle_event_valid_sched hoare_vcg_imp_lift' |simp)+ + apply (wp handle_event_valid_sched hoare_vcg_if_lift3 + | simp + | strengthen non_kernel_IRQs_strg[where Q=True, simplified], simp cong: conj_cong)+ + apply (clarsimp simp: active_from_running) + apply (clarsimp simp: active_from_running') + done + +lemma kernel_corres: + "corres dc (einvs and (\s. event \ Interrupt \ ct_running s) and (ct_running or ct_idle) and + (\s. scheduler_action s = resume_cur_thread) and + (\s. 0 < domain_time s \ valid_domain_list s)) + (invs' and (\s. event \ Interrupt \ ct_running' s) and (ct_running' or ct_idle') and + (\s. ksSchedulerAction s = ResumeCurrentThread)) + (call_kernel event) (callKernel event)" + unfolding callKernel_def K_bind_def + apply (rule corres_guard_imp) + apply (rule corres_add_noop_lhs2) + apply (simp only: bind_assoc[symmetric]) + apply (rule corres_split[where r'=dc and + R="\_ s. 0 < domain_time s \ valid_domain_list s" and + R'="\_. \"]) + apply (simp only: bind_assoc) + apply (rule kernel_corres') + apply (rule corres_bind_return2, rule corres_stateAssert_assume_stronger) + apply simp + apply (simp add: kernelExitAssertions_def state_relation_def) + apply (wp call_kernel_domain_time_inv_det_ext call_kernel_domain_list_inv_det_ext) + apply wp + apply clarsimp + apply clarsimp + done + +lemma user_mem_corres: + "corres (=) invs invs' (gets (\x. g (user_mem x))) (gets (\x. g (user_mem' x)))" + by (clarsimp simp add: gets_def get_def return_def bind_def + invs_def invs'_def + corres_underlying_def user_mem_relation) + +lemma device_mem_corres: + "corres (=) invs invs' (gets (\x. g (device_mem x))) (gets (\x. g (device_mem' x)))" + by (clarsimp simp add: gets_def get_def return_def bind_def + invs_def invs'_def + corres_underlying_def device_mem_relation) + +lemma entry_corres: + "corres (=) (einvs and (\s. event \ Interrupt \ ct_running s) and + (\s. 0 < domain_time s) and valid_domain_list and (ct_running or ct_idle) and + (\s. scheduler_action s = resume_cur_thread)) + (invs' and (\s. event \ Interrupt \ ct_running' s) and + (\s. 0 < ksDomainTime s) and valid_domain_list' and (ct_running' or ct_idle') and + (\s. ksSchedulerAction s = ResumeCurrentThread)) + (kernel_entry event tc) (kernelEntry event tc)" + apply (simp add: kernel_entry_def kernelEntry_def) + apply (rule corres_guard_imp) + apply (rule corres_split[OF getCurThread_corres]) + apply (rule corres_split) + apply simp + apply (rule threadset_corresT) + apply (simp add: tcb_relation_def arch_tcb_relation_def + arch_tcb_context_set_def atcbContextSet_def) + apply (clarsimp simp: tcb_cap_cases_def cteSizeBits_def) + apply (clarsimp simp: tcb_cte_cases_def cteSizeBits_def) + apply (simp add: exst_same_def) + apply (rule corres_split[OF kernel_corres]) + apply (rule corres_split_eqr[OF getCurThread_corres]) + apply (rule threadGet_corres) + apply (simp add: tcb_relation_def arch_tcb_relation_def + arch_tcb_context_get_def atcbContextGet_def) + apply wp+ + apply (rule hoare_strengthen_post, rule akernel_invs_det_ext, + simp add: invs_def valid_state_def valid_pspace_def cur_tcb_def) + apply (rule hoare_strengthen_post, rule ckernel_invs, simp add: invs'_def cur_tcb'_def) + apply (wp thread_set_invs_trivial thread_set_ct_running + threadSet_invs_trivial threadSet_ct_running' + select_wp thread_set_not_state_valid_sched static_imp_wp + hoare_vcg_disj_lift ct_in_state_thread_state_lift + | simp add: tcb_cap_cases_def ct_in_state'_def thread_set_no_change_tcb_state + | (wps, wp threadSet_st_tcb_at2) )+ + apply (clarsimp simp: invs_def cur_tcb_def valid_state_def valid_pspace_def) + apply (clarsimp simp: ct_in_state'_def) + done + +lemma corres_gets_machine_state: + "corres (=) \ \ (gets (f \ machine_state)) (gets (f \ ksMachineState))" + by (clarsimp simp: gets_def corres_underlying_def + in_monad bind_def get_def return_def state_relation_def) + +lemma do_user_op_corres: + "corres (=) (einvs and ct_running) + (invs' and (%s. ksSchedulerAction s = ResumeCurrentThread) and + ct_running') + (do_user_op f tc) (doUserOp f tc)" + apply (simp add: do_user_op_def doUserOp_def split_def) + apply (rule corres_guard_imp) + apply (rule corres_split[OF getCurThread_corres]) + apply (rule_tac r'="(=)" and P=einvs and P'=invs' in corres_split) + apply (fastforce dest: absKState_correct [rotated]) + apply (rule_tac r'="(=)" and P=einvs and P'=invs' in corres_split) + apply (fastforce dest: absKState_correct [rotated]) + apply (rule_tac r'="(=)" and P=invs and P'=invs' in corres_split) + apply (rule user_mem_corres) + apply (rule_tac r'="(=)" and P=invs and P'=invs' in corres_split) + apply (rule device_mem_corres) + apply (rule_tac r'="(=)" in corres_split) + apply (rule corres_gets_machine_state) + apply (rule_tac F = "dom (rvb \ addrFromPPtr) \ - dom rvd" in corres_gen_asm) + apply (rule_tac F = "dom (rvc \ addrFromPPtr) \ dom rvd" in corres_gen_asm) + apply simp + apply (rule_tac r'="(=)" in corres_split[OF corres_select]) + apply simp + apply (rule corres_underlying_split[OF corres_machine_op]) + apply simp + apply (rule corres_underlying_trivial) + apply (simp add: user_memory_update_def) + apply (wp | simp)+ + apply (rule corres_underlying_split[OF corres_machine_op,where Q = dc and Q'=dc]) + apply (rule corres_underlying_trivial) + apply (wp | simp add: dc_def device_memory_update_def)+ + apply (clarsimp simp: invs_def valid_state_def pspace_respects_device_region_def) + apply fastforce + done + +lemma ct_running_related: + "\ (a, c) \ state_relation; ct_running' c \ + \ ct_running a" + apply (clarsimp simp: ct_in_state_def ct_in_state'_def + curthread_relation) + apply (frule(1) st_tcb_at_coerce_abstract) + apply (erule st_tcb_weakenE) + apply (case_tac st, simp_all)[1] + done + +lemma ct_idle_related: + "\ (a, c) \ state_relation; ct_idle' c \ + \ ct_idle a" + apply (clarsimp simp: ct_in_state_def ct_in_state'_def + curthread_relation) + apply (frule(1) st_tcb_at_coerce_abstract) + apply (erule st_tcb_weakenE) + apply (case_tac st, simp_all)[1] + done + +definition + "full_invs' \ {((tc,s),m,e). invs' s \ + ex_abs (einvs::det_ext state \ bool) s \ + ksSchedulerAction s = ResumeCurrentThread \ + (ct_running' s \ ct_idle' s) \ + (m = KernelMode \ e \ None) \ + (m = UserMode \ ct_running' s) \ + (m = IdleMode \ ct_idle' s) \ + (e \ None \ e \ Some Interrupt \ ct_running' s) \ + 0 < ksDomainTime s \ valid_domain_list' s}" + +lemma check_active_irq_corres': + "corres (=) \ \ (check_active_irq) (checkActiveIRQ)" + apply (simp add: check_active_irq_def checkActiveIRQ_def) + apply (rule corres_guard_imp) + apply (rule corres_split[OF corres_machine_op[OF corres_underlying_trivial], where R="\_. \" and R'="\_. \"]) + apply simp + apply (rule no_fail_getActiveIRQ) + apply (wp | simp )+ + done + +lemma check_active_irq_corres: + "corres (=) + (invs and (ct_running or ct_idle) and einvs and (\s. scheduler_action s = resume_cur_thread) + and (\s. 0 < domain_time s) and valid_domain_list) + (invs' and (\s. ksSchedulerAction s = ResumeCurrentThread) + and (\s. 0 < ksDomainTime s) and valid_domain_list' and (ct_running' or ct_idle')) + (check_active_irq) (checkActiveIRQ)" + apply (rule corres_guard_imp) + apply (rule check_active_irq_corres', auto) + done + +lemma checkActiveIRQ_just_running_corres: + "corres (=) + (invs and ct_running and einvs and (\s. scheduler_action s = resume_cur_thread) + and (\s. 0 < domain_time s) and valid_domain_list) + (invs' and ct_running' + and (\s. 0 < ksDomainTime s) and valid_domain_list' + and (\s. ksSchedulerAction s = ResumeCurrentThread)) + (check_active_irq) (checkActiveIRQ)" + apply (rule corres_guard_imp) + apply (rule check_active_irq_corres', auto) + done + +lemma checkActiveIRQ_just_idle_corres: + "corres (=) + (invs and ct_idle and einvs and (\s. scheduler_action s = resume_cur_thread) + and (\s. 0 < domain_time s) and valid_domain_list) + (invs' and ct_idle' + and (\s. 0 < ksDomainTime s) and valid_domain_list' + and (\s. ksSchedulerAction s = ResumeCurrentThread)) + (check_active_irq) (checkActiveIRQ)" + apply (rule corres_guard_imp) + apply (rule check_active_irq_corres', auto) + done + +lemma checkActiveIRQ_invs': + "\invs' and ex_abs invs and (ct_running' or ct_idle') + and (\s. ksSchedulerAction s = ResumeCurrentThread)\ + checkActiveIRQ + \\_. invs' and (ct_running' or ct_idle') + and (\s. ksSchedulerAction s = ResumeCurrentThread)\" + apply (simp add: checkActiveIRQ_def ex_abs_def) + apply (wp dmo_invs' | simp)+ + done + +lemma checkActiveIRQ_invs'_just_running: + "\invs' and ex_abs invs and ct_running' + and (\s. ksSchedulerAction s = ResumeCurrentThread)\ + checkActiveIRQ + \\_. invs' and ct_running' + and (\s. ksSchedulerAction s = ResumeCurrentThread)\" + apply (simp add: checkActiveIRQ_def) + apply (wp | simp)+ + done + +lemma checkActiveIRQ_invs'_just_idle: + "\invs' and ex_abs invs and ct_idle' + and (\s. ksSchedulerAction s = ResumeCurrentThread)\ + checkActiveIRQ + \\_. invs' and ct_idle' + and (\s. ksSchedulerAction s = ResumeCurrentThread)\" + apply (simp add: checkActiveIRQ_def) + apply (wp | simp)+ + done + +lemma sched_act_rct_related: + "\ (a, c) \ state_relation; ksSchedulerAction c = ResumeCurrentThread\ + \ scheduler_action a = resume_cur_thread" + by (case_tac "scheduler_action a", simp_all add: state_relation_def) + +lemma domain_time_rel_eq: + "(a, c) \ state_relation \ P (ksDomainTime c) = P (domain_time a)" + by (clarsimp simp: state_relation_def) + +lemma domain_list_rel_eq: + "(a, c) \ state_relation \ P (ksDomSchedule c) = P (domain_list a)" + by (clarsimp simp: state_relation_def) + +crunch valid_objs': doUserOp, checkActiveIRQ valid_objs' + (wp: crunch_wps select_wp) + +lemma ckernel_invariant: + "ADT_H uop \ full_invs'" + unfolding full_invs'_def + supply word_neq_0_conv[simp] + supply domain_time_rel_eq[simp] domain_list_rel_eq[simp] + apply (rule invariantI) + apply (clarsimp simp add: ADT_H_def) + apply (subst conj_commute, simp) + apply (rule conjI) + apply (frule init_refinement[simplified subset_eq, THEN bspec]) + apply (clarsimp simp: ex_abs_def lift_state_relation_def) + apply (frule akernel_init_invs[THEN bspec]) + apply (rule_tac x = s in exI) + apply (clarsimp simp: Init_A_def) + apply (insert ckernel_init_invs)[1] + apply clarsimp + apply (frule ckernel_init_sch_norm) + apply (frule ckernel_init_ctr) + apply (frule ckernel_init_domain_time) + apply (frule ckernel_init_domain_list) + apply (fastforce simp: Init_H_def valid_domain_list'_def) + apply (clarsimp simp: ADT_A_def ADT_H_def global_automaton_def) + + apply (erule_tac P="a \ (\x. b x)" for a b in disjE) + + apply (clarsimp simp: kernel_call_H_def) + + apply (drule use_valid[OF _ valid_corres_combined + [OF kernel_entry_invs entry_corres], + OF _ kernelEntry_invs'[THEN hoare_weaken_pre]]) + apply fastforce + apply (fastforce simp: ex_abs_def sch_act_simple_def ct_running_related ct_idle_related + sched_act_rct_related) + apply (clarsimp simp: kernel_call_H_def) + apply (fastforce simp: ex_abs_def sch_act_simple_def ct_running_related ct_idle_related + sched_act_rct_related) + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp add: do_user_op_H_def monad_to_transition_def) + apply (drule use_valid) + apply (rule hoare_vcg_conj_lift) + apply (rule doUserOp_valid_objs') + apply (rule valid_corres_combined[OF do_user_op_invs2 corres_guard_imp2[OF do_user_op_corres]]) + apply clarsimp + apply (rule doUserOp_invs'[THEN hoare_weaken_pre]) + apply (fastforce simp: ex_abs_def) + apply (clarsimp simp: invs_valid_objs' ex_abs_def, rule_tac x=s in exI, + clarsimp simp: ct_running_related sched_act_rct_related) + apply (clarsimp simp: ex_abs_def) + apply (fastforce simp: ex_abs_def ct_running_related sched_act_rct_related) + + apply (erule_tac P="a \ b \ c \ (\x. d x)" for a b c d in disjE) + apply (clarsimp simp add: do_user_op_H_def monad_to_transition_def) + apply (drule use_valid) + apply (rule hoare_vcg_conj_lift) + apply (rule doUserOp_valid_objs') + apply (rule valid_corres_combined[OF do_user_op_invs2 corres_guard_imp2[OF do_user_op_corres]]) + apply clarsimp + apply (rule doUserOp_invs'[THEN hoare_weaken_pre]) + apply (fastforce simp: ex_abs_def) + apply (fastforce simp: ex_abs_def ct_running_related sched_act_rct_related) + apply (fastforce simp: ex_abs_def) + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp: check_active_irq_H_def) + apply (drule use_valid) + apply (rule hoare_vcg_conj_lift) + apply (rule checkActiveIRQ_valid_objs') + apply (rule valid_corres_combined[OF check_active_irq_invs_just_running checkActiveIRQ_just_running_corres]) + apply (rule checkActiveIRQ_invs'_just_running[THEN hoare_weaken_pre]) + apply (fastforce simp: ex_abs_def) + apply (fastforce simp: ex_abs_def ct_running_related sched_act_rct_related) + apply (fastforce simp: ex_abs_def) + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp: check_active_irq_H_def) + apply (drule use_valid) + apply (rule hoare_vcg_conj_lift) + apply (rule checkActiveIRQ_valid_objs') + apply (rule valid_corres_combined[OF check_active_irq_invs_just_idle checkActiveIRQ_just_idle_corres]) + apply (rule checkActiveIRQ_invs'_just_idle[THEN hoare_weaken_pre]) + apply clarsimp + apply (fastforce simp: ex_abs_def) + apply (fastforce simp: ex_abs_def ct_idle_related sched_act_rct_related) + apply (fastforce simp: ex_abs_def) + + apply (clarsimp simp: check_active_irq_H_def) + apply (drule use_valid) + apply (rule hoare_vcg_conj_lift) + apply (rule checkActiveIRQ_valid_objs') + apply (rule valid_corres_combined[OF check_active_irq_invs check_active_irq_corres]) + apply (rule checkActiveIRQ_invs'[THEN hoare_weaken_pre]) + apply clarsimp + apply (fastforce simp: ex_abs_def) + apply (fastforce simp: ex_abs_def ct_running_related ct_idle_related sched_act_rct_related) + apply (fastforce simp: ex_abs_def) + done + +text \The top-level theorem\ + +lemma fw_sim_A_H: + "LI (ADT_A uop) + (ADT_H uop) + (lift_state_relation state_relation) + (full_invs \ full_invs')" + apply (unfold LI_def full_invs_def full_invs'_def) + apply (simp add: ADT_H_def ADT_A_def) + apply (intro conjI) + apply (rule init_refinement) + apply (clarsimp simp: rel_semi_def relcomp_unfold in_lift_state_relation_eq) + apply (rename_tac tc ak m ev tc' ck' m' ev' ck) + apply (simp add: global_automaton_def) + + apply (erule_tac P="a \ (\x. b x)" for a b in disjE) + apply (clarsimp simp add: kernel_call_H_def kernel_call_A_def) + apply (rule rev_mp, rule_tac tc=tc and event=x in entry_corres) + apply (clarsimp simp: corres_underlying_def) + apply (drule (1) bspec) + apply (clarsimp simp: sch_act_simple_def) + apply (drule (1) bspec) + apply clarsimp + apply (rule conjI) + apply clarsimp + apply (rule_tac x=b in exI) + apply (rule conjI) + apply (rule impI, simp) + apply (frule (2) ct_running_related) + apply clarsimp + apply (rule_tac x=b in exI) + apply (drule use_valid, rule kernelEntry_invs') + apply (simp add: sch_act_simple_def) + apply clarsimp + apply (frule (1) ct_idle_related) + apply (clarsimp simp: ct_in_state_def st_tcb_at_def obj_at_def) + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp: do_user_op_H_def do_user_op_A_def monad_to_transition_def) + apply (rule rev_mp, rule_tac tc1=tc and f1=uop and P="ct_running and einvs" in corres_guard_imp2[OF do_user_op_corres]) + apply simp + apply (clarsimp simp add: corres_underlying_def) + apply (drule (1) bspec, clarsimp) + apply (drule (1) bspec, clarsimp) + apply fastforce + + apply (erule_tac P="a \ b \ c \ (\x. d x)" for a b c d in disjE) + apply (clarsimp simp: do_user_op_H_def do_user_op_A_def monad_to_transition_def) + apply (rule rev_mp, rule_tac tc1=tc and f1=uop and P="ct_running and einvs" in corres_guard_imp2[OF do_user_op_corres]) + apply simp + apply (clarsimp simp add: corres_underlying_def) + apply (drule (1) bspec, clarsimp) + apply (drule (1) bspec, clarsimp) + apply fastforce + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp: check_active_irq_H_def check_active_irq_A_def) + apply (rule rev_mp, rule check_active_irq_corres) + apply (clarsimp simp: corres_underlying_def) + apply fastforce + + apply (erule_tac P="a \ b" for a b in disjE) + apply (clarsimp simp: check_active_irq_H_def check_active_irq_A_def) + apply (rule rev_mp, rule check_active_irq_corres) + apply (clarsimp simp: corres_underlying_def) + apply fastforce + + apply (clarsimp simp: check_active_irq_H_def check_active_irq_A_def) + apply (rule rev_mp, rule check_active_irq_corres) + apply (clarsimp simp: corres_underlying_def) + apply fastforce + + apply (clarsimp simp: absKState_correct dest!: lift_state_relationD) + done + +theorem refinement: + "ADT_H uop \ ADT_A uop" + apply (rule sim_imp_refines) + apply (rule L_invariantI) + apply (rule akernel_invariant) + apply (rule ckernel_invariant) + apply (rule fw_sim_A_H) + done + +end + +end