VirtualBox

Changeset 72560 in vbox for trunk


Ignore:
Timestamp:
Jun 15, 2018 11:00:02 AM (7 years ago)
Author:
vboxsync
Message:

EM,HM: Replaced HM exit history with the EM one. VT-x now reads TSC on every exit even when VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT is set. VT-x needed an API for updating the PC as RIP and CS are fetched from the VMCB. bugref:9044

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/em.h

    r72559 r72560  
    215215 *
    216216 * @{  */
    217 #define EMEXIT_F_TYPE_MASK  UINT32_C(0x0fff)    /**< The exit type mask. */
    218 #define EMEXIT_F_KIND_EM    UINT32_C(0x0000)    /**< EMEXITTYPE */
    219 #define EMEXIT_F_KIND_VMX   UINT32_C(0x1000)    /**< VT-x exit codes. */
    220 #define EMEXIT_F_KIND_SVM   UINT32_C(0x2000)    /**< SVM exit codes. */
    221 #define EMEXIT_F_KIND_NEM   UINT32_C(0x3000)    /**< NEMEXITTYPE */
    222 #define EMEXIT_F_KIND_XCPT  UINT32_C(0x4000)    /**< Exception numbers (raw-mode). */
    223 #define EMEXIT_F_KIND_MASK  UINT32_C(0x7000)
    224 #define EMEXIT_F_CS_EIP     UINT32_C(0x8000)
     217#define EMEXIT_F_TYPE_MASK      UINT32_C(0x00000fff)    /**< The exit type mask. */
     218#define EMEXIT_F_KIND_EM        UINT32_C(0x00000000)    /**< EMEXITTYPE */
     219#define EMEXIT_F_KIND_VMX       UINT32_C(0x00001000)    /**< VT-x exit codes. */
     220#define EMEXIT_F_KIND_SVM       UINT32_C(0x00002000)    /**< SVM exit codes. */
     221#define EMEXIT_F_KIND_NEM       UINT32_C(0x00003000)    /**< NEMEXITTYPE */
     222#define EMEXIT_F_KIND_XCPT      UINT32_C(0x00004000)    /**< Exception numbers (raw-mode). */
     223#define EMEXIT_F_KIND_MASK      UINT32_C(0x00007000)
     224#define EMEXIT_F_CS_EIP         UINT32_C(0x00008000)    /**< The PC is EIP in the low dword and CS in the high. */
     225#define EMEXIT_F_UNFLATTENED_PC UINT32_C(0x00010000)    /**< The PC hasn't had CS.BASE added to it. */
    225226/** Combines flags and exit type into EMHistoryAddExit() input. */
    226227#define EMEXIT_MAKE_FLAGS_AND_TYPE(a_fFlags, a_uType)   ((a_fFlags) | (uint32_t)(a_uType))
     
    239240VMMRC_INT_DECL(void)            EMRCHistoryAddExitNoTs(PVMCPU pVCpu, uint32_t uFlagsAndType, uint16_t uCs, uint32_t uEip);
    240241#endif
     242#ifdef IN_RING0
     243VMMR0_INT_DECL(void)            EMR0HistoryUpdatePC(PVMCPU pVCpu, uint64_t uFlatPC, bool fFlattened);
     244#endif
     245
    241246
    242247/** @name Deprecated interpretation related APIs (use IEM).
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r72559 r72560  
    407407 *
    408408 * @returns Suggested action to take.
    409  * @param   pVCpu           The corss context virtual CPU structure.
     409 * @param   pVCpu           The cross context virtual CPU structure.
    410410 * @param   uFlagsAndType   Combined flags and type (see EMEXIT_MAKE_FLAGS_AND_TYPE).
    411  * @param   uFlatPC         The flattened program counter (RIP).
     411 * @param   uFlatPC         The flattened program counter (RIP).  UINT64_MAX if not available.
    412412 * @param   uTimestamp      The TSC value for the exit, 0 if not available.
    413413 * @thread  EMT(pVCpu)
     
    446446 * we start seriously caring about raw-mode again, we may extend it.
    447447 *
    448  * @param   pVCpu           The corss context virtual CPU structure.
     448 * @param   pVCpu           The cross context virtual CPU structure.
    449449 * @param   uFlagsAndType   Combined flags and type (see EMEXIT_MAKE_FLAGS_AND_TYPE).
    450450 * @param   uCs             The CS.
     
    460460    pHistEntry->uFlagsAndType = uFlagsAndType | EMEXIT_F_CS_EIP;
    461461    pHistEntry->idxSlot       = UINT32_MAX;
     462}
     463#endif
     464
     465
     466#ifdef IN_RING0
     467/**
     468 * Interface that VT-x uses to supply the PC of an exit when CS:RIP is being read.
     469 *
     470 * @param   pVCpu           The cross context virtual CPU structure.
     471 * @param   uFlatPC         The flattened program counter (RIP).  UINT64_MAX if not available.
     472 * @param   fFlattened      Set if RIP was subjected to CS.BASE, clear if not.
     473 */
     474VMMR0_INT_DECL(void) EMR0HistoryUpdatePC(PVMCPU pVCpu, uint64_t uFlatPC, bool fFlattened)
     475{
     476    AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256);
     477    PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[((uintptr_t)pVCpu->em.s.iNextExit - 1) & 0xff];
     478    pHistEntry->uFlatPC = uFlatPC;
     479    if (fFlattened)
     480        pHistEntry->uFlagsAndType &= ~EMEXIT_F_UNFLATTENED_PC;
     481    else
     482        pHistEntry->uFlagsAndType |= EMEXIT_F_UNFLATTENED_PC;
    462483}
    463484#endif
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r72534 r72560  
    10401040    pVmcbCtrl->u64MSRPMPhysAddr = pVCpu->hm.s.svm.HCPhysMsrBitmap;
    10411041
    1042     /* Initialize the #VMEXIT history array with end-of-array markers (UINT16_MAX). */
    1043     Assert(!pVCpu->hm.s.idxExitHistoryFree);
    1044     HMCPU_EXIT_HISTORY_RESET(pVCpu);
    1045 
    10461042    /* Initially all VMCB clean bits MBZ indicating that everything should be loaded from the VMCB in memory. */
    10471043    Assert(pVmcbCtrl->u32VmcbCleanBits == 0);
     
    10611057        memcpy(pbMsrBitmapCur, pbMsrBitmap, SVM_MSRPM_PAGES << X86_PAGE_4K_SHIFT);
    10621058        pVmcbCtrlCur->u64MSRPMPhysAddr = pVCpuCur->hm.s.svm.HCPhysMsrBitmap;
    1063 
    1064         /* Initialize the #VMEXIT history array with end-of-array markers (UINT16_MAX). */
    1065         Assert(!pVCpuCur->hm.s.idxExitHistoryFree);
    1066         HMCPU_EXIT_HISTORY_RESET(pVCpuCur);
    10671059
    10681060        /* Initially all VMCB clean bits MBZ indicating that everything should be loaded from the VMCB in memory. */
     
    45844576
    45854577    pSvmTransient->u64ExitCode  = pVmcbCtrl->u64ExitCode;       /* Save the #VMEXIT reason. */
    4586     HMCPU_EXIT_HISTORY_ADD(pVCpu, pVmcbCtrl->u64ExitCode);      /* Update the #VMEXIT history array. */
    45874578    pVmcbCtrl->u32VmcbCleanBits       = HMSVM_VMCB_CLEAN_ALL;   /* Mark the VMCB-state cache as unmodified by VMM. */
    45884579    pSvmTransient->fVectoringDoublePF = false;                  /* Vectoring double page-fault needs to be determined later. */
     
    46114602        }
    46124603    }
     4604
     4605    EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_SVM, pSvmTransient->u64ExitCode & EMEXIT_F_TYPE_MASK),
     4606                     pMixedCtx->cs.u64Base + pMixedCtx->rip, uHostTsc);
    46134607}
    46144608
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r72533 r72560  
    28442844        Log4(("VMXR0SetupVM: pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
    28452845
    2846        /* Initialize the VM-exit history array with end-of-array markers (UINT16_MAX). */
    2847         Assert(!pVCpu->hm.s.idxExitHistoryFree);
    2848         HMCPU_EXIT_HISTORY_RESET(pVCpu);
    2849 
    28502846        /* Set revision dword at the beginning of the VMCS structure. */
    28512847        *(uint32_t *)pVCpu->hm.s.vmx.pvVmcs = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(pVM->hm.s.vmx.Msrs.u64BasicInfo);
     
    36533649        Log4(("Load[%RU32]: VMX_VMCS_GUEST_RIP=%#RX64 fContextUseFlags=%#RX32\n", pVCpu->idCpu, pMixedCtx->rip,
    36543650              HMCPU_CF_VALUE(pVCpu)));
     3651
     3652        /* Update the exit history entry with the correct CS.BASE + RIP or just RIP. */
     3653        if (HMCPU_CF_IS_SET(pVCpu, HM_CHANGED_GUEST_SEGMENT_REGS))
     3654            EMR0HistoryUpdatePC(pVCpu, pMixedCtx->cs.u64Base + pMixedCtx->rip, true);
     3655        else
     3656            EMR0HistoryUpdatePC(pVCpu, pMixedCtx->rip, false);
    36553657    }
    36563658    return rc;
     
    45944596        Log4(("Load[%RU32]: CS=%#RX16 Base=%#RX64 Limit=%#RX32 Attr=%#RX32\n", pVCpu->idCpu, pMixedCtx->cs.Sel,
    45954597              pMixedCtx->cs.u64Base, pMixedCtx->cs.u32Limit, pMixedCtx->cs.Attr.u));
     4598
     4599        /* Update the exit history entry with the correct CS.BASE + RIP. */
     4600        if (HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_RIP))
     4601            EMR0HistoryUpdatePC(pVCpu, pMixedCtx->cs.u64Base + pMixedCtx->rip, true);
    45964602    }
    45974603
     
    92089214{
    92099215    NOREF(pVM);
     9216    uint64_t uHostTsc = ASMReadTSC();
    92109217
    92119218    Assert(!VMMRZCallRing3IsEnabled(pVCpu));
     
    92199226
    92209227    if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT))
    9221         TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVCpu->hm.s.vmx.u64TSCOffset);
     9228        TMCpuTickSetLastSeen(pVCpu, uHostTsc + pVCpu->hm.s.vmx.u64TSCOffset);
    92229229
    92239230    STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatExit1, x);
     
    92619268         *
    92629269         * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
     9270         *
     9271         * Note! We don't have CS or RIP at this point.  Will probably address that later
     9272         *       by amending the history entry added here.
    92639273         */
    9264         HMCPU_EXIT_HISTORY_ADD(pVCpu, pVmxTransient->uExitReason);
     9274        EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_SVM, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
     9275                         UINT64_MAX, uHostTsc);
    92659276
    92669277        if (!pVmxTransient->fVMEntryFailed)
  • trunk/src/VBox/VMM/VMMR3/EMR3Dbg.cpp

    r72558 r72560  
    290290     * Register info dumpers.
    291291     */
    292     int rc = DBGFR3InfoRegisterInternalEx(pVM, "exits", "Dumps the VM-exit history.",
    293                                           emR3InfoExitHistory, DBGFINFO_FLAGS_ALL_EMTS);
     292    const char *pszExitsDesc = "Dumps the VM-exit history. Arguments: Number of entries; 'asc', 'ascending' or 'reverse'.";
     293    int rc = DBGFR3InfoRegisterInternalEx(pVM, "exits", pszExitsDesc, emR3InfoExitHistory, DBGFINFO_FLAGS_ALL_EMTS);
     294    AssertLogRelRCReturn(rc, rc);
     295    rc = DBGFR3InfoRegisterInternalEx(pVM, "exithistory", pszExitsDesc, emR3InfoExitHistory, DBGFINFO_FLAGS_ALL_EMTS);
    294296    AssertLogRelRCReturn(rc, rc);
    295297
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r72555 r72560  
    383383static DECLCALLBACK(int)  hmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
    384384static DECLCALLBACK(void) hmR3InfoSvmNstGstVmcbCache(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    385 static DECLCALLBACK(void) hmR3InfoExitHistory(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
     385static DECLCALLBACK(void) hmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    386386static DECLCALLBACK(void) hmR3InfoEventPending(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    387387static int                hmR3InitCPU(PVM pVM);
     
    439439     * Register info handlers.
    440440     */
    441     rc = DBGFR3InfoRegisterInternalEx(pVM, "exithistory", "Dumps the HM VM-exit history.", hmR3InfoExitHistory,
    442                                       DBGFINFO_FLAGS_ALL_EMTS);
     441    rc = DBGFR3InfoRegisterInternalEx(pVM, "hm", "Dumps HM info.", hmR3Info, DBGFINFO_FLAGS_ALL_EMTS);
    443442    AssertRCReturn(rc, rc);
    444443
     
    36803679 * @param   pszArgs     Arguments, ignored.
    36813680 */
    3682 static DECLCALLBACK(void) hmR3InfoExitHistory(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
     3681static DECLCALLBACK(void) hmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
    36833682{
    36843683    NOREF(pszArgs);
     
    36893688    if (HMIsEnabled(pVM))
    36903689    {
    3691         bool const fIsVtx = pVM->hm.s.vmx.fSupported;
    3692         const char * const *papszDesc;
    3693         unsigned cMaxExitDesc;
    3694         if (fIsVtx)
    3695         {
    3696             cMaxExitDesc = MAX_EXITREASON_VTX;
    3697             papszDesc    = &g_apszVTxExitReasons[0];
    3698             pHlp->pfnPrintf(pHlp, "CPU[%u]: VT-x VM-exit history:\n", pVCpu->idCpu);
    3699         }
     3690        if (pVM->hm.s.vmx.fSupported)
     3691            pHlp->pfnPrintf(pHlp, "CPU[%u]: VT-x info:\n", pVCpu->idCpu);
    37003692        else
    3701         {
    3702             cMaxExitDesc = MAX_EXITREASON_AMDV;
    3703             papszDesc    = &g_apszAmdVExitReasons[0];
    3704             pHlp->pfnPrintf(pHlp, "CPU[%u]: AMD-V #VMEXIT history:\n", pVCpu->idCpu);
    3705         }
    3706 
    3707         pHlp->pfnPrintf(pHlp, "  idxExitHistoryFree = %u\n", pVCpu->hm.s.idxExitHistoryFree);
    3708         unsigned const idxLast = pVCpu->hm.s.idxExitHistoryFree > 0 ?
    3709                                                                     pVCpu->hm.s.idxExitHistoryFree - 1 :
    3710                                                                     RT_ELEMENTS(pVCpu->hm.s.auExitHistory) - 1;
    3711         for (unsigned i = 0; i < RT_ELEMENTS(pVCpu->hm.s.auExitHistory); i++)
    3712         {
    3713             uint16_t const uExit = pVCpu->hm.s.auExitHistory[i];
    3714             const char *pszExit  = NULL;
    3715             if (uExit <= cMaxExitDesc)
    3716                 pszExit = papszDesc[uExit];
    3717             else if (!fIsVtx)
    3718                 pszExit = hmSvmGetSpecialExitReasonDesc(uExit);
    3719             else
    3720                 pszExit = NULL;
    3721 
    3722             pHlp->pfnPrintf(pHlp, "  auExitHistory[%2u] = 0x%04x  %s %s\n", i, uExit, pszExit,
    3723                             idxLast == i ? "<-- Latest exit" : "");
    3724         }
    3725         pHlp->pfnPrintf(pHlp, "HM error = %#x (%u)\n", pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError);
     3693            pHlp->pfnPrintf(pHlp, "CPU[%u]: AMD-V info:\n", pVCpu->idCpu);
     3694        pHlp->pfnPrintf(pHlp, "  HM error = %#x (%u)\n", pVCpu->hm.s.u32HMError, pVCpu->hm.s.u32HMError);
    37263695    }
    37273696    else
  • trunk/src/VBox/VMM/include/EMInternal.h

    r72555 r72560  
    306306typedef struct EMEXITENTRY
    307307{
    308     /** The flat PC (CS:EIP/RIP) address of the exit. */
     308    /** The flat PC (CS:EIP/RIP) address of the exit.
     309     * UINT64_MAX if not available.  */
    309310    uint64_t        uFlatPC;
    310311    /** The EMEXIT_MAKE_FLAGS_AND_TYPE */
  • trunk/src/VBox/VMM/include/HMInternal.h

    r72532 r72560  
    128128#define HMCPU_CF_VALUE(pVCpu)                     (ASMAtomicUoReadU32(&(pVCpu)->hm.s.fContextUseFlags))
    129129
    130 
    131 /** Resets/initializes the VM-exit/\#VMEXIT history array. */
    132 #define HMCPU_EXIT_HISTORY_RESET(pVCpu)           (memset(&(pVCpu)->hm.s.auExitHistory, 0xff, sizeof((pVCpu)->hm.s.auExitHistory)))
    133 
    134 /** Updates the VM-exit/\#VMEXIT history array. */
    135 #define HMCPU_EXIT_HISTORY_ADD(pVCpu, a_ExitReason) \
    136     do { \
    137         AssertMsg((pVCpu)->hm.s.idxExitHistoryFree < RT_ELEMENTS((pVCpu)->hm.s.auExitHistory), ("%u\n", (pVCpu)->hm.s.idxExitHistoryFree)); \
    138         (pVCpu)->hm.s.auExitHistory[(pVCpu)->hm.s.idxExitHistoryFree++] = (uint16_t)(a_ExitReason); \
    139         if ((pVCpu)->hm.s.idxExitHistoryFree == RT_ELEMENTS((pVCpu)->hm.s.auExitHistory)) \
    140             (pVCpu)->hm.s.idxExitHistoryFree = 0; \
    141         (pVCpu)->hm.s.auExitHistory[(pVCpu)->hm.s.idxExitHistoryFree] = UINT16_MAX; \
    142     } while (0)
    143130
    144131/** Maximum number of exit reason statistics counters. */
     
    970957     * HMR0Enter and cleared in HMR0Leave. */
    971958    RTCPUID                 idEnteredCpu;
    972 
    973     /** VT-x/AMD-V VM-exit/\#VMXEXIT history, circular array. */
    974     uint16_t                auExitHistory[31];
    975     /** The index of the next free slot in the history array. */
    976     uint16_t                idxExitHistoryFree;
    977959
    978960    /** For saving stack space, the disassembler state is allocated here instead of
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