VirtualBox

source: vbox/trunk/src/VBox/VMM/include/CPUMInternal.h@ 57446

Last change on this file since 57446 was 57446, checked in by vboxsync, 9 years ago

VMM: Removing VBOX_WITH_HYBRID_32BIT_KERNEL and other 32-bit darwin fun.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 18.5 KB
Line 
1/* $Id: CPUMInternal.h 57446 2015-08-18 17:33:53Z vboxsync $ */
2/** @file
3 * CPUM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___CPUMInternal_h
19#define ___CPUMInternal_h
20
21#ifndef VBOX_FOR_DTRACE_LIB
22# include <VBox/cdefs.h>
23# include <VBox/types.h>
24# include <VBox/vmm/stam.h>
25# include <iprt/x86.h>
26#else
27# pragma D depends_on library x86.d
28# pragma D depends_on library cpumctx.d
29
30/* Some fudging. */
31typedef uint32_t CPUMMICROARCH;
32typedef uint32_t CPUMUNKNOWNCPUID;
33typedef struct CPUMCPUIDLEAF *PCPUMCPUIDLEAF;
34typedef struct CPUMMSRRANGE *PCPUMMSRRANGE;
35typedef uint64_t STAMCOUNTER;
36#endif
37
38
39
40
41/** @defgroup grp_cpum_int Internals
42 * @ingroup grp_cpum
43 * @internal
44 * @{
45 */
46
47/** Flags and types for CPUM fault handlers
48 * @{ */
49/** Type: Load DS */
50#define CPUM_HANDLER_DS 1
51/** Type: Load ES */
52#define CPUM_HANDLER_ES 2
53/** Type: Load FS */
54#define CPUM_HANDLER_FS 3
55/** Type: Load GS */
56#define CPUM_HANDLER_GS 4
57/** Type: IRET */
58#define CPUM_HANDLER_IRET 5
59/** Type mask. */
60#define CPUM_HANDLER_TYPEMASK 0xff
61/** If set EBP points to the CPUMCTXCORE that's being used. */
62#define CPUM_HANDLER_CTXCORE_IN_EBP RT_BIT(31)
63/** @} */
64
65
66/** Use flags (CPUM::fUseFlags).
67 * (Don't forget to sync this with CPUMInternal.mac !)
68 * @{ */
69/** Used the FPU, SSE or such stuff. */
70#define CPUM_USED_FPU RT_BIT(0)
71/** Used the FPU, SSE or such stuff since last we were in REM.
72 * REM syncing is clearing this, lazy FPU is setting it. */
73#define CPUM_USED_FPU_SINCE_REM RT_BIT(1)
74/** The XMM state was manually restored. (AMD only) */
75#define CPUM_USED_MANUAL_XMM_RESTORE RT_BIT(2)
76
77/** Host OS is using SYSENTER and we must NULL the CS. */
78#define CPUM_USE_SYSENTER RT_BIT(3)
79/** Host OS is using SYSENTER and we must NULL the CS. */
80#define CPUM_USE_SYSCALL RT_BIT(4)
81
82/** Debug registers are used by host and that DR7 and DR6 must be saved and
83 * disabled when switching to raw-mode. */
84#define CPUM_USE_DEBUG_REGS_HOST RT_BIT(5)
85/** Records that we've saved the host DRx registers.
86 * In ring-0 this means all (DR0-7), while in raw-mode context this means DR0-3
87 * since DR6 and DR7 are covered by CPUM_USE_DEBUG_REGS_HOST. */
88#define CPUM_USED_DEBUG_REGS_HOST RT_BIT(6)
89/** Set to indicate that we should save host DR0-7 and load the hypervisor debug
90 * registers in the raw-mode world switchers. (See CPUMRecalcHyperDRx.) */
91#define CPUM_USE_DEBUG_REGS_HYPER RT_BIT(7)
92/** Used in ring-0 to indicate that we have loaded the hypervisor debug
93 * registers. */
94#define CPUM_USED_DEBUG_REGS_HYPER RT_BIT(8)
95/** Used in ring-0 to indicate that we have loaded the guest debug
96 * registers (DR0-3 and maybe DR6) for direct use by the guest.
97 * DR7 (and AMD-V DR6) are handled via the VMCB. */
98#define CPUM_USED_DEBUG_REGS_GUEST RT_BIT(9)
99
100
101/** Sync the FPU state on next entry (32->64 switcher only). */
102#define CPUM_SYNC_FPU_STATE RT_BIT(16)
103/** Sync the debug state on next entry (32->64 switcher only). */
104#define CPUM_SYNC_DEBUG_REGS_GUEST RT_BIT(17)
105/** Sync the debug state on next entry (32->64 switcher only).
106 * Almost the same as CPUM_USE_DEBUG_REGS_HYPER in the raw-mode switchers. */
107#define CPUM_SYNC_DEBUG_REGS_HYPER RT_BIT(18)
108/** Host CPU requires fxsave/fxrstor leaky bit handling. */
109#define CPUM_USE_FFXSR_LEAKY RT_BIT(19)
110/** Set if the VM supports long-mode. */
111#define CPUM_USE_SUPPORTS_LONGMODE RT_BIT(20)
112/** @} */
113
114
115/** @name CPUM Saved State Version.
116 * @{ */
117/** The current saved state version. */
118#define CPUM_SAVED_STATE_VERSION CPUM_SAVED_STATE_VERSION_XSAVE
119/** The saved state version including XSAVE state. */
120#define CPUM_SAVED_STATE_VERSION_XSAVE 17
121/** The saved state version with good CPUID leaf count. */
122#define CPUM_SAVED_STATE_VERSION_GOOD_CPUID_COUNT 16
123/** CPUID changes with explode forgetting to update the leaf count on
124 * restore, resulting in garbage being saved restoring+saving old states). */
125#define CPUM_SAVED_STATE_VERSION_BAD_CPUID_COUNT 15
126/** The saved state version before the CPUIDs changes. */
127#define CPUM_SAVED_STATE_VERSION_PUT_STRUCT 14
128/** The saved state version before using SSMR3PutStruct. */
129#define CPUM_SAVED_STATE_VERSION_MEM 13
130/** The saved state version before introducing the MSR size field. */
131#define CPUM_SAVED_STATE_VERSION_NO_MSR_SIZE 12
132/** The saved state version of 3.2, 3.1 and 3.3 trunk before the hidden
133 * selector register change (CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID). */
134#define CPUM_SAVED_STATE_VERSION_VER3_2 11
135/** The saved state version of 3.0 and 3.1 trunk before the teleportation
136 * changes. */
137#define CPUM_SAVED_STATE_VERSION_VER3_0 10
138/** The saved state version for the 2.1 trunk before the MSR changes. */
139#define CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR 9
140/** The saved state version of 2.0, used for backwards compatibility. */
141#define CPUM_SAVED_STATE_VERSION_VER2_0 8
142/** The saved state version of 1.6, used for backwards compatibility. */
143#define CPUM_SAVED_STATE_VERSION_VER1_6 6
144/** @} */
145
146
147/**
148 * CPU info
149 */
150typedef struct CPUMINFO
151{
152 /** The number of MSR ranges (CPUMMSRRANGE) in the array pointed to below. */
153 uint32_t cMsrRanges;
154 /** Mask applied to ECX before looking up the MSR for a RDMSR/WRMSR
155 * instruction. Older hardware has been observed to ignore higher bits. */
156 uint32_t fMsrMask;
157
158 /** The number of CPUID leaves (CPUMCPUIDLEAF) in the array pointed to below. */
159 uint32_t cCpuIdLeaves;
160 /** The index of the first extended CPUID leaf in the array.
161 * Set to cCpuIdLeaves if none present. */
162 uint32_t iFirstExtCpuIdLeaf;
163 /** Alignment padding. */
164 uint32_t uPadding;
165 /** How to handle unknown CPUID leaves. */
166 CPUMUNKNOWNCPUID enmUnknownCpuIdMethod;
167 /** For use with CPUMUNKNOWNCPUID_DEFAULTS (DB & VM),
168 * CPUMUNKNOWNCPUID_LAST_STD_LEAF (VM) and CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX (VM). */
169 CPUMCPUID DefCpuId;
170
171 /** Scalable bus frequency used for reporting other frequencies. */
172 uint64_t uScalableBusFreq;
173
174 /** Pointer to the MSR ranges (ring-0 pointer). */
175 R0PTRTYPE(PCPUMMSRRANGE) paMsrRangesR0;
176 /** Pointer to the CPUID leaves (ring-0 pointer). */
177 R0PTRTYPE(PCPUMCPUIDLEAF) paCpuIdLeavesR0;
178
179 /** Pointer to the MSR ranges (ring-3 pointer). */
180 R3PTRTYPE(PCPUMMSRRANGE) paMsrRangesR3;
181 /** Pointer to the CPUID leaves (ring-3 pointer). */
182 R3PTRTYPE(PCPUMCPUIDLEAF) paCpuIdLeavesR3;
183
184 /** Pointer to the MSR ranges (raw-mode context pointer). */
185 RCPTRTYPE(PCPUMMSRRANGE) paMsrRangesRC;
186 /** Pointer to the CPUID leaves (raw-mode context pointer). */
187 RCPTRTYPE(PCPUMCPUIDLEAF) paCpuIdLeavesRC;
188} CPUMINFO;
189/** Pointer to a CPU info structure. */
190typedef CPUMINFO *PCPUMINFO;
191/** Pointer to a const CPU info structure. */
192typedef CPUMINFO const *CPCPUMINFO;
193
194
195/**
196 * The saved host CPU state.
197 */
198typedef struct CPUMHOSTCTX
199{
200 /** General purpose register, selectors, flags and more
201 * @{ */
202#if HC_ARCH_BITS == 64
203 /** General purpose register ++
204 * { */
205 /*uint64_t rax; - scratch*/
206 uint64_t rbx;
207 /*uint64_t rcx; - scratch*/
208 /*uint64_t rdx; - scratch*/
209 uint64_t rdi;
210 uint64_t rsi;
211 uint64_t rbp;
212 uint64_t rsp;
213 /*uint64_t r8; - scratch*/
214 /*uint64_t r9; - scratch*/
215 uint64_t r10;
216 uint64_t r11;
217 uint64_t r12;
218 uint64_t r13;
219 uint64_t r14;
220 uint64_t r15;
221 /*uint64_t rip; - scratch*/
222 uint64_t rflags;
223#endif
224
225#if HC_ARCH_BITS == 32
226 /*uint32_t eax; - scratch*/
227 uint32_t ebx;
228 /*uint32_t ecx; - scratch*/
229 /*uint32_t edx; - scratch*/
230 uint32_t edi;
231 uint32_t esi;
232 uint32_t ebp;
233 X86EFLAGS eflags;
234 /*uint32_t eip; - scratch*/
235 /* lss pair! */
236 uint32_t esp;
237#endif
238 /** @} */
239
240 /** Selector registers
241 * @{ */
242 RTSEL ss;
243 RTSEL ssPadding;
244 RTSEL gs;
245 RTSEL gsPadding;
246 RTSEL fs;
247 RTSEL fsPadding;
248 RTSEL es;
249 RTSEL esPadding;
250 RTSEL ds;
251 RTSEL dsPadding;
252 RTSEL cs;
253 RTSEL csPadding;
254 /** @} */
255
256#if HC_ARCH_BITS == 32
257 /** Control registers.
258 * @{ */
259 uint32_t cr0;
260 /*uint32_t cr2; - scratch*/
261 uint32_t cr3;
262 uint32_t cr4;
263 /** @} */
264
265 /** Debug registers.
266 * @{ */
267 uint32_t dr0;
268 uint32_t dr1;
269 uint32_t dr2;
270 uint32_t dr3;
271 uint32_t dr6;
272 uint32_t dr7;
273 /** @} */
274
275 /** Global Descriptor Table register. */
276 X86XDTR32 gdtr;
277 uint16_t gdtrPadding;
278 /** Interrupt Descriptor Table register. */
279 X86XDTR32 idtr;
280 uint16_t idtrPadding;
281 /** The task register. */
282 RTSEL ldtr;
283 RTSEL ldtrPadding;
284 /** The task register. */
285 RTSEL tr;
286 RTSEL trPadding;
287 uint32_t SysEnterPadding;
288
289 /** The sysenter msr registers.
290 * This member is not used by the hypervisor context. */
291 CPUMSYSENTER SysEnter;
292
293 /** MSRs
294 * @{ */
295 uint64_t efer;
296 /** @} */
297
298 /* padding to get 64byte aligned size */
299 uint8_t auPadding[20];
300
301#elif HC_ARCH_BITS == 64
302
303 /** Control registers.
304 * @{ */
305 uint64_t cr0;
306 /*uint64_t cr2; - scratch*/
307 uint64_t cr3;
308 uint64_t cr4;
309 uint64_t cr8;
310 /** @} */
311
312 /** Debug registers.
313 * @{ */
314 uint64_t dr0;
315 uint64_t dr1;
316 uint64_t dr2;
317 uint64_t dr3;
318 uint64_t dr6;
319 uint64_t dr7;
320 /** @} */
321
322 /** Global Descriptor Table register. */
323 X86XDTR64 gdtr;
324 uint16_t gdtrPadding;
325 /** Interrupt Descriptor Table register. */
326 X86XDTR64 idtr;
327 uint16_t idtrPadding;
328 /** The task register. */
329 RTSEL ldtr;
330 RTSEL ldtrPadding;
331 /** The task register. */
332 RTSEL tr;
333 RTSEL trPadding;
334
335 /** MSRs
336 * @{ */
337 CPUMSYSENTER SysEnter;
338 uint64_t FSbase;
339 uint64_t GSbase;
340 uint64_t efer;
341 /** @} */
342
343 /* padding to get 32byte aligned size */
344 uint8_t auPadding[4];
345
346#else
347# error HC_ARCH_BITS not defined or unsupported
348#endif
349
350 /** Pointer to the FPU/SSE/AVX/XXXX state raw-mode mapping. */
351 RCPTRTYPE(PX86XSAVEAREA) pXStateRC;
352 /** Pointer to the FPU/SSE/AVX/XXXX state ring-0 mapping. */
353 R0PTRTYPE(PX86XSAVEAREA) pXStateR0;
354 /** Pointer to the FPU/SSE/AVX/XXXX state ring-3 mapping. */
355 R3PTRTYPE(PX86XSAVEAREA) pXStateR3;
356 /** The XCR0 register. */
357 uint64_t xcr0;
358 /** The mask to pass to XSAVE/XRSTOR in EDX:EAX. If zero we use
359 * FXSAVE/FXRSTOR (since bit 0 will always be set, we only need to test it). */
360 uint64_t fXStateMask;
361} CPUMHOSTCTX;
362AssertCompileSizeAlignment(CPUMHOSTCTX, 64);
363/** Pointer to the saved host CPU state. */
364typedef CPUMHOSTCTX *PCPUMHOSTCTX;
365
366
367/**
368 * CPUM Data (part of VM)
369 */
370typedef struct CPUM
371{
372 /** Offset from CPUM to CPUMCPU for the first CPU. */
373 uint32_t offCPUMCPU0;
374
375 /** Use flags.
376 * These flags indicates which CPU features the host uses.
377 */
378 uint32_t fHostUseFlags;
379
380 /** CR4 mask */
381 struct
382 {
383 uint32_t AndMask; /**< @todo Move these to the per-CPU structure and fix the switchers. Saves a register! */
384 uint32_t OrMask;
385 } CR4;
386
387 /** The (more) portable CPUID level. */
388 uint8_t u8PortableCpuIdLevel;
389 /** Indicates that a state restore is pending.
390 * This is used to verify load order dependencies (PGM). */
391 bool fPendingRestore;
392 uint8_t abPadding0[6];
393
394 /** XSAVE/XRTOR components we can expose to the guest mask. */
395 uint64_t fXStateGuestMask;
396 /** XSAVE/XRSTOR host mask. Only state components in this mask can be exposed
397 * to the guest. This is 0 if no XSAVE/XRSTOR bits can be exposed. */
398 uint64_t fXStateHostMask;
399 uint8_t abPadding1[24];
400
401 /** Host CPU feature information.
402 * Externaly visible via the VM structure, aligned on 64-byte boundrary. */
403 CPUMFEATURES HostFeatures;
404 /** Guest CPU feature information.
405 * Externaly visible via that VM structure, aligned with HostFeatures. */
406 CPUMFEATURES GuestFeatures;
407 /** Guest CPU info. */
408 CPUMINFO GuestInfo;
409
410
411 /** The standard set of CpuId leaves. */
412 CPUMCPUID aGuestCpuIdPatmStd[6];
413 /** The extended set of CpuId leaves. */
414 CPUMCPUID aGuestCpuIdPatmExt[10];
415 /** The centaur set of CpuId leaves. */
416 CPUMCPUID aGuestCpuIdPatmCentaur[4];
417
418 /** @name MSR statistics.
419 * @{ */
420 STAMCOUNTER cMsrWrites;
421 STAMCOUNTER cMsrWritesToIgnoredBits;
422 STAMCOUNTER cMsrWritesRaiseGp;
423 STAMCOUNTER cMsrWritesUnknown;
424 STAMCOUNTER cMsrReads;
425 STAMCOUNTER cMsrReadsRaiseGp;
426 STAMCOUNTER cMsrReadsUnknown;
427 /** @} */
428} CPUM;
429AssertCompileMemberOffset(CPUM, HostFeatures, 64);
430AssertCompileMemberOffset(CPUM, GuestFeatures, 96);
431/** Pointer to the CPUM instance data residing in the shared VM structure. */
432typedef CPUM *PCPUM;
433
434/**
435 * CPUM Data (part of VMCPU)
436 */
437typedef struct CPUMCPU
438{
439 /**
440 * Guest context.
441 * Aligned on a 64-byte boundary.
442 */
443 CPUMCTX Guest;
444
445 /**
446 * Guest context - misc MSRs
447 * Aligned on a 64-byte boundary.
448 */
449 CPUMCTXMSRS GuestMsrs;
450
451 /** Use flags.
452 * These flags indicates both what is to be used and what has been used.
453 */
454 uint32_t fUseFlags;
455
456 /** Changed flags.
457 * These flags indicates to REM (and others) which important guest
458 * registers which has been changed since last time the flags were cleared.
459 * See the CPUM_CHANGED_* defines for what we keep track of.
460 */
461 uint32_t fChanged;
462
463 /** Offset from CPUM to CPUMCPU. */
464 uint32_t offCPUM;
465
466 /** Temporary storage for the return code of the function called in the
467 * 32-64 switcher. */
468 uint32_t u32RetCode;
469
470#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
471 /** The address of the APIC mapping, NULL if no APIC.
472 * Call CPUMR0SetLApic to update this before doing a world switch. */
473 RTHCPTR pvApicBase;
474 /** Used by the world switcher code to store which vectors needs restoring on
475 * the way back. */
476 uint32_t fApicDisVectors;
477 /** Set if the CPU has the X2APIC mode enabled.
478 * Call CPUMR0SetLApic to update this before doing a world switch. */
479 bool fX2Apic;
480#else
481 uint8_t abPadding3[(HC_ARCH_BITS == 64 ? 8 : 4) + 4 + 1];
482#endif
483
484 /** Have we entered raw-mode? */
485 bool fRawEntered;
486 /** Have we entered the recompiler? */
487 bool fRemEntered;
488
489 /** Align the next member on a 64-bit boundrary. */
490 uint8_t abPadding2[64 - 16 - (HC_ARCH_BITS == 64 ? 8 : 4) - 4 - 1 - 2];
491
492 /** Saved host context. Only valid while inside RC or HM contexts.
493 * Must be aligned on a 64-byte boundary. */
494 CPUMHOSTCTX Host;
495 /** Hypervisor context. Must be aligned on a 64-byte boundary. */
496 CPUMCTX Hyper;
497
498#ifdef VBOX_WITH_CRASHDUMP_MAGIC
499 uint8_t aMagic[56];
500 uint64_t uMagic;
501#endif
502} CPUMCPU;
503/** Pointer to the CPUMCPU instance data residing in the shared VMCPU structure. */
504typedef CPUMCPU *PCPUMCPU;
505
506#ifndef VBOX_FOR_DTRACE_LIB
507RT_C_DECLS_BEGIN
508
509PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf);
510PCPUMCPUIDLEAF cpumCpuIdGetLeafEx(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf, bool *pfExactSubLeafHit);
511
512#ifdef IN_RING3
513int cpumR3DbgInit(PVM pVM);
514int cpumR3CpuIdExplodeFeatures(PCCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, PCPUMFEATURES pFeatures);
515int cpumR3InitCpuIdAndMsrs(PVM pVM);
516void cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM);
517int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion);
518int cpumR3LoadCpuIdPre32(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion);
519DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
520
521int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo);
522int cpumR3MsrRangesInsert(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange);
523int cpumR3MsrApplyFudge(PVM pVM);
524int cpumR3MsrRegStats(PVM pVM);
525int cpumR3MsrStrictInitChecks(void);
526PCPUMMSRRANGE cpumLookupMsrRange(PVM pVM, uint32_t idMsr);
527#endif
528
529#ifdef IN_RC
530DECLASM(int) cpumHandleLazyFPUAsm(PCPUMCPU pCPUM);
531#endif
532
533#ifdef IN_RING0
534DECLASM(int) cpumR0SaveHostRestoreGuestFPUState(PCPUMCPU pCPUM);
535DECLASM(int) cpumR0SaveGuestRestoreHostFPUState(PCPUMCPU pCPUM);
536DECLASM(int) cpumR0SaveHostFPUState(PCPUMCPU pCPUM);
537DECLASM(int) cpumR0RestoreHostFPUState(PCPUMCPU pCPUM);
538DECLASM(void) cpumR0LoadFPU(PCPUMCTX pCtx);
539DECLASM(void) cpumR0SaveFPU(PCPUMCTX pCtx);
540DECLASM(void) cpumR0LoadXMM(PCPUMCTX pCtx);
541DECLASM(void) cpumR0SaveXMM(PCPUMCTX pCtx);
542DECLASM(void) cpumR0SetFCW(uint16_t u16FCW);
543DECLASM(uint16_t) cpumR0GetFCW(void);
544DECLASM(void) cpumR0SetMXCSR(uint32_t u32MXCSR);
545DECLASM(uint32_t) cpumR0GetMXCSR(void);
546#endif
547
548RT_C_DECLS_END
549#endif /* !VBOX_FOR_DTRACE_LIB */
550
551/** @} */
552
553#endif
554
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette