VirtualBox

Changeset 72555 in vbox for trunk/src


Ignore:
Timestamp:
Jun 14, 2018 9:28:31 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123048
Message:

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

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

Legend:

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

    r72490 r72555  
    401401
    402402#endif /* IN_RING3 */
     403
     404
     405/**
     406 * Adds an exit to the history for this CPU.
     407 *
     408 * @returns Suggested action to take.
     409 * @param   pVCpu           The corss context virtual CPU structure.
     410 * @param   uFlagsAndType   Combined flags and type (see EMEXIT_MAKE_FLAGS_AND_TYPE).
     411 * @param   uFlatPC         The flattened program counter (RIP).
     412 * @param   uTimestamp      The TSC value for the exit, 0 if not available.
     413 * @thread  EMT(pVCpu)
     414 */
     415VMM_INT_DECL(EMEXITACTION) EMHistoryAddExit(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp)
     416{
     417    VMCPU_ASSERT_EMT(pVCpu);
     418
     419    /*
     420     * Add the exit history entry.
     421     */
     422    AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256);
     423    PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)(pVCpu->em.s.iNextExit++) & 0xff];
     424    pHistEntry->uFlatPC       = uFlatPC;
     425    pHistEntry->uTimestamp    = uTimestamp;
     426    pHistEntry->uFlagsAndType = uFlagsAndType;
     427    pHistEntry->idxSlot       = UINT32_MAX;
     428
     429    /*
     430     * If common exit type, we will insert/update the exit into the shared hash table.
     431     */
     432    if ((uFlagsAndType & EMEXIT_F_KIND_MASK) == EMEXIT_F_KIND_EM)
     433    {
     434        /** @todo later */
     435    }
     436
     437    return EMEXITACTION_NORMAL;
     438}
     439
    403440
    404441/**
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r72551 r72555  
    19091909     * Emulate the memory access, either access handler or special memory.
    19101910     */
     1911    EMHistoryAddExit(pVCpu,
     1912                       pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     1913                     ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE)
     1914                     : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ),
     1915                     pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
    19111916    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
    19121917    VBOXSTRICTRC rcStrict;
     
    19982003     * Emulate the memory access, either access handler or special memory.
    19992004     */
     2005    EMHistoryAddExit(pVCpu,
     2006                       pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite
     2007                     ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_WRITE)
     2008                     : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MMIO_READ),
     2009                     pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2010
    20002011    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
    20012012    rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM | CPUMCTX_EXTRN_DS | CPUMCTX_EXTRN_ES);
     
    20522063         * Simple port I/O.
    20532064         */
     2065        EMHistoryAddExit(pVCpu,
     2066                           pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     2067                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE)
     2068                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ),
     2069                         pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2070
    20542071        static uint32_t const s_fAndMask[8] =
    20552072        {   UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX,   UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX   };
     
    21252142         * the opcode bytes for possible evil prefixes.
    21262143         */
     2144        EMHistoryAddExit(pVCpu,
     2145                           pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     2146                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE)
     2147                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ),
     2148                         pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2149
    21272150        nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
    21282151        pCtx->fExtrn &= ~(  CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI
     
    21962219         * Simple port I/O.
    21972220         */
     2221        EMHistoryAddExit(pVCpu,
     2222                           pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite
     2223                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_WRITE)
     2224                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_READ),
     2225                         pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2226
    21982227        static uint32_t const s_fAndMask[8] =
    21992228        {   UINT32_MAX, UINT32_C(0xff), UINT32_C(0xffff), UINT32_MAX,   UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX   };
     
    22492278         * the opcode bytes for possible evil prefixes.
    22502279         */
     2280        EMHistoryAddExit(pVCpu,
     2281                           pExit->MemoryAccess.AccessInfo.AccessType == WHvMemoryAccessWrite
     2282                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_WRITE)
     2283                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_IO_PORT_STR_READ),
     2284                         pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2285
    22512286        nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
    22522287        pCtx->fExtrn &= ~(  CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDI | CPUMCTX_EXTRN_RSI
     
    23202355     * Just copy the state we've got and handle it in the loop for now.
    23212356     */
     2357    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_INTTERRUPT_WINDOW),
     2358                     pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2359
    23222360    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, &pMsg->Header);
    23232361    Log4(("IntWinExit/%u: %04x:%08RX64/%s: %u IF=%d InterruptShadow=%d\n",
     
    23542392     * Just copy the state we've got and handle it in the loop for now.
    23552393     */
     2394    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_INTTERRUPT_WINDOW),
     2395                     pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2396
    23562397    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
    23572398    Log4(("IntWinExit/%u: %04x:%08RX64/%s: %u IF=%d InterruptShadow=%d\n",
     
    23742415 * @param   pMsg            The message.
    23752416 * @param   pCtx            The register context.
     2417 * @sa      nemR3WinHandleExitCpuId
    23762418 */
    23772419NEM_TMPL_STATIC VBOXSTRICTRC nemHCWinHandleMessageCpuId(PVMCPU pVCpu, HV_X64_CPUID_INTERCEPT_MESSAGE const *pMsg, PCPUMCTX pCtx)
     
    23852427     *       function and make everyone use it.
    23862428     */
     2429    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID),
     2430                     pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2431
    23872432    /** @todo Combine implementations into IEMExecDecodedCpuId as this will
    23882433     *        only get weirder with nested VT-x and AMD-V support. */
     
    24192464 * @param   pExit           The VM exit information to handle.
    24202465 * @param   pCtx            The register context.
    2421  * @sa      nemHCWinHandleMessageInterruptWindow
     2466 * @sa      nemHCWinHandleMessageCpuId
    24222467 */
    24232468NEM_TMPL_STATIC VBOXSTRICTRC
     
    24322477     *       function and make everyone use it.
    24332478     */
     2479    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID),
     2480                     pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2481
    24342482    /** @todo Combine implementations into IEMExecDecodedCpuId as this will
    24352483     *        only get weirder with nested VT-x and AMD-V support. */
     
    24872535    if (pMsg->Header.ExecutionState.Cpl == 0)
    24882536    {
     2537        EMHistoryAddExit(pVCpu,
     2538                           pMsg->Header.InterceptAccessType == HV_INTERCEPT_ACCESS_WRITE
     2539                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE)
     2540                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ),
     2541                         pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2542
    24892543        /*
    24902544         * Get all the MSR state.  Since we're getting EFER, we also need to
     
    26132667         * get CR0, CR4 and CR3.
    26142668         */
     2669        EMHistoryAddExit(pVCpu,
     2670                           pExit->MsrAccess.AccessInfo.IsWrite
     2671                         ? EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_WRITE)
     2672                         : EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_MSR_READ),
     2673                         pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
     2674
    26152675        nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
    26162676        rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx,
     
    28732933        case X86_XCPT_UD:
    28742934            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionUd);
     2935            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_UD),
     2936                             pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
     2937
    28752938            if (nemHcWinIsInterestingUndefinedOpcode(pMsg->InstructionByteCount, pMsg->InstructionBytes,
    28762939                                                     pMsg->Header.ExecutionState.EferLma && pMsg->Header.CsSegment.Long ))
     
    28932956        case X86_XCPT_DB:
    28942957            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionDb);
     2958            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_DB),
     2959                             pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
    28952960            Log4(("XcptExit/%u: %04x:%08RX64/%s: #DB - TODO\n",
    28962961                  pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header) ));
     
    28992964        case X86_XCPT_BP:
    29002965            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionBp);
     2966            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_BP),
     2967                             pMsg->Header.Rip + pMsg->Header.CsSegment.Base, ASMReadTSC());
    29012968            Log4(("XcptExit/%u: %04x:%08RX64/%s: #BP - TODO - %u\n", pVCpu->idCpu, pMsg->Header.CsSegment.Selector,
    29022969                  pMsg->Header.Rip, nemHCWinExecStateToLogStr(&pMsg->Header), pMsg->Header.InstructionLength));
     
    29713038        case X86_XCPT_UD:
    29723039            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionUd);
     3040            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_UD),
     3041                             pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
    29733042            if (nemHcWinIsInterestingUndefinedOpcode(pExit->VpException.InstructionByteCount, pExit->VpException.InstructionBytes,
    29743043                                                     pExit->VpContext.ExecutionState.EferLma && pExit->VpContext.Cs.Long ))
     
    29943063        case X86_XCPT_DB:
    29953064            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionDb);
     3065            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_DB),
     3066                             pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
    29963067            Log4(("XcptExit/%u: %04x:%08RX64/%s: #DB - TODO\n",
    29973068                  pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext) ));
     
    30003071        case X86_XCPT_BP:
    30013072            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionBp);
     3073            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_XCPT_BP),
     3074                             pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
    30023075            Log4(("XcptExit/%u: %04x:%08RX64/%s: #BP - TODO - %u\n", pVCpu->idCpu, pExit->VpContext.Cs.Selector,
    30033076                  pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), pExit->VpContext.InstructionLength));
     
    30573130     * Let IEM decide whether this is really it.
    30583131     */
     3132    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_UNRECOVERABLE_EXCEPTION),
     3133                     pMsgHdr->Rip + pMsgHdr->CsSegment.Base, ASMReadTSC());
    30593134    nemHCWinCopyStateFromX64Header(pVCpu, pCtx, pMsgHdr);
    30603135    VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, pGVCpu, pCtx,
     
    31123187     * Let IEM decide whether this is really it.
    31133188     */
     3189    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_UNRECOVERABLE_EXCEPTION),
     3190                     pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
    31143191    nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext);
    31153192    VBOXSTRICTRC rcStrict = nemHCWinImportStateIfNeededStrict(pVCpu, NULL, pCtx,
     
    31813258            case HvMessageTypeX64Halt:
    31823259                STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHalt);
     3260                EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_HALT),
     3261                                 pMsg->X64InterceptHeader.Rip + pMsg->X64InterceptHeader.CsSegment.Base, ASMReadTSC());
    31833262                Log4(("HaltExit\n"));
    31843263                return VINF_EM_HALT;
     
    32633342        case WHvRunVpExitReasonX64Halt:
    32643343            STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitHalt);
     3344            EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_NEM, NEMEXITTYPE_HALT),
     3345                             pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC());
    32653346            Log4(("HaltExit\n"));
    32663347            return VINF_EM_HALT;
  • 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.
  • trunk/src/VBox/VMM/include/EMInternal.h

    r72490 r72555  
    292292
    293293/**
     294 * Exit history entry.
     295 *
     296 * @remarks We could perhaps trim this down a little bit by assuming uFlatPC
     297 *          only needs 48 bits (currently true but will change) and stuffing
     298 *          the flags+type in the available 16 bits made available.  The
     299 *          timestamp could likewise be shortened to accomodate the index, or
     300 *          we might skip the index entirely.  However, since we will have to
     301 *          deal with 56-bit wide PC address before long, there's not point.
     302 *
     303 *          On the upside, there are unused bits in both uFlagsAndType and the
     304 *          idxSlot fields if needed for anything.
     305 */
     306typedef struct EMEXITENTRY
     307{
     308    /** The flat PC (CS:EIP/RIP) address of the exit. */
     309    uint64_t        uFlatPC;
     310    /** The EMEXIT_MAKE_FLAGS_AND_TYPE */
     311    uint32_t        uFlagsAndType;
     312    /** The index into the exit slot hash table.
     313     * UINT32_MAX if too many collisions and not entered into it. */
     314    uint32_t        idxSlot;
     315    /** The TSC timestamp of the exit.
     316     * This is 0 if not timestamped. */
     317    uint64_t        uTimestamp;
     318} EMEXITENTRY;
     319/** Pointer to an exit history entry. */
     320typedef EMEXITENTRY *PEMEXITENTRY;
     321/** Pointer to a const exit history entry. */
     322typedef EMEXITENTRY const *PCEMEXITENTRY;
     323
     324
     325/**
    294326 * Converts a EM pointer into a VM pointer.
    295327 * @returns Pointer to the VM structure the EM is part of.
     
    464496    uint64_t                padding1;
    465497#endif
     498
     499    /** Where to store the next exit history entry.
     500     * Since aExitHistory is 256 items longs, we'll just increment this and
     501     * mask it when using it.  That help the readers detect whether we've
     502     * wrapped around or not.  */
     503    uint64_t                iNextExit;
     504    /** Exit history table (6KB). */
     505    EMEXITENTRY             aExitHistory[256];
    466506} EMCPU;
    467507/** Pointer to EM VM instance data. */
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r72541 r72555  
    102102# define NEM_TMPL_STATIC
    103103#endif
     104
     105
     106/**
     107 * Generic NEM exit type enumeration for use with EMHistoryAddExit.
     108 *
     109 * On windows we've got two different set of exit types and they are both jumping
     110 * around the place value wise, so EM can use their values.
     111 *
     112 * @note We only have exit types for exits not covered by EM here.
     113 */
     114typedef enum NEMEXITTYPE
     115{
     116    /* windows: */
     117    NEMEXITTYPE_UNRECOVERABLE_EXCEPTION = 1,
     118    NEMEXITTYPE_INVALID_VP_REGISTER_VALUE,
     119    NEMEXITTYPE_INTTERRUPT_WINDOW,
     120    NEMEXITTYPE_HALT,
     121    NEMEXITTYPE_XCPT_UD,
     122    NEMEXITTYPE_XCPT_DB,
     123    NEMEXITTYPE_XCPT_BP,
     124    NEMEXITTYPE_CANCELED
     125} NEMEXITTYPE;
    104126
    105127
Note: See TracChangeset for help on using the changeset viewer.

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