VirtualBox

Changeset 86115 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Sep 14, 2020 6:52:26 AM (4 years ago)
Author:
vboxsync
Message:

VMM/NEM: Implement Mesa vmwgfx #GP(0) workaround existing for SVM and VT-x already, fixes ticketref:19884

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h

    r86067 r86115  
    31713171
    31723172
     3173/**
     3174 * Advances the guest RIP by the number of bytes specified in @a cb.
     3175 *
     3176 * @param   pVCpu       The cross context virtual CPU structure.
     3177 * @param   cb          RIP increment value in bytes.
     3178 */
     3179DECLINLINE(void) nemHcWinAdvanceRip(PVMCPUCC pVCpu, uint32_t cb)
     3180{
     3181    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     3182    pCtx->rip += cb;
     3183
     3184    /* Update interrupt shadow. */
     3185    if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
     3186        && pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
     3187        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     3188}
     3189
     3190
     3191/**
     3192 * Hacks its way around the lovely mesa driver's backdoor accesses.
     3193 *
     3194 * @sa hmR0VmxHandleMesaDrvGp
     3195 * @sa hmR0SvmHandleMesaDrvGp
     3196 */
     3197static int nemHcWinHandleMesaDrvGp(PVMCPUCC pVCpu, PCPUMCTX pCtx)
     3198{
     3199    Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_GPRS_MASK)));
     3200
     3201    /* For now we'll just skip the instruction. */
     3202    nemHcWinAdvanceRip(pVCpu, 1);
     3203    return VINF_SUCCESS;
     3204}
     3205
     3206
     3207/**
     3208 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
     3209 * backdoor logging w/o checking what it is running inside.
     3210 *
     3211 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
     3212 * backdoor port and magic numbers loaded in registers.
     3213 *
     3214 * @returns true if it is, false if it isn't.
     3215 * @sa      hmR0VmxIsMesaDrvGp
     3216 * @sa      hmR0SvmIsMesaDrvGp
     3217 */
     3218DECLINLINE(bool) nemHcWinIsMesaDrvGp(PVMCPUCC pVCpu, PCPUMCTX pCtx, const uint8_t *pbInsn, uint32_t cbInsn)
     3219{
     3220    /* #GP(0) is already checked by caller. */
     3221
     3222    /* Check magic and port. */
     3223    Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RAX)));
     3224    if (pCtx->dx != UINT32_C(0x5658))
     3225        return false;
     3226    if (pCtx->rax != UINT32_C(0x564d5868))
     3227        return false;
     3228
     3229    /* Flat ring-3 CS. */
     3230    if (CPUMGetGuestCPL(pVCpu) != 3)
     3231        return false;
     3232    if (pCtx->cs.u64Base != 0)
     3233        return false;
     3234
     3235    /* 0xed:  IN eAX,dx */
     3236    if (cbInsn < 1) /* Play safe (shouldn't happen). */
     3237    {
     3238        uint8_t abInstr[1];
     3239        int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
     3240        if (RT_FAILURE(rc))
     3241            return false;
     3242        if (abInstr[0] != 0xed)
     3243            return false;
     3244    }
     3245    else
     3246    {
     3247        if (pbInsn[0] != 0xed)
     3248            return false;
     3249    }
     3250
     3251    return true;
     3252}
     3253
     3254
    31733255#ifdef NEM_WIN_TEMPLATE_MODE_OWN_RUN_API
    31743256/**
     
    32633345            break;
    32643346
     3347        case X86_XCPT_GP:
     3348        {
     3349            PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     3350            if (   !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
     3351                || !nemHcWinIsMesaDrvGp(pVCpu, pCtx, pMsg->InstructionBytes, pMsg->InstructionByteCount))
     3352            {
     3353                /** @todo Need to emulate instruction or we get a triple fault when trying to inject the #GP... */
     3354                rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), pMsg->Header.Rip,
     3355                                                        pMsg->InstructionBytes, pMsg->InstructionByteCount);
     3356                Log4(("XcptExit/%u: %04x:%08RX64/%s: #GP -> emulated -> %Rrc\n",
     3357                      pVCpu->idCpu, pMsg->Header.CsSegment.Selector, pMsg->Header.Rip,
     3358                      nemHCWinExecStateToLogStr(&pMsg->Header), VBOXSTRICTRC_VAL(rcStrict) ));
     3359                STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionUdHandled);
     3360                return rcStrict;
     3361            }
     3362            return nemHcWinHandleMesaDrvGp(pVCpu, pCtx);
     3363        }
     3364
    32653365        /*
    32663366         * Filter debug exceptions.
     
    33623462                  pExit->VpException.InstructionByteCount, pExit->VpException.InstructionBytes ));
    33633463            break;
     3464
     3465        case X86_XCPT_GP:
     3466        {
     3467            PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
     3468            if (   !pVCpu->nem.s.fTrapXcptGpForLovelyMesaDrv
     3469                || !nemHcWinIsMesaDrvGp(pVCpu, pCtx, pExit->VpException.InstructionBytes,
     3470                                        pExit->VpException.InstructionByteCount))
     3471            {
     3472                /** @todo Need to emulate instruction or we get a triple fault when trying to inject the #GP... */
     3473                rcStrict = IEMExecOneWithPrefetchedByPC(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx), pExit->VpContext.Rip,
     3474                                                        pExit->VpException.InstructionBytes,
     3475                                                        pExit->VpException.InstructionByteCount);
     3476                Log4(("XcptExit/%u: %04x:%08RX64/%s: #GP -> emulated -> %Rrc\n",
     3477                      pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip,
     3478                      nemR3WinExecStateToLogStr(&pExit->VpContext), VBOXSTRICTRC_VAL(rcStrict) ));
     3479                STAM_REL_COUNTER_INC(&pVCpu->nem.s.StatExitExceptionUdHandled);
     3480                return rcStrict;
     3481            }
     3482            return nemHcWinHandleMesaDrvGp(pVCpu, pCtx);
     3483        }
    33643484
    33653485        /*
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