VirtualBox

Changeset 75822 in vbox


Ignore:
Timestamp:
Nov 29, 2018 5:37:35 PM (6 years ago)
Author:
vboxsync
Message:

HMVMX,ConsoleImpl: Workaround for incorrect assumptions in mesa vmsvga 3d driver. AMD-V variant, untested.

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

Legend:

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

    r75759 r75822  
    401401static FNSVMEXITHANDLER hmR0SvmExitXcptAC;
    402402static FNSVMEXITHANDLER hmR0SvmExitXcptBP;
     403static FNSVMEXITHANDLER hmR0SvmExitXcptGP;
    403404#if defined(HMSVM_ALWAYS_TRAP_ALL_XCPTS) || defined(VBOX_WITH_NESTED_HWVIRT_SVM)
    404405static FNSVMEXITHANDLER hmR0SvmExitXcptGeneric;
     
    982983    if (pVCpu->hm.s.fGIMTrapXcptUD)
    983984        pVmcbCtrl->u32InterceptXcpt |= RT_BIT(X86_XCPT_UD);
     985
     986    /* The mesa 3d driver hack needs #GP. */
     987    if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
     988        pVmcbCtrl->u32InterceptXcpt |= RT_BIT(X86_XCPT_GP);
    984989
    985990    /* Set up unconditional intercepts and conditions. */
     
    14271432    Assert(uXcpt != X86_XCPT_DB);
    14281433    Assert(uXcpt != X86_XCPT_AC);
     1434    Assert(uXcpt != X86_XCPT_GP);
    14291435#ifndef HMSVM_ALWAYS_TRAP_ALL_XCPTS
    14301436    if (pVmcb->ctrl.u32InterceptXcpt & RT_BIT(uXcpt))
     
    22322238     * Merge the guest's exception intercepts into the nested-guest VMCB.
    22332239     *
    2234      * - \#UD: Exclude these as the outer guest's GIM hypercalls are not applicable
     2240     * - #UD: Exclude these as the outer guest's GIM hypercalls are not applicable
    22352241     * while executing the nested-guest.
    22362242     *
    2237      * - \#BP: Exclude breakpoints set by the VM debugger for the outer guest. This can
     2243     * - #BP: Exclude breakpoints set by the VM debugger for the outer guest. This can
    22382244     * be tweaked later depending on how we wish to implement breakpoints.
     2245     *
     2246     * - #GP: Exclude these as it's the inner VMMs problem to get vmsvga 3d drivers
     2247     *        loaded into their guests, not ours.
    22392248     *
    22402249     * Warning!! This ASSUMES we only intercept \#UD for hypercall purposes and \#BP
     
    22422251     */
    22432252#ifndef HMSVM_ALWAYS_TRAP_ALL_XCPTS
    2244     pVmcbNstGstCtrl->u32InterceptXcpt  |= (pVmcb->ctrl.u32InterceptXcpt & ~(  RT_BIT(X86_XCPT_UD)
    2245                                                                             | RT_BIT(X86_XCPT_BP)));
     2253    pVmcbNstGstCtrl->u32InterceptXcpt  |= pVmcb->ctrl.u32InterceptXcpt
     2254                                        & ~(  RT_BIT(X86_XCPT_UD)
     2255                                            | RT_BIT(X86_XCPT_BP)
     2256                                            | (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv ? RT_BIT(X86_XCPT_GP) : 0));
    22462257#else
    22472258    pVmcbNstGstCtrl->u32InterceptXcpt  |= pVmcb->ctrl.u32InterceptXcpt;
     
    56905701        case SVM_EXIT_XCPT_AC:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptAC(pVCpu, pSvmTransient));
    56915702        case SVM_EXIT_XCPT_BP:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptBP(pVCpu, pSvmTransient));
     5703        case SVM_EXIT_XCPT_GP:      VMEXIT_CALL_RET(0, hmR0SvmExitXcptGP(pVCpu, pSvmTransient));
    56925704        case SVM_EXIT_XSETBV:       VMEXIT_CALL_RET(0, hmR0SvmExitXsetbv(pVCpu, pSvmTransient));
    56935705        case SVM_EXIT_FERR_FREEZE:  VMEXIT_CALL_RET(0, hmR0SvmExitFerrFreeze(pVCpu, pSvmTransient));
     
    57585770                case SVM_EXIT_XCPT_NP:
    57595771                case SVM_EXIT_XCPT_SS:
    5760                 case SVM_EXIT_XCPT_GP:
     5772                /*   SVM_EXIT_XCPT_GP: */       /* Handled above. */
    57615773                /*   SVM_EXIT_XCPT_PF: */
    57625774                case SVM_EXIT_XCPT_15:          /* Reserved. */
     
    77987810
    77997811
     7812/**
     7813 * Hacks its way around the lovely mesa driver's backdoor accesses.
     7814 *
     7815 * @sa hmR0VmxHandleMesaDrvGp
     7816 */
     7817static int hmR0SvmHandleMesaDrvGp(PVMCPU pVCpu, PSVMTRANSIENT pSvmTransient, PCPUMCTX pCtx, PCSVMVMCB pVmcb)
     7818{
     7819    Log(("hmR0SvmHandleMesaDrvGp: at %04x:%08RX64 rcx=%RX64 rbx=%RX64\n",
     7820         pVmcb->guest.CS.u16Sel, pVmcb->guest.u64RIP, pCtx->rcx, pCtx->rbx));
     7821    RT_NOREF(pCtx, pSvmTransient, pVmcb);
     7822
     7823    /* For now we'll just skip the instruction. */
     7824    hmR0SvmAdvanceRip(pVCpu, 1);
     7825    return VINF_SUCCESS;
     7826}
     7827
     7828
     7829/**
     7830 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
     7831 * backdoor logging w/o checking what it is running inside.
     7832 *
     7833 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
     7834 * backdoor port and magic numbers loaded in registers.
     7835 *
     7836 * @returns true if it is, false if it isn't.
     7837 * @sa      hmR0VmxIsMesaDrvGp
     7838 */
     7839DECLINLINE(bool) hmR0SvmIsMesaDrvGp(PVMCPU pVCpu, PSVMTRANSIENT pSvmTransient, PCPUMCTX pCtx, PCSVMVMCB pVmcb)
     7840{
     7841    /* Check magic and port. */
     7842    Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
     7843    /*Log(("hmR0SvmIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->fExtrn & CPUMCTX_EXTRN_RAX ? pCtx->rax : pVmcb->guest.u64RAX, pCtx->rdx));*/
     7844    if (pCtx->dx != UINT32_C(0x5658))
     7845        return false;
     7846    if ((pCtx->fExtrn & CPUMCTX_EXTRN_RAX ? pCtx->rax : pVmcb->guest.u64RAX) != UINT32_C(0x564d5868))
     7847        return false;
     7848
     7849    /* Check that it is #GP(0). */
     7850    if (pSvmTransient->u64ExitCode != 0)
     7851        return false;
     7852
     7853    /* Flat ring-3 CS. */
     7854    /*Log(("hmR0SvmIsMesaDrvGp: u8CPL=%d base=%Rx64\n", pVmcb->guest.u8CPL, pCtx->fExtrn & CPUMCTX_EXTRN_CS ? pVmcb->guest.CS.u64Base : pCtx->cs.Sel));*/
     7855    if (pVmcb->guest.u8CPL != 3)
     7856        return false;
     7857    if ((pCtx->fExtrn & CPUMCTX_EXTRN_CS ? pVmcb->guest.CS.u64Base : pCtx->cs.Sel) != 0)
     7858        return false;
     7859
     7860    /* 0xed:  IN eAX,dx */
     7861    uint64_t const uRip = pCtx->fExtrn & CPUMCTX_EXTRN_RIP ? pCtx->rip : pVmcb->guest.u64RIP;
     7862    uint8_t abInstr[1];
     7863    if (   hmR0SvmSupportsNextRipSave(pVCpu)
     7864        && pVmcb->ctrl.u64NextRIP - uRip != sizeof(abInstr))
     7865        return false;
     7866    if (pVmcb->ctrl.cbInstrFetched >= 1)
     7867    {
     7868        /*Log(("hmR0SvmIsMesaDrvGp: %#x\n", pVmcb->ctrl.abInstr));*/
     7869        if (pVmcb->ctrl.abInstr[0] != 0xed)
     7870            return false;
     7871    }
     7872    else
     7873    {
     7874        int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, uRip, sizeof(abInstr));
     7875        /*Log(("hmR0SvmIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
     7876        if (RT_FAILURE(rc))
     7877            return false;
     7878        if (abInstr[0] != 0xed)
     7879            return false;
     7880    }
     7881
     7882    return true;
     7883}
     7884
     7885
     7886/**
     7887 * \#VMEXIT handler for general protection faults (SVM_EXIT_XCPT_BP).
     7888 * Conditional \#VMEXIT.
     7889 */
     7890HMSVM_EXIT_DECL hmR0SvmExitXcptGP(PVMCPU pVCpu, PSVMTRANSIENT pSvmTransient)
     7891{
     7892    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pSvmTransient);
     7893    HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY(pVCpu, pSvmTransient);
     7894
     7895    PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
     7896    Assert(pSvmTransient->u64ExitCode == pVmcb->ctrl.u64ExitCode);
     7897
     7898    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     7899    if (   !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
     7900        || hmR0SvmIsMesaDrvGp(pVCpu, pSvmTransient, pCtx, pVmcb))
     7901    {
     7902        SVMEVENT Event;
     7903        Event.u                  = 0;
     7904        Event.n.u1Valid          = 1;
     7905        Event.n.u3Type           = SVM_EVENT_EXCEPTION;
     7906        Event.n.u8Vector         = X86_XCPT_GP;
     7907        Event.n.u1ErrorCodeValid = 1;
     7908        Event.n.u32ErrorCode     = (uint32_t)pSvmTransient->u64ExitCode;
     7909        hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);
     7910        return VINF_SUCCESS;
     7911    }
     7912    return hmR0SvmHandleMesaDrvGp(pVCpu, pSvmTransient, pCtx, pVmcb);
     7913}
     7914
     7915
    78007916#if defined(HMSVM_ALWAYS_TRAP_ALL_XCPTS) || defined(VBOX_WITH_NESTED_HWVIRT_SVM)
    78017917/**
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r75821 r75822  
    1316813168/**
    1316913169 * Hacks its way around the lovely mesa driver's backdoor accesses.
     13170 *
     13171 * @sa hmR0SvmHandleMesaDrvGp
    1317013172 */
    1317113173static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
     
    1318713189 *
    1318813190 * @returns true if it is, false if it isn't.
     13191 * @sa      hmR0SvmIsMesaDrvGp
    1318913192 */
    1319013193DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
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