VirtualBox

Changeset 94882 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
May 6, 2022 6:33:54 AM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
151284
Message:

VMM: First stab at Guest Compatibility Manager, fixing up things like division overflows caused by fast CPUs (see bugref:9735).

Location:
trunk/src/VBox/VMM/VMMR0
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r93963 r94882  
    3131#include <VBox/vmm/tm.h>
    3232#include <VBox/vmm/em.h>
     33#include <VBox/vmm/gcm.h>
    3334#include <VBox/vmm/gim.h>
    3435#include <VBox/vmm/apic.h>
     
    357358static FNSVMEXITHANDLER hmR0SvmExitFerrFreeze;
    358359static FNSVMEXITHANDLER hmR0SvmExitIret;
     360static FNSVMEXITHANDLER hmR0SvmExitXcptDE;
    359361static FNSVMEXITHANDLER hmR0SvmExitXcptPF;
    360362static FNSVMEXITHANDLER hmR0SvmExitXcptUD;
     
    10021004        pVmcbCtrl0->u32InterceptXcpt |= RT_BIT(X86_XCPT_UD);
    10031005
     1006    /* Apply the exceptions intercepts needed by the GCM fixers. */
     1007    if (pVCpu0->hm.s.fGCMTrapXcptDE)
     1008        pVmcbCtrl0->u32InterceptXcpt |= RT_BIT(X86_XCPT_DE);
     1009
    10041010    /* The mesa 3d driver hack needs #GP. */
    10051011    if (pVCpu0->hm.s.fTrapXcptGpForLovelyMesaDrv)
     
    11541160        /* Verify our assumption that GIM providers trap #UD uniformly across VCPUs initially. */
    11551161        Assert(pVCpuCur->hm.s.fGIMTrapXcptUD == pVCpu0->hm.s.fGIMTrapXcptUD);
     1162        /* Same for GCM, #DE trapping should be uniform across VCPUs. */
     1163        Assert(pVCpuCur->hm.s.fGCMTrapXcptDE == pVCpu0->hm.s.fGCMTrapXcptDE);
    11561164    }
    11571165
     
    26822690
    26832691        if (fWhat & CPUMCTX_EXTRN_RFLAGS)
     2692        {
    26842693            pCtx->eflags.u32 = pVmcbGuest->u64RFlags;
     2694            if (pVCpu->hmr0.s.fClearTrapFlag)
     2695            {
     2696                pVCpu->hmr0.s.fClearTrapFlag = false;
     2697                pCtx->eflags.Bits.u1TF = 0;
     2698            }
     2699        }
    26852700
    26862701        if (fWhat & CPUMCTX_EXTRN_RSP)
     
    32173232    Log4Func(("u=%#RX64 u8Vector=%#x Type=%#x ErrorCodeValid=%RTbool ErrorCode=%#RX32\n", pEvent->u, pEvent->n.u8Vector,
    32183233              (uint8_t)pEvent->n.u3Type, !!pEvent->n.u1ErrorCodeValid, pEvent->n.u32ErrorCode));
     3234}
     3235
     3236
     3237/**
     3238 * Sets an divide error (\#DE) exception as pending-for-injection into the VM.
     3239 *
     3240 * @param   pVCpu       The cross context virtual CPU structure.
     3241 */
     3242DECLINLINE(void) hmR0SvmSetPendingXcptDE(PVMCPUCC pVCpu)
     3243{
     3244    SVMEVENT Event;
     3245    Event.u          = 0;
     3246    Event.n.u1Valid  = 1;
     3247    Event.n.u3Type   = SVM_EVENT_EXCEPTION;
     3248    Event.n.u8Vector = X86_XCPT_DE;
     3249    hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);
    32193250}
    32203251
     
    53485379        case SVM_EXIT_RDPMC:        VMEXIT_CALL_RET(0, hmR0SvmExitRdpmc(pVCpu, pSvmTransient));
    53495380        case SVM_EXIT_IRET:         VMEXIT_CALL_RET(0, hmR0SvmExitIret(pVCpu, pSvmTransient));
     5381        case SVM_EXIT_XCPT_DE:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptDE(pVCpu, pSvmTransient));
    53505382        case SVM_EXIT_XCPT_UD:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptUD(pVCpu, pSvmTransient));
    53515383        case SVM_EXIT_XCPT_MF:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptMF(pVCpu, pSvmTransient));
     
    83508382
    83518383
     8384
     8385/**
     8386 * \#VMEXIT handler for division overflow exceptions (SVM_EXIT_XCPT_1).
     8387 * Conditional \#VMEXIT.
     8388 */
     8389HMSVM_EXIT_DECL hmR0SvmExitXcptDE(PVMCPUCC pVCpu, PSVMTRANSIENT pSvmTransient)
     8390{
     8391    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pSvmTransient);
     8392    HMSVM_ASSERT_NOT_IN_NESTED_GUEST(&pVCpu->cpum.GstCtx);
     8393    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE);
     8394
     8395    /* Paranoia; Ensure we cannot be called as a result of event delivery. */
     8396    PSVMVMCB        pVmcb         = hmR0SvmGetCurrentVmcb(pVCpu);
     8397    Assert(!pVmcb->ctrl.ExitIntInfo.n.u1Valid);  NOREF(pVmcb);
     8398
     8399    int rc = VERR_SVM_UNEXPECTED_XCPT_EXIT;
     8400    if (pVCpu->hm.s.fGCMTrapXcptDE)
     8401    {
     8402        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, HMSVM_CPUMCTX_EXTRN_ALL);
     8403        uint8_t cbInstr = 0;
     8404        VBOXSTRICTRC rcStrict = GCMXcptDE(pVCpu, &pVCpu->cpum.GstCtx, NULL /* pDis */, &cbInstr);
     8405        if (rcStrict == VINF_SUCCESS)
     8406            rc = VINF_SUCCESS;      /* Restart instruction with modified guest register context. */
     8407        else if (rcStrict == VINF_EM_RAW_GUEST_TRAP)
     8408            rc = VERR_NOT_FOUND;    /* Deliver the exception. */
     8409        else
     8410            Assert(RT_FAILURE(VBOXSTRICTRC_VAL(rcStrict)));
     8411    }
     8412
     8413    /* If the GCM #DE exception handler didn't succeed or wasn't needed, raise #DE. */
     8414    if (RT_FAILURE(rc))
     8415    {
     8416        hmR0SvmSetPendingXcptDE(pVCpu);
     8417        rc = VINF_SUCCESS;
     8418    }
     8419
     8420    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE);
     8421    return rc;
     8422}
     8423
     8424
    83528425/**
    83538426 * \#VMEXIT handler for undefined opcode (SVM_EXIT_XCPT_6).
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r94844 r94882  
    3434#include <VBox/vmm/tm.h>
    3535#include <VBox/vmm/em.h>
     36#include <VBox/vmm/gcm.h>
    3637#include <VBox/vmm/gim.h>
    3738#include <VBox/vmm/apic.h>
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