VirtualBox

Changeset 73351 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jul 25, 2018 1:02:11 PM (6 years ago)
Author:
vboxsync
Message:

VBoxGuest,VMMDev,DBGF,VM: Added bug check report to VBoxGuest/VMMDev and hooked it up to DBGF. Made DBGF remember the last reported bug check, adding an info handler for displaying it. Added VM reset counters w/ getters for use in bug check reporting.

Location:
trunk/src/VBox/VMM
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/GIMAllHv.cpp

    r73348 r73351  
    934934                LogRel(("GIM: HyperV: Guest indicates a fatal condition! P0=%#RX64 P1=%#RX64 P2=%#RX64 P3=%#RX64 P4=%#RX64\n",
    935935                        pHv->uCrashP0Msr, pHv->uCrashP1Msr, pHv->uCrashP2Msr, pHv->uCrashP3Msr, pHv->uCrashP4Msr));
    936                 char szDetails[512];
    937                 DBGFR3FormatBugCheck(pVM->pUVM, szDetails, sizeof(szDetails), pHv->uCrashP0Msr, pHv->uCrashP1Msr,
     936                DBGFR3ReportBugCheck(pVM, pVCpu, DBGFEVENT_BSOD_MSR, pHv->uCrashP0Msr, pHv->uCrashP1Msr,
    938937                                     pHv->uCrashP2Msr, pHv->uCrashP3Msr, pHv->uCrashP4Msr);
    939                 LogRel(("%s", szDetails));
    940 
    941                 if (DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_BSOD_MSR))
    942                     DBGFEventGenericWithArgs(pVM, pVCpu, DBGFEVENT_BSOD_MSR, DBGFEVENTCTX_OTHER, 5 /*cArgs*/, pHv->uCrashP0Msr,
    943                                              pHv->uCrashP1Msr, pHv->uCrashP2Msr, pHv->uCrashP3Msr, pHv->uCrashP4Msr);
    944938                /* (Do not try pass VINF_EM_DBG_EVENT, doesn't work from here!) */
    945939            }
  • trunk/src/VBox/VMM/VMMAll/VMAll.cpp

    r69111 r73351  
    391391}
    392392
     393
     394/**
     395 * Gets the total reset count.
     396 *
     397 * @returns Reset count. UINT32_MAX if @a pVM is invalid.
     398 * @param   pVM         The VM handle.
     399 */
     400VMMDECL(uint32_t) VMGetResetCount(PVM pVM)
     401{
     402    VM_ASSERT_VALID_EXT_RETURN(pVM, UINT32_MAX);
     403    return pVM->vm.s.cResets;
     404}
     405
     406
     407/**
     408 * Gets the soft reset count.
     409 *
     410 * @returns Soft reset count. UINT32_MAX if @a pVM is invalid.
     411 * @param   pVM         The VM handle.
     412 */
     413VMMDECL(uint32_t) VMGetSoftResetCount(PVM pVM)
     414{
     415    VM_ASSERT_VALID_EXT_RETURN(pVM, UINT32_MAX);
     416    return pVM->vm.s.cSoftResets;
     417}
     418
     419
     420/**
     421 * Gets the hard reset count.
     422 *
     423 * @returns Hard reset count. UINT32_MAX if @a pVM is invalid.
     424 * @param   pVM         The VM handle.
     425 */
     426VMMDECL(uint32_t) VMGetHardResetCount(PVM pVM)
     427{
     428    VM_ASSERT_VALID_EXT_RETURN(pVM, UINT32_MAX);
     429    return pVM->vm.s.cHardResets;
     430}
     431
  • trunk/src/VBox/VMM/VMMR3/DBGF.cpp

    r72493 r73351  
    186186                            if (RT_SUCCESS(rc))
    187187                            {
    188                                 return VINF_SUCCESS;
     188                                rc = dbgfR3BugCheckInit(pVM);
     189                                if (RT_SUCCESS(rc))
     190                                {
     191                                    return VINF_SUCCESS;
     192                                }
     193                                dbgfR3PlugInTerm(pUVM);
    189194                            }
    190195                            dbgfR3OSTerm(pUVM);
  • trunk/src/VBox/VMM/VMMR3/DBGFR3BugCheck.cpp

    r73348 r73351  
    2323#include <VBox/vmm/dbgf.h>
    2424#include <VBox/vmm/mm.h>
     25#include <VBox/vmm/tm.h>
    2526#include "DBGFInternal.h"
     27#include <VBox/vmm/vm.h>
    2628#include <VBox/vmm/uvm.h>
    2729#include <VBox/err.h>
     
    2931#include <iprt/assert.h>
    3032#include <iprt/ctype.h>
     33
     34
     35/*********************************************************************************************************************************
     36*   Internal Functions                                                                                                           *
     37*********************************************************************************************************************************/
     38static FNDBGFHANDLERINT dbgfR3BugCheckInfo;
     39
     40
     41/**
     42 * Initializes the bug check state and registers the info callback.
     43 *
     44 * No termination function needed.
     45 *
     46 * @returns VBox status code.
     47 * @param   pVM         The VM handle.
     48 */
     49int dbgfR3BugCheckInit(PVM pVM)
     50{
     51    pVM->dbgf.s.BugCheck.idCpu    = NIL_VMCPUID;
     52    pVM->dbgf.s.BugCheck.enmEvent = DBGFEVENT_END;
     53
     54    return DBGFR3InfoRegisterInternal(pVM, "bugcheck",
     55                                      "Show bugcheck info.  Can specify bug check code and parameters to lookup info.",
     56                                      dbgfR3BugCheckInfo);
     57}
    3158
    3259
     
    5178}
    5279
     80
    5381/**
    5482 * Formats a symbol for DBGFR3FormatBugCheck.
     
    6593            RTStrPrintf(pszSymbol, cchSymbol, "%s%s", pszPrefix, pSym->szName);
    6694        else if (offDisp > 0)
    67             RTStrPrintf(pszSymbol, cchSymbol, "%s%s + %RGv", pszPrefix, pSym->szName, offDisp);
     95            RTStrPrintf(pszSymbol, cchSymbol, "%s%s + %#RX64", pszPrefix, pSym->szName, (uint64_t)offDisp);
    6896        else
    69             RTStrPrintf(pszSymbol, cchSymbol, "%s%s - %RGv", pszPrefix, pSym->szName, -offDisp);
     97            RTStrPrintf(pszSymbol, cchSymbol, "%s%s - %#RX64", pszPrefix, pSym->szName, (uint64_t)-offDisp);
    7098        RTDbgSymbolFree(pSym);
    7199    }
     
    85113 * @param   pszDetails          The output buffer.
    86114 * @param   cbDetails           The size of the output buffer.
    87  * @param   uP0                 The bugheck code.
     115 * @param   uBugCheck           The bugheck code.
    88116 * @param   uP1                 Bug check parameter 1.
    89117 * @param   uP2                 Bug check parameter 2.
     
    92120 */
    93121VMMR3DECL(int) DBGFR3FormatBugCheck(PUVM pUVM, char *pszDetails, size_t cbDetails,
    94                                     uint64_t uP0, uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4)
     122                                    uint64_t uBugCheck, uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4)
    95123{
    96124    /*
     
    98126     */
    99127    size_t cchUsed = RTStrPrintf(pszDetails, cbDetails,
    100                                  "BugCheck %RX64 {%RX64, %RX64, %RX64, %RX64}\n", uP0, uP1, uP2, uP3, uP4);
     128                                 "BugCheck %RX64 {%RX64, %RX64, %RX64, %RX64}\n", uBugCheck, uP1, uP2, uP3, uP4);
    101129    if (cchUsed >= cbDetails)
    102130        return VINF_BUFFER_OVERFLOW;
     
    108136     */
    109137    char szSym[512];
    110     switch (uP0)
     138    switch (uBugCheck)
    111139    {
    112140        case 0x00000001: cchUsed = RTStrPrintf(pszDetails, cbDetails, "APC_INDEX_MISMATCH\n"); break;
     
    220248                                  "P3: %016RX64 - %s\n"
    221249                                  "P4: %016RX64 - reserved\n",
    222                                   uP0 & 0x10000000 ? "_M" : "", uP1, uP2, uP3, uP3 & RT_BIT_64(0) ? "write" : "read", uP4);
     250                                  uBugCheck & 0x10000000 ? "_M" : "", uP1, uP2, uP3, uP3 & RT_BIT_64(0) ? "write" : "read", uP4);
    223251            break;
    224252        case 0x00000051: cchUsed = RTStrPrintf(pszDetails, cbDetails, "REGISTRY_ERROR\n"); break;
     
    274302                                  "P3: %016RX64 - Xcpt address\n"
    275303                                  "P4: %016RX64 - Context address\n",
    276                                   uP0 & 0x10000000 ? "_M" : "", uP1, dbgfR3GetNtStatusName((uint32_t)uP1),
     304                                  uBugCheck & 0x10000000 ? "_M" : "", uP1, dbgfR3GetNtStatusName((uint32_t)uP1),
    277305                                  uP2, dbgfR3FormatSymbol(pUVM, szSym, sizeof(szSym), ": ", uP2),
    278306                                  uP3, uP4);
     
    286314                                  "P3: %016RX64 - reserved\n"
    287315                                  "P4: %016RX64 - reserved\n",
    288                                   uP0 & 0x10000000 ? "_M" : "", uP1, uP2, uP3, uP4);
     316                                  uBugCheck & 0x10000000 ? "_M" : "", uP1, uP2, uP3, uP4);
    289317            break;
    290318        case 0x00000080: cchUsed = RTStrPrintf(pszDetails, cbDetails, "NMI_HARDWARE_FAILURE\n"); break;
     
    304332                                  "P3: %016RX64 - Trap frame address\n"
    305333                                  "P4: %016RX64 - reserved\n",
    306                                   uP0 & 0x10000000 ? "_M" : "", uP1, dbgfR3GetNtStatusName((uint32_t)uP1),
     334                                  uBugCheck & 0x10000000 ? "_M" : "", uP1, dbgfR3GetNtStatusName((uint32_t)uP1),
    307335                                  uP2, dbgfR3FormatSymbol(pUVM, szSym, sizeof(szSym), ": ", uP2),
    308336                                  uP3, uP4);
     
    760788}
    761789
     790
     791/**
     792 * Report a bug check.
     793 *
     794 * @returns
     795 * @param   pVM             The cross context VM structure.
     796 * @param   pVCpu           The cross context per virtual CPU structure.
     797 * @param   enmEvent        The kind of BSOD event this is.
     798 * @param   uBugCheck       The bug check number.
     799 * @param   uP1             The bug check parameter \#1.
     800 * @param   uP2             The bug check parameter \#2.
     801 * @param   uP3             The bug check parameter \#3.
     802 * @param   uP4             The bug check parameter \#4.
     803 */
     804VMMR3DECL(VBOXSTRICTRC) DBGFR3ReportBugCheck(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, uint64_t uBugCheck,
     805                                             uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4)
     806{
     807    /*
     808     * Be careful.
     809     */
     810    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
     811    VMCPU_ASSERT_EMT_RETURN(pVCpu, VERR_INVALID_VMCPU_HANDLE);
     812    const char *pszSource;
     813    switch (enmEvent)
     814    {
     815        case DBGFEVENT_BSOD_MSR:        pszSource = "GIMHv"; break;
     816        case DBGFEVENT_BSOD_EFI:        pszSource = "EFI"; break;
     817        case DBGFEVENT_BSOD_VMMDEV:     pszSource = "VMMDev"; break;
     818        default:
     819            AssertMsgFailedReturn(("enmEvent=%d\n", enmEvent), VERR_INVALID_PARAMETER);
     820    }
     821
     822    /*
     823     * Note it down.
     824     */
     825    pVM->dbgf.s.BugCheck.enmEvent        = enmEvent;
     826    pVM->dbgf.s.BugCheck.uBugCheck       = uBugCheck;
     827    pVM->dbgf.s.BugCheck.auParameters[0] = uP1;
     828    pVM->dbgf.s.BugCheck.auParameters[1] = uP2;
     829    pVM->dbgf.s.BugCheck.auParameters[2] = uP3;
     830    pVM->dbgf.s.BugCheck.auParameters[3] = uP4;
     831    pVM->dbgf.s.BugCheck.idCpu           = pVCpu->idCpu;
     832    pVM->dbgf.s.BugCheck.uTimestamp      = TMVirtualGet(pVM);
     833    pVM->dbgf.s.BugCheck.uResetNo        = VMGetResetCount(pVM);
     834
     835    /*
     836     * Log the details.
     837     */
     838    char szDetails[2048];
     839    DBGFR3FormatBugCheck(pVM->pUVM, szDetails, sizeof(szDetails), uBugCheck, uP1, uP2, uP3, uP4);
     840    LogRel(("%s: %s", pszSource, szDetails));
     841
     842    /*
     843     * Raise debugger event.
     844     */
     845    VBOXSTRICTRC rc = VINF_SUCCESS;
     846    if (DBGF_IS_EVENT_ENABLED(pVM, enmEvent))
     847        rc = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent, DBGFEVENTCTX_OTHER, 5 /*cArgs*/, uBugCheck, uP1, uP2, uP3, uP4);
     848
     849    /*
     850     * Take actions.
     851     */
     852    /** @todo Take actions on BSOD, like notifying main or stopping the VM...
     853     * For testing it makes little sense to continue after a BSOD. */
     854    return rc;
     855}
     856
     857
     858/**
     859 * @callback_method_impl{FNDBGFHANDLERINT, bugcheck}
     860 */
     861static DECLCALLBACK(void) dbgfR3BugCheckInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     862{
     863    char szDetails[2048];
     864
     865    /*
     866     * Any arguments for bug check formatting?
     867     */
     868    if (pszArgs && *pszArgs)
     869        pszArgs = RTStrStripL(pszArgs);
     870    if (pszArgs && *pszArgs)
     871    {
     872        uint64_t auData[5] = { 0, 0, 0, 0, 0 };
     873        unsigned iData = 0;
     874        do
     875        {
     876            /* Find the next hex digit  */
     877            char ch;
     878            while ((ch = *pszArgs) != '\0' && !RT_C_IS_XDIGIT(ch))
     879                pszArgs++;
     880            if (ch == '\0')
     881                break;
     882
     883            /* Extract the number. */
     884            char *pszNext = (char *)pszArgs + 1;
     885            RTStrToUInt64Ex(pszArgs, &pszNext, 16, &auData[iData]);
     886
     887            /* Advance. */
     888            pszArgs = pszNext;
     889            iData++;
     890        } while (iData < RT_ELEMENTS(auData) && *pszArgs);
     891
     892        /* Format it. */
     893        DBGFR3FormatBugCheck(pVM->pUVM, szDetails, sizeof(szDetails), auData[0], auData[1], auData[2], auData[3], auData[4]);
     894        pHlp->pfnPrintf(pHlp, "%s", szDetails);
     895    }
     896    /*
     897     * Format what's been reported (if any).
     898     */
     899    else if (pVM->dbgf.s.BugCheck.enmEvent != DBGFEVENT_END)
     900    {
     901        DBGFR3FormatBugCheck(pVM->pUVM, szDetails, sizeof(szDetails), pVM->dbgf.s.BugCheck.uBugCheck,
     902                             pVM->dbgf.s.BugCheck.auParameters[0], pVM->dbgf.s.BugCheck.auParameters[1],
     903                             pVM->dbgf.s.BugCheck.auParameters[2], pVM->dbgf.s.BugCheck.auParameters[3]);
     904        const char *pszSource  = pVM->dbgf.s.BugCheck.enmEvent == DBGFEVENT_BSOD_MSR    ? "GIMHv"
     905                               : pVM->dbgf.s.BugCheck.enmEvent == DBGFEVENT_BSOD_EFI    ? "EFI"
     906                               : pVM->dbgf.s.BugCheck.enmEvent == DBGFEVENT_BSOD_VMMDEV ? "VMMDev" : "<unknown>";
     907        uint32_t const uFreq   = TMVirtualGetFreq(pVM);
     908        uint64_t const cSecs   = pVM->dbgf.s.BugCheck.uTimestamp / uFreq;
     909        uint32_t const cMillis = (pVM->dbgf.s.BugCheck.uTimestamp - cSecs * uFreq) * 1000 / uFreq;
     910        pHlp->pfnPrintf(pHlp, "BugCheck on CPU #%u after %RU64.%03u s VM uptime, %u resets ago (src: %s)\n%s",
     911                        pVM->dbgf.s.BugCheck.idCpu, cSecs, cMillis,  VMGetResetCount(pVM) - pVM->dbgf.s.BugCheck.uResetNo,
     912                        pszSource, szDetails);
     913    }
     914    else
     915        pHlp->pfnPrintf(pHlp, "No bug check reported.\n");
     916}
     917
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r73097 r73351  
    27542754        if (RT_FAILURE(rc))
    27552755            return rc;
     2756        pVM->vm.s.cResets++;
     2757        pVM->vm.s.cSoftResets++;
    27562758    }
    27572759
     
    28442846        if (RT_FAILURE(rc))
    28452847            return rc;
     2848        pVM->vm.s.cResets++;
     2849        pVM->vm.s.cHardResets++;
    28462850    }
    28472851
  • trunk/src/VBox/VMM/include/DBGFInternal.h

    r69474 r73351  
    300300    /** INT3 breakpoint search optimizations. */
    301301    DBGFBPSEARCHOPT             Int3;
     302
     303    /**
     304     * Bug check data.
     305     * @note This will not be reset on reset.
     306     */
     307    struct
     308    {
     309        /** The ID of the CPU reporting it. */
     310        VMCPUID                 idCpu;
     311        /** The event associated with the bug check (gives source).
     312         * This is set to DBGFEVENT_END if no BSOD data here. */
     313        DBGFEVENTTYPE           enmEvent;
     314        /** The total reset count at the time (VMGetResetCount). */
     315        uint32_t                uResetNo;
     316        /** Explicit padding. */
     317        uint32_t                uPadding;
     318        /** When it was reported (TMVirtualGet). */
     319        uint64_t                uTimestamp;
     320        /** The bug check number.
     321         * @note This is really just 32-bit wide, see KeBugCheckEx.  */
     322        uint64_t                uBugCheck;
     323        /** The bug check parameters. */
     324        uint64_t                auParameters[4];
     325    } BugCheck;
    302326} DBGF;
    303327AssertCompileMemberAlignment(DBGF, DbgEvent, 8);
     
    490514int  dbgfR3PlugInInit(PUVM pUVM);
    491515void dbgfR3PlugInTerm(PUVM pUVM);
     516int  dbgfR3BugCheckInit(PVM pVM);
    492517
    493518
  • trunk/src/VBox/VMM/include/VMInternal.h

    r69474 r73351  
    166166    /** The VM should power off instead of reset. */
    167167    bool                            fPowerOffInsteadOfReset;
     168    /** Reset counter (soft + hard). */
     169    uint32_t                        cResets;
     170    /** Hard reset counter. */
     171    uint32_t                        cHardResets;
     172    /** Soft reset counter. */
     173    uint32_t                        cSoftResets;
    168174} VMINT;
    169175/** Pointer to the VM Internal Data (part of the VM structure). */
Note: See TracChangeset for help on using the changeset viewer.

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