VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp@ 4953

Last change on this file since 4953 was 4598, checked in by vboxsync, 17 years ago

Only check for vmx root mode for 64 bits hosts.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.5 KB
Line 
1/* $Id: HWACCMR0.cpp 4598 2007-09-07 09:23:11Z vboxsync $ */
2/** @file
3 * HWACCM - Host Context Ring 0.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_HWACCM
23#include <VBox/hwaccm.h>
24#include "HWACCMInternal.h"
25#include <VBox/vm.h>
26#include <VBox/x86.h>
27#include <VBox/hwacc_vmx.h>
28#include <VBox/hwacc_svm.h>
29#include <VBox/pgm.h>
30#include <VBox/pdm.h>
31#include <VBox/err.h>
32#include <VBox/log.h>
33#include <VBox/selm.h>
34#include <VBox/iom.h>
35#include <iprt/param.h>
36#include <iprt/assert.h>
37#include <iprt/asm.h>
38#include "HWVMXR0.h"
39#include "HWSVMR0.h"
40
41/**
42 * Does Ring-0 HWACCM initialization.
43 *
44 * This is mainly to check that the Host CPU mode is compatible
45 * with VMX.
46 *
47 * @returns VBox status code.
48 * @param pVM The VM to operate on.
49 */
50HWACCMR0DECL(int) HWACCMR0Init(PVM pVM)
51{
52 LogComFlow(("HWACCMR0Init: %p\n", pVM));
53
54 pVM->hwaccm.s.vmx.fSupported = false;;
55 pVM->hwaccm.s.svm.fSupported = false;;
56
57#ifndef VBOX_WITH_HYBIRD_32BIT_KERNEL /* paranoia */
58
59 pVM->hwaccm.s.fHWACCMR0Init = true;
60 pVM->hwaccm.s.lLastError = VINF_SUCCESS;
61
62 /*
63 * Check for VMX capabilities
64 */
65 if (ASMHasCpuId())
66 {
67 uint32_t u32FeaturesECX;
68 uint32_t u32Dummy;
69 uint32_t u32FeaturesEDX;
70 uint32_t u32VendorEBX, u32VendorECX, u32VendorEDX;
71
72 ASMCpuId(0, &u32Dummy, &u32VendorEBX, &u32VendorECX, &u32VendorEDX);
73 ASMCpuId(1, &u32Dummy, &u32Dummy, &u32FeaturesECX, &u32FeaturesEDX);
74 /* Query AMD features. */
75 ASMCpuId(0x80000001, &u32Dummy, &u32Dummy, &pVM->hwaccm.s.cpuid.u32AMDFeatureECX, &pVM->hwaccm.s.cpuid.u32AMDFeatureEDX);
76
77 if ( u32VendorEBX == X86_CPUID_VENDOR_INTEL_EBX
78 && u32VendorECX == X86_CPUID_VENDOR_INTEL_ECX
79 && u32VendorEDX == X86_CPUID_VENDOR_INTEL_EDX
80 )
81 {
82 /*
83 * Read all VMX MSRs if VMX is available. (same goes for RDMSR/WRMSR)
84 * We also assume all VMX-enabled CPUs support fxsave/fxrstor.
85 */
86 if ( (u32FeaturesECX & X86_CPUID_FEATURE_ECX_VMX)
87 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
88 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
89 )
90 {
91 pVM->hwaccm.s.vmx.msr.feature_ctrl = ASMRdMsr(MSR_IA32_FEATURE_CONTROL);
92 /*
93 * Both the LOCK and VMXON bit must be set; otherwise VMXON will generate a #GP.
94 * Once the lock bit is set, this MSR can no longer be modified.
95 */
96 /** @todo need to check this for each cpu/core in the system!!!) */
97 if (!(pVM->hwaccm.s.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK)))
98 {
99 /* MSR is not yet locked; we can change it ourselves here */
100 pVM->hwaccm.s.vmx.msr.feature_ctrl |= (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK);
101 ASMWrMsr(MSR_IA32_FEATURE_CONTROL, pVM->hwaccm.s.vmx.msr.feature_ctrl);
102 }
103
104 if ( (pVM->hwaccm.s.vmx.msr.feature_ctrl & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
105 == (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK))
106 {
107 pVM->hwaccm.s.vmx.fSupported = true;
108 pVM->hwaccm.s.vmx.msr.vmx_basic_info = ASMRdMsr(MSR_IA32_VMX_BASIC_INFO);
109 pVM->hwaccm.s.vmx.msr.vmx_pin_ctls = ASMRdMsr(MSR_IA32_VMX_PINBASED_CTLS);
110 pVM->hwaccm.s.vmx.msr.vmx_proc_ctls = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS);
111 pVM->hwaccm.s.vmx.msr.vmx_exit = ASMRdMsr(MSR_IA32_VMX_EXIT_CTLS);
112 pVM->hwaccm.s.vmx.msr.vmx_entry = ASMRdMsr(MSR_IA32_VMX_ENTRY_CTLS);
113 pVM->hwaccm.s.vmx.msr.vmx_misc = ASMRdMsr(MSR_IA32_VMX_MISC);
114 pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed0 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED0);
115 pVM->hwaccm.s.vmx.msr.vmx_cr0_fixed1 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED1);
116 pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed0 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED0);
117 pVM->hwaccm.s.vmx.msr.vmx_cr4_fixed1 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED1);
118 pVM->hwaccm.s.vmx.msr.vmx_vmcs_enum = ASMRdMsr(MSR_IA32_VMX_VMCS_ENUM);
119
120 /*
121 * Check CR4.VMXE
122 */
123 pVM->hwaccm.s.vmx.hostCR4 = ASMGetCR4();
124 if (!(pVM->hwaccm.s.vmx.hostCR4 & X86_CR4_VMXE))
125 {
126 /* In theory this bit could be cleared behind our back. Which would cause #UD faults when we
127 * try to execute the VMX instructions...
128 */
129 ASMSetCR4(pVM->hwaccm.s.vmx.hostCR4 | X86_CR4_VMXE);
130 }
131
132 if ( pVM->hwaccm.s.vmx.pVMXONPhys
133 && pVM->hwaccm.s.vmx.pVMXON)
134 {
135 /* Set revision dword at the beginning of the structure. */
136 *(uint32_t *)pVM->hwaccm.s.vmx.pVMXON = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hwaccm.s.vmx.msr.vmx_basic_info);
137
138#if HC_ARCH_BITS == 64
139 /* Enter VMX Root Mode */
140 int rc = VMXEnable(pVM->hwaccm.s.vmx.pVMXONPhys);
141 if (VBOX_FAILURE(rc))
142 {
143 /* KVM leaves the CPU in VMX root mode. Not only is this not allowed, it will crash the host when we enter raw mode, because
144 * (a) clearing X86_CR4_VMXE in CR4 causes a #GP (we no longer modify this bit)
145 * (b) turning off paging causes a #GP (unavoidable when switching from long to 32 bits mode)
146 *
147 * They should fix their code, but until they do we simply refuse to run.
148 */
149 return VERR_VMX_IN_VMX_ROOT_MODE;
150 }
151 VMXDisable();
152#endif
153 }
154 }
155 else
156 pVM->hwaccm.s.lLastError = VERR_VMX_ILLEGAL_FEATURE_CONTROL_MSR;
157 }
158 else
159 pVM->hwaccm.s.lLastError = VERR_VMX_NO_VMX;
160 }
161 else
162 if ( u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX
163 && u32VendorECX == X86_CPUID_VENDOR_AMD_ECX
164 && u32VendorEDX == X86_CPUID_VENDOR_AMD_EDX
165 )
166 {
167 /*
168 * Read all SVM MSRs if SVM is available. (same goes for RDMSR/WRMSR)
169 * We also assume all SVM-enabled CPUs support fxsave/fxrstor.
170 */
171 if ( (pVM->hwaccm.s.cpuid.u32AMDFeatureECX & X86_CPUID_AMD_FEATURE_ECX_SVM)
172 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_MSR)
173 && (u32FeaturesEDX & X86_CPUID_FEATURE_EDX_FXSR)
174 )
175 {
176 uint64_t val;
177
178 /* Check if SVM is disabled */
179 val = ASMRdMsr(MSR_K8_VM_CR);
180 if (!(val & MSR_K8_VM_CR_SVM_DISABLE))
181 {
182 /* Turn on SVM in the EFER MSR. */
183 val = ASMRdMsr(MSR_K6_EFER);
184 if (!(val & MSR_K6_EFER_SVME))
185 {
186 ASMWrMsr(MSR_K6_EFER, val | MSR_K6_EFER_SVME);
187 }
188 /* Paranoia. */
189 val = ASMRdMsr(MSR_K6_EFER);
190 if (val & MSR_K6_EFER_SVME)
191 {
192 /* Query AMD features. */
193 ASMCpuId(0x8000000A, &pVM->hwaccm.s.svm.u32Rev, &pVM->hwaccm.s.svm.u32MaxASID, &u32Dummy, &u32Dummy);
194
195 pVM->hwaccm.s.svm.fSupported = true;
196 }
197 else
198 {
199 pVM->hwaccm.s.lLastError = VERR_SVM_ILLEGAL_EFER_MSR;
200 AssertFailed();
201 }
202 }
203 else
204 pVM->hwaccm.s.lLastError = VERR_SVM_DISABLED;
205 }
206 else
207 pVM->hwaccm.s.lLastError = VERR_SVM_NO_SVM;
208 }
209 else
210 pVM->hwaccm.s.lLastError = VERR_HWACCM_UNKNOWN_CPU;
211 }
212 else
213 pVM->hwaccm.s.lLastError = VERR_HWACCM_NO_CPUID;
214
215#endif /* !VBOX_WITH_HYBIRD_32BIT_KERNEL */
216
217 return VINF_SUCCESS;
218}
219
220
221/**
222 * Sets up and activates VMX
223 *
224 * @returns VBox status code.
225 * @param pVM The VM to operate on.
226 */
227HWACCMR0DECL(int) HWACCMR0SetupVMX(PVM pVM)
228{
229 int rc = VINF_SUCCESS;
230
231 if (pVM == NULL)
232 return VERR_INVALID_PARAMETER;
233
234 /* Setup Intel VMX. */
235 if (pVM->hwaccm.s.vmx.fSupported)
236 rc = VMXR0Setup(pVM);
237 else
238 rc = SVMR0Setup(pVM);
239
240 return rc;
241}
242
243
244/**
245 * Enable VMX or SVN
246 *
247 * @returns VBox status code.
248 * @param pVM The VM to operate on.
249 */
250HWACCMR0DECL(int) HWACCMR0Enable(PVM pVM)
251{
252 CPUMCTX *pCtx;
253 int rc;
254
255 rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
256 if (VBOX_FAILURE(rc))
257 return rc;
258
259 /* Always load the guest's FPU/XMM state on-demand. */
260 CPUMDeactivateGuestFPUState(pVM);
261
262 /* Always reload the host context and the guest's CR0 register. (!!!!) */
263 pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_CR0 | HWACCM_CHANGED_HOST_CONTEXT;
264
265 if (pVM->hwaccm.s.vmx.fSupported)
266 {
267 rc = VMXR0Enable(pVM);
268 AssertRC(rc);
269 rc |= VMXR0SaveHostState(pVM);
270 AssertRC(rc);
271 rc |= VMXR0LoadGuestState(pVM, pCtx);
272 AssertRC(rc);
273 if (rc != VINF_SUCCESS)
274 return rc;
275 }
276 else
277 {
278 Assert(pVM->hwaccm.s.svm.fSupported);
279 rc = SVMR0Enable(pVM);
280 AssertRC(rc);
281 rc |= SVMR0LoadGuestState(pVM, pCtx);
282 AssertRC(rc);
283 if (rc != VINF_SUCCESS)
284 return rc;
285
286 }
287 return VINF_SUCCESS;
288}
289
290
291/**
292 * Disable VMX or SVN
293 *
294 * @returns VBox status code.
295 * @param pVM The VM to operate on.
296 */
297HWACCMR0DECL(int) HWACCMR0Disable(PVM pVM)
298{
299 CPUMCTX *pCtx;
300 int rc;
301
302 rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
303 if (VBOX_FAILURE(rc))
304 return rc;
305
306 /** @note It's rather tricky with longjmps done by e.g. Log statements or the page fault handler. */
307 /* We must restore the host FPU here to make absolutely sure we don't leave the guest FPU state active
308 * or trash somebody else's FPU state.
309 */
310
311 /* Restore host FPU and XMM state if necessary. */
312 if (CPUMIsGuestFPUStateActive(pVM))
313 {
314 Log2(("CPUMRestoreHostFPUState\n"));
315 /** @note CPUMRestoreHostFPUState keeps the current CR0 intact. */
316 CPUMRestoreHostFPUState(pVM);
317
318 pVM->hwaccm.s.fContextUseFlags |= HWACCM_CHANGED_GUEST_CR0;
319 }
320
321 if (pVM->hwaccm.s.vmx.fSupported)
322 {
323 return VMXR0Disable(pVM);
324 }
325 else
326 {
327 Assert(pVM->hwaccm.s.svm.fSupported);
328 return SVMR0Disable(pVM);
329 }
330}
331
332/**
333 * Runs guest code in a hardware accelerated VM.
334 *
335 * @returns VBox status code.
336 * @param pVM The VM to operate on.
337 */
338HWACCMR0DECL(int) HWACCMR0RunGuestCode(PVM pVM)
339{
340 CPUMCTX *pCtx;
341 int rc;
342
343 rc = CPUMQueryGuestCtxPtr(pVM, &pCtx);
344 if (VBOX_FAILURE(rc))
345 return rc;
346
347 if (pVM->hwaccm.s.vmx.fSupported)
348 {
349 return VMXR0RunGuestCode(pVM, pCtx);
350 }
351 else
352 {
353 Assert(pVM->hwaccm.s.svm.fSupported);
354 return SVMR0RunGuestCode(pVM, pCtx);
355 }
356}
357
358
359#ifdef VBOX_STRICT
360#include <iprt/string.h>
361/**
362 * Dumps a descriptor.
363 *
364 * @param Desc Descriptor to dump.
365 * @param Sel Selector number.
366 * @param pszMsg Message to prepend the log entry with.
367 */
368HWACCMR0DECL(void) HWACCMR0DumpDescriptor(PX86DESCHC Desc, RTSEL Sel, const char *pszMsg)
369{
370 /*
371 * Make variable description string.
372 */
373 static struct
374 {
375 unsigned cch;
376 const char *psz;
377 } const aTypes[32] =
378 {
379 #define STRENTRY(str) { sizeof(str) - 1, str }
380
381 /* system */
382#if HC_ARCH_BITS == 64
383 STRENTRY("Reserved0 "), /* 0x00 */
384 STRENTRY("Reserved1 "), /* 0x01 */
385 STRENTRY("LDT "), /* 0x02 */
386 STRENTRY("Reserved3 "), /* 0x03 */
387 STRENTRY("Reserved4 "), /* 0x04 */
388 STRENTRY("Reserved5 "), /* 0x05 */
389 STRENTRY("Reserved6 "), /* 0x06 */
390 STRENTRY("Reserved7 "), /* 0x07 */
391 STRENTRY("Reserved8 "), /* 0x08 */
392 STRENTRY("TSS64Avail "), /* 0x09 */
393 STRENTRY("ReservedA "), /* 0x0a */
394 STRENTRY("TSS64Busy "), /* 0x0b */
395 STRENTRY("Call64 "), /* 0x0c */
396 STRENTRY("ReservedD "), /* 0x0d */
397 STRENTRY("Int64 "), /* 0x0e */
398 STRENTRY("Trap64 "), /* 0x0f */
399#else
400 STRENTRY("Reserved0 "), /* 0x00 */
401 STRENTRY("TSS16Avail "), /* 0x01 */
402 STRENTRY("LDT "), /* 0x02 */
403 STRENTRY("TSS16Busy "), /* 0x03 */
404 STRENTRY("Call16 "), /* 0x04 */
405 STRENTRY("Task "), /* 0x05 */
406 STRENTRY("Int16 "), /* 0x06 */
407 STRENTRY("Trap16 "), /* 0x07 */
408 STRENTRY("Reserved8 "), /* 0x08 */
409 STRENTRY("TSS32Avail "), /* 0x09 */
410 STRENTRY("ReservedA "), /* 0x0a */
411 STRENTRY("TSS32Busy "), /* 0x0b */
412 STRENTRY("Call32 "), /* 0x0c */
413 STRENTRY("ReservedD "), /* 0x0d */
414 STRENTRY("Int32 "), /* 0x0e */
415 STRENTRY("Trap32 "), /* 0x0f */
416#endif
417 /* non system */
418 STRENTRY("DataRO "), /* 0x10 */
419 STRENTRY("DataRO Accessed "), /* 0x11 */
420 STRENTRY("DataRW "), /* 0x12 */
421 STRENTRY("DataRW Accessed "), /* 0x13 */
422 STRENTRY("DataDownRO "), /* 0x14 */
423 STRENTRY("DataDownRO Accessed "), /* 0x15 */
424 STRENTRY("DataDownRW "), /* 0x16 */
425 STRENTRY("DataDownRW Accessed "), /* 0x17 */
426 STRENTRY("CodeEO "), /* 0x18 */
427 STRENTRY("CodeEO Accessed "), /* 0x19 */
428 STRENTRY("CodeER "), /* 0x1a */
429 STRENTRY("CodeER Accessed "), /* 0x1b */
430 STRENTRY("CodeConfEO "), /* 0x1c */
431 STRENTRY("CodeConfEO Accessed "), /* 0x1d */
432 STRENTRY("CodeConfER "), /* 0x1e */
433 STRENTRY("CodeConfER Accessed ") /* 0x1f */
434 #undef SYSENTRY
435 };
436 #define ADD_STR(psz, pszAdd) do { strcpy(psz, pszAdd); psz += strlen(pszAdd); } while (0)
437 char szMsg[128];
438 char *psz = &szMsg[0];
439 unsigned i = Desc->Gen.u1DescType << 4 | Desc->Gen.u4Type;
440 memcpy(psz, aTypes[i].psz, aTypes[i].cch);
441 psz += aTypes[i].cch;
442
443 if (Desc->Gen.u1Present)
444 ADD_STR(psz, "Present ");
445 else
446 ADD_STR(psz, "Not-Present ");
447#if HC_ARCH_BITS == 64
448 if (Desc->Gen.u1Long)
449 ADD_STR(psz, "64-bit ");
450 else
451 ADD_STR(psz, "Comp ");
452#else
453 if (Desc->Gen.u1Granularity)
454 ADD_STR(psz, "Page ");
455 if (Desc->Gen.u1DefBig)
456 ADD_STR(psz, "32-bit ");
457 else
458 ADD_STR(psz, "16-bit ");
459#endif
460 #undef ADD_STR
461 *psz = '\0';
462
463 /*
464 * Limit and Base and format the output.
465 */
466 uint32_t u32Limit = Desc->Gen.u4LimitHigh << 16 | Desc->Gen.u16LimitLow;
467 if (Desc->Gen.u1Granularity)
468 u32Limit = u32Limit << PAGE_SHIFT | PAGE_OFFSET_MASK;
469
470#if HC_ARCH_BITS == 64
471 uint64_t u32Base = ((uintptr_t)Desc->Gen.u32BaseHigh3 << 32ULL) | Desc->Gen.u8BaseHigh2 << 24ULL | Desc->Gen.u8BaseHigh1 << 16ULL | Desc->Gen.u16BaseLow;
472
473 Log(("%s %04x - %VX64 %VX64 - base=%VX64 limit=%08x dpl=%d %s\n", pszMsg,
474 Sel, Desc->au64[0], Desc->au64[1], u32Base, u32Limit, Desc->Gen.u2Dpl, szMsg));
475#else
476 uint32_t u32Base = Desc->Gen.u8BaseHigh2 << 24 | Desc->Gen.u8BaseHigh1 << 16 | Desc->Gen.u16BaseLow;
477
478 Log(("%s %04x - %08x %08x - base=%08x limit=%08x dpl=%d %s\n", pszMsg,
479 Sel, Desc->au32[0], Desc->au32[1], u32Base, u32Limit, Desc->Gen.u2Dpl, szMsg));
480#endif
481}
482
483/**
484 * Formats a full register dump.
485 *
486 * @param pCtx The context to format.
487 */
488HWACCMR0DECL(void) HWACCMDumpRegs(PCPUMCTX pCtx)
489{
490 /*
491 * Format the flags.
492 */
493 static struct
494 {
495 const char *pszSet; const char *pszClear; uint32_t fFlag;
496 } aFlags[] =
497 {
498 { "vip",NULL, X86_EFL_VIP },
499 { "vif",NULL, X86_EFL_VIF },
500 { "ac", NULL, X86_EFL_AC },
501 { "vm", NULL, X86_EFL_VM },
502 { "rf", NULL, X86_EFL_RF },
503 { "nt", NULL, X86_EFL_NT },
504 { "ov", "nv", X86_EFL_OF },
505 { "dn", "up", X86_EFL_DF },
506 { "ei", "di", X86_EFL_IF },
507 { "tf", NULL, X86_EFL_TF },
508 { "nt", "pl", X86_EFL_SF },
509 { "nz", "zr", X86_EFL_ZF },
510 { "ac", "na", X86_EFL_AF },
511 { "po", "pe", X86_EFL_PF },
512 { "cy", "nc", X86_EFL_CF },
513 };
514 char szEFlags[80];
515 char *psz = szEFlags;
516 uint32_t efl = pCtx->eflags.u32;
517 for (unsigned i = 0; i < ELEMENTS(aFlags); i++)
518 {
519 const char *pszAdd = aFlags[i].fFlag & efl ? aFlags[i].pszSet : aFlags[i].pszClear;
520 if (pszAdd)
521 {
522 strcpy(psz, pszAdd);
523 psz += strlen(pszAdd);
524 *psz++ = ' ';
525 }
526 }
527 psz[-1] = '\0';
528
529
530 /*
531 * Format the registers.
532 */
533 Log(("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\n"
534 "eip=%08x esp=%08x ebp=%08x iopl=%d %*s\n"
535 "cs={%04x base=%08x limit=%08x flags=%08x} dr0=%08x dr1=%08x\n"
536 "ds={%04x base=%08x limit=%08x flags=%08x} dr2=%08x dr3=%08x\n"
537 "es={%04x base=%08x limit=%08x flags=%08x} dr4=%08x dr5=%08x\n"
538 "fs={%04x base=%08x limit=%08x flags=%08x} dr6=%08x dr7=%08x\n"
539 ,
540 pCtx->eax, pCtx->ebx, pCtx->ecx, pCtx->edx, pCtx->esi, pCtx->edi,
541 pCtx->eip, pCtx->esp, pCtx->ebp, X86_EFL_GET_IOPL(efl), 31, szEFlags,
542 (RTSEL)pCtx->cs, pCtx->csHid.u32Base, pCtx->csHid.u32Limit, pCtx->csHid.Attr.u, pCtx->dr0, pCtx->dr1,
543 (RTSEL)pCtx->ds, pCtx->dsHid.u32Base, pCtx->dsHid.u32Limit, pCtx->dsHid.Attr.u, pCtx->dr2, pCtx->dr3,
544 (RTSEL)pCtx->es, pCtx->esHid.u32Base, pCtx->esHid.u32Limit, pCtx->esHid.Attr.u, pCtx->dr4, pCtx->dr5,
545 (RTSEL)pCtx->fs, pCtx->fsHid.u32Base, pCtx->fsHid.u32Limit, pCtx->fsHid.Attr.u, pCtx->dr6, pCtx->dr7));
546
547 Log(("gs={%04x base=%08x limit=%08x flags=%08x} cr0=%08x cr2=%08x\n"
548 "ss={%04x base=%08x limit=%08x flags=%08x} cr3=%08x cr4=%08x\n"
549 "gdtr=%08x:%04x idtr=%08x:%04x eflags=%08x\n"
550 "ldtr={%04x base=%08x limit=%08x flags=%08x}\n"
551 "tr ={%04x base=%08x limit=%08x flags=%08x}\n"
552 "SysEnter={cs=%04llx eip=%08llx esp=%08llx}\n"
553 "FCW=%04x FSW=%04x FTW=%04x\n",
554 (RTSEL)pCtx->gs, pCtx->gsHid.u32Base, pCtx->gsHid.u32Limit, pCtx->gsHid.Attr.u, pCtx->cr0, pCtx->cr2,
555 (RTSEL)pCtx->ss, pCtx->ssHid.u32Base, pCtx->ssHid.u32Limit, pCtx->ssHid.Attr.u, pCtx->cr3, pCtx->cr4,
556 pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt, pCtx->idtr.pIdt, pCtx->idtr.cbIdt, efl,
557 (RTSEL)pCtx->ldtr, pCtx->ldtrHid.u32Base, pCtx->ldtrHid.u32Limit, pCtx->ldtrHid.Attr.u,
558 (RTSEL)pCtx->tr, pCtx->trHid.u32Base, pCtx->trHid.u32Limit, pCtx->trHid.Attr.u,
559 pCtx->SysEnter.cs, pCtx->SysEnter.eip, pCtx->SysEnter.esp,
560 pCtx->fpu.FCW, pCtx->fpu.FSW, pCtx->fpu.FTW));
561
562
563}
564#endif
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