VirtualBox

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

Last change on this file since 80309 was 80191, checked in by vboxsync, 5 years ago

VMM/r3: Refactored VMCPU enumeration in preparation that aCpus will be replaced with a pointer array. Removed two raw-mode offset members from the CPUM and CPUMCPU sub-structures. bugref:9217 bugref:9517

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