VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGuruMeditation.cpp@ 20869

最後變更 在這個檔案從20869是 20869,由 vboxsync 提交於 16 年 前

VMMR3RawRunGC: cause guru meditation if cr3 mismatches. EMR3FatalError: change to guru meditation or we risk resuming execution and blowing up.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 20.2 KB
 
1/* $Id: VMMGuruMeditation.cpp 20869 2009-06-24 00:27:17Z vboxsync $ */
2/** @file
3 * VMM - The Virtual Machine Monitor, Guru Meditation Code.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_VMM
26#include <VBox/vmm.h>
27#include <VBox/pdmapi.h>
28#include <VBox/pdmcritsect.h>
29#include <VBox/trpm.h>
30#include <VBox/dbgf.h>
31#include "VMMInternal.h"
32#include <VBox/vm.h>
33#include <VBox/mm.h>
34#include <VBox/iom.h>
35#include <VBox/em.h>
36
37#include <VBox/err.h>
38#include <VBox/param.h>
39#include <VBox/version.h>
40#include <VBox/hwaccm.h>
41#include <iprt/assert.h>
42#include <iprt/time.h>
43#include <iprt/stream.h>
44#include <iprt/string.h>
45#include <iprt/stdarg.h>
46
47
48/*******************************************************************************
49* Structures and Typedefs *
50*******************************************************************************/
51/**
52 * Structure to pass to DBGFR3Info() and for doing all other
53 * output during fatal dump.
54 */
55typedef struct VMMR3FATALDUMPINFOHLP
56{
57 /** The helper core. */
58 DBGFINFOHLP Core;
59 /** The release logger instance. */
60 PRTLOGGER pRelLogger;
61 /** The saved release logger flags. */
62 RTUINT fRelLoggerFlags;
63 /** The logger instance. */
64 PRTLOGGER pLogger;
65 /** The saved logger flags. */
66 RTUINT fLoggerFlags;
67 /** The saved logger destination flags. */
68 RTUINT fLoggerDestFlags;
69 /** Whether to output to stderr or not. */
70 bool fStdErr;
71} VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;
72/** Pointer to a VMMR3FATALDUMPINFOHLP structure. */
73typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;
74
75
76/**
77 * Print formatted string.
78 *
79 * @param pHlp Pointer to this structure.
80 * @param pszFormat The format string.
81 * @param ... Arguments.
82 */
83static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
84{
85 va_list args;
86 va_start(args, pszFormat);
87 pHlp->pfnPrintfV(pHlp, pszFormat, args);
88 va_end(args);
89}
90
91
92/**
93 * Print formatted string.
94 *
95 * @param pHlp Pointer to this structure.
96 * @param pszFormat The format string.
97 * @param args Argument list.
98 */
99static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
100{
101 PCVMMR3FATALDUMPINFOHLP pMyHlp = (PCVMMR3FATALDUMPINFOHLP)pHlp;
102
103 if (pMyHlp->pRelLogger)
104 {
105 va_list args2;
106 va_copy(args2, args);
107 RTLogLoggerV(pMyHlp->pRelLogger, pszFormat, args2);
108 va_end(args2);
109 }
110 if (pMyHlp->pLogger)
111 {
112 va_list args2;
113 va_copy(args2, args);
114 RTLogLoggerV(pMyHlp->pLogger, pszFormat, args);
115 va_end(args2);
116 }
117 if (pMyHlp->fStdErr)
118 {
119 va_list args2;
120 va_copy(args2, args);
121 RTStrmPrintfV(g_pStdErr, pszFormat, args);
122 va_end(args2);
123 }
124}
125
126
127/**
128 * Initializes the fatal dump output helper.
129 *
130 * @param pHlp The structure to initialize.
131 */
132static void vmmR3FatalDumpInfoHlpInit(PVMMR3FATALDUMPINFOHLP pHlp)
133{
134 memset(pHlp, 0, sizeof(*pHlp));
135
136 pHlp->Core.pfnPrintf = vmmR3FatalDumpInfoHlp_pfnPrintf;
137 pHlp->Core.pfnPrintfV = vmmR3FatalDumpInfoHlp_pfnPrintfV;
138
139 /*
140 * The loggers.
141 */
142 pHlp->pRelLogger = RTLogRelDefaultInstance();
143#ifndef LOG_ENABLED
144 if (!pHlp->pRelLogger)
145#endif
146 pHlp->pLogger = RTLogDefaultInstance();
147
148 if (pHlp->pRelLogger)
149 {
150 pHlp->fRelLoggerFlags = pHlp->pRelLogger->fFlags;
151 pHlp->pRelLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
152 }
153
154 if (pHlp->pLogger)
155 {
156 pHlp->fLoggerFlags = pHlp->pLogger->fFlags;
157 pHlp->fLoggerDestFlags = pHlp->pLogger->fDestFlags;
158 pHlp->pLogger->fFlags &= ~(RTLOGFLAGS_BUFFERED | RTLOGFLAGS_DISABLED);
159#ifndef DEBUG_sandervl
160 pHlp->pLogger->fDestFlags |= RTLOGDEST_DEBUGGER;
161#endif
162 }
163
164 /*
165 * Check if we need write to stderr.
166 */
167#ifdef DEBUG_sandervl
168 pHlp->fStdErr = false; /* takes too long to display here */
169#else
170 pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
171 && (!pHlp->pLogger || !(pHlp->pLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
172#endif
173}
174
175
176/**
177 * Deletes the fatal dump output helper.
178 *
179 * @param pHlp The structure to delete.
180 */
181static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)
182{
183 if (pHlp->pRelLogger)
184 {
185 RTLogFlush(pHlp->pRelLogger);
186 pHlp->pRelLogger->fFlags = pHlp->fRelLoggerFlags;
187 }
188
189 if (pHlp->pLogger)
190 {
191 RTLogFlush(pHlp->pLogger);
192 pHlp->pLogger->fFlags = pHlp->fLoggerFlags;
193 pHlp->pLogger->fDestFlags = pHlp->fLoggerDestFlags;
194 }
195}
196
197
198/**
199 * Dumps the VM state on a fatal error.
200 *
201 * @param pVM VM Handle.
202 * @param pVCpu VMCPU Handle.
203 * @param rcErr VBox status code.
204 */
205VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr)
206{
207 /*
208 * Create our output helper and sync it with the log settings.
209 * This helper will be used for all the output.
210 */
211 VMMR3FATALDUMPINFOHLP Hlp;
212 PCDBGFINFOHLP pHlp = &Hlp.Core;
213 vmmR3FatalDumpInfoHlpInit(&Hlp);
214
215 /* Release owned locks to make sure other VCPUs can continue in case they were waiting for one. */
216#if 1
217 PDMR3CritSectLeaveAll(pVM);
218#else
219 MMR3ReleaseOwnedLocks(pVM);
220 PGMR3ReleaseOwnedLocks(pVM);
221 PDMR3ReleaseOwnedLocks(pVM);
222 IOMR3ReleaseOwnedLocks(pVM);
223 EMR3ReleaseOwnedLocks(pVM);
224#endif
225
226 /*
227 * Header.
228 */
229 pHlp->pfnPrintf(pHlp,
230 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
231 "!!\n"
232 "!! Guru Meditation %d (%Rrc)\n"
233 "!!\n",
234 rcErr, rcErr);
235
236 /*
237 * Continue according to context.
238 */
239 bool fDoneHyper = false;
240 switch (rcErr)
241 {
242 /*
243 * Hypervisor errors.
244 */
245 case VERR_VMM_RING0_ASSERTION:
246 case VINF_EM_DBG_HYPER_ASSERTION:
247 {
248 const char *pszMsg1 = VMMR3GetRZAssertMsg1(pVM);
249 while (pszMsg1 && *pszMsg1 == '\n')
250 pszMsg1++;
251 const char *pszMsg2 = VMMR3GetRZAssertMsg2(pVM);
252 while (pszMsg2 && *pszMsg2 == '\n')
253 pszMsg2++;
254 pHlp->pfnPrintf(pHlp,
255 "%s"
256 "%s",
257 pszMsg1,
258 pszMsg2);
259 if ( !pszMsg2
260 || !*pszMsg2
261 || strchr(pszMsg2, '\0')[-1] != '\n')
262 pHlp->pfnPrintf(pHlp, "\n");
263 pHlp->pfnPrintf(pHlp, "!!\n");
264 /* fall thru */
265 }
266 case VERR_TRPM_DONT_PANIC:
267 case VERR_TRPM_PANIC:
268 case VINF_EM_RAW_STALE_SELECTOR:
269 case VINF_EM_RAW_IRET_TRAP:
270 case VINF_EM_DBG_HYPER_BREAKPOINT:
271 case VINF_EM_DBG_HYPER_STEPPED:
272 case VERR_VMM_HYPER_CR3_MISMATCH:
273 {
274 /*
275 * Active trap? This is only of partial interest when in hardware
276 * assisted virtualization mode, thus the different messages.
277 */
278 uint32_t uEIP = CPUMGetHyperEIP(pVCpu);
279 TRPMEVENT enmType;
280 uint8_t u8TrapNo = 0xce;
281 RTGCUINT uErrorCode = 0xdeadface;
282 RTGCUINTPTR uCR2 = 0xdeadface;
283 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
284 if (!HWACCMIsEnabled(pVM))
285 {
286 if (RT_SUCCESS(rc2))
287 pHlp->pfnPrintf(pHlp,
288 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d\n",
289 u8TrapNo, uErrorCode, uCR2, uEIP, enmType);
290 else
291 pHlp->pfnPrintf(pHlp,
292 "!! EIP=%RX32 NOTRAP\n",
293 uEIP);
294 }
295 else if (RT_SUCCESS(rc2))
296 pHlp->pfnPrintf(pHlp,
297 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",
298 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType);
299
300 /*
301 * The hypervisor dump is not relevant when we're in VT-x/AMD-V mode.
302 */
303 if (HWACCMIsEnabled(pVM))
304 {
305 pHlp->pfnPrintf(pHlp, "\n");
306#if defined(RT_OS_WINDOWS) && HC_ARCH_BITS == 32
307 /* Callstack. */
308 PCDBGFSTACKFRAME pFirstFrame;
309 DBGFADDRESS eip, ebp, esp;
310
311 eip.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
312#if HC_ARCH_BITS == 64
313 eip.FlatPtr = eip.off = pVCpu->vmm.s.CallHostR0JmpBuf.rip;
314#else
315 eip.FlatPtr = eip.off = pVCpu->vmm.s.CallHostR0JmpBuf.eip;
316#endif
317 eip.Sel = DBGF_SEL_FLAT;
318 ebp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
319 ebp.FlatPtr = ebp.off = pVCpu->vmm.s.CallHostR0JmpBuf.SavedEbp;
320 ebp.Sel = DBGF_SEL_FLAT;
321 esp.fFlags = DBGFADDRESS_FLAGS_RING0 | DBGFADDRESS_FLAGS_VALID;
322 esp.Sel = DBGF_SEL_FLAT;
323 esp.FlatPtr = esp.off = pVCpu->vmm.s.CallHostR0JmpBuf.SavedEsp;
324
325 rc2 = DBGFR3StackWalkBeginEx(pVM, pVCpu->idCpu, DBGFCODETYPE_RING0, &ebp, &esp, &eip,
326 DBGFRETURNTYPE_INVALID, &pFirstFrame);
327 if (RT_SUCCESS(rc2))
328 {
329 pHlp->pfnPrintf(pHlp,
330 "!!\n"
331 "!! Call Stack:\n"
332 "!!\n"
333 "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
334 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
335 pFrame;
336 pFrame = DBGFR3StackWalkNext(pFrame))
337 {
338 pHlp->pfnPrintf(pHlp,
339 "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
340 (uint32_t)pFrame->AddrFrame.off,
341 (uint32_t)pFrame->AddrReturnFrame.off,
342 (uint32_t)pFrame->AddrReturnPC.Sel,
343 (uint32_t)pFrame->AddrReturnPC.off,
344 pFrame->Args.au32[0],
345 pFrame->Args.au32[1],
346 pFrame->Args.au32[2],
347 pFrame->Args.au32[3]);
348 pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
349 if (pFrame->pSymPC)
350 {
351 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
352 if (offDisp > 0)
353 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
354 else if (offDisp < 0)
355 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
356 else
357 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
358 }
359 if (pFrame->pLinePC)
360 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
361 pHlp->pfnPrintf(pHlp, "\n");
362 }
363 DBGFR3StackWalkEnd(pFirstFrame);
364 }
365#endif /* defined(RT_OS_WINDOWS) && HC_ARCH_BITS == 32 */
366 }
367 else
368 {
369 /*
370 * Try figure out where eip is.
371 */
372 /* core code? */
373 if (uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC < pVM->vmm.s.cbCoreCode)
374 pHlp->pfnPrintf(pHlp,
375 "!! EIP is in CoreCode, offset %#x\n",
376 uEIP - (RTGCUINTPTR)pVM->vmm.s.pvCoreCodeRC);
377 else
378 { /* ask PDM */ /** @todo ask DBGFR3Sym later? */
379 char szModName[64];
380 RTRCPTR RCPtrMod;
381 char szNearSym1[260];
382 RTRCPTR RCPtrNearSym1;
383 char szNearSym2[260];
384 RTRCPTR RCPtrNearSym2;
385 int rc = PDMR3LdrQueryRCModFromPC(pVM, uEIP,
386 &szModName[0], sizeof(szModName), &RCPtrMod,
387 &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1,
388 &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2);
389 if (RT_SUCCESS(rc))
390 pHlp->pfnPrintf(pHlp,
391 "!! EIP in %s (%RRv) at rva %x near symbols:\n"
392 "!! %RRv rva %RRv off %08x %s\n"
393 "!! %RRv rva %RRv off -%08x %s\n",
394 szModName, RCPtrMod, (unsigned)(uEIP - RCPtrMod),
395 RCPtrNearSym1, RCPtrNearSym1 - RCPtrMod, (unsigned)(uEIP - RCPtrNearSym1), szNearSym1,
396 RCPtrNearSym2, RCPtrNearSym2 - RCPtrMod, (unsigned)(RCPtrNearSym2 - uEIP), szNearSym2);
397 else
398 pHlp->pfnPrintf(pHlp,
399 "!! EIP is not in any code known to VMM!\n");
400 }
401
402 /* Disassemble the instruction. */
403 char szInstr[256];
404 rc2 = DBGFR3DisasInstrEx(pVM, pVCpu->idCpu, 0, 0, DBGF_DISAS_FLAGS_CURRENT_HYPER, &szInstr[0], sizeof(szInstr), NULL);
405 if (RT_SUCCESS(rc2))
406 pHlp->pfnPrintf(pHlp,
407 "!! %s\n", szInstr);
408
409 /* Dump the hypervisor cpu state. */
410 pHlp->pfnPrintf(pHlp,
411 "!!\n"
412 "!!\n"
413 "!!\n");
414 rc2 = DBGFR3Info(pVM, "cpumhyper", "verbose", pHlp);
415 fDoneHyper = true;
416
417 /* Callstack. */
418 PCDBGFSTACKFRAME pFirstFrame;
419 rc2 = DBGFR3StackWalkBegin(pVM, pVCpu->idCpu, DBGFCODETYPE_HYPER, &pFirstFrame);
420 if (RT_SUCCESS(rc2))
421 {
422 pHlp->pfnPrintf(pHlp,
423 "!!\n"
424 "!! Call Stack:\n"
425 "!!\n"
426 "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
427 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
428 pFrame;
429 pFrame = DBGFR3StackWalkNext(pFrame))
430 {
431 pHlp->pfnPrintf(pHlp,
432 "%08RX32 %08RX32 %04RX32:%08RX32 %08RX32 %08RX32 %08RX32 %08RX32",
433 (uint32_t)pFrame->AddrFrame.off,
434 (uint32_t)pFrame->AddrReturnFrame.off,
435 (uint32_t)pFrame->AddrReturnPC.Sel,
436 (uint32_t)pFrame->AddrReturnPC.off,
437 pFrame->Args.au32[0],
438 pFrame->Args.au32[1],
439 pFrame->Args.au32[2],
440 pFrame->Args.au32[3]);
441 pHlp->pfnPrintf(pHlp, " %RTsel:%08RGv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
442 if (pFrame->pSymPC)
443 {
444 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
445 if (offDisp > 0)
446 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
447 else if (offDisp < 0)
448 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
449 else
450 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
451 }
452 if (pFrame->pLinePC)
453 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
454 pHlp->pfnPrintf(pHlp, "\n");
455 }
456 DBGFR3StackWalkEnd(pFirstFrame);
457 }
458
459 /* raw stack */
460 pHlp->pfnPrintf(pHlp,
461 "!!\n"
462 "!! Raw stack (mind the direction). pbEMTStackRC=%RRv pbEMTStackBottomRC=%RRv\n"
463 "!!\n"
464 "%.*Rhxd\n",
465 pVCpu->vmm.s.pbEMTStackRC, pVCpu->vmm.s.pbEMTStackBottomRC,
466 VMM_STACK_SIZE, pVCpu->vmm.s.pbEMTStackR3);
467 } /* !HWACCMIsEnabled */
468 break;
469 }
470
471 default:
472 {
473 break;
474 }
475
476 } /* switch (rcErr) */
477
478
479 /*
480 * Generic info dumper loop.
481 */
482 static struct
483 {
484 const char *pszInfo;
485 const char *pszArgs;
486 } const aInfo[] =
487 {
488 { "mappings", NULL },
489 { "hma", NULL },
490 { "cpumguest", "verbose" },
491 { "cpumguestinstr", "verbose" },
492 { "cpumhyper", "verbose" },
493 { "cpumhost", "verbose" },
494 { "mode", "all" },
495 { "cpuid", "verbose" },
496 { "gdt", NULL },
497 { "ldt", NULL },
498 //{ "tss", NULL },
499 { "ioport", NULL },
500 { "mmio", NULL },
501 { "phys", NULL },
502 //{ "pgmpd", NULL }, - doesn't always work at init time...
503 { "timers", NULL },
504 { "activetimers", NULL },
505 { "handlers", "phys virt hyper stats" },
506 { "cfgm", NULL },
507 };
508 for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
509 {
510 if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))
511 continue;
512 pHlp->pfnPrintf(pHlp,
513 "!!\n"
514 "!! {%s, %s}\n"
515 "!!\n",
516 aInfo[i].pszInfo, aInfo[i].pszArgs);
517 DBGFR3Info(pVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
518 }
519
520 /* done */
521 pHlp->pfnPrintf(pHlp,
522 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
523
524
525 /*
526 * Delete the output instance (flushing and restoring of flags).
527 */
528 vmmR3FatalDumpInfoHlpDelete(&Hlp);
529
530 /*
531 * Reset the ring-0 long jump buffer and stack.
532 */
533 /** @todo reset the R0 for the calling virtual cpu. We'll assert (luckily) in
534 * PGMPhys.cpp otherwise. */
535}
536
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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