VirtualBox

Changeset 40356 in vbox


Ignore:
Timestamp:
Mar 5, 2012 1:51:50 PM (13 years ago)
Author:
vboxsync
Message:

MWAIT fixes: Only clear the mwait-active flag when actually resuming code execution. Trigger reschedule in the EMMWAIT_FLAG_BREAKIRQIF0 case when VMR3WaitHalted returns and IRQs are pending.

Location:
trunk
Files:
8 edited

Legend:

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

    r39327 r40356  
    176176VMMDECL(int)            EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
    177177VMMDECL(int)            EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
    178 VMMDECL(bool)           EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
     178VMM_INT_DECL(bool)      EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
     179VMM_INT_DECL(int)       EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx);
     180VMM_INT_DECL(int)       EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx);
    179181
    180182/** @name Assembly routines
  • trunk/src/VBox/VMM/Makefile.kmk

    r40274 r40356  
    3232ifdef VBOX_WITH_RAW_MODE
    3333 VMM_COMMON_DEFS += VBOX_WITH_RAW_MODE
     34endif
     35ifdef VBOX_WITH_IEM
     36 VMM_COMMON_DEFS += VBOX_WITH_IEM
    3437endif
    3538ifdef VBOX_WITH_REM
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r40274 r40356  
    25782578}
    25792579
     2580
     2581/**
     2582 * Prepare an MWAIT - essentials of the MONITOR instruction.
     2583 *
     2584 * @returns VINF_SUCCESS
     2585 * @param   pVCpu               The current CPU.
     2586 * @param   rax                 The content of RAX.
     2587 * @param   rcx                 The content of RCX.
     2588 * @param   rdx                 The content of RDX.
     2589 */
     2590VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx)
     2591{
     2592    pVCpu->em.s.MWait.uMonitorRAX = rax;
     2593    pVCpu->em.s.MWait.uMonitorRCX = rcx;
     2594    pVCpu->em.s.MWait.uMonitorRDX = rdx;
     2595    pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;
     2596    /** @todo Complete MONITOR implementation.  */
     2597    return VINF_SUCCESS;
     2598}
     2599
     2600
     2601/**
     2602 * Performs an MWAIT.
     2603 *
     2604 * @returns VINF_SUCCESS
     2605 * @param   pVCpu               The current CPU.
     2606 * @param   rax                 The content of RAX.
     2607 * @param   rcx                 The content of RCX.
     2608 */
     2609VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx)
     2610{
     2611    pVCpu->em.s.MWait.uMWaitRAX = rax;
     2612    pVCpu->em.s.MWait.uMWaitRCX = rcx;
     2613    pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_ACTIVE;
     2614    if (rcx)
     2615        pVCpu->em.s.MWait.fWait |= EMMWAIT_FLAG_BREAKIRQIF0;
     2616    else
     2617        pVCpu->em.s.MWait.fWait &= ~EMMWAIT_FLAG_BREAKIRQIF0;
     2618    /** @todo not completely correct?? */
     2619    return VINF_EM_HALT;
     2620}
     2621
     2622
    25802623/**
    25812624 * MONITOR Emulation.
     
    26012644        return VERR_EM_INTERPRETER; /* not supported */
    26022645
    2603     pVCpu->em.s.mwait.uMonitorEAX = pRegFrame->rax;
    2604     pVCpu->em.s.mwait.uMonitorECX = pRegFrame->rcx;
    2605     pVCpu->em.s.mwait.uMonitorEDX = pRegFrame->rdx;
    2606     pVCpu->em.s.mwait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE;
     2646    EMMonitorWaitPrepare(pVCpu, pRegFrame->rax, pRegFrame->rcx, pRegFrame->rdx);
    26072647    return VINF_SUCCESS;
    26082648}
     
    26432683    }
    26442684
    2645     if (pRegFrame->ecx)
    2646     {
    2647         if (!(u32MWaitFeatures & X86_CPUID_MWAIT_ECX_BREAKIRQIF0))
    2648         {
    2649             Log(("EMInterpretMWait: unsupported X86_CPUID_MWAIT_ECX_BREAKIRQIF0 -> recompiler\n"));
    2650             return VERR_EM_INTERPRETER; /* illegal value. */
    2651         }
    2652 
    2653         pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0;
    2654     }
    2655     else
    2656         pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE;
    2657 
    2658     pVCpu->em.s.mwait.uMWaitEAX = pRegFrame->rax;
    2659     pVCpu->em.s.mwait.uMWaitECX = pRegFrame->rcx;
    2660 
    2661     /** @todo not completely correct */
    2662     return VINF_EM_HALT;
     2685    if (pRegFrame->ecx && !(u32MWaitFeatures & X86_CPUID_MWAIT_ECX_BREAKIRQIF0))
     2686    {
     2687        Log(("EMInterpretMWait: unsupported X86_CPUID_MWAIT_ECX_BREAKIRQIF0 -> recompiler\n"));
     2688        return VERR_EM_INTERPRETER; /* illegal value. */
     2689    }
     2690
     2691    return EMMonitorWaitPerform(pVCpu, pRegFrame->rax, pRegFrame->rcx);
    26632692}
    26642693
     
    32193248
    32203249/**
    3221  * Determine if we should continue after encountering a hlt or mwait instruction
     3250 * Determine if we should continue after encountering a hlt or mwait
     3251 * instruction.
     3252 *
     3253 * Clears MWAIT flags if returning @c true.
    32223254 *
    32233255 * @returns boolean
    32243256 * @param   pVCpu           The VMCPU to operate on.
    3225  * @param   pCtx            Current CPU context
    3226  */
    3227 VMMDECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
    3228 {
    3229     if (    pCtx->eflags.Bits.u1IF
    3230         ||  ((pVCpu->em.s.mwait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)))
    3231     {
    3232         pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
    3233         return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC));
     3257 * @param   pCtx            Current CPU context.
     3258 */
     3259VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx)
     3260{
     3261    if (   pCtx->eflags.Bits.u1IF
     3262        || (   (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
     3263            ==                            (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) )
     3264    {
     3265        pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
     3266        return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC));
    32343267    }
    32353268
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r40280 r40356  
    23552355
    23562356    case SVM_EXIT_HLT:
    2357         /** Check if external interrupts are pending; if so, don't switch back. */
     2357        /* Check if external interrupts are pending; if so, don't switch back. */
    23582358        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt);
    23592359        pCtx->rip++;    /* skip hlt */
     
    23742374            pCtx->rip += 3;     /* Note: hardcoded opcode size assumption! */
    23752375
    2376             /** Check if external interrupts are pending; if so, don't switch back. */
     2376            /* Check if external interrupts are pending; if so, don't switch back. */
    23772377            if (    rc == VINF_SUCCESS
    23782378                ||  (   rc == VINF_EM_HALT
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r40280 r40356  
    41114111
    41124112    case VMX_EXIT_HLT:                  /* 12 Guest software attempted to execute HLT. */
    4113         /** Check if external interrupts are pending; if so, don't switch back. */
     4113        /* Check if external interrupts are pending; if so, don't switch back. */
    41144114        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt);
    41154115        pCtx->rip++;    /* skip hlt */
     
    41304130            pCtx->rip += cbInstr;
    41314131
    4132             /** Check if external interrupts are pending; if so, don't switch back. */
     4132            /* Check if external interrupts are pending; if so, don't switch back. */
    41334133            if (    rc == VINF_SUCCESS
    41344134                ||  (   rc == VINF_EM_HALT
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r40274 r40356  
    510510
    511511        /* Save mwait state. */
    512         rc = SSMR3PutU32(pSSM, pVCpu->em.s.mwait.fWait);
     512        rc = SSMR3PutU32(pSSM, pVCpu->em.s.MWait.fWait);
    513513        AssertRCReturn(rc, rc);
    514         rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitEAX);
     514        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRAX);
    515515        AssertRCReturn(rc, rc);
    516         rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitECX);
     516        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMWaitRCX);
    517517        AssertRCReturn(rc, rc);
    518         rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEAX);
     518        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRAX);
    519519        AssertRCReturn(rc, rc);
    520         rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorECX);
     520        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRCX);
    521521        AssertRCReturn(rc, rc);
    522         rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEDX);
     522        rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.MWait.uMonitorRDX);
    523523        AssertRCReturn(rc, rc);
    524524    }
     
    574574        {
    575575            /* Load mwait state. */
    576             rc = SSMR3GetU32(pSSM, &pVCpu->em.s.mwait.fWait);
     576            rc = SSMR3GetU32(pSSM, &pVCpu->em.s.MWait.fWait);
    577577            AssertRCReturn(rc, rc);
    578             rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitEAX);
     578            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRAX);
    579579            AssertRCReturn(rc, rc);
    580             rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitECX);
     580            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMWaitRCX);
    581581            AssertRCReturn(rc, rc);
    582             rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEAX);
     582            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRAX);
    583583            AssertRCReturn(rc, rc);
    584             rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorECX);
     584            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRCX);
    585585            AssertRCReturn(rc, rc);
    586             rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEDX);
     586            rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.MWait.uMonitorRDX);
    587587            AssertRCReturn(rc, rc);
    588588        }
     
    18961896             */
    18971897            Log2(("EMR3ExecuteVM: rc=%Rrc\n", rc));
     1898            EMSTATE const enmOldState = pVCpu->em.s.enmState;
    18981899            switch (rc)
    18991900            {
     
    21042105            }
    21052106
     2107            /*
     2108             * Act on state transition.
     2109             */
     2110            EMSTATE const enmNewState = pVCpu->em.s.enmState;
     2111            if (enmOldState != enmNewState)
     2112            {
     2113                /* Clear MWait flags. */
     2114                if (   enmOldState == EMSTATE_HALTED
     2115                    && (pVCpu->em.s.MWait.fWait & EMMWAIT_FLAG_ACTIVE)
     2116                    && (   enmNewState == EMSTATE_RAW
     2117                        || enmNewState == EMSTATE_HWACC
     2118                        || enmNewState == EMSTATE_REM
     2119                        || enmNewState == EMSTATE_DEBUG_GUEST_RAW
     2120                        || enmNewState == EMSTATE_DEBUG_GUEST_HWACC
     2121                        || enmNewState == EMSTATE_DEBUG_GUEST_REM) )
     2122                {
     2123                    LogFlow(("EMR3ExecuteVM: Clearing MWAIT\n"));
     2124                    pVCpu->em.s.MWait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
     2125                }
     2126            }
     2127
    21062128            STAM_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x); /* (skip this in release) */
    21072129            STAM_PROFILE_ADV_START(&pVCpu->em.s.StatTotal, x);
     
    21592181                {
    21602182                    STAM_REL_PROFILE_START(&pVCpu->em.s.StatHalted, y);
    2161                     if (pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_ACTIVE)
     2183                    /* MWAIT has a special extension where it's woken up when
     2184                       an interrupt is pending even when IF=0. */
     2185                    if (   (pVCpu->em.s.MWait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
     2186                        ==                            (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))
    21622187                    {
    2163                         /* mwait has a special extension where it's woken up when an interrupt is pending even when IF=0. */
    2164                         rc = VMR3WaitHalted(pVM, pVCpu, !(pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_BREAKIRQIF0) && !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF));
    2165                         pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0);
     2188                        rc = VMR3WaitHalted(pVM, pVCpu, false /*fIgnoreInterrupts*/);
     2189                        if (   rc == VINF_SUCCESS
     2190                            && VMCPU_FF_ISPENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
     2191                        {
     2192                            Log(("EMR3ExecuteVM: Triggering reschedule on pending IRQ after MWAIT\n"));
     2193                            rc = VINF_EM_RESCHEDULE;
     2194                        }
    21662195                    }
    21672196                    else
     
    21782207                    TMR3NotifySuspend(pVM, pVCpu);
    21792208                    STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
    2180                     Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
     2209                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
    21812210                    return VINF_EM_SUSPEND;
    21822211
     
    22072236                        pVCpu->em.s.enmState = EMSTATE_GURU_MEDITATION;
    22082237                        VMMR3FatalDump(pVM, pVCpu, rc);
    2209                         Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
     2238                        Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
    22102239                        return rc;
    22112240                    }
     
    22252254                    emR3Debug(pVM, pVCpu, rc);
    22262255                    STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
    2227                     Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
     2256                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
    22282257                    return rc;
    22292258                }
     
    22392268                    TMR3NotifySuspend(pVM, pVCpu);
    22402269                    STAM_REL_PROFILE_ADV_STOP(&pVCpu->em.s.StatTotal, x);
    2241                     Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(pVCpu->em.s.enmPrevState)));
     2270                    Log(("EMR3ExecuteVM: actually returns %Rrc (state %s / %s)\n", rc, emR3GetStateName(pVCpu->em.s.enmState), emR3GetStateName(enmOldState)));
    22422271                    return VERR_EM_INTERNAL_ERROR;
    22432272            }
  • trunk/src/VBox/VMM/VMMR3/EMRaw.cpp

    r40274 r40356  
    364364    }
    365365
    366 #if 0
    367     /* Try our own instruction emulator before falling back to the recompiler. */
    368     DISCPUSTATE Cpu;
    369     rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pCtx->rip, &Cpu, "GEN EMU");
    370     if (RT_SUCCESS(rc))
    371     {
    372         uint32_t size;
    373 
    374         switch (Cpu.pCurInstr->opcode)
    375         {
    376         /* @todo we can do more now */
    377         case OP_MOV:
    378         case OP_AND:
    379         case OP_OR:
    380         case OP_XOR:
    381         case OP_POP:
    382         case OP_INC:
    383         case OP_DEC:
    384         case OP_XCHG:
    385             STAM_PROFILE_START(&pVCpu->em.s.StatMiscEmu, a);
    386             rc = EMInterpretInstructionCPU(pVM, &Cpu, CPUMCTX2CORE(pCtx), 0, &size);
    387             if (RT_SUCCESS(rc))
    388             {
    389                 pCtx->rip += Cpu.opsize;
    390                 STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
    391                 return rc;
    392             }
    393             if (rc != VERR_EM_INTERPRETER)
    394                 AssertMsgFailedReturn(("rc=%Rrc\n", rc), rc);
    395             STAM_PROFILE_STOP(&pVCpu->em.s.StatMiscEmu, a);
    396             break;
    397         }
    398     }
    399 #endif /* 0 */
    400366    STAM_PROFILE_START(&pVCpu->em.s.StatREMEmu, a);
    401367    Log(("EMINS: %04x:%RGv RSP=%RGv\n", pCtx->cs, (RTGCPTR)pCtx->rip, (RTGCPTR)pCtx->rsp));
  • trunk/src/VBox/VMM/include/EMInternal.h

    r40274 r40356  
    4444
    4545
    46 /**
    47  * MWait state flags.
    48  */
    49 /* MWait activated. */
     46/** @name MWait state flags.
     47 * @{
     48 */
     49/** MWait activated. */
    5050#define EMMWAIT_FLAG_ACTIVE             RT_BIT(0)
    51 /* MWait will continue when an interrupt is pending even when IF=0. */
     51/** MWait will continue when an interrupt is pending even when IF=0. */
    5252#define EMMWAIT_FLAG_BREAKIRQIF0        RT_BIT(1)
    53 /* Monitor instruction was executed previously. */
     53/** Monitor instruction was executed previously. */
    5454#define EMMWAIT_FLAG_MONITOR_ACTIVE     RT_BIT(2)
     55/** @} */
    5556
    5657/** EM time slice in ms; used for capping execution time. */
     
    333334    EMSTATE volatile        enmState;
    334335
    335     /** Previous Execution Manager State. */
     336    /** The state prior to the suspending of the VM. */
    336337    EMSTATE                 enmPrevState;
    337338
     
    364365    uint64_t                u64Alignment;
    365366
    366     /* MWait halt state. */
     367    /** MWait halt state. */
    367368    struct
    368369    {
    369         uint32_t            fWait;          /* type of mwait; see EMMWAIT_FLAG_* */
    370         uint32_t            a32Padding[1];
    371         RTGCPTR             uMWaitEAX;      /* mwait hints */
    372         RTGCPTR             uMWaitECX;      /* mwait extensions */
    373         RTGCPTR             uMonitorEAX;    /* monitored address. */
    374         RTGCPTR             uMonitorECX;    /* monitor extension. */
    375         RTGCPTR             uMonitorEDX;    /* monitor hint. */
    376     } mwait;
     370        uint32_t            fWait;          /** Type of mwait; see EMMWAIT_FLAG_*. */
     371        uint32_t            u32Padding;
     372        RTGCPTR             uMWaitRAX;      /** MWAIT hints. */
     373        RTGCPTR             uMWaitRCX;      /** MWAIT extensions. */
     374        RTGCPTR             uMonitorRAX;    /** Monitored address. */
     375        RTGCPTR             uMonitorRCX;    /** Monitor extension. */
     376        RTGCPTR             uMonitorRDX;    /** Monitor hint. */
     377    } MWait;
    377378
    378379    union
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