(* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: GPL-2.0-only *) (* * State translation. * * Takes a state of the system as defined in the abstract seL4 * specification, and returns an equivalent state of the system * defined in terms of the CapDL specification. *) theory StateTranslation_D imports Lemmas_D begin context begin interpretation Arch . (*FIXME: arch_split*) type_synonym kernel_object = Structures_A.kernel_object type_synonym tcb = Structures_A.tcb type_synonym pte = ARM_A.pte (* Transform an abstract-spec cap ptr to a capDL one. This is currently * a no-(;) however, it is conceivable that the capDL cptr representation could * be changed. Allowing for this potential change is the purpose of this * definition. *) definition transform_cptr :: "word32 \ cdl_cptr" where "transform_cptr w \ w" (* transform an abstract-spec recv_slot description to a capDL one *) definition transform_recv_slot :: "(word32 \ word32 \ word8) \ (cdl_cptr \ word32 \ word8)" where "transform_recv_slot x \ let (cap,w32,w8) = x in (transform_cptr cap,w32,w8)" (* * Convert a user value to a CDL type. * * We repeat "FrameType" multiple times because CapDL doesn't * treat the different frame sizes as different types. *) definition transform_type :: "word32 \ cdl_object_type option" where "transform_type x \ if x = 0 then Some UntypedType else if x = 1 then Some TcbType else if x = 2 then Some EndpointType else if x = 3 then Some NotificationType else if x = 4 then Some CNodeType else if x = 5 then Some PageDirectoryType else if x = 6 then Some (FrameType 12) else if x = 7 then Some (FrameType 16) else if x = 8 then Some (FrameType 20) else if x = 9 then Some (FrameType 24) else if x = 10 then Some PageTableType else None" definition transform_intent_untyped_retype :: "word32 list \ cdl_untyped_intent option" where "transform_intent_untyped_retype args = (case args of type#size_bits#index#depth#offset#window#_ \ (case transform_type type of Some x \ Some (UntypedRetypeIntent x size_bits index depth offset window) | _ \ None) | _ \ None)" (* Arch flags always set to 0 here as they have no meaning on ARM. *) definition transform_intent_tcb_read_registers :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_read_registers args = (case args of flags#n#_ \ Some (TcbReadRegistersIntent (flags !! 0) 0 n) | _ \ None)" (* Arch flags always set to 0 here as they have no meaning on ARM. *) definition transform_intent_tcb_write_registers :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_write_registers args = (case args of flags#n#values \ Some (TcbWriteRegistersIntent (flags !! 0) 0 n values) | _ \ None)" (* Arch flags always set to 0 here as they have no meaning on ARM. *) definition transform_intent_tcb_copy_registers :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_copy_registers args = (case args of flags#_ \ Some (TcbCopyRegistersIntent (flags !! 0) (flags !! 1) (flags !! 2) (flags !! 3) 0) | _ \ None)" (* Priority always set to 0 here. This should change if priorities * are ever added to the capDL spec. *) definition prio_from_arg :: "word32 \ word8" where "prio_from_arg _ = 0" definition transform_intent_tcb_configure :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_configure args = (case args of fault_ep#croot_data#vroot_data#buffer#_ \ Some (TcbConfigureIntent fault_ep croot_data vroot_data buffer) | _ \ None)" definition transform_intent_tcb_set_priority :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_set_priority args = (case args of prio#_ \ Some (TcbSetPriorityIntent (prio_from_arg prio)) | _ \ None)" definition transform_intent_tcb_set_mcpriority :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_set_mcpriority args = (case args of mcp#_ \ Some (TcbSetMCPriorityIntent (prio_from_arg mcp)) | _ \ None)" definition transform_intent_tcb_set_sched_params :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_set_sched_params args = (case args of mcp#priority#_ \ Some (TcbSetSchedParamsIntent (prio_from_arg mcp) (prio_from_arg priority)) | _ \ None)" definition transform_intent_tcb_set_ipc_buffer :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_set_ipc_buffer args = (case args of buffer#_ \ Some (TcbSetIPCBufferIntent buffer) | _ \ None)" definition transform_intent_tcb_set_space :: "word32 list \ cdl_tcb_intent option" where "transform_intent_tcb_set_space args = (case args of fault_ep#croot_data#vroot_data#_ \ Some (TcbSetSpaceIntent fault_ep croot_data vroot_data) | _ \ None)" definition transform_cnode_index_and_depth :: "(word32 \ word32 \ 'a) \ word32 list \ 'a option" where "transform_cnode_index_and_depth func args \ case args of index#depth#_ \ Some (func index depth) | _ \ None" definition transform_intent_cnode_copy :: "word32 list \ cdl_cnode_intent option" where "transform_intent_cnode_copy args \ case args of destindex#destdepth#srcindex#srcdepth#rightsWord#_ \ Some (CNodeCopyIntent destindex destdepth srcindex srcdepth (data_to_rights rightsWord)) | _ \ Nothing" definition transform_intent_cnode_mint :: "word32 list \ cdl_cnode_intent option" where "transform_intent_cnode_mint args \ case args of destindex#destdepth#srcindex#srcdepth#rightsWord#capData#_ \ Some (CNodeMintIntent destindex destdepth srcindex srcdepth (data_to_rights rightsWord) capData) | _ \ Nothing" definition transform_intent_cnode_move :: "word32 list \ cdl_cnode_intent option" where "transform_intent_cnode_move args \ case args of destindex#destdepth#srcindex#srcdepth#rest \ Some (CNodeMoveIntent destindex destdepth srcindex srcdepth) | _ \ Nothing" definition transform_intent_cnode_mutate :: "word32 list \ cdl_cnode_intent option" where "transform_intent_cnode_mutate args \ case args of destindex#destdepth#srcindex#srcdepth#capData#_ \ Some (CNodeMutateIntent destindex destdepth srcindex srcdepth capData) | _ \ Nothing" definition transform_intent_cnode_rotate :: "word32 list \ cdl_cnode_intent option" where "transform_intent_cnode_rotate args \ case args of destindex#destdepth#pivotbadge#pivotindex# pivotdepth#srcbadge#srcindex#srcdepth#_ \ Some (CNodeRotateIntent destindex destdepth pivotindex pivotdepth pivotbadge srcindex srcdepth srcbadge) | _ \ Nothing" definition transform_intent_issue_irq_handler :: "word32 list \ cdl_irq_control_intent option" where "transform_intent_issue_irq_handler args \ case args of irqW#index#depth#_ \ Some (IrqControlIssueIrqHandlerIntent ((ucast irqW)::10 word) index depth) | _ \ Nothing" definition arch_transform_intent_issue_irq_handler :: "word32 list \ cdl_irq_control_intent option" where "arch_transform_intent_issue_irq_handler args \ case args of irqW#trigger#index#depth#_ \ Some (IrqControlIssueIrqHandlerIntent ((ucast irqW)::10 word) index depth) | _ \ Nothing" definition transform_intent_page_table_map :: "word32 list \ cdl_page_table_intent option" where "transform_intent_page_table_map args = (case args of vaddr#attr#_ \ Some (PageTableMapIntent vaddr attr) | _ \ Nothing)" definition transform_intent_page_map :: "word32 list \ cdl_page_intent option" where "transform_intent_page_map args = (case args of vaddr#rightsW#attr#_ \ Some (PageMapIntent vaddr (data_to_rights rightsW) attr) | _ \ Nothing)" definition transform_intent_domain :: "word32 list \ cdl_domain_intent option" where "transform_intent_domain args = (case args of d#_ \ Some (DomainSetIntent (ucast d :: word8)) | _ \ Nothing)" (* Added for IOAPIC patch *) definition to_bool :: "word32 \ bool" where "to_bool w \ w \ 0" (* A dispatch function that converts the user's message label * and IPC buffer into an intent by dispatching on the message label. * For malformed messages etc., we return None. *) definition transform_intent :: "invocation_label \ word32 list \ cdl_intent option" where "transform_intent label args \ case label of GenInvocationLabel InvalidInvocation \ None | GenInvocationLabel UntypedRetype \ map_option UntypedIntent (transform_intent_untyped_retype args) | GenInvocationLabel TCBReadRegisters \ map_option TcbIntent (transform_intent_tcb_read_registers args) | GenInvocationLabel TCBWriteRegisters \ map_option TcbIntent (transform_intent_tcb_write_registers args) | GenInvocationLabel TCBCopyRegisters \ map_option TcbIntent (transform_intent_tcb_copy_registers args) | GenInvocationLabel TCBConfigure \ map_option TcbIntent (transform_intent_tcb_configure args) | GenInvocationLabel TCBSetPriority \ map_option TcbIntent (transform_intent_tcb_set_priority args) | GenInvocationLabel TCBSetMCPriority \ map_option TcbIntent (transform_intent_tcb_set_mcpriority args) | GenInvocationLabel TCBSetSchedParams \ map_option TcbIntent (transform_intent_tcb_set_sched_params args) | GenInvocationLabel TCBSetIPCBuffer \ map_option TcbIntent (transform_intent_tcb_set_ipc_buffer args) | GenInvocationLabel TCBSetSpace \ map_option TcbIntent (transform_intent_tcb_set_space args) | GenInvocationLabel TCBSuspend \ Some (TcbIntent TcbSuspendIntent) | GenInvocationLabel TCBResume \ Some (TcbIntent TcbResumeIntent) | GenInvocationLabel TCBBindNotification \ Some (TcbIntent TcbBindNTFNIntent) | GenInvocationLabel TCBUnbindNotification \ Some (TcbIntent TcbUnbindNTFNIntent) | GenInvocationLabel TCBSetTLSBase \ Some (TcbIntent TcbSetTLSBaseIntent) | GenInvocationLabel CNodeRevoke \ map_option CNodeIntent (transform_cnode_index_and_depth CNodeRevokeIntent args) | GenInvocationLabel CNodeDelete \ map_option CNodeIntent (transform_cnode_index_and_depth CNodeDeleteIntent args) | GenInvocationLabel CNodeCancelBadgedSends \ map_option CNodeIntent (transform_cnode_index_and_depth CNodeCancelBadgedSendsIntent args) | GenInvocationLabel CNodeCopy \ map_option CNodeIntent (transform_intent_cnode_copy args) | GenInvocationLabel CNodeMint \ map_option CNodeIntent (transform_intent_cnode_mint args) | GenInvocationLabel CNodeMove \ map_option CNodeIntent (transform_intent_cnode_move args) | GenInvocationLabel CNodeMutate \ map_option CNodeIntent (transform_intent_cnode_mutate args) | GenInvocationLabel CNodeRotate \ map_option CNodeIntent (transform_intent_cnode_rotate args) | GenInvocationLabel CNodeSaveCaller \ map_option CNodeIntent (transform_cnode_index_and_depth CNodeSaveCallerIntent args) | GenInvocationLabel IRQIssueIRQHandler \ map_option IrqControlIntent (transform_intent_issue_irq_handler args) | GenInvocationLabel IRQAckIRQ \ Some (IrqHandlerIntent IrqHandlerAckIntent) | GenInvocationLabel IRQSetIRQHandler \ Some (IrqHandlerIntent IrqHandlerSetEndpointIntent) | GenInvocationLabel IRQClearIRQHandler \ Some (IrqHandlerIntent IrqHandlerClearIntent) | ArchInvocationLabel ARMPageTableMap \ map_option PageTableIntent (transform_intent_page_table_map args) | ArchInvocationLabel ARMPageTableUnmap \ Some (PageTableIntent PageTableUnmapIntent) | ArchInvocationLabel ARMPageMap \ map_option PageIntent (transform_intent_page_map args) | ArchInvocationLabel ARMPageUnmap \ Some (PageIntent PageUnmapIntent) | ArchInvocationLabel ARMPageClean_Data \ Some (PageIntent PageFlushCachesIntent ) | ArchInvocationLabel ARMPageInvalidate_Data \ Some (PageIntent PageFlushCachesIntent ) | ArchInvocationLabel ARMPageCleanInvalidate_Data \ Some (PageIntent PageFlushCachesIntent ) | ArchInvocationLabel ARMPageUnify_Instruction \ Some (PageIntent PageFlushCachesIntent ) | ArchInvocationLabel ARMPageGetAddress \ Some (PageIntent PageGetAddressIntent ) | ArchInvocationLabel ARMPDClean_Data \ Some (PageDirectoryIntent PageDirectoryFlushIntent ) | ArchInvocationLabel ARMPDInvalidate_Data \ Some (PageDirectoryIntent PageDirectoryFlushIntent ) | ArchInvocationLabel ARMPDCleanInvalidate_Data \ Some (PageDirectoryIntent PageDirectoryFlushIntent) | ArchInvocationLabel ARMPDUnify_Instruction \ Some (PageDirectoryIntent PageDirectoryFlushIntent ) | ArchInvocationLabel ARMASIDControlMakePool \ map_option AsidControlIntent (transform_cnode_index_and_depth AsidControlMakePoolIntent args) | ArchInvocationLabel ARMASIDPoolAssign \ Some (AsidPoolIntent AsidPoolAssignIntent ) | ArchInvocationLabel ARMIRQIssueIRQHandler \ map_option IrqControlIntent (arch_transform_intent_issue_irq_handler args) | GenInvocationLabel DomainSetSet \ map_option DomainIntent (transform_intent_domain args)" lemmas transform_intent_tcb_defs = transform_intent_tcb_read_registers_def transform_intent_tcb_write_registers_def transform_intent_tcb_copy_registers_def transform_intent_tcb_configure_def transform_intent_tcb_set_priority_def transform_intent_tcb_set_mcpriority_def transform_intent_tcb_set_sched_params_def transform_intent_tcb_set_ipc_buffer_def transform_intent_tcb_set_space_def lemma transform_tcb_intent_invocation: "transform_intent label args = Some (TcbIntent ti) \ ( ((label = GenInvocationLabel TCBReadRegisters) = (ti = (TcbReadRegistersIntent ((args ! 0)!!0) 0 (args ! 1)) \ length args \ 2)) \ ((label = GenInvocationLabel TCBWriteRegisters) = (ti = (TcbWriteRegistersIntent ((args ! 0)!!0) 0 (args ! 1) (drop 2 args)) \ length args \ 2)) \ ((label = GenInvocationLabel TCBCopyRegisters) = (ti = (TcbCopyRegistersIntent ((args ! 0)!!0) ((args ! 0)!!1) ((args ! 0)!!2) ((args ! 0)!!3) 0) \ length args \ 1)) \ ((label = GenInvocationLabel TCBConfigure) = (ti = (TcbConfigureIntent (args ! 0) (args ! 1) (args ! 2) (args ! 3)) \ length args \ 4)) \ ((label = GenInvocationLabel TCBSetPriority) = (ti = (TcbSetPriorityIntent (prio_from_arg (args ! 0))) \ length args \ 1)) \ ((label = GenInvocationLabel TCBSetMCPriority) = (ti = (TcbSetMCPriorityIntent (prio_from_arg (args ! 0))) \ length args \ 1)) \ ((label = GenInvocationLabel TCBSetSchedParams) = (ti = (TcbSetSchedParamsIntent (prio_from_arg (args ! 0)) (prio_from_arg (args ! 1))) \ length args \ 2)) \ ((label = GenInvocationLabel TCBSetSpace) = (ti = (TcbSetSpaceIntent (args ! 0) (args ! 1) (args ! 2)) \ length args \ 3)) \ ((label = GenInvocationLabel TCBSuspend) = (ti = TcbSuspendIntent)) \ ((label = GenInvocationLabel TCBResume) = (ti = TcbResumeIntent)) \ ((label = GenInvocationLabel TCBBindNotification) = (ti = TcbBindNTFNIntent)) \ ((label = GenInvocationLabel TCBUnbindNotification) = (ti = TcbUnbindNTFNIntent)) \ ((label = GenInvocationLabel TCBSetTLSBase) = (ti = TcbSetTLSBaseIntent)) ) \ ( label \ GenInvocationLabel InvalidInvocation \ label \ GenInvocationLabel UntypedRetype \ label \ GenInvocationLabel CNodeRevoke \ label \ GenInvocationLabel CNodeDelete \ label \ GenInvocationLabel CNodeCancelBadgedSends \ label \ GenInvocationLabel CNodeCopy \ label \ GenInvocationLabel CNodeMint \ label \ GenInvocationLabel CNodeMove \ label \ GenInvocationLabel CNodeMutate \ label \ GenInvocationLabel CNodeRotate \ label \ GenInvocationLabel CNodeSaveCaller \ label \ GenInvocationLabel IRQIssueIRQHandler \ label \ GenInvocationLabel IRQAckIRQ \ label \ GenInvocationLabel IRQSetIRQHandler \ label \ GenInvocationLabel IRQClearIRQHandler \ label \ ArchInvocationLabel ARMPageTableMap \ label \ ArchInvocationLabel ARMPageTableUnmap \ label \ ArchInvocationLabel ARMPageMap \ label \ ArchInvocationLabel ARMPageUnmap \ label \ ArchInvocationLabel ARMPageClean_Data \ label \ ArchInvocationLabel ARMPageInvalidate_Data \ label \ ArchInvocationLabel ARMPageCleanInvalidate_Data \ label \ ArchInvocationLabel ARMPageUnify_Instruction \ label \ ArchInvocationLabel ARMPageGetAddress \ label \ ArchInvocationLabel ARMPDClean_Data \ label \ ArchInvocationLabel ARMPDInvalidate_Data \ label \ ArchInvocationLabel ARMPDCleanInvalidate_Data \ label \ ArchInvocationLabel ARMPDUnify_Instruction \ label \ ArchInvocationLabel ARMASIDControlMakePool \ label \ GenInvocationLabel DomainSetSet)" apply(intro conjI) apply(rule iffI, simp add: transform_intent_def transform_intent_tcb_defs split: list.split_asm, simp add: transform_intent_def transform_intent_tcb_defs split: gen_invocation_labels.split_asm invocation_label.split_asm arch_invocation_label.split_asm list.split_asm)+ (* 30 subgoals *) apply(simp add: transform_intent_def transform_intent_tcb_defs split: gen_invocation_labels.split_asm invocation_label.split_asm arch_invocation_label.split_asm)+ done lemma transform_intent_isnot_UntypedIntent: "(\ (\ ui. Some (UntypedIntent ui) = transform_intent label args)) = ((label \ GenInvocationLabel UntypedRetype) \ (label = GenInvocationLabel UntypedRetype \ length args < 6) \ (label = GenInvocationLabel UntypedRetype \ length args \ 6 \ args ! 0 > 10))" apply(rule iffI) apply(erule contrapos_np) apply(clarsimp) apply(simp add: transform_intent_def) apply(unfold transform_intent_untyped_retype_def) apply (clarsimp split: list.split, safe, simp_all)[1] apply (clarsimp simp: transform_type_def) apply (simp add: unat_arith_simps) apply (simp add: eval_nat_numeral linorder_not_less le_Suc_eq) apply(erule disjE) apply(auto simp: transform_intent_def option_map_def split: gen_invocation_labels.split invocation_label.split arch_invocation_label.split option.split_asm)[1] apply (erule disjE) apply (auto simp: transform_intent_def transform_intent_untyped_retype_def option_map_def split: invocation_label.split option.split_asm list.split)[1] apply clarsimp apply (clarsimp simp: transform_intent_def transform_type_def transform_intent_untyped_retype_def) apply (clarsimp simp: option_map_def split: invocation_label.splits arch_invocation_label.splits option.splits list.splits) apply (clarsimp simp: transform_type_def split: if_split_asm) done lemma transform_cnode_index_and_depth_success: "(\ci. Some (C ci) = map_option C (transform_cnode_index_and_depth C2 args)) = (\ length args < 2)" apply(rule iffI) apply(unfold option_map_def transform_cnode_index_and_depth_def) apply(case_tac args) apply(auto split: list.split) done lemmas transform_intent_cnode_defs = transform_cnode_index_and_depth_def transform_intent_cnode_copy_def transform_intent_cnode_mint_def transform_intent_cnode_move_def transform_intent_cnode_mutate_def transform_intent_cnode_rotate_def method case_labels for label :: invocation_label = (cases label, find_goal \match premises in "label = GenInvocationLabel x" for x \ \cases x\\, find_goal \match premises in "label = ArchInvocationLabel x" for x \ \cases x\\) lemma transform_intent_isnot_CNodeIntent: "(\ (\ ui. Some (CNodeIntent ui) = transform_intent label args)) = ((label = GenInvocationLabel CNodeRevoke \ length args < 2) \ (label = GenInvocationLabel CNodeDelete \ length args < 2) \ (label = GenInvocationLabel CNodeCancelBadgedSends \ length args < 2) \ (label = GenInvocationLabel CNodeCopy \ length args < 5) \ (label = GenInvocationLabel CNodeMint \ length args < 6) \ (label = GenInvocationLabel CNodeMove \ length args < 4) \ (label = GenInvocationLabel CNodeMutate \ length args < 5) \ (label = GenInvocationLabel CNodeRotate \ length args < 8) \ (label = GenInvocationLabel CNodeSaveCaller \ length args < 2))" apply(rule iffI) apply(erule contrapos_np) apply(clarsimp simp: transform_intent_def) apply(cases label; simp) apply(rename_tac gen_label, case_tac gen_label; simp add: transform_intent_cnode_defs option_map_def split: list.split) prefer 10 apply(clarify) apply(case_labels label; clarsimp simp: transform_intent_def option_map_def transform_intent_cnode_defs split: list.split_asm option.split_asm) apply(auto) done lemma transform_intent_isnot_TcbIntent: "(\ (\ ti. Some (TcbIntent ti) = transform_intent label args)) = ((label = GenInvocationLabel TCBReadRegisters \ length args < 2) \ (label = GenInvocationLabel TCBWriteRegisters \ length args < 2) \ (label = GenInvocationLabel TCBCopyRegisters \ length args < 1) \ (label = GenInvocationLabel TCBConfigure \ length args < 4) \ (label = GenInvocationLabel TCBSetPriority \ length args < 1) \ (label = GenInvocationLabel TCBSetMCPriority \ length args < 1) \ (label = GenInvocationLabel TCBSetSchedParams \ length args < 2) \ (label = GenInvocationLabel TCBSetIPCBuffer \ length args < 1) \ (label = GenInvocationLabel TCBSetSpace \ length args < 3) \ (label \ GenInvocationLabel TCBSuspend) \ (label \ GenInvocationLabel TCBResume) \ (label \ GenInvocationLabel TCBBindNotification) \ (label \ GenInvocationLabel TCBUnbindNotification) \ (label \ GenInvocationLabel TCBSetTLSBase))" apply(rule iffI) subgoal apply(erule contrapos_np) apply(clarsimp simp: transform_intent_def) apply(case_labels label; simp) apply(fastforce simp: transform_intent_tcb_defs option_map_def split: list.split)+ done apply(unfold transform_intent_def) apply(case_labels label; simp add: option_map_def split: option.split) apply(auto simp: transform_intent_tcb_defs split: list.splits arch_invocation_label.splits) done (* * Convert a partial function of type "word \ 'b" into * a partial function of type "nat \ 'b". * * It would be nice if we could just use the original * partial function as "p (unat x)". Unfortunately, this * would mean that "p ((unat x) + 2^32)" would return * some non-None value, which isn't what we want. * * Instead, return a new function that performs a range * check prior to calling the original function. *) definition unat_map :: "(('a :: len) word \ 'b) \ (nat \ 'b)" where "unat_map x z \ if z < 2^len_of(TYPE('a)) then x (of_nat z) else None" lemma unat_map_unat [simp]: "(unat_map p) (unat x) = p x" by (clarsimp simp: unat_map_def) (* * Convert a cslot_ptr into a cdl_cap_ref. *) definition transform_cslot_ptr :: "cslot_ptr \ cdl_cap_ref" where "transform_cslot_ptr \ \ (a, b). (a, nat (bl_to_bin b))" (* * Convert an asid into a cdl_asid with asid_low_bits * hardcoded. *) definition transform_asid :: "asid \ cdl_asid" where "transform_asid asid = (unat (asid_high_bits_of asid), unat (ucast asid :: 10 word))" definition transform_mapping :: "(asid \ vspace_ref) option \ cdl_mapped_addr option" where " transform_mapping mp = option_map (\x. (transform_asid (fst x),snd x)) mp" (* * Transform a cap in the abstract spec to an equivalent * CapDL cap. *) definition "free_range_of_untyped \ (\idx size_bits ptr. (if (idx \ 2^size_bits - 1) then {ptr + of_nat idx .. ptr + 2^size_bits - 1} else {}))" definition transform_cap :: "cap \ cdl_cap" where "transform_cap c \ case c of Structures_A.NullCap \ Types_D.NullCap | Structures_A.UntypedCap dev ptr size_bits idx \ Types_D.UntypedCap dev {ptr .. ptr + 2^ size_bits - 1} (free_range_of_untyped idx size_bits ptr) | Structures_A.EndpointCap ptr badge cap_rights_ \ Types_D.EndpointCap ptr badge cap_rights_ | Structures_A.NotificationCap ptr badge cap_rights_ \ Types_D.NotificationCap ptr badge cap_rights_ | Structures_A.ReplyCap ptr is_master cap_rights_ \ if is_master then Types_D.MasterReplyCap ptr else Types_D.ReplyCap ptr cap_rights_ | Structures_A.CNodeCap ptr size_bits guard \ Types_D.CNodeCap ptr (of_bl guard) (length guard) size_bits | Structures_A.ThreadCap ptr \ Types_D.TcbCap ptr | Structures_A.DomainCap \ Types_D.DomainCap | Structures_A.IRQControlCap \ Types_D.IrqControlCap | Structures_A.IRQHandlerCap irq \ Types_D.IrqHandlerCap irq | Structures_A.Zombie ptr _ _ \ Types_D.ZombieCap ptr | Structures_A.ArchObjectCap arch_cap \ (case arch_cap of ARM_A.ASIDControlCap \ Types_D.AsidControlCap | ARM_A.ASIDPoolCap ptr asid \ Types_D.AsidPoolCap ptr (fst $ (transform_asid asid)) | ARM_A.PageCap dev ptr cap_rights_ sz mp \ Types_D.FrameCap dev ptr cap_rights_ (pageBitsForSize sz) Real (transform_mapping mp) | ARM_A.PageTableCap ptr mp \ Types_D.PageTableCap ptr Real (transform_mapping mp) | ARM_A.PageDirectoryCap ptr mp \ Types_D.PageDirectoryCap ptr Real (option_map transform_asid mp) ) " (* Transform a list of (caps, refs) into CDL equivalents. *) definition transform_cap_list :: "(cap \ cslot_ptr) list \ (cdl_cap \ cdl_cap_ref) list" where "transform_cap_list \ map (\(cap, slot). (transform_cap cap, transform_cslot_ptr slot))" \ \Convert a nat into a bool list of the given size.\ definition nat_to_bl :: "nat \ nat \ bool list option" where "nat_to_bl bits n \ if n \ 2^bits then None else Some $ bin_to_bl bits (of_nat n)" lemma nat_to_bl_id [simp]: "nat_to_bl (size (x :: (('a::len) word))) (unat x) = Some (to_bl x)" by (clarsimp simp: nat_to_bl_def to_bl_def le_def word_size) (* FIXME: MOVE *) definition option_join :: "'a option option \ 'a option" where "option_join x \ case x of Some (Some y) \ Some y | _ \ None" definition option_map_join :: "('a \ 'b option) \ 'a option \ 'b option" where "option_map_join f x \ case x of Some y \ f y | _ \ None" lemmas option_map_join_simps = option_map_join_def [split_simps option.split] (* Transform a CNode. *) definition transform_cnode_contents :: "nat \ cnode_contents \ cdl_cap_map" where "transform_cnode_contents sz c \ \n. option_map transform_cap (option_map_join c (nat_to_bl sz n))" (* Create a "TCB pending operation" cap based on the given thread's * current state. *) definition infer_tcb_pending_op :: "obj_ref \ Structures_A.thread_state \ cdl_cap" where "infer_tcb_pending_op ptr t \ case t of Structures_A.BlockedOnReceive ptr payload \ PendingSyncRecvCap ptr False (receiver_can_grant payload) | Structures_A.BlockedOnReply \ PendingSyncRecvCap ptr True False | Structures_A.BlockedOnSend ptr payload \ PendingSyncSendCap ptr (sender_badge payload) (sender_is_call payload) (sender_can_grant payload) (sender_can_grant_reply payload) False | Structures_A.BlockedOnNotification ptr \ PendingNtfnRecvCap ptr | Structures_A.Restart \ RestartCap | Structures_A.Running \ RunningCap | _ \ Types_D.NullCap " (* Create a "Bound NTFN" cap based on the given thread's * current state. *) definition infer_tcb_bound_notification :: "obj_ref option \ cdl_cap" where "infer_tcb_bound_notification a \ case a of Some ntfn \ BoundNotificationCap ntfn | _ \ Types_D.NullCap" definition evalMonad :: "('s, 'a) nondet_monad \ 's \ 'a option" where "evalMonad m s = (if fst (m s) = {} then None else Some (SOME x. x \ fst ` (fst (m s))))" (* The monad here avoids repeating the def of loadWord *) definition get_ipc_buffer_words :: "machine_state \ tcb \ nat list \ word32 list" where "get_ipc_buffer_words ms tcb ns \ let p = tcb_ipc_buffer tcb; cap = tcb_ipcframe tcb; wordsM = case cap of cap.ArchObjectCap (arch_cap.PageCap dev buf rights sz mapdata) \ if AllowRead \ rights then mapM loadWord (map (\n. buf + (p && mask(pageBitsForSize sz)) + (of_nat (n * word_size))) ns) else return [] | _ \ return [] in the (evalMonad wordsM ms)" definition get_tcb_message_info :: "tcb \ Structures_A.message_info" where "get_tcb_message_info t \ data_to_message_info ((arch_tcb_context_get (tcb_arch t)) msg_info_register)" definition get_tcb_mrs :: "machine_state \ tcb \ word32 list" where "get_tcb_mrs ms tcb \ let info = get_tcb_message_info tcb; cpu_mrs = map (arch_tcb_context_get (tcb_arch tcb)) msg_registers; mem_mrs = get_ipc_buffer_words ms tcb [length msg_registers + 1 ..< Suc msg_max_length] in (take (unat (mi_length info)) (cpu_mrs @ mem_mrs))" (* Convert contents of the user's IPC buffer into an intent. *) definition "guess_error \ \x. x \ (0::word32)" definition transform_full_intent :: "machine_state \ obj_ref \ tcb \ cdl_full_intent" where "transform_full_intent ms r tcb \ let mi = get_tcb_message_info tcb; offset = msg_max_length + msg_max_extra_caps + 2 in \ cdl_intent_op = (transform_intent (invocation_type (mi_label mi)) (get_tcb_mrs ms tcb)), cdl_intent_error = guess_error (mi_label mi), cdl_intent_cap = arch_tcb_context_get (tcb_arch tcb) cap_register, cdl_intent_extras = get_ipc_buffer_words ms tcb [buffer_cptr_index ..< buffer_cptr_index + (unat (mi_extra_caps mi))], cdl_intent_recv_slot = case (get_ipc_buffer_words ms tcb [offset ..< offset + 3]) of [croot, index, depth] \ Some (croot, index, unat depth) | _ \ None \" lemma invocation_type0: "invocation_type 0 = GenInvocationLabel InvalidInvocation" by (clarsimp simp: invocation_type_def toEnum_def enum_invocation_label enum_gen_invocation_labels) (* Transform a TCB object. *) abbreviation "tcb_has_fault \ \tcb. tcb_fault tcb \ None" definition transform_tcb :: "machine_state \ obj_ref \ tcb \ etcb \ cdl_object" where "transform_tcb ms ptr tcb etcb \ Types_D.Tcb \ cdl_tcb_caps = [ tcb_cspace_slot \ (transform_cap $ tcb_ctable tcb), tcb_vspace_slot \ (transform_cap $ tcb_vtable tcb), tcb_replycap_slot \ (transform_cap $ tcb_reply tcb), tcb_caller_slot \ (transform_cap $ tcb_caller tcb), tcb_ipcbuffer_slot \ (transform_cap $ tcb_ipcframe tcb), tcb_pending_op_slot \ (infer_tcb_pending_op ptr (tcb_state tcb)), tcb_boundntfn_slot \ (infer_tcb_bound_notification (tcb_bound_notification tcb)) ], cdl_tcb_fault_endpoint = (of_bl (tcb_fault_handler tcb)), \ \Decode the thread's intent.\ cdl_tcb_intent = transform_full_intent ms ptr tcb, cdl_tcb_has_fault = (tcb_has_fault tcb), cdl_tcb_domain = tcb_domain etcb \" definition transform_asid_pool_entry :: "obj_ref option \ cdl_cap" where "transform_asid_pool_entry p \ case p of None \ Types_D.NullCap | Some p \ Types_D.PageDirectoryCap p Fake None" (* * Transform an AsidPool. * * This converts the object references into PageDirectory caps. *) definition transform_asid_pool_contents :: "(10 word \ obj_ref option) \ cdl_cap_map" where "transform_asid_pool_contents M \ unat_map (Some \ transform_asid_pool_entry \ M)" definition transform_paddr :: "paddr \ cdl_object_id" where "transform_paddr = ptrFromPAddr" declare transform_paddr_def[simp] (* * Transform a PageTable, one entry(PTE) at a time. * * This transforms the references to frames into frame caps. *) definition transform_pte :: "ARM_A.pte \ cdl_cap" where "transform_pte pte \ case pte of ARM_A.InvalidPTE \ cdl_cap.NullCap | ARM_A.LargePagePTE ref _ rights_ \ Types_D.FrameCap False (transform_paddr ref) rights_ (pageBitsForSize ARMLargePage) Fake None | ARM_A.SmallPagePTE ref _ rights_ \ Types_D.FrameCap False (transform_paddr ref) rights_ (pageBitsForSize ARMSmallPage) Fake None" definition transform_page_table_contents :: "(word8 \ ARM_A.pte) \ (nat \ cdl_cap option)" where "transform_page_table_contents M \ unat_map (Some o transform_pte o M)" (* * Transform a PageDirectory, one entry(PDE) at a time. * * This transforms the references to frames into PageTable or Frame caps. *) definition transform_pde :: "ARM_A.pde \ cdl_cap" where "transform_pde pde \ case pde of ARM_A.InvalidPDE \ cdl_cap.NullCap | ARM_A.PageTablePDE ref _ _ \ Types_D.PageTableCap (transform_paddr ref) Fake None | ARM_A.SectionPDE ref _ _ rights_ \ Types_D.FrameCap False (transform_paddr ref) rights_ (pageBitsForSize ARMSection) Fake None | ARM_A.SuperSectionPDE ref _ rights_ \ Types_D.FrameCap False (transform_paddr ref) rights_ (pageBitsForSize ARMSuperSection) Fake None" definition kernel_pde_mask :: "(12 word \ ARM_A.pde) \ (12 word \ ARM_A.pde)" where "kernel_pde_mask M \ \x. if (ucast (kernel_base >> 20)) \ x then ARM_A.InvalidPDE else M x" definition transform_page_directory_contents :: "(12 word \ ARM_A.pde) \ (nat \ cdl_cap option)" where "transform_page_directory_contents M \ unat_map (Some o transform_pde o kernel_pde_mask M)" (* sseefried: The 'undefined' case below will never occur as long as this function is invoked in an environment where the invariant 'valid_etcbs s' holds *) (* Transform a kernel object. *) definition transform_object :: "machine_state \ obj_ref \ etcb option \ kernel_object \ cdl_object" where "transform_object ms ref opt_etcb ko \ case ko of Structures_A.CNode 0 c \ Types_D.IRQNode \cdl_irq_node_caps = transform_cnode_contents 0 c\ | Structures_A.CNode sz c \ Types_D.CNode \ cdl_cnode_caps = transform_cnode_contents sz c, cdl_cnode_size_bits = sz \ | Structures_A.TCB tcb \ (case opt_etcb of Some etcb \ transform_tcb ms ref tcb etcb | None \ undefined) | Structures_A.Endpoint _ \ Types_D.Endpoint | Structures_A.Notification _ \ Types_D.Notification | Structures_A.ArchObj (ARM_A.ASIDPool ap) \ Types_D.AsidPool \cdl_asid_pool_caps = (transform_asid_pool_contents ap)\ | Structures_A.ArchObj (ARM_A.PageTable ptx) \ Types_D.PageTable \cdl_page_table_caps = (transform_page_table_contents ptx)\ | Structures_A.ArchObj (ARM_A.PageDirectory pd) \ Types_D.PageDirectory \cdl_page_directory_caps = (transform_page_directory_contents pd)\ | Structures_A.ArchObj (ARM_A.DataPage dev sz) \ Types_D.Frame \cdl_frame_size_bits = pageBitsForSize sz\" lemmas transform_object_simps [simp] = transform_object_def [split_simps Structures_A.kernel_object.split ARM_A.arch_kernel_obj.split] (* Lifts a map over a function, returning the empty map if that function would be insufficiently injective *) definition map_lift_over :: "('a \ 'b) \ ('a \ 'a) \ ('b \ 'b)" where "map_lift_over f m = (if inj_on f (dom m \ ran m) then (\x. if \y. f y = x \ y \ dom m then map_option f (m (inv_into (dom m) f x)) else None) else Map.empty)" (* Transform the CDT. *) definition transform_cdt :: "'z::state_ext state \ cdl_cdt" where "transform_cdt s = map_lift_over transform_cslot_ptr (cdt s)" definition get_obj :: "'z::state_ext state \ obj_ref \ kernel_object option" where "get_obj s r \ (kheap s) r" definition cap_installed_at_irq :: "irq \ 'z::state_ext state \ cap option" where "cap_installed_at_irq irq s \ caps_of_state s (interrupt_irq_node s irq, [])" abbreviation option_map2 :: "('a \ 'b \ 'c) \ 'a option \ 'b option \ 'c option" where "option_map2 f opt_a opt_b \ case opt_a of None \ None | Some a \ (case opt_b of None \ None | Some b \ Some (f a b))" (* Transform objects in the abstract spec to CapDL. Empty memory is transformed into Untyped objects. *) definition transform_objects :: "det_ext state \ (cdl_object_id \ cdl_object option)" where "transform_objects s = (\ptr. Some Types_D.Untyped) |` (- {idle_thread s}) ++ (\ptr. map_option (transform_object (machine_state s) ptr ((ekheap s |` (- {idle_thread s})) ptr)) ((kheap s |` (- {idle_thread s})) ptr))" lemma evalMonad_return [simp]: "evalMonad (return x) s = Some x" by (simp add: evalMonad_def return_def) definition "det_or_fail f \ \s. fst (f s) = {} \ (\r. fst (f s) = {r})" lemma evalMonad_bind: assumes f: "\P. \P\ f \\_. P\" assumes det: "det_or_fail f" shows "evalMonad (f >>= g) s = (if evalMonad f s = None then None else evalMonad (g (the (evalMonad f s))) s)" apply (case_tac "evalMonad f s") apply (simp add: evalMonad_def split: if_split_asm) apply (simp add: bind_def) apply simp apply (simp add: evalMonad_def) apply (clarsimp simp: bind_def) apply (insert det) apply (clarsimp simp: det_or_fail_def split: if_split_asm) apply (erule_tac x=s in allE) apply clarsimp apply (subgoal_tac "b = s") apply simp apply (subgoal_tac "(a,b) \ fst (f s)") apply (drule use_valid, rule f [where P="(=) s"]) apply (rule refl) apply simp apply simp done lemma bind_dfI: "\ det_or_fail f; \x. det_or_fail (g x) \ \ det_or_fail (f >>= g)" apply (auto simp: det_or_fail_def bind_def split_def) apply force done lemma return_df: "det_or_fail (return x)" by (simp add: det_or_fail_def return_def) lemma assert_df: "det_or_fail (assert P)" by (simp add: assert_def fail_def det_or_fail_def return_def) lemma mapM_df: "(\x. det_or_fail (f x)) \ det_or_fail (mapM f xs)" apply (induct xs) apply (simp add: mapM_Nil return_df) apply (simp add: mapM_Cons) apply (rule bind_dfI, assumption) apply (rule bind_dfI, assumption) apply (rule return_df) done lemma df_loadWord: "det_or_fail (loadWord x)" apply (unfold loadWord_def) apply (rule bind_dfI) apply (simp add: simpler_gets_def det_or_fail_def) apply clarsimp apply (rule bind_dfI) apply (rule assert_df) apply (rule return_df) done lemma evalMonad_loadWord_cong: "underlying_memory ms = underlying_memory ms' \ evalMonad (loadWord x) ms = evalMonad (loadWord x) ms'" by (simp add: loadWord_def bind_def simpler_gets_def assert_def return_def fail_def evalMonad_def) lemma evalMonad_mapM_cong: assumes f: "\x. evalMonad (f x) ms = evalMonad (f x) ms'" assumes P: "\P x. \P\ f x \\_. P\" assumes det: "\x. det_or_fail (f x)" shows "evalMonad (mapM f xs) ms = evalMonad (mapM f xs) ms'" apply (induct xs) apply (simp add: mapM_Nil) apply (simp add: mapM_Cons) apply (subst evalMonad_bind [OF P det]) apply (subst evalMonad_bind [OF P det]) apply (clarsimp simp: f) apply (subst evalMonad_bind) apply (wp mapM_wp' P) apply (rule mapM_df, rule det) apply (subst evalMonad_bind) apply (wp mapM_wp' P) apply (rule mapM_df, rule det) apply simp done lemma evalMonad_mapM_loadWord_cong: "underlying_memory ms = underlying_memory ms' \ evalMonad (mapM loadWord xs) ms = evalMonad (mapM loadWord xs) ms'" apply (rule evalMonad_mapM_cong) apply (simp cong: evalMonad_loadWord_cong) apply (wp loadWord_inv) apply (rule df_loadWord) done lemma get_ipc_buffer_words_cong: "underlying_memory ms = underlying_memory ms' \ get_ipc_buffer_words ms = get_ipc_buffer_words ms'" apply (rule ext)+ apply (simp add: get_ipc_buffer_words_def Let_def cong: evalMonad_mapM_loadWord_cong split: cap.splits arch_cap.splits) done lemma get_tcb_mrs_cong: "underlying_memory ms = underlying_memory ms' \ get_tcb_mrs ms = get_tcb_mrs ms'" apply (rule ext) apply (simp add: get_tcb_mrs_def Let_def cong: get_ipc_buffer_words_cong) done lemma transform_objects_ms_underlying_mem: "transform_objects s = transform_objects (s \ machine_state := undefined \ underlying_memory := underlying_memory (machine_state s) \ \)" supply option.case_cong[cong] apply (rule ext) apply (simp add: transform_objects_def map_add_def option_map_def split: option.split) apply (simp add: transform_object_def transform_tcb_def transform_full_intent_def Let_def split: Structures_A.kernel_object.split) apply (clarsimp simp: transform_intent_def cong: get_tcb_mrs_cong get_ipc_buffer_words_cong) done lemmas transform_objects_def2 = trans [OF transform_objects_ms_underlying_mem transform_objects_def, simplified] (* * Transform the current thread in the abstract spec to CapDL. * * We just return the thread's memory address, unless it happens * to be the idle thread, which CapDL maps as "None". *) definition transform_current_thread :: "'z::state_ext state \ cdl_object_id option" where "transform_current_thread s \ if (cur_thread s \ idle_thread s) then Some (cur_thread s) else None" definition transform_asid_table_entry :: "obj_ref option \ cdl_cap" where "transform_asid_table_entry p \ case p of None \ Types_D.NullCap | Some p \ Types_D.AsidPoolCap p 0" definition transform_asid_table :: "'z::state_ext state \ cdl_cap_map" where "transform_asid_table s \ let asid_table = arm_asid_table $ arch_state s in unat_map (Some \ transform_asid_table_entry \ asid_table)" definition transform_current_domain :: "det_ext state \ word8" where "transform_current_domain s = cur_domain s" (* * Transform an abstract spec state into the corresponding * CDL state. *) definition transform :: "det_ext state \ cdl_state" where "transform s \ \ cdl_arch = ARM11, cdl_objects = transform_objects s, cdl_cdt = transform_cdt s, cdl_current_thread = transform_current_thread s, cdl_irq_node = interrupt_irq_node s, cdl_asid_table = transform_asid_table s, cdl_current_domain = transform_current_domain s \" end end