2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /*-----------------------------------------------------------------------
31 ** C routines that we are adding to the MacOS X kernel.
33 -----------------------------------------------------------------------*/
35 #include <ppc/exception.h>
37 #ifndef _VEMULATION_H_
38 #define _VEMULATION_H_
40 /*************************************************************************************
41 External Emulation Types
42 **************************************************************************************/
44 typedef union vmm_vector_register_t
{
48 } vmm_vector_register_t
;
50 typedef union vmm_fp_register_t
{
58 typedef struct vmm_regs32_t
{
60 unsigned long ppcPC
; /* 000 */
61 unsigned long ppcMSR
; /* 004 */
63 unsigned long ppcGPRs
[32]; /* 008 */
65 unsigned long ppcCR
; /* 088 */
66 unsigned long ppcXER
; /* 08C */
67 unsigned long ppcLR
; /* 090 */
68 unsigned long ppcCTR
; /* 094 */
69 unsigned long ppcMQ
; /* 098 - Obsolete */
70 unsigned long ppcVRSave
; /* 09C */
71 unsigned long ppcRsrvd0A0
[40]; /* 0A0 */
75 #pragma pack(4) /* Make sure the structure stays as we defined it */
76 typedef struct vmm_regs64_t
{
78 unsigned long long ppcPC
; /* 000 */
79 unsigned long long ppcMSR
; /* 008 */
81 unsigned long long ppcGPRs
[32]; /* 010 */
83 unsigned long long ppcXER
; /* 110 */
84 unsigned long long ppcLR
; /* 118 */
85 unsigned long long ppcCTR
; /* 120 */
86 unsigned long ppcCR
; /* 128 */
87 unsigned long ppcVRSave
; /* 12C */
88 unsigned long ppcRsvd130
[4]; /* 130 */
94 #pragma pack(4) /* Make sure the structure stays as we defined it */
95 typedef union vmm_regs_t
{
96 vmm_regs32_t ppcRegs32
;
97 vmm_regs64_t ppcRegs64
;
101 #pragma pack(4) /* Make sure the structure stays as we defined it */
102 typedef struct vmm_processor_state_t
{
104 vmm_regs_t ppcRegs
; /* Define registers areas */
106 /* We must be 16-byte aligned here */
108 vmm_vector_register_t ppcVRs
[32]; /* These are only valid after a kVmmGetVectorState */
109 vmm_vector_register_t ppcVSCR
; /* This is always loaded/saved at host/guest transition */
111 /* We must be 8-byte aligned here */
113 vmm_fp_register_t ppcFPRs
[32]; /* These are only valid after a kVmmGetFloatState */
114 vmm_fp_register_t ppcFPSCR
; /* This is always loaded/saved at host/guest transition */
115 unsigned long ppcReserved2
[2]; /* Pad out to multiple of 16 bytes */
116 } vmm_processor_state_t
;
119 typedef unsigned long vmm_return_code_t
;
121 typedef unsigned long vmm_thread_index_t
;
122 #define vmmTInum 0x000000FF
123 #define vmmTIadsp 0x0000FF00
124 typedef unsigned long vmm_adsp_id_t
;
127 kVmmCurMajorVersion
= 0x0001,
128 kVmmCurMinorVersion
= 0x0007,
129 kVmmMinMajorVersion
= 0x0001,
131 #define kVmmCurrentVersion ((kVmmCurMajorVersion << 16) | kVmmCurMinorVersion)
133 typedef unsigned long vmm_features_t
;
135 kVmmFeature_LittleEndian
= 0x00000001,
136 kVmmFeature_Stop
= 0x00000002,
137 kVmmFeature_ExtendedMapping
= 0x00000004,
138 kVmmFeature_ListMapping
= 0x00000008,
139 kVmmFeature_FastAssist
= 0x00000010,
140 kVmmFeature_XA
= 0x00000020,
141 kVmmFeature_SixtyFourBit
= 0x00000040,
142 kVmmFeature_MultAddrSpace
= 0x00000080,
143 kVmmFeature_GuestShadowAssist
= 0x00000100, /* Guest->physical shadow hash table */
144 kVmmFeature_GlobalMappingAssist
= 0x00000200, /* Global shadow mapping support */
145 kVmmFeature_HostShadowAssist
= 0x00000400, /* Linear shadow mapping of an area of
146 host virtual as guest physical */
147 kVmmFeature_MultAddrSpaceAssist
= 0x00000800, /* Expanded pool of guest virtual
150 #define kVmmCurrentFeatures (kVmmFeature_LittleEndian | kVmmFeature_Stop | kVmmFeature_ExtendedMapping \
151 | kVmmFeature_ListMapping | kVmmFeature_FastAssist | kVmmFeature_XA \
152 | kVmmFeature_GuestShadowAssist)
155 vmm64Bit
= 0x80000000, /* Make guest 64-bit */
156 vmmGSA
= 0x40000000, /* Enable guest shadow assist (GSA) */
157 vmmGMA
= 0x20000000, /* Enable global shadow mapping assist (GMA) */
160 #define kVmmSupportedSetXA (vmm64Bit | vmmGSA | vmmGMA)
162 typedef unsigned long vmm_version_t
;
164 typedef struct vmm_ret_parms32_t
{
165 unsigned long return_params
[4];
168 typedef struct vmm_ret_parms64_t
{
169 unsigned long long return_params
[4];
172 #pragma pack(4) /* Make sure the structure stays as we defined it */
173 typedef union vmm_ret_parms_t
{
174 vmm_ret_parms64_t vmmrp64
; /* 64-bit flavor */
175 vmm_ret_parms32_t vmmrp32
; /* 32-bit flavor */
176 unsigned int retgas
[11]; /* Force this to be 11 words long */
180 #pragma pack(4) /* Make sure the structure stays as we defined it */
181 typedef struct vmm_fastassist_state32_t
{
182 unsigned long fastassist_dispatch
;
183 unsigned long fastassist_refcon
;
185 unsigned long fastassist_dispatch_code
;
186 unsigned long fastassist_parameter
[5];
188 unsigned long guest_register
[8];
190 unsigned long guest_pc
;
191 unsigned long guest_msr
;
193 unsigned long fastassist_intercepts
;
194 unsigned long fastassist_reserved1
;
195 } vmm_fastassist_state32_t
;
197 typedef struct vmm_fastassist_state64_t
{
198 unsigned long long fastassist_dispatch
;
199 unsigned long long fastassist_refcon
;
201 unsigned long long fastassist_dispatch_code
;
202 unsigned long long fastassist_parameter
[5];
204 unsigned long long guest_register
[8];
206 unsigned long long guest_pc
;
207 unsigned long long guest_msr
;
209 unsigned long fastassist_intercepts
;
210 unsigned long fastassist_reserved1
;
211 } vmm_fastassist_state64_t
;
213 typedef union vmm_fastassist_state_t
{
214 vmm_fastassist_state64_t vmmfs64
; /* 64-bit flavor */
215 vmm_fastassist_state32_t vmmfs32
; /* 32-bit flavor */
216 } vmm_fastassist_state_t
;
219 #pragma pack(4) /* Make sure the structure stays as we defined it */
220 typedef struct vmm_state_page_t
{
221 /* This structure must remain below 4Kb (one page) in size */
222 vmm_version_t interface_version
;
223 vmm_thread_index_t thread_index
;
224 unsigned int vmmStat
; /* Note: this field is identical to vmmFlags in vmmCntrlEntry */
225 unsigned int vmmCntrl
;
226 #define vmmFloatLoad 0x80000000
227 #define vmmFloatLoadb 0
228 #define vmmVectLoad 0x40000000
229 #define vmmVectLoadb 1
230 #define vmmVectVRall 0x20000000
231 #define vmmVectVRallb 2
232 #define vmmVectVAss 0x10000000
233 #define vmmVectVAssb 3
234 #define vmmXStart 0x08000000
236 #define vmmKey 0x04000000
238 #define vmmFamEna 0x02000000
240 #define vmmFamSet 0x01000000
243 vmm_return_code_t return_code
;
244 vmm_ret_parms_t vmmRet
;
246 /* The next portion of the structure must remain 32-byte aligned */
247 vmm_processor_state_t vmm_proc_state
;
249 /* The next portion of the structure must remain 16-byte aligned */
250 vmm_fastassist_state_t vmm_fastassist_state
;
255 #pragma pack(4) /* Make sure the structure stays as we defined it */
256 typedef struct vmm_comm_page_t
{
258 vmm_state_page_t vmcpState
; /* Reserve area for state */
259 unsigned int vmcpPad
[768]; /* Reserve space for 3/4 page state area */
261 unsigned int vmcpComm
[256]; /* Define last 1024 bytes as a communications area - function specific */
266 /* Function Indices (passed in r3) */
267 kVmmGetVersion
= 0, /* Get VMM system version */
268 kVmmvGetFeatures
, /* Get VMM supported features */
269 kVmmInitContext
, /* Initialize a context */
270 kVmmTearDownContext
, /* Destroy a context */
271 kVmmTearDownAll
, /* Destory all contexts */
272 kVmmMapPage
, /* Map a host to guest address space */
273 kVmmGetPageMapping
, /* Get host address of a guest page */
274 kVmmUnmapPage
, /* Unmap a guest page */
275 kVmmUnmapAllPages
, /* Unmap all pages in a guest address space */
276 kVmmGetPageDirtyFlag
, /* Check if guest page modified */
277 kVmmGetFloatState
, /* Retrieve guest floating point context */
278 kVmmGetVectorState
, /* Retrieve guest vector context */
279 kVmmSetTimer
, /* Set a guest timer */
280 kVmmGetTimer
, /* Get a guest timer */
281 kVmmExecuteVM
, /* Launch a guest */
282 kVmmProtectPage
, /* Set protection attributes for a guest page */
283 kVmmMapExecute
, /* Map guest page and launch */
284 kVmmProtectExecute
, /* Set prot attributes and launch */
285 kVmmMapList
, /* Map a list of pages into guest address spaces */
286 kVmmUnmapList
, /* Unmap a list of pages from guest address spaces */
287 kvmmExitToHost
, /* Exit from FAM to host -- fast-path syscall */
288 kvmmResumeGuest
, /* Resume guest from FAM -- fast-path syscall */
289 kvmmGetGuestRegister
, /* Get guest register from FAM -- fast-path syscall */
290 kvmmSetGuestRegister
, /* Set guest register from FAM -- fast-path syscall */
292 kVmmActivateXA
, /* Activate extended architecture features for a VM */
293 kVmmDeactivateXA
, /* Deactivate extended architecture features for a VM */
294 kVmmGetXA
, /* Get extended architecture features from a VM */
296 kVmmMapPage64
, /* Map a host to guest address space - supports 64-bit */
297 kVmmGetPageMapping64
, /* Get host address of a guest page - supports 64-bit */
298 kVmmUnmapPage64
, /* Unmap a guest page - supports 64-bit */
299 kVmmGetPageDirtyFlag64
, /* Check if guest page modified - supports 64-bit */
300 kVmmProtectPage64
, /* Set protection attributes for a guest page - supports 64-bit */
301 kVmmMapExecute64
, /* Map guest page and launch - supports 64-bit */
302 kVmmProtectExecute64
, /* Set prot attributes and launch - supports 64-bit */
303 kVmmMapList64
, /* Map a list of pages into guest address spaces - supports 64-bit */
304 kVmmUnmapList64
, /* Unmap a list of pages from guest address spaces - supports 64-bit */
305 kVmmMaxAddr
, /* Returns the maximum virtual address that is mappable */
307 kVmmSetGuestMemory
, /* Sets base and extent of guest physical memory in host address space */
308 kVmmPurgeLocal
, /* Purges all non-global mappings for a given guest address space */
311 #define kVmmReturnNull 0
312 #define kVmmBogusContext 1
313 #define kVmmStopped 2
314 #define kVmmReturnDataPageFault 3
315 #define kVmmReturnInstrPageFault 4
316 #define kVmmReturnAlignmentFault 6
317 #define kVmmReturnProgramException 7
318 #define kVmmReturnSystemCall 12
319 #define kVmmReturnTraceException 13
320 #define kVmmAltivecAssist 22
321 #define kVmmInvalidAddress 0x1000
322 #define kVmmInvalidAdSpace 0x1001
325 * Notes on guest address spaces.
327 * Address spaces are loosely coupled to virtual machines. The default is for
328 * a guest with an index of 1 to use address space 1, 2 to use 2, etc. However,
329 * any guest may be launched using any address space and any address space may be the
330 * target for a map or unmap function. Note that the (un)map list functions may pass in
331 * an address space ID on a page-by-page basis.
333 * An address space is instantiated either explicitly by mapping something into it, or
334 * implicitly by launching a guest with it.
336 * An address space is destroyed explicitly by kVmmTearDownAll or kVmmUnmapAllPages. It is
337 * destroyed implicitly by kVmmTearDownContext. The latter is done in order to remain
338 * backwards compatible with the previous implementation, which does not have decoupled
339 * guests and address spaces.
341 * An address space supports the maximum virtual address supported by the processor.
342 * The 64-bit variant of the mapping functions can be used on non-64-bit machines. If an
343 * unmappable address (e.g., an address larger than 4GB-1 on a 32-bit machine) is requested,
344 * the operation fails with a kVmmInvalidAddress return code.
346 * Note that for 64-bit calls, both host and guest are specified at 64-bit values.
354 * Storage Extended Protection modes
356 * To keep compatibility, vmmKey and the PPC key have reversed meanings,
357 * i.e., vmmKey 0 is PPC key 1 and vice versa.
362 * kVmmProtNARW not accessible read/write VM_PROT_NONE (not settable via VM calls)
363 * kVmmProtRORW read only read/write
364 * kVmmProtRWRW read/write read/write VM_PROT_WRITE or (VM_PROT_WRITE | VM_PROT_READ)
365 * kVmmProtRORO read only read only VM_PROT_READ
369 #define kVmmProtXtnd 0x00000008
370 #define kVmmProtNARW (kVmmProtXtnd | 0x00000000)
371 #define kVmmProtRORW (kVmmProtXtnd | 0x00000001)
372 #define kVmmProtRWRW (kVmmProtXtnd | 0x00000002)
373 #define kVmmProtRORO (kVmmProtXtnd | 0x00000003)
377 * The last 12 bits in the guest virtual address is used as flags as follows:
378 * 0x007 - for the map calls, this is the key to set
379 * 0x3F0 - for both map and unmap, this is the address space ID upon which to operate.
380 * Note that if 0, the address space ID from the function call is used instead.
383 typedef struct vmmMList
{
384 unsigned int vmlva
; /* Virtual address in host address space */
385 unsigned int vmlava
; /* Virtual address in guest address space */
388 typedef struct vmmMList64
{
389 unsigned long long vmlva
; /* Virtual address in host address space */
390 unsigned long long vmlava
; /* Virtual address in guest address space */
393 typedef struct vmmUMList
{
394 unsigned int vmlava
; /* Virtual address in guest address space */
397 typedef struct vmmUMList64
{
398 unsigned long long vmlava
; /* Virtual address in guest address space */
401 #define vmmlFlgs 0x00000FFF /* Flags passed in in vmlava low order 12 bits */
402 #define vmmlProt 0x00000007 /* Protection flags for the page */
403 #define vmmlAdID 0x000003F0 /* Guest address space ID - used only if non-zero */
404 #define vmmlGlob 0x00000400 /* Mapping is global */
405 #define vmmlRsvd 0x00000800 /* Reserved for future */
407 /*************************************************************************************
408 Internal Emulation Types
409 **************************************************************************************/
411 #define kVmmMaxContexts 32
412 #define kVmmMaxUnmapPages 64
413 #define kVmmMaxMapPages 64
415 #pragma pack(4) /* Make sure the structure stays as we defined it */
416 typedef struct vmmCntrlEntry
{ /* Virtual Machine Monitor control table entry */
417 unsigned int vmmFlags
; /* Assorted control flags */
418 #define vmmInUse 0x80000000
420 #define vmmFloatCngd 0x40000000
421 #define vmmFloatCngdb 1
422 #define vmmVectCngd 0x20000000
423 #define vmmVectCngdb 2
424 #define vmmTimerPop 0x10000000
425 #define vmmTimerPopb 3
426 #define vmmFAMmode 0x04000000
427 #define vmmFAMmodeb 5
428 #define vmmXStop 0x00800000
430 #define vmmSpfSave 0x000000FF
431 #define vmmSpfSaveb 24
432 unsigned int vmmXAFlgs
; /* Extended Architecture flags */
433 vmm_state_page_t
*vmmContextKern
; /* Kernel address of context communications area */
434 ppnum_t vmmContextPhys
; /* Physical address of context communications area */
435 vmm_state_page_t
*vmmContextUser
; /* User address of context communications area */
436 facility_context vmmFacCtx
; /* Header for vector and floating point contexts */
437 pmap_t vmmPmap
; /* Last dispatched pmap */
438 uint64_t vmmTimer
; /* Last set timer value. Zero means unset */
439 unsigned int vmmFAMintercept
; /* FAM intercepted exceptions */
443 #pragma pack(4) /* Make sure the structure stays as we defined it */
444 typedef struct vmmCntrlTable
{ /* Virtual Machine Monitor Control table */
445 unsigned int vmmGFlags
; /* Global flags */
446 #define vmmLastAdSp 0xFF /* Remember the address space that was mapped last */
447 addr64_t vmmLastMap
; /* Last vaddr mapping made */
448 vmmCntrlEntry vmmc
[kVmmMaxContexts
]; /* One entry for each possible Virtual Machine Monitor context */
449 pmap_t vmmAdsp
[kVmmMaxContexts
]; /* Guest address space pmaps */
453 /* function decls for kernel level routines... */
454 extern void vmm_execute_vm(thread_t act
, vmm_thread_index_t index
);
455 extern kern_return_t
vmm_tear_down_context(thread_t act
, vmm_thread_index_t index
);
456 extern kern_return_t
vmm_get_float_state(thread_t act
, vmm_thread_index_t index
);
457 extern kern_return_t
vmm_get_vector_state(thread_t act
, vmm_thread_index_t index
);
458 extern kern_return_t
vmm_set_timer(thread_t act
, vmm_thread_index_t index
, unsigned int timerhi
, unsigned int timerlo
);
459 extern kern_return_t
vmm_get_timer(thread_t act
, vmm_thread_index_t index
);
460 extern void vmm_tear_down_all(thread_t act
);
461 extern kern_return_t
vmm_map_page(thread_t act
, vmm_thread_index_t hindex
, addr64_t cva
,
462 addr64_t ava
, vm_prot_t prot
);
463 extern vmm_return_code_t
vmm_map_execute(thread_t act
, vmm_thread_index_t hindex
, addr64_t cva
,
464 addr64_t ava
, vm_prot_t prot
);
465 extern kern_return_t
vmm_protect_page(thread_t act
, vmm_thread_index_t hindex
, addr64_t va
,
467 extern vmm_return_code_t
vmm_protect_execute(thread_t act
, vmm_thread_index_t hindex
, addr64_t va
,
469 extern addr64_t
vmm_get_page_mapping(thread_t act
, vmm_thread_index_t index
,
471 extern kern_return_t
vmm_unmap_page(thread_t act
, vmm_thread_index_t index
, addr64_t va
);
472 extern void vmm_unmap_all_pages(thread_t act
, vmm_thread_index_t index
);
473 extern boolean_t
vmm_get_page_dirty_flag(thread_t act
, vmm_thread_index_t index
,
474 addr64_t va
, unsigned int reset
);
475 extern kern_return_t
vmm_activate_XA(thread_t act
, vmm_thread_index_t index
, unsigned int xaflags
);
476 extern kern_return_t
vmm_deactivate_XA(thread_t act
, vmm_thread_index_t index
, unsigned int xaflags
);
477 extern unsigned int vmm_get_XA(thread_t act
, vmm_thread_index_t index
);
478 extern int vmm_get_features(struct savearea
*);
479 extern int vmm_get_version(struct savearea
*);
480 extern int vmm_init_context(struct savearea
*);
481 extern int vmm_dispatch(struct savearea
*);
482 extern int vmm_exit(thread_t act
, struct savearea
*);
483 extern void vmm_force_exit(thread_t act
, struct savearea
*);
484 extern int vmm_stop_vm(struct savearea
*save
);
485 extern void vmm_timer_pop(thread_t act
);
486 extern void vmm_interrupt(ReturnHandler
*rh
, thread_t act
);
487 extern kern_return_t
vmm_map_list(thread_t act
, vmm_thread_index_t index
, unsigned int cnt
, unsigned int flavor
);
488 extern kern_return_t
vmm_unmap_list(thread_t act
, vmm_thread_index_t index
, unsigned int cnt
, unsigned int flavor
);
489 extern vmm_return_code_t
vmm_resume_guest(vmm_thread_index_t index
, unsigned long pc
,
490 unsigned long vmmCntrl
, unsigned long vmmCntrMaskl
);
491 extern vmm_return_code_t
vmm_exit_to_host(vmm_thread_index_t index
);
492 extern unsigned long vmm_get_guest_register(vmm_thread_index_t index
, unsigned long reg_index
);
493 extern vmm_return_code_t
vmm_set_guest_register(vmm_thread_index_t index
, unsigned long reg_index
, unsigned long reg_value
);
494 extern addr64_t
vmm_max_addr(thread_t act
);
495 extern kern_return_t
vmm_set_guest_memory(thread_t act
, vmm_thread_index_t index
, addr64_t base
, addr64_t extent
);
496 extern kern_return_t
vmm_purge_local(thread_t act
, vmm_thread_index_t index
);