VirtualBox

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

Last change on this file since 94249 was 93901, checked in by vboxsync, 3 years ago

VMM,Main,++: Removed VM_IS_RAW_MODE_ENABLED/VM_EXEC_ENGINE_RAW_MODE and added VM_IS_EXEC_ENGINE_IEM/VM_EXEC_ENGINE_IEM instead. In IMachineDebugger::getExecutionEngine VMExecutionEngine_RawMode was removed and VMExecutionEngine_Emulated added. Removed dead code and updated frontends accordingly. On darwin.arm64 HM now falls back on IEM execution since neither HM or NEM is availble there. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 26.9 KB
Line 
1/* $Id: VMMGuruMeditation.cpp 93901 2022-02-23 15:35:26Z vboxsync $ */
2/** @file
3 * VMM - The Virtual Machine Monitor, Guru Meditation Code.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_VMM
23#include <VBox/vmm/vmm.h>
24#include <VBox/vmm/pdmapi.h>
25#include <VBox/vmm/pdmcritsect.h>
26#include <VBox/vmm/trpm.h>
27#include <VBox/vmm/dbgf.h>
28#include "VMMInternal.h"
29#include <VBox/vmm/vm.h>
30#include <VBox/vmm/mm.h>
31#include <VBox/vmm/iom.h>
32#include <VBox/vmm/em.h>
33
34#include <VBox/err.h>
35#include <VBox/param.h>
36#include <VBox/version.h>
37#include <VBox/vmm/hm.h>
38#include <iprt/assert.h>
39#include <iprt/dbg.h>
40#include <iprt/time.h>
41#include <iprt/stream.h>
42#include <iprt/string.h>
43#include <iprt/stdarg.h>
44
45
46/*********************************************************************************************************************************
47* Structures and Typedefs *
48*********************************************************************************************************************************/
49/**
50 * Structure to pass to DBGFR3Info() and for doing all other
51 * output during fatal dump.
52 */
53typedef struct VMMR3FATALDUMPINFOHLP
54{
55 /** The helper core. */
56 DBGFINFOHLP Core;
57 /** The release logger instance. */
58 PRTLOGGER pRelLogger;
59 /** The saved release logger flags. */
60 uint32_t fRelLoggerFlags;
61 /** The logger instance. */
62 PRTLOGGER pLogger;
63 /** The saved logger flags. */
64 uint32_t fLoggerFlags;
65 /** The saved logger destination flags. */
66 uint32_t fLoggerDestFlags;
67 /** Whether to output to stderr or not. */
68 bool fStdErr;
69 /** Whether we're still recording the summary or not. */
70 bool fRecSummary;
71 /** Buffer for the summary. */
72 char szSummary[4096 - 2];
73 /** The current summary offset. */
74 size_t offSummary;
75 /** Standard error buffer. */
76 char achStdErrBuf[4096 - 8];
77 /** Standard error buffer offset. */
78 size_t offStdErrBuf;
79} VMMR3FATALDUMPINFOHLP, *PVMMR3FATALDUMPINFOHLP;
80/** Pointer to a VMMR3FATALDUMPINFOHLP structure. */
81typedef const VMMR3FATALDUMPINFOHLP *PCVMMR3FATALDUMPINFOHLP;
82
83
84/**
85 * Flushes the content of achStdErrBuf, setting offStdErrBuf to zero.
86 *
87 * @param pHlp The instance to flush.
88 */
89static void vmmR3FatalDumpInfoHlpFlushStdErr(PVMMR3FATALDUMPINFOHLP pHlp)
90{
91 size_t cch = pHlp->offStdErrBuf;
92 if (cch)
93 {
94 RTStrmWrite(g_pStdErr, pHlp->achStdErrBuf, cch);
95 pHlp->offStdErrBuf = 0;
96 }
97}
98
99/**
100 * @callback_method_impl{FNRTSTROUTPUT, For buffering stderr output.}
101 */
102static DECLCALLBACK(size_t) vmmR3FatalDumpInfoHlp_BufferedStdErrOutput(void *pvArg, const char *pachChars, size_t cbChars)
103{
104 PVMMR3FATALDUMPINFOHLP pHlp = (PVMMR3FATALDUMPINFOHLP)pvArg;
105 if (cbChars)
106 {
107 size_t offBuf = pHlp->offStdErrBuf;
108 if (cbChars < sizeof(pHlp->achStdErrBuf) - offBuf)
109 { /* likely */ }
110 else
111 {
112 vmmR3FatalDumpInfoHlpFlushStdErr(pHlp);
113 if (cbChars < sizeof(pHlp->achStdErrBuf))
114 offBuf = 0;
115 else
116 {
117 RTStrmWrite(g_pStdErr, pachChars, cbChars);
118 return cbChars;
119 }
120 }
121 memcpy(&pHlp->achStdErrBuf[offBuf], pachChars, cbChars);
122 pHlp->offStdErrBuf = offBuf + cbChars;
123 }
124 return cbChars;
125}
126
127
128/**
129 * Print formatted string.
130 *
131 * @param pHlp Pointer to this structure.
132 * @param pszFormat The format string.
133 * @param ... Arguments.
134 */
135static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
136{
137 va_list args;
138 va_start(args, pszFormat);
139 pHlp->pfnPrintfV(pHlp, pszFormat, args);
140 va_end(args);
141}
142
143/**
144 * Print formatted string.
145 *
146 * @param pHlp Pointer to this structure.
147 * @param pszFormat The format string.
148 * @param args Argument list.
149 */
150static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
151{
152 PVMMR3FATALDUMPINFOHLP pMyHlp = (PVMMR3FATALDUMPINFOHLP)pHlp;
153
154 if (pMyHlp->pRelLogger)
155 {
156 va_list args2;
157 va_copy(args2, args);
158 RTLogLoggerV(pMyHlp->pRelLogger, pszFormat, args2);
159 va_end(args2);
160 }
161 if (pMyHlp->pLogger)
162 {
163 va_list args2;
164 va_copy(args2, args);
165 RTLogLoggerV(pMyHlp->pLogger, pszFormat, args);
166 va_end(args2);
167 }
168 if (pMyHlp->fStdErr)
169 {
170 va_list args2;
171 va_copy(args2, args);
172 RTStrFormatV(vmmR3FatalDumpInfoHlp_BufferedStdErrOutput, pMyHlp, NULL, NULL, pszFormat, args2);
173 //RTStrmPrintfV(g_pStdErr, pszFormat, args2);
174 va_end(args2);
175 }
176 if (pMyHlp->fRecSummary)
177 {
178 size_t cchLeft = sizeof(pMyHlp->szSummary) - pMyHlp->offSummary;
179 if (cchLeft > 1)
180 {
181 va_list args2;
182 va_copy(args2, args);
183 size_t cch = RTStrPrintfV(&pMyHlp->szSummary[pMyHlp->offSummary], cchLeft, pszFormat, args);
184 va_end(args2);
185 Assert(cch <= cchLeft);
186 pMyHlp->offSummary += cch;
187 }
188 }
189}
190
191
192/**
193 * Initializes the fatal dump output helper.
194 *
195 * @param pHlp The structure to initialize.
196 */
197static void vmmR3FatalDumpInfoHlpInit(PVMMR3FATALDUMPINFOHLP pHlp)
198{
199 RT_BZERO(pHlp, sizeof(*pHlp));
200
201 pHlp->Core.pfnPrintf = vmmR3FatalDumpInfoHlp_pfnPrintf;
202 pHlp->Core.pfnPrintfV = vmmR3FatalDumpInfoHlp_pfnPrintfV;
203 pHlp->Core.pfnGetOptError = DBGFR3InfoGenericGetOptError;
204
205 /*
206 * The loggers.
207 */
208 pHlp->pRelLogger = RTLogRelGetDefaultInstance();
209#ifdef LOG_ENABLED
210 pHlp->pLogger = RTLogDefaultInstance();
211#else
212 if (pHlp->pRelLogger)
213 pHlp->pLogger = RTLogGetDefaultInstance();
214 else
215 pHlp->pLogger = RTLogDefaultInstance();
216#endif
217
218 if (pHlp->pRelLogger)
219 {
220 pHlp->fRelLoggerFlags = RTLogGetFlags(pHlp->pRelLogger);
221 RTLogChangeFlags(pHlp->pRelLogger, RTLOGFLAGS_BUFFERED, RTLOGFLAGS_DISABLED);
222 }
223
224 if (pHlp->pLogger)
225 {
226 pHlp->fLoggerFlags = RTLogGetFlags(pHlp->pLogger);
227 pHlp->fLoggerDestFlags = RTLogGetDestinations(pHlp->pLogger);
228 RTLogChangeFlags(pHlp->pLogger, RTLOGFLAGS_BUFFERED, RTLOGFLAGS_DISABLED);
229#ifndef DEBUG_sandervl
230 RTLogChangeDestinations(pHlp->pLogger, RTLOGDEST_DEBUGGER, 0);
231#endif
232 }
233
234 /*
235 * Check if we need write to stderr.
236 */
237 pHlp->fStdErr = (!pHlp->pRelLogger || !(RTLogGetDestinations(pHlp->pRelLogger) & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
238 && (!pHlp->pLogger || !(RTLogGetDestinations(pHlp->pLogger) & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)));
239#ifdef DEBUG_sandervl
240 pHlp->fStdErr = false; /* takes too long to display here */
241#endif
242 pHlp->offStdErrBuf = 0;
243
244 /*
245 * Init the summary recording.
246 */
247 pHlp->fRecSummary = true;
248 pHlp->offSummary = 0;
249 pHlp->szSummary[0] = '\0';
250}
251
252
253/**
254 * Deletes the fatal dump output helper.
255 *
256 * @param pHlp The structure to delete.
257 */
258static void vmmR3FatalDumpInfoHlpDelete(PVMMR3FATALDUMPINFOHLP pHlp)
259{
260 if (pHlp->pRelLogger)
261 {
262 RTLogFlush(pHlp->pRelLogger);
263 RTLogChangeFlags(pHlp->pRelLogger,
264 pHlp->fRelLoggerFlags & RTLOGFLAGS_DISABLED,
265 pHlp->fRelLoggerFlags & RTLOGFLAGS_BUFFERED);
266 }
267
268 if (pHlp->pLogger)
269 {
270 RTLogFlush(pHlp->pLogger);
271 RTLogChangeFlags(pHlp->pLogger,
272 pHlp->fLoggerFlags & RTLOGFLAGS_DISABLED,
273 pHlp->fLoggerFlags & RTLOGFLAGS_BUFFERED);
274 RTLogChangeDestinations(pHlp->pLogger, 0, pHlp->fLoggerDestFlags & RTLOGDEST_DEBUGGER);
275 }
276
277 if (pHlp->fStdErr)
278 vmmR3FatalDumpInfoHlpFlushStdErr(pHlp);
279}
280
281
282/**
283 * @callback_method_impl{FNVMMEMTRENDEZVOUS}
284 */
285static DECLCALLBACK(VBOXSTRICTRC) vmmR3FatalDumpRendezvousDoneCallback(PVM pVM, PVMCPU pVCpu, void *pvUser)
286{
287 VM_FF_CLEAR(pVM, VM_FF_CHECK_VM_STATE);
288 RT_NOREF(pVCpu, pvUser);
289 return VINF_SUCCESS;
290}
291
292
293/**
294 * Dumps the VM state on a fatal error.
295 *
296 * @param pVM The cross context VM structure.
297 * @param pVCpu The cross context virtual CPU structure.
298 * @param rcErr VBox status code.
299 */
300VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr)
301{
302 /*
303 * Create our output helper and sync it with the log settings.
304 * This helper will be used for all the output.
305 */
306 VMMR3FATALDUMPINFOHLP Hlp;
307 PCDBGFINFOHLP pHlp = &Hlp.Core;
308 vmmR3FatalDumpInfoHlpInit(&Hlp);
309
310 /* Release owned locks to make sure other VCPUs can continue in case they were waiting for one. */
311 PDMR3CritSectLeaveAll(pVM);
312
313 /*
314 * Header.
315 */
316 pHlp->pfnPrintf(pHlp,
317 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
318 "!!\n"
319 "!! VCPU%u: Guru Meditation %d (%Rrc)\n"
320 "!!\n",
321 pVCpu->idCpu, rcErr, rcErr);
322
323 /*
324 * Continue according to context.
325 */
326 bool fDoneHyper = false;
327 bool fDoneImport = false;
328 switch (rcErr)
329 {
330 /*
331 * Hypervisor errors.
332 */
333 case VERR_VMM_RING0_ASSERTION:
334 case VINF_EM_DBG_HYPER_ASSERTION:
335 case VERR_VMM_RING3_CALL_DISABLED:
336 case VERR_VMM_WRONG_HM_VMCPU_STATE:
337 case VERR_VMM_CONTEXT_HOOK_STILL_ENABLED:
338 {
339 const char *pszMsg1 = VMMR3GetRZAssertMsg1(pVM);
340 while (pszMsg1 && *pszMsg1 == '\n')
341 pszMsg1++;
342 const char *pszMsg2 = VMMR3GetRZAssertMsg2(pVM);
343 while (pszMsg2 && *pszMsg2 == '\n')
344 pszMsg2++;
345 pHlp->pfnPrintf(pHlp,
346 "%s"
347 "%s",
348 pszMsg1,
349 pszMsg2);
350 if ( !pszMsg2
351 || !*pszMsg2
352 || strchr(pszMsg2, '\0')[-1] != '\n')
353 pHlp->pfnPrintf(pHlp, "\n");
354 }
355 RT_FALL_THRU();
356 case VERR_TRPM_DONT_PANIC:
357 case VERR_TRPM_PANIC:
358 case VINF_EM_RAW_STALE_SELECTOR:
359 case VINF_EM_RAW_IRET_TRAP:
360 case VINF_EM_DBG_HYPER_BREAKPOINT:
361 case VINF_EM_DBG_HYPER_STEPPED:
362 case VINF_EM_TRIPLE_FAULT:
363 case VERR_VMM_HYPER_CR3_MISMATCH:
364 case VERR_VMM_LONG_JMP_ERROR:
365 {
366 /*
367 * Active trap? This is only of partial interest when in hardware
368 * assisted virtualization mode, thus the different messages.
369 */
370 TRPMEVENT enmType;
371 uint8_t u8TrapNo = 0xce;
372 uint32_t uErrorCode = 0xdeadface;
373 RTGCUINTPTR uCR2 = 0xdeadface;
374 uint8_t cbInstr = UINT8_MAX;
375 bool fIcebp = false;
376 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, &cbInstr, &fIcebp);
377 if (RT_SUCCESS(rc2))
378 pHlp->pfnPrintf(pHlp,
379 "!! ACTIVE TRAP=%02x ERRCD=%RX32 CR2=%RGv PC=%RGr Type=%d cbInstr=%02x fIcebp=%RTbool (Guest!)\n",
380 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType, cbInstr, fIcebp);
381
382 /*
383 * Dump the relevant hypervisor registers and stack.
384 */
385 if (rcErr == VERR_VMM_RING0_ASSERTION)
386 {
387 /* Dump the jmpbuf. */
388 pHlp->pfnPrintf(pHlp,
389 "!!\n"
390 "!! AssertJmpBuf:\n"
391 "!!\n");
392 pHlp->pfnPrintf(pHlp,
393 "UnwindSp=%RHv UnwindRetSp=%RHv UnwindBp=%RHv UnwindPc=%RHv\n",
394 pVCpu->vmm.s.AssertJmpBuf.UnwindSp,
395 pVCpu->vmm.s.AssertJmpBuf.UnwindRetSp,
396 pVCpu->vmm.s.AssertJmpBuf.UnwindBp,
397 pVCpu->vmm.s.AssertJmpBuf.UnwindPc);
398 pHlp->pfnPrintf(pHlp,
399 "UnwindRetPcValue=%RHv UnwindRetPcLocation=%RHv\n",
400 pVCpu->vmm.s.AssertJmpBuf.UnwindRetPcValue,
401 pVCpu->vmm.s.AssertJmpBuf.UnwindRetPcLocation);
402 pHlp->pfnPrintf(pHlp,
403 "pfn=%RHv pvUser1=%RHv pvUser2=%RHv\n",
404 pVCpu->vmm.s.AssertJmpBuf.pfn,
405 pVCpu->vmm.s.AssertJmpBuf.pvUser1,
406 pVCpu->vmm.s.AssertJmpBuf.pvUser2);
407
408 /* Dump the resume register frame on the stack. */
409 PRTHCUINTPTR const pBP = (PRTHCUINTPTR)&pVCpu->vmm.s.abAssertStack[ pVCpu->vmm.s.AssertJmpBuf.UnwindBp
410 - pVCpu->vmm.s.AssertJmpBuf.UnwindSp];
411#if HC_ARCH_BITS == 32
412 pHlp->pfnPrintf(pHlp,
413 "eax=volatile ebx=%08x ecx=volatile edx=volatile esi=%08x edi=%08x\n"
414 "eip=%08x esp=%08x ebp=%08x efl=%08x\n"
415 ,
416 pBP[-3], pBP[-2], pBP[-1],
417 pBP[1], pVCpu->vmm.s.AssertJmpBuf.SavedEbp - 8, pBP[0], pBP[-4]);
418#else
419# ifdef RT_OS_WINDOWS
420 pHlp->pfnPrintf(pHlp,
421 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
422 "rsi=%016RX64 rdi=%016RX64 r8=volatile r9=volatile \n"
423 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
424 "r14=%016RX64 r15=%016RX64\n"
425 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rfl=%08RX64\n"
426 ,
427 pBP[-7],
428 pBP[-6], pBP[-5],
429 pBP[-4], pBP[-3],
430 pBP[-2], pBP[-1],
431 pBP[1], pVCpu->vmm.s.AssertJmpBuf.UnwindRetSp, pBP[0], pBP[-8]);
432# else
433 pHlp->pfnPrintf(pHlp,
434 "rax=volatile rbx=%016RX64 rcx=volatile rdx=volatile\n"
435 "rsi=volatile rdi=volatile r8=volatile r9=volatile \n"
436 "r10=volatile r11=volatile r12=%016RX64 r13=%016RX64\n"
437 "r14=%016RX64 r15=%016RX64\n"
438 "rip=%016RX64 rsp=%016RX64 rbp=%016RX64 rflags=%08RX64\n"
439 ,
440 pBP[-5],
441 pBP[-4], pBP[-3],
442 pBP[-2], pBP[-1],
443 pBP[1], pVCpu->vmm.s.AssertJmpBuf.UnwindRetSp, pBP[0], pBP[-6]);
444# endif
445#endif
446
447 /* Callstack. */
448 DBGFADDRESS AddrPc, AddrBp, AddrSp;
449 PCDBGFSTACKFRAME pFirstFrame;
450 rc2 = DBGFR3StackWalkBeginEx(pVM->pUVM, pVCpu->idCpu, DBGFCODETYPE_RING0,
451 DBGFR3AddrFromHostR0(&AddrBp, pVCpu->vmm.s.AssertJmpBuf.UnwindBp),
452 DBGFR3AddrFromHostR0(&AddrSp, pVCpu->vmm.s.AssertJmpBuf.UnwindSp),
453 DBGFR3AddrFromHostR0(&AddrPc, pVCpu->vmm.s.AssertJmpBuf.UnwindPc),
454 RTDBGRETURNTYPE_INVALID, &pFirstFrame);
455 if (RT_SUCCESS(rc2))
456 {
457 pHlp->pfnPrintf(pHlp,
458 "!!\n"
459 "!! Call Stack:\n"
460 "!!\n");
461#if HC_ARCH_BITS == 32
462 pHlp->pfnPrintf(pHlp, "EBP Ret EBP Ret CS:EIP Arg0 Arg1 Arg2 Arg3 CS:EIP Symbol [line]\n");
463#else
464 pHlp->pfnPrintf(pHlp, "RBP Ret RBP Ret RIP RIP Symbol [line]\n");
465#endif
466 for (PCDBGFSTACKFRAME pFrame = pFirstFrame;
467 pFrame;
468 pFrame = DBGFR3StackWalkNext(pFrame))
469 {
470#if HC_ARCH_BITS == 32
471 pHlp->pfnPrintf(pHlp,
472 "%RHv %RHv %04RX32:%RHv %RHv %RHv %RHv %RHv",
473 (RTHCUINTPTR)pFrame->AddrFrame.off,
474 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
475 (RTHCUINTPTR)pFrame->AddrReturnPC.Sel,
476 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
477 pFrame->Args.au32[0],
478 pFrame->Args.au32[1],
479 pFrame->Args.au32[2],
480 pFrame->Args.au32[3]);
481 pHlp->pfnPrintf(pHlp, " %RTsel:%08RHv", pFrame->AddrPC.Sel, pFrame->AddrPC.off);
482#else
483 pHlp->pfnPrintf(pHlp,
484 "%RHv %RHv %RHv %RHv",
485 (RTHCUINTPTR)pFrame->AddrFrame.off,
486 (RTHCUINTPTR)pFrame->AddrReturnFrame.off,
487 (RTHCUINTPTR)pFrame->AddrReturnPC.off,
488 (RTHCUINTPTR)pFrame->AddrPC.off);
489#endif
490 if (pFrame->pSymPC)
491 {
492 RTGCINTPTR offDisp = pFrame->AddrPC.FlatPtr - pFrame->pSymPC->Value;
493 if (offDisp > 0)
494 pHlp->pfnPrintf(pHlp, " %s+%llx", pFrame->pSymPC->szName, (int64_t)offDisp);
495 else if (offDisp < 0)
496 pHlp->pfnPrintf(pHlp, " %s-%llx", pFrame->pSymPC->szName, -(int64_t)offDisp);
497 else
498 pHlp->pfnPrintf(pHlp, " %s", pFrame->pSymPC->szName);
499 }
500 if (pFrame->pLinePC)
501 pHlp->pfnPrintf(pHlp, " [%s @ 0i%d]", pFrame->pLinePC->szFilename, pFrame->pLinePC->uLineNo);
502 pHlp->pfnPrintf(pHlp, "\n");
503 for (uint32_t iReg = 0; iReg < pFrame->cSureRegs; iReg++)
504 {
505 const char *pszName = pFrame->paSureRegs[iReg].pszName;
506 if (!pszName)
507 pszName = DBGFR3RegCpuName(pVM->pUVM, pFrame->paSureRegs[iReg].enmReg,
508 pFrame->paSureRegs[iReg].enmType);
509 char szValue[1024];
510 szValue[0] = '\0';
511 DBGFR3RegFormatValue(szValue, sizeof(szValue), &pFrame->paSureRegs[iReg].Value,
512 pFrame->paSureRegs[iReg].enmType, false);
513 pHlp->pfnPrintf(pHlp, " %-3s=%s\n", pszName, szValue);
514 }
515 }
516 DBGFR3StackWalkEnd(pFirstFrame);
517 }
518
519 /* Symbols on the stack. */
520 uint32_t const cbRawStack = RT_MIN(pVCpu->vmm.s.AssertJmpBuf.cbStackValid, sizeof(pVCpu->vmm.s.abAssertStack));
521 uintptr_t const * const pauAddr = (uintptr_t const *)&pVCpu->vmm.s.abAssertStack[0];
522 uint32_t const iEnd = cbRawStack / sizeof(uintptr_t);
523 uint32_t iAddr = 0;
524 pHlp->pfnPrintf(pHlp,
525 "!!\n"
526 "!! Addresses on the stack (iAddr=%#x, iEnd=%#x)\n"
527 "!!\n",
528 iAddr, iEnd);
529 while (iAddr < iEnd)
530 {
531 uintptr_t const uAddr = pauAddr[iAddr];
532 if (uAddr > X86_PAGE_SIZE)
533 {
534 DBGFADDRESS Addr;
535 DBGFR3AddrFromFlat(pVM->pUVM, &Addr, uAddr);
536 RTGCINTPTR offDisp = 0;
537 RTGCINTPTR offLineDisp = 0;
538 PRTDBGSYMBOL pSym = DBGFR3AsSymbolByAddrA(pVM->pUVM, DBGF_AS_R0, &Addr,
539 RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL
540 | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED,
541 &offDisp, NULL);
542 PRTDBGLINE pLine = DBGFR3AsLineByAddrA(pVM->pUVM, DBGF_AS_R0, &Addr, &offLineDisp, NULL);
543 if (pLine || pSym)
544 {
545 pHlp->pfnPrintf(pHlp, "%#06x: %p =>", iAddr * sizeof(uintptr_t), uAddr);
546 if (pSym)
547 pHlp->pfnPrintf(pHlp, " %s + %#x", pSym->szName, (intptr_t)offDisp);
548 if (pLine)
549 pHlp->pfnPrintf(pHlp, " [%s:%u + %#x]\n", pLine->szFilename, pLine->uLineNo, offLineDisp);
550 else
551 pHlp->pfnPrintf(pHlp, "\n");
552 RTDbgSymbolFree(pSym);
553 RTDbgLineFree(pLine);
554 }
555 }
556 iAddr++;
557 }
558
559 /* raw stack */
560 Hlp.fRecSummary = false;
561 pHlp->pfnPrintf(pHlp,
562 "!!\n"
563 "!! Raw stack (mind the direction).\n"
564 "!! pbEMTStackR0=%RHv cbRawStack=%#x\n"
565 "!! pbEmtStackR3=%p\n"
566 "!!\n"
567 "%.*Rhxd\n",
568 pVCpu->vmm.s.AssertJmpBuf.UnwindSp, cbRawStack,
569 &pVCpu->vmm.s.abAssertStack[0],
570 cbRawStack, &pVCpu->vmm.s.abAssertStack[0]);
571 }
572 else
573 {
574 pHlp->pfnPrintf(pHlp,
575 "!! Skipping ring-0 registers and stack, rcErr=%Rrc\n", rcErr);
576 }
577 break;
578 }
579
580 case VERR_IEM_INSTR_NOT_IMPLEMENTED:
581 case VERR_IEM_ASPECT_NOT_IMPLEMENTED:
582 case VERR_PATM_IPE_TRAP_IN_PATCH_CODE:
583 case VERR_EM_GUEST_CPU_HANG:
584 {
585 CPUMImportGuestStateOnDemand(pVCpu, CPUMCTX_EXTRN_ABSOLUTELY_ALL);
586 fDoneImport = true;
587
588 DBGFR3Info(pVM->pUVM, "cpumguest", NULL, pHlp);
589 DBGFR3Info(pVM->pUVM, "cpumguestinstr", NULL, pHlp);
590 DBGFR3Info(pVM->pUVM, "cpumguesthwvirt", NULL, pHlp);
591 break;
592 }
593
594 /*
595 * For some problems (e.g. VERR_INVALID_STATE in VMMR0.cpp), there could be
596 * additional details in the assertion messages.
597 */
598 default:
599 {
600 const char *pszMsg1 = VMMR3GetRZAssertMsg1(pVM);
601 while (pszMsg1 && *pszMsg1 == '\n')
602 pszMsg1++;
603 if (pszMsg1 && *pszMsg1 != '\0')
604 pHlp->pfnPrintf(pHlp, "AssertMsg1: %s\n", pszMsg1);
605
606 const char *pszMsg2 = VMMR3GetRZAssertMsg2(pVM);
607 while (pszMsg2 && *pszMsg2 == '\n')
608 pszMsg2++;
609 if (pszMsg2 && *pszMsg2 != '\0')
610 pHlp->pfnPrintf(pHlp, "AssertMsg2: %s\n", pszMsg2);
611 break;
612 }
613
614 } /* switch (rcErr) */
615 Hlp.fRecSummary = false;
616
617
618 /*
619 * Generic info dumper loop.
620 */
621 if (!fDoneImport)
622 CPUMImportGuestStateOnDemand(pVCpu, CPUMCTX_EXTRN_ABSOLUTELY_ALL);
623 static struct
624 {
625 const char *pszInfo;
626 const char *pszArgs;
627 } const aInfo[] =
628 {
629 { "mappings", NULL },
630 { "hma", NULL },
631 { "cpumguest", "verbose" },
632 { "cpumguesthwvirt", "verbose" },
633 { "cpumguestinstr", "verbose" },
634 { "cpumhyper", "verbose" },
635 { "cpumhost", "verbose" },
636 { "mode", "all" },
637 { "cpuid", "verbose" },
638 { "handlers", "phys virt hyper stats" },
639 { "timers", NULL },
640 { "activetimers", NULL },
641 };
642 for (unsigned i = 0; i < RT_ELEMENTS(aInfo); i++)
643 {
644 if (fDoneHyper && !strcmp(aInfo[i].pszInfo, "cpumhyper"))
645 continue;
646 pHlp->pfnPrintf(pHlp,
647 "!!\n"
648 "!! {%s, %s}\n"
649 "!!\n",
650 aInfo[i].pszInfo, aInfo[i].pszArgs);
651 DBGFR3Info(pVM->pUVM, aInfo[i].pszInfo, aInfo[i].pszArgs, pHlp);
652 }
653
654 /* All other info items */
655 DBGFR3InfoMulti(pVM,
656 "*",
657 "mappings|hma|cpum|cpumguest|cpumguesthwvirt|cpumguestinstr|cpumhyper|cpumhost|mode|cpuid"
658 "|pgmpd|pgmcr3|timers|activetimers|handlers|help|exithistory",
659 "!!\n"
660 "!! {%s}\n"
661 "!!\n",
662 pHlp);
663
664
665 /* done */
666 pHlp->pfnPrintf(pHlp,
667 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
668
669
670 /*
671 * Repeat the summary to stderr so we don't have to scroll half a mile up.
672 */
673 vmmR3FatalDumpInfoHlpFlushStdErr(&Hlp);
674 if (Hlp.szSummary[0])
675 RTStrmPrintf(g_pStdErr,
676 "%s\n"
677 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",
678 Hlp.szSummary);
679
680 /*
681 * Delete the output instance (flushing and restoring of flags).
682 */
683 vmmR3FatalDumpInfoHlpDelete(&Hlp);
684
685 /*
686 * Rendezvous with the other EMTs and clear the VM_FF_CHECK_VM_STATE so we can
687 * stop burning CPU cycles.
688 */
689 VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmmR3FatalDumpRendezvousDoneCallback, NULL);
690}
691
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