VirtualBox

Changeset 94882 in vbox


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
Files:
4 added
9 edited

Legend:

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

    r94799 r94882  
    14621462    } R0Stats;
    14631463
     1464    union
     1465    {
     1466#ifdef VMM_INCLUDED_SRC_include_GCMInternal_h
     1467        struct GCM  s;
     1468#endif
     1469        uint8_t     padding[32];       /* multiple of 8 */
     1470    } gcm;
     1471
    14641472    /** Padding for aligning the structure size on a page boundrary. */
    1465     uint8_t         abAlignment2[8912 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
     1473    uint8_t         abAlignment2[8880 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
    14661474
    14671475    /* ---- end small stuff ---- */
  • trunk/include/VBox/vmm/vm.mac

    r93650 r94882  
    165165    .iem                    resb 8
    166166    .R0Stats                resb 64
     167    .gcm                    resb 32
    167168
    168169    times ((($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB + 16383) & ~16383) - ($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB)) resb 1
  • trunk/src/VBox/VMM/Makefile.kmk

    r94769 r94882  
    124124        VMMR3/EMHM.cpp \
    125125        VMMR3/EMR3Nem.cpp \
     126        VMMR3/GCM.cpp \
    126127        VMMR3/GIM.cpp \
    127128        VMMR3/GIMHv.cpp \
     
    200201        VMMAll/SELMAll.cpp \
    201202        VMMAll/EMAll.cpp \
     203        VMMAll/GCMAll.cpp \
    202204        VMMAll/GIMAll.cpp \
    203205        VMMAll/GIMAllHv.cpp \
     
    521523        $(if-expr defined(VBOX_WITH_DBGF_TRACING), VMMAll/DBGFAllTracer.cpp,) \
    522524        VMMAll/EMAll.cpp \
     525        VMMAll/GCMAll.cpp \
    523526        VMMAll/GIMAll.cpp \
    524527        VMMAll/GIMAllHv.cpp \
  • trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h

    r94620 r94882  
    21462146            if (VCPU_2_VMXSTATE(pVCpu).fTrapXcptGpForLovelyMesaDrv)
    21472147                uXcptBitmap |= RT_BIT(X86_XCPT_GP);
     2148            if (VCPU_2_VMXSTATE(pVCpu).fGCMTrapXcptDE)
     2149                uXcptBitmap |= RT_BIT(X86_XCPT_DE);
    21482150            Assert(VM_IS_VMX_NESTED_PAGING(pVM) || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
    21492151
     
    68356837
    68366838/**
     6839 * VM-exit exception handler for \#DE (Divide Error).
     6840 *
     6841 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
     6842 */
     6843static VBOXSTRICTRC vmxHCExitXcptDE(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
     6844{
     6845    HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
     6846    STAM_COUNTER_INC(&VCPU_2_VMXSTATS(pVCpu).StatExitGuestDE);
     6847
     6848    int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
     6849    AssertRCReturn(rc, rc);
     6850
     6851    VBOXSTRICTRC rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
     6852    if (pVCpu->hm.s.fGCMTrapXcptDE)
     6853    {
     6854        uint8_t cbInstr = 0;
     6855        rc = GCMXcptDE(pVCpu, &pVCpu->cpum.GstCtx, NULL /* pDis */, &cbInstr);
     6856        if (rc == VINF_SUCCESS)
     6857            rcStrict = VINF_SUCCESS;    /* Restart instruction with modified guest register context. */
     6858        else if (rc == VINF_EM_RAW_GUEST_TRAP)
     6859            rcStrict = VERR_NOT_FOUND;  /* Deliver the exception. */
     6860        else
     6861            Assert(RT_FAILURE(VBOXSTRICTRC_VAL(rcStrict)));
     6862    }
     6863    else
     6864        rcStrict = VINF_SUCCESS;        /* Do nothing. */
     6865
     6866    /* If the GCM #DE exception handler didn't succeed or wasn't needed, raise #DE. */
     6867    if (RT_FAILURE(rc))
     6868    {
     6869        vmxHCSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
     6870                               pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
     6871        rcStrict = VINF_SUCCESS;
     6872    }
     6873
     6874    Assert(rcStrict == VINF_SUCCESS || rcStrict == VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE);
     6875    return VBOXSTRICTRC_VAL(rcStrict);
     6876}
     6877
     6878
     6879/**
    68376880 * VM-exit exception handler wrapper for all other exceptions that are not handled
    68386881 * by a specific handler.
     
    69436986                case X86_XCPT_BP: return vmxHCExitXcptBP(pVCpu, pVmxTransient);
    69446987                case X86_XCPT_AC: return vmxHCExitXcptAC(pVCpu, pVmxTransient);
     6988                case X86_XCPT_DE: return vmxHCExitXcptDE(pVCpu, pVmxTransient);
    69456989                default:
    69466990                    return vmxHCExitXcptOthers(pVCpu, pVmxTransient);
  • 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>
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r94790 r94882  
    4646#include <VBox/vmm/ssm.h>
    4747#include <VBox/vmm/gim.h>
     48#include <VBox/vmm/gcm.h>
    4849#include <VBox/vmm/trpm.h>
    4950#include <VBox/vmm/dbgf.h>
     
    723724        pVCpu->hm.s.fActive = false;
    724725        pVCpu->hm.s.fGIMTrapXcptUD = GIMShouldTrapXcptUD(pVCpu);    /* Is safe to call now since GIMR3Init() has completed. */
     726        pVCpu->hm.s.fGCMTrapXcptDE = GCMShouldTrapXcptDE(pVCpu);    /* Is safe to call now since GCMR3Init() has completed. */
    725727    }
    726728
  • trunk/src/VBox/VMM/VMMR3/VM.cpp

    r94809 r94882  
    6666#include <VBox/vmm/hm.h>
    6767#include <VBox/vmm/gim.h>
     68#include <VBox/vmm/gcm.h>
    6869#include "VMInternal.h"
    6970#include <VBox/vmm/vmcc.h>
     
    886887                                                            if (RT_SUCCESS(rc))
    887888                                                            {
    888                                                                 rc = PDMR3Init(pVM);
     889                                                                rc = GCMR3Init(pVM);
    889890                                                                if (RT_SUCCESS(rc))
    890891                                                                {
    891                                                                     rc = PGMR3InitFinalize(pVM);
    892                                                                     if (RT_SUCCESS(rc))
    893                                                                         rc = TMR3InitFinalize(pVM);
     892                                                                    rc = PDMR3Init(pVM);
    894893                                                                    if (RT_SUCCESS(rc))
    895894                                                                    {
    896                                                                         PGMR3MemSetup(pVM, false /*fAtReset*/);
    897                                                                         PDMR3MemSetup(pVM, false /*fAtReset*/);
     895                                                                        rc = PGMR3InitFinalize(pVM);
     896                                                                        if (RT_SUCCESS(rc))
     897                                                                            rc = TMR3InitFinalize(pVM);
     898                                                                        if (RT_SUCCESS(rc))
     899                                                                        {
     900                                                                            PGMR3MemSetup(pVM, false /*fAtReset*/);
     901                                                                            PDMR3MemSetup(pVM, false /*fAtReset*/);
     902                                                                        }
     903                                                                        if (RT_SUCCESS(rc))
     904                                                                            rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_RING3);
     905                                                                        if (RT_SUCCESS(rc))
     906                                                                        {
     907                                                                            LogFlow(("vmR3InitRing3: returns %Rrc\n", VINF_SUCCESS));
     908                                                                            return VINF_SUCCESS;
     909                                                                        }
     910
     911                                                                        int rc2 = PDMR3Term(pVM);
     912                                                                        AssertRC(rc2);
    898913                                                                    }
    899                                                                     if (RT_SUCCESS(rc))
    900                                                                         rc = vmR3InitDoCompleted(pVM, VMINITCOMPLETED_RING3);
    901                                                                     if (RT_SUCCESS(rc))
    902                                                                     {
    903                                                                         LogFlow(("vmR3InitRing3: returns %Rrc\n", VINF_SUCCESS));
    904                                                                         return VINF_SUCCESS;
    905                                                                     }
    906 
    907                                                                     int rc2 = PDMR3Term(pVM);
     914                                                                    int rc2 = GCMR3Term(pVM);
    908915                                                                    AssertRC(rc2);
    909916                                                                }
     
    10601067    PDMR3Relocate(pVM, offDelta);
    10611068    GIMR3Relocate(pVM, offDelta);
     1069    GCMR3Relocate(pVM, offDelta);
    10621070}
    10631071
  • trunk/src/VBox/VMM/include/HMInternal.h

    r94419 r94882  
    748748    /** Whether we're executing a single instruction. */
    749749    bool                        fSingleInstruction;
    750 
    751     bool                        afAlignment0[2];
     750    /** Whether \#DE needs to be intercepted (may be required by GCM). */
     751    bool                        fGCMTrapXcptDE;
     752
     753    bool                        afAlignment0[1];
    752754
    753755    /** An additional error code used for some gurus. */
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