/* * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /*----------------------------------------------------------------------- ** vmachmon.h ** ** C routines that we are adding to the MacOS X kernel. ** -----------------------------------------------------------------------*/ #include #ifndef _VEMULATION_H_ #define _VEMULATION_H_ /************************************************************************************* External Emulation Types **************************************************************************************/ typedef union vmm_vector_register_t { unsigned long i[4]; unsigned short s[8]; unsigned char b[16]; } vmm_vector_register_t; typedef union vmm_fp_register_t { double d; unsigned long i[2]; unsigned short s[4]; unsigned char b[8]; } vmm_fp_register_t; typedef struct vmm_regs32_t { unsigned long ppcPC; /* 000 */ unsigned long ppcMSR; /* 004 */ unsigned long ppcGPRs[32]; /* 008 */ unsigned long ppcCR; /* 088 */ unsigned long ppcXER; /* 08C */ unsigned long ppcLR; /* 090 */ unsigned long ppcCTR; /* 094 */ unsigned long ppcMQ; /* 098 - Obsolete */ unsigned long ppcVRSave; /* 09C */ unsigned long ppcRsrvd0A0[40]; /* 0A0 */ /* 140 */ } vmm_regs32_t; #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmm_regs64_t { unsigned long long ppcPC; /* 000 */ unsigned long long ppcMSR; /* 008 */ unsigned long long ppcGPRs[32]; /* 010 */ unsigned long long ppcXER; /* 110 */ unsigned long long ppcLR; /* 118 */ unsigned long long ppcCTR; /* 120 */ unsigned long ppcCR; /* 128 */ unsigned long ppcVRSave; /* 12C */ unsigned long ppcRsvd130[4]; /* 130 */ /* 140 */ } vmm_regs64_t; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef union vmm_regs_t { vmm_regs32_t ppcRegs32; vmm_regs64_t ppcRegs64; } vmm_regs_t; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmm_processor_state_t { /* 32-byte bndry */ vmm_regs_t ppcRegs; /* Define registers areas */ /* We must be 16-byte aligned here */ vmm_vector_register_t ppcVRs[32]; /* These are only valid after a kVmmGetVectorState */ vmm_vector_register_t ppcVSCR; /* This is always loaded/saved at host/guest transition */ /* We must be 8-byte aligned here */ vmm_fp_register_t ppcFPRs[32]; /* These are only valid after a kVmmGetFloatState */ vmm_fp_register_t ppcFPSCR; /* This is always loaded/saved at host/guest transition */ unsigned long ppcReserved2[2]; /* Pad out to multiple of 16 bytes */ } vmm_processor_state_t; #pragma pack() typedef unsigned long vmm_return_code_t; typedef unsigned long vmm_thread_index_t; #define vmmTInum 0x000000FF #define vmmTIadsp 0x0000FF00 typedef unsigned long vmm_adsp_id_t; enum { kVmmCurMajorVersion = 0x0001, kVmmCurMinorVersion = 0x0007, kVmmMinMajorVersion = 0x0001, }; #define kVmmCurrentVersion ((kVmmCurMajorVersion << 16) | kVmmCurMinorVersion) typedef unsigned long vmm_features_t; enum { kVmmFeature_LittleEndian = 0x00000001, kVmmFeature_Stop = 0x00000002, kVmmFeature_ExtendedMapping = 0x00000004, kVmmFeature_ListMapping = 0x00000008, kVmmFeature_FastAssist = 0x00000010, kVmmFeature_XA = 0x00000020, kVmmFeature_SixtyFourBit = 0x00000040, kVmmFeature_MultAddrSpace = 0x00000080, kVmmFeature_GuestShadowAssist = 0x00000100, /* Guest->physical shadow hash table */ kVmmFeature_GlobalMappingAssist = 0x00000200, /* Global shadow mapping support */ kVmmFeature_HostShadowAssist = 0x00000400, /* Linear shadow mapping of an area of host virtual as guest physical */ kVmmFeature_MultAddrSpaceAssist = 0x00000800, /* Expanded pool of guest virtual address spaces */ }; #define kVmmCurrentFeatures (kVmmFeature_LittleEndian | kVmmFeature_Stop | kVmmFeature_ExtendedMapping \ | kVmmFeature_ListMapping | kVmmFeature_FastAssist | kVmmFeature_XA \ | kVmmFeature_GuestShadowAssist) enum { vmm64Bit = 0x80000000, /* Make guest 64-bit */ vmmGSA = 0x40000000, /* Enable guest shadow assist (GSA) */ vmmGMA = 0x20000000, /* Enable global shadow mapping assist (GMA) */ }; #define kVmmSupportedSetXA (vmm64Bit | vmmGSA | vmmGMA) typedef unsigned long vmm_version_t; typedef struct vmm_ret_parms32_t { unsigned long return_params[4]; } vmm_ret_parms32_t; typedef struct vmm_ret_parms64_t { unsigned long long return_params[4]; } vmm_ret_parms64_t; #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef union vmm_ret_parms_t { vmm_ret_parms64_t vmmrp64; /* 64-bit flavor */ vmm_ret_parms32_t vmmrp32; /* 32-bit flavor */ unsigned int retgas[11]; /* Force this to be 11 words long */ } vmm_ret_parms_t; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmm_fastassist_state32_t { unsigned long fastassist_dispatch; unsigned long fastassist_refcon; unsigned long fastassist_dispatch_code; unsigned long fastassist_parameter[5]; unsigned long guest_register[8]; unsigned long guest_pc; unsigned long guest_msr; unsigned long fastassist_intercepts; unsigned long fastassist_reserved1; } vmm_fastassist_state32_t; typedef struct vmm_fastassist_state64_t { unsigned long long fastassist_dispatch; unsigned long long fastassist_refcon; unsigned long long fastassist_dispatch_code; unsigned long long fastassist_parameter[5]; unsigned long long guest_register[8]; unsigned long long guest_pc; unsigned long long guest_msr; unsigned long fastassist_intercepts; unsigned long fastassist_reserved1; } vmm_fastassist_state64_t; typedef union vmm_fastassist_state_t { vmm_fastassist_state64_t vmmfs64; /* 64-bit flavor */ vmm_fastassist_state32_t vmmfs32; /* 32-bit flavor */ } vmm_fastassist_state_t; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmm_state_page_t { /* This structure must remain below 4Kb (one page) in size */ vmm_version_t interface_version; vmm_thread_index_t thread_index; unsigned int vmmStat; /* Note: this field is identical to vmmFlags in vmmCntrlEntry */ unsigned int vmmCntrl; #define vmmFloatLoad 0x80000000 #define vmmFloatLoadb 0 #define vmmVectLoad 0x40000000 #define vmmVectLoadb 1 #define vmmVectVRall 0x20000000 #define vmmVectVRallb 2 #define vmmVectVAss 0x10000000 #define vmmVectVAssb 3 #define vmmXStart 0x08000000 #define vmmXStartb 4 #define vmmKey 0x04000000 #define vmmKeyb 5 #define vmmFamEna 0x02000000 #define vmmFamEnab 6 #define vmmFamSet 0x01000000 #define vmmFamSetb 7 vmm_return_code_t return_code; vmm_ret_parms_t vmmRet; /* The next portion of the structure must remain 32-byte aligned */ vmm_processor_state_t vmm_proc_state; /* The next portion of the structure must remain 16-byte aligned */ vmm_fastassist_state_t vmm_fastassist_state; } vmm_state_page_t; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmm_comm_page_t { union { vmm_state_page_t vmcpState; /* Reserve area for state */ unsigned int vmcpPad[768]; /* Reserve space for 3/4 page state area */ } vmcpfirst; unsigned int vmcpComm[256]; /* Define last 1024 bytes as a communications area - function specific */ } vmm_comm_page_t; #pragma pack() enum { /* Function Indices (passed in r3) */ kVmmGetVersion = 0, /* Get VMM system version */ kVmmvGetFeatures, /* Get VMM supported features */ kVmmInitContext, /* Initialize a context */ kVmmTearDownContext, /* Destroy a context */ kVmmTearDownAll, /* Destory all contexts */ kVmmMapPage, /* Map a host to guest address space */ kVmmGetPageMapping, /* Get host address of a guest page */ kVmmUnmapPage, /* Unmap a guest page */ kVmmUnmapAllPages, /* Unmap all pages in a guest address space */ kVmmGetPageDirtyFlag, /* Check if guest page modified */ kVmmGetFloatState, /* Retrieve guest floating point context */ kVmmGetVectorState, /* Retrieve guest vector context */ kVmmSetTimer, /* Set a guest timer */ kVmmGetTimer, /* Get a guest timer */ kVmmExecuteVM, /* Launch a guest */ kVmmProtectPage, /* Set protection attributes for a guest page */ kVmmMapExecute, /* Map guest page and launch */ kVmmProtectExecute, /* Set prot attributes and launch */ kVmmMapList, /* Map a list of pages into guest address spaces */ kVmmUnmapList, /* Unmap a list of pages from guest address spaces */ kvmmExitToHost, /* Exit from FAM to host -- fast-path syscall */ kvmmResumeGuest, /* Resume guest from FAM -- fast-path syscall */ kvmmGetGuestRegister, /* Get guest register from FAM -- fast-path syscall */ kvmmSetGuestRegister, /* Set guest register from FAM -- fast-path syscall */ kVmmActivateXA, /* Activate extended architecture features for a VM */ kVmmDeactivateXA, /* Deactivate extended architecture features for a VM */ kVmmGetXA, /* Get extended architecture features from a VM */ kVmmMapPage64, /* Map a host to guest address space - supports 64-bit */ kVmmGetPageMapping64, /* Get host address of a guest page - supports 64-bit */ kVmmUnmapPage64, /* Unmap a guest page - supports 64-bit */ kVmmGetPageDirtyFlag64, /* Check if guest page modified - supports 64-bit */ kVmmProtectPage64, /* Set protection attributes for a guest page - supports 64-bit */ kVmmMapExecute64, /* Map guest page and launch - supports 64-bit */ kVmmProtectExecute64, /* Set prot attributes and launch - supports 64-bit */ kVmmMapList64, /* Map a list of pages into guest address spaces - supports 64-bit */ kVmmUnmapList64, /* Unmap a list of pages from guest address spaces - supports 64-bit */ kVmmMaxAddr, /* Returns the maximum virtual address that is mappable */ kVmmSetGuestMemory, /* Sets base and extent of guest physical memory in host address space */ kVmmPurgeLocal, /* Purges all non-global mappings for a given guest address space */ }; #define kVmmReturnNull 0 #define kVmmBogusContext 1 #define kVmmStopped 2 #define kVmmReturnDataPageFault 3 #define kVmmReturnInstrPageFault 4 #define kVmmReturnAlignmentFault 6 #define kVmmReturnProgramException 7 #define kVmmReturnSystemCall 12 #define kVmmReturnTraceException 13 #define kVmmAltivecAssist 22 #define kVmmInvalidAddress 0x1000 #define kVmmInvalidAdSpace 0x1001 /* * Notes on guest address spaces. * * Address spaces are loosely coupled to virtual machines. The default is for * a guest with an index of 1 to use address space 1, 2 to use 2, etc. However, * any guest may be launched using any address space and any address space may be the * target for a map or unmap function. Note that the (un)map list functions may pass in * an address space ID on a page-by-page basis. * * An address space is instantiated either explicitly by mapping something into it, or * implicitly by launching a guest with it. * * An address space is destroyed explicitly by kVmmTearDownAll or kVmmUnmapAllPages. It is * destroyed implicitly by kVmmTearDownContext. The latter is done in order to remain * backwards compatible with the previous implementation, which does not have decoupled * guests and address spaces. * * An address space supports the maximum virtual address supported by the processor. * The 64-bit variant of the mapping functions can be used on non-64-bit machines. If an * unmappable address (e.g., an address larger than 4GB-1 on a 32-bit machine) is requested, * the operation fails with a kVmmInvalidAddress return code. * * Note that for 64-bit calls, both host and guest are specified at 64-bit values. * */ /* * Storage Extended Protection modes * Notes: * To keep compatibility, vmmKey and the PPC key have reversed meanings, * i.e., vmmKey 0 is PPC key 1 and vice versa. * * vmmKey Notes * Mode 0 1 * * kVmmProtNARW not accessible read/write VM_PROT_NONE (not settable via VM calls) * kVmmProtRORW read only read/write * kVmmProtRWRW read/write read/write VM_PROT_WRITE or (VM_PROT_WRITE | VM_PROT_READ) * kVmmProtRORO read only read only VM_PROT_READ */ #define kVmmProtXtnd 0x00000008 #define kVmmProtNARW (kVmmProtXtnd | 0x00000000) #define kVmmProtRORW (kVmmProtXtnd | 0x00000001) #define kVmmProtRWRW (kVmmProtXtnd | 0x00000002) #define kVmmProtRORO (kVmmProtXtnd | 0x00000003) /* * Map list formats * The last 12 bits in the guest virtual address is used as flags as follows: * 0x007 - for the map calls, this is the key to set * 0x3F0 - for both map and unmap, this is the address space ID upon which to operate. * Note that if 0, the address space ID from the function call is used instead. */ typedef struct vmmMList { unsigned int vmlva; /* Virtual address in host address space */ unsigned int vmlava; /* Virtual address in guest address space */ } vmmMList; typedef struct vmmMList64 { unsigned long long vmlva; /* Virtual address in host address space */ unsigned long long vmlava; /* Virtual address in guest address space */ } vmmMList64; typedef struct vmmUMList { unsigned int vmlava; /* Virtual address in guest address space */ } vmmUMList; typedef struct vmmUMList64 { unsigned long long vmlava; /* Virtual address in guest address space */ } vmmUMList64; #define vmmlFlgs 0x00000FFF /* Flags passed in in vmlava low order 12 bits */ #define vmmlProt 0x00000007 /* Protection flags for the page */ #define vmmlAdID 0x000003F0 /* Guest address space ID - used only if non-zero */ #define vmmlGlob 0x00000400 /* Mapping is global */ #define vmmlRsvd 0x00000800 /* Reserved for future */ /************************************************************************************* Internal Emulation Types **************************************************************************************/ #define kVmmMaxContexts 32 #define kVmmMaxUnmapPages 64 #define kVmmMaxMapPages 64 #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmmCntrlEntry { /* Virtual Machine Monitor control table entry */ unsigned int vmmFlags; /* Assorted control flags */ #define vmmInUse 0x80000000 #define vmmInUseb 0 #define vmmFloatCngd 0x40000000 #define vmmFloatCngdb 1 #define vmmVectCngd 0x20000000 #define vmmVectCngdb 2 #define vmmTimerPop 0x10000000 #define vmmTimerPopb 3 #define vmmFAMmode 0x04000000 #define vmmFAMmodeb 5 #define vmmXStop 0x00800000 #define vmmXStopb 8 #define vmmSpfSave 0x000000FF #define vmmSpfSaveb 24 unsigned int vmmXAFlgs; /* Extended Architecture flags */ vmm_state_page_t *vmmContextKern; /* Kernel address of context communications area */ ppnum_t vmmContextPhys; /* Physical address of context communications area */ vmm_state_page_t *vmmContextUser; /* User address of context communications area */ facility_context vmmFacCtx; /* Header for vector and floating point contexts */ pmap_t vmmPmap; /* Last dispatched pmap */ uint64_t vmmTimer; /* Last set timer value. Zero means unset */ unsigned int vmmFAMintercept; /* FAM intercepted exceptions */ } vmmCntrlEntry; #pragma pack() #pragma pack(4) /* Make sure the structure stays as we defined it */ typedef struct vmmCntrlTable { /* Virtual Machine Monitor Control table */ unsigned int vmmGFlags; /* Global flags */ #define vmmLastAdSp 0xFF /* Remember the address space that was mapped last */ addr64_t vmmLastMap; /* Last vaddr mapping made */ vmmCntrlEntry vmmc[kVmmMaxContexts]; /* One entry for each possible Virtual Machine Monitor context */ pmap_t vmmAdsp[kVmmMaxContexts]; /* Guest address space pmaps */ } vmmCntrlTable; #pragma pack() /* function decls for kernel level routines... */ extern void vmm_execute_vm(thread_t act, vmm_thread_index_t index); extern kern_return_t vmm_tear_down_context(thread_t act, vmm_thread_index_t index); extern kern_return_t vmm_get_float_state(thread_t act, vmm_thread_index_t index); extern kern_return_t vmm_get_vector_state(thread_t act, vmm_thread_index_t index); extern kern_return_t vmm_set_timer(thread_t act, vmm_thread_index_t index, unsigned int timerhi, unsigned int timerlo); extern kern_return_t vmm_get_timer(thread_t act, vmm_thread_index_t index); extern void vmm_tear_down_all(thread_t act); extern kern_return_t vmm_map_page(thread_t act, vmm_thread_index_t hindex, addr64_t cva, addr64_t ava, vm_prot_t prot); extern vmm_return_code_t vmm_map_execute(thread_t act, vmm_thread_index_t hindex, addr64_t cva, addr64_t ava, vm_prot_t prot); extern kern_return_t vmm_protect_page(thread_t act, vmm_thread_index_t hindex, addr64_t va, vm_prot_t prot); extern vmm_return_code_t vmm_protect_execute(thread_t act, vmm_thread_index_t hindex, addr64_t va, vm_prot_t prot); extern addr64_t vmm_get_page_mapping(thread_t act, vmm_thread_index_t index, addr64_t va); extern kern_return_t vmm_unmap_page(thread_t act, vmm_thread_index_t index, addr64_t va); extern void vmm_unmap_all_pages(thread_t act, vmm_thread_index_t index); extern boolean_t vmm_get_page_dirty_flag(thread_t act, vmm_thread_index_t index, addr64_t va, unsigned int reset); extern kern_return_t vmm_activate_XA(thread_t act, vmm_thread_index_t index, unsigned int xaflags); extern kern_return_t vmm_deactivate_XA(thread_t act, vmm_thread_index_t index, unsigned int xaflags); extern unsigned int vmm_get_XA(thread_t act, vmm_thread_index_t index); extern int vmm_get_features(struct savearea *); extern int vmm_get_version(struct savearea *); extern int vmm_init_context(struct savearea *); extern int vmm_dispatch(struct savearea *); extern int vmm_exit(thread_t act, struct savearea *); extern void vmm_force_exit(thread_t act, struct savearea *); extern int vmm_stop_vm(struct savearea *save); extern void vmm_timer_pop(thread_t act); extern void vmm_interrupt(ReturnHandler *rh, thread_t act); extern kern_return_t vmm_map_list(thread_t act, vmm_thread_index_t index, unsigned int cnt, unsigned int flavor); extern kern_return_t vmm_unmap_list(thread_t act, vmm_thread_index_t index, unsigned int cnt, unsigned int flavor); extern vmm_return_code_t vmm_resume_guest(vmm_thread_index_t index, unsigned long pc, unsigned long vmmCntrl, unsigned long vmmCntrMaskl); extern vmm_return_code_t vmm_exit_to_host(vmm_thread_index_t index); extern unsigned long vmm_get_guest_register(vmm_thread_index_t index, unsigned long reg_index); extern vmm_return_code_t vmm_set_guest_register(vmm_thread_index_t index, unsigned long reg_index, unsigned long reg_value); extern addr64_t vmm_max_addr(thread_t act); extern kern_return_t vmm_set_guest_memory(thread_t act, vmm_thread_index_t index, addr64_t base, addr64_t extent); extern kern_return_t vmm_purge_local(thread_t act, vmm_thread_index_t index); #endif