VirtualBox

Changeset 72555 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Jun 14, 2018 9:28:31 PM (6 years ago)
Author:
vboxsync
Message:

EM,NEM,HM: Started on generic exit history, only hooked up to NEM/win. bugref:9044

Location:
trunk/src/VBox/VMM/VMMR3
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/EMR3Dbg.cpp

    r69111 r72555  
    2222#define LOG_GROUP LOG_GROUP_EM
    2323#include <VBox/vmm/em.h>
     24#include <VBox/vmm/hm.h>
     25#include <VBox/vmm/nem.h>
    2426#include <VBox/dbg.h>
    2527#include "EMInternal.h"
     28#include <VBox/vmm/vm.h>
     29#include <iprt/string.h>
     30#include <iprt/ctype.h>
    2631
    2732
     
    6671};
    6772
     73VMM_INT_DECL(const char *) EMR3GetExitTypeName(uint32_t uExitType)
     74{
     75    switch ((EMEXITTYPE)uExitType)
     76    {
     77        case EMEXITTYPE_INVALID:            return "invalid";
     78        case EMEXITTYPE_IO_PORT_READ:       return "I/O port read";
     79        case EMEXITTYPE_IO_PORT_WRITE:      return "I/O port write";
     80        case EMEXITTYPE_IO_PORT_STR_READ:   return "I/O port string read";
     81        case EMEXITTYPE_IO_PORT_STR_WRITE:  return "I/O port string write";
     82        case EMEXITTYPE_MMIO_READ:          return "MMIO read";
     83        case EMEXITTYPE_MMIO_WRITE:         return "MMIO write";
     84        case EMEXITTYPE_MSR_READ:           return "MSR read";
     85        case EMEXITTYPE_MSR_WRITE:          return "MSR write";
     86        case EMEXITTYPE_CPUID:              return "CPUID";
     87    }
     88    return NULL;
     89}
     90
     91/**
     92 * Translates flags+type into an exit name.
     93 *
     94 * @returns Exit name.
     95 * @param   uFlagsAndType   The exit to name.
     96 * @param   pszFallback     Buffer for formatting a numeric fallback.
     97 * @param   cbFallback      Size of fallback buffer.
     98 */
     99static const char *emR3HistoryGetExitName(uint32_t uFlagsAndType, char *pszFallback, size_t cbFallback)
     100{
     101    const char *pszExitName;
     102    switch (uFlagsAndType & EMEXIT_F_KIND_MASK)
     103    {
     104        case EMEXIT_F_KIND_EM:
     105            pszExitName = EMR3GetExitTypeName(uFlagsAndType & EMEXIT_F_TYPE_MASK);
     106            break;
     107
     108        case EMEXIT_F_KIND_VMX:
     109            pszExitName = HMR3GetVmxExitName( uFlagsAndType & EMEXIT_F_TYPE_MASK);
     110            break;
     111
     112        case EMEXIT_F_KIND_SVM:
     113            pszExitName = HMR3GetSvmExitName( uFlagsAndType & EMEXIT_F_TYPE_MASK);
     114            break;
     115
     116        case EMEXIT_F_KIND_NEM:
     117            pszExitName = NEMR3GetExitName(   uFlagsAndType & EMEXIT_F_TYPE_MASK);
     118            break;
     119
     120        case EMEXIT_F_KIND_XCPT:
     121            switch (uFlagsAndType & EMEXIT_F_TYPE_MASK)
     122            {
     123                case X86_XCPT_DE:               return "Xcpt #DE";
     124                case X86_XCPT_DB:               return "Xcpt #DB";
     125                case X86_XCPT_NMI:              return "Xcpt #NMI";
     126                case X86_XCPT_BP:               return "Xcpt #BP";
     127                case X86_XCPT_OF:               return "Xcpt #OF";
     128                case X86_XCPT_BR:               return "Xcpt #BR";
     129                case X86_XCPT_UD:               return "Xcpt #UD";
     130                case X86_XCPT_NM:               return "Xcpt #NM";
     131                case X86_XCPT_DF:               return "Xcpt #DF";
     132                case X86_XCPT_CO_SEG_OVERRUN:   return "Xcpt #CO_SEG_OVERRUN";
     133                case X86_XCPT_TS:               return "Xcpt #TS";
     134                case X86_XCPT_NP:               return "Xcpt #NP";
     135                case X86_XCPT_SS:               return "Xcpt #SS";
     136                case X86_XCPT_GP:               return "Xcpt #GP";
     137                case X86_XCPT_PF:               return "Xcpt #PF";
     138                case X86_XCPT_MF:               return "Xcpt #MF";
     139                case X86_XCPT_AC:               return "Xcpt #AC";
     140                case X86_XCPT_MC:               return "Xcpt #MC";
     141                case X86_XCPT_XF:               return "Xcpt #XF";
     142                case X86_XCPT_VE:               return "Xcpt #VE";
     143                case X86_XCPT_SX:               return "Xcpt #SX";
     144                default:
     145                    pszExitName = NULL;
     146                    break;
     147            }
     148            break;
     149
     150        default:
     151            AssertFailed();
     152            pszExitName = NULL;
     153            break;
     154    }
     155    if (pszExitName)
     156        return pszExitName;
     157    RTStrPrintf(pszFallback, cbFallback, "%#06x", uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_TYPE_MASK));
     158    return pszFallback;
     159}
     160
     161
     162/**
     163 * Displays the VM-exit history.
     164 *
     165 * @param   pVM         The cross context VM structure.
     166 * @param   pHlp        The info helper functions.
     167 * @param   pszArgs     Arguments, ignored.
     168 */
     169static DECLCALLBACK(void) emR3InfoExitHistory(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     170{
     171    NOREF(pszArgs);
     172
     173    /*
     174     * Figure out target cpu and parse arguments.
     175     */
     176    PVMCPU   pVCpu    = VMMGetCpu(pVM);
     177    if (!pVCpu)
     178        pVCpu = &pVM->aCpus[0];
     179    bool     fReverse = true;
     180    uint32_t cLeft    = RT_ELEMENTS(pVCpu->em.s.aExitHistory);
     181
     182    while (pszArgs && *pszArgs)
     183    {
     184        pszArgs = RTStrStripL(pszArgs);
     185        if (!*pszArgs)
     186            break;
     187        if (RT_C_IS_DIGIT(*pszArgs))
     188        {
     189            /* The number to dump. */
     190            uint32_t uValue = cLeft;
     191            RTStrToUInt32Ex(pszArgs, (char **)&pszArgs, 0, &uValue);
     192            if (uValue > 0)
     193                cLeft = RT_MIN(uValue, RT_ELEMENTS(pVCpu->em.s.aExitHistory));
     194        }
     195        else if (RTStrCmp(pszArgs, "reverse") == 0)
     196        {
     197            pszArgs += 7;
     198            fReverse = true;
     199        }
     200        else if (RTStrCmp(pszArgs, "ascending") == 0)
     201        {
     202            pszArgs += 9;
     203            fReverse = false;
     204        }
     205        else if (RTStrCmp(pszArgs, "asc") == 0)
     206        {
     207            pszArgs += 3;
     208            fReverse = false;
     209        }
     210        else
     211        {
     212            const char *pszStart = pszArgs;
     213            while (*pszArgs && !RT_C_IS_SPACE(*pszArgs))
     214                pszArgs++;
     215            pHlp->pfnPrintf(pHlp, "Unknown option: %.*s\n", pszArgs - pszStart, pszArgs);
     216        }
     217    }
     218
     219    /*
     220     * Do the job.
     221     */
     222    uint64_t idx = pVCpu->em.s.iNextExit;
     223    if (idx == 0)
     224        pHlp->pfnPrintf(pHlp, "CPU[%u]: VM-exit history: empty\n", pVCpu->idCpu);
     225    else
     226    {
     227        /*
     228         * Print header.
     229         */
     230        pHlp->pfnPrintf(pHlp, "CPU[%u]: VM-exit history:\n", pVCpu->idCpu);
     231        pHlp->pfnPrintf(pHlp, "   Exit No.:      TSC timestamp / delta    Flat RIP         Exit   Name\n");
     232
     233        /*
     234         * Adjust bounds if ascending order.
     235         */
     236        if (!fReverse)
     237        {
     238            if (idx > cLeft)
     239                idx -= cLeft;
     240            else
     241            {
     242                cLeft = idx;
     243                idx = 0;
     244            }
     245        }
     246
     247        /*
     248         * Print the entries.
     249         */
     250        uint64_t uPrevTimestamp = 0;
     251        do
     252        {
     253            if (fReverse)
     254                idx -= 1;
     255            PCEMEXITENTRY const pEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)idx & 0xff];
     256            if (!fReverse)
     257                idx += 1;
     258
     259            /* Get the exit name. */
     260            char        szExitName[16];
     261            const char *pszExitName = emR3HistoryGetExitName(pEntry->uFlagsAndType, szExitName, sizeof(szExitName));
     262
     263            int64_t offDelta = uPrevTimestamp != 0 && pEntry->uTimestamp != 0 ? pEntry->uTimestamp - uPrevTimestamp : 0;
     264            uPrevTimestamp = pEntry->uTimestamp;
     265
     266            if (pEntry->idxSlot == UINT32_MAX)
     267                pHlp->pfnPrintf(pHlp, " %10RU64: %#018RX64/%+-9RI64 %016RX64 %#06x %s\n",
     268                                idx, pEntry->uTimestamp, offDelta, pEntry->uFlatPC, pEntry->uFlagsAndType, pszExitName);
     269            else
     270            {
     271                /** @todo more on this later */
     272                pHlp->pfnPrintf(pHlp, " %10RU64: %#018RX64/%+-9RI64 %016RX64 %#06x %s slot=%#x\n",
     273                                idx, pEntry->uTimestamp, offDelta, pEntry->uFlatPC, pEntry->uFlagsAndType, pszExitName,
     274                                pEntry->idxSlot);
     275            }
     276        } while (--cLeft > 0 && idx > 0);
     277    }
     278}
     279
    68280
    69281int emR3InitDbg(PVM pVM)
    70282{
    71     RT_NOREF_PV(pVM);
    72     int rc = VINF_SUCCESS;
     283    /*
     284     * Register info dumpers.
     285     */
     286    int rc = DBGFR3InfoRegisterInternalEx(pVM, "exits", "Dumps the VM-exit history.",
     287                                          emR3InfoExitHistory, DBGFINFO_FLAGS_ALL_EMTS);
     288    AssertLogRelRCReturn(rc, rc);
     289
    73290#ifdef VBOX_WITH_DEBUGGER
     291    /*
     292     * Register debugger commands.
     293     */
    74294    rc = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
    75     AssertLogRelRC(rc);
     295    AssertLogRelRCReturn(rc, rc);
    76296#endif
    77     return rc;
    78 }
    79 
     297
     298    return VINF_SUCCESS;
     299}
     300
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r72208 r72555  
    36463646
    36473647/**
     3648 * Gets the name of a VT-x exit code.
     3649 *
     3650 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
     3651 * @param   uExit               The VT-x exit to name.
     3652 */
     3653VMMR3DECL(const char *) HMR3GetVmxExitName(uint32_t uExit)
     3654{
     3655    if (uExit < RT_ELEMENTS(g_apszVTxExitReasons))
     3656        return g_apszVTxExitReasons[uExit];
     3657    return NULL;
     3658}
     3659
     3660
     3661/**
     3662 * Gets the name of an AMD-V exit code.
     3663 *
     3664 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
     3665 * @param   uExit               The AMD-V exit to name.
     3666 */
     3667VMMR3DECL(const char *) HMR3GetSvmExitName(uint32_t uExit)
     3668{
     3669    if (uExit < RT_ELEMENTS(g_apszAmdVExitReasons))
     3670        return g_apszAmdVExitReasons[uExit];
     3671    return hmSvmGetSpecialExitReasonDesc(uExit);
     3672}
     3673
     3674
     3675/**
    36483676 * Displays the guest VM-exit history.
    36493677 *
  • trunk/src/VBox/VMM/VMMR3/NEMR3.cpp

    r72526 r72555  
    327327
    328328
     329/**
     330 * Gets the name of a generic NEM exit code.
     331 *
     332 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
     333 * @param   uExit               The NEM exit to name.
     334 */
     335VMMR3DECL(const char *) NEMR3GetExitName(uint32_t uExit)
     336{
     337    switch ((NEMEXITTYPE)uExit)
     338    {
     339        case NEMEXITTYPE_UNRECOVERABLE_EXCEPTION:       return "NEM unrecoverable exception";
     340        case NEMEXITTYPE_INVALID_VP_REGISTER_VALUE:     return "NEM invalid vp register value";
     341        case NEMEXITTYPE_INTTERRUPT_WINDOW:             return "NEM interrupt window";
     342        case NEMEXITTYPE_HALT:                          return "NEM halt";
     343        case NEMEXITTYPE_XCPT_UD:                       return "NEM #UD";
     344        case NEMEXITTYPE_XCPT_DB:                       return "NEM #DB";
     345        case NEMEXITTYPE_XCPT_BP:                       return "NEM #BP";
     346        case NEMEXITTYPE_CANCELED:                      return "NEM canceled";
     347    }
     348
     349    return NULL;
     350}
     351
    329352
    330353VMMR3_INT_DECL(VBOXSTRICTRC) NEMR3RunGC(PVM pVM, PVMCPU pVCpu)
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r72546 r72555  
    14451445         */
    14461446
    1447 #if 1 && defined(DEBUG_bird)
     1447#if 0 && defined(DEBUG_bird)
    14481448        /*
    14491449         * Poke and probe a little.
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