VirtualBox

Changeset 76500 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Dec 28, 2018 4:51:32 AM (6 years ago)
Author:
vboxsync
Message:

VMM/EM: Fix NMI injection. Clear pending-NMI and set blocking-by-NMI FFs after injecting an NMI through a pending TRPM trap.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r76402 r76500  
    21552155
    21562156        /*
    2157          * NMIs.
    2158          * NMIs take priority over external interrupts.
     2157         * Guest event injection.
    21592158         */
    21602159        bool fWakeupPending = false;
    2161         if (    VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)
    2162             && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)
    2163             && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    2164         {
    2165             rc2 = TRPMAssertTrap(pVCpu, X86_XCPT_NMI, TRPM_TRAP);
    2166             if (rc2 == VINF_SUCCESS)
    2167             {
    2168                 fWakeupPending = true;
    2169                 if (pVM->em.s.fIemExecutesAll)
    2170                     rc2 = VINF_EM_RESCHEDULE;
    2171                 else
    2172                 {
    2173                     rc2 = HMR3IsActive(pVCpu)    ? VINF_EM_RESCHEDULE_HM
    2174                         : VM_IS_NEM_ENABLED(pVM) ? VINF_EM_RESCHEDULE
    2175                         :                          VINF_EM_RESCHEDULE_REM;
    2176                 }
    2177             }
    2178             UPDATE_RC();
    2179         }
    2180 
    2181         /*
    2182          * Interrupts.
    2183          */
    21842160        if (   !VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)
    21852161            && (!rc || rc >= VINF_EM_RESCHEDULE_HM)
    2186             && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
    2187             && !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */
    2188         {
     2162            && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)  /* Interrupt shadows block both NMIs and interrupts. */
     2163            && !TRPMHasTrap(pVCpu))                                  /* An event could already be scheduled for dispatching. */
     2164        {
     2165            /*
     2166             * NMIs (take priority over external interrupts).
     2167             */
    21892168            Assert(!HMR3IsEventPending(pVCpu));
    2190             bool fGif = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
     2169            if (    VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)
     2170                && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
     2171            {
     2172                rc2 = TRPMAssertTrap(pVCpu, X86_XCPT_NMI, TRPM_TRAP);
     2173                if (rc2 == VINF_SUCCESS)
     2174                {
     2175                    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
     2176                    VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     2177                    fWakeupPending = true;
     2178                    if (pVM->em.s.fIemExecutesAll)
     2179                        rc2 = VINF_EM_RESCHEDULE;
     2180                    else
     2181                    {
     2182                        rc2 = HMR3IsActive(pVCpu)    ? VINF_EM_RESCHEDULE_HM
     2183                            : VM_IS_NEM_ENABLED(pVM) ? VINF_EM_RESCHEDULE
     2184                            :                          VINF_EM_RESCHEDULE_REM;
     2185                    }
     2186                }
     2187                UPDATE_RC();
     2188            }
     2189            else
     2190            {
     2191                /*
     2192                 * External Interrupts.
     2193                 */
     2194                bool fGif = CPUMGetGuestGif(&pVCpu->cpum.GstCtx);
    21912195#ifdef VBOX_WITH_RAW_MODE
    2192             fGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip);
    2193 #endif
    2194             if (fGif)
    2195             {
    2196                 /*
    2197                  * With VMX, virtual interrupts takes priority over physical interrupts.
    2198                  * With SVM, physical interrupts takes priority over virtual interrupts.
    2199                  */
    2200                 if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
    2201                     && CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
    2202                     && CPUMIsGuestVmxVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx))
     2196                fGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip);
     2197#endif
     2198                if (fGif)
    22032199                {
    2204                     /** @todo NSTVMX: virtual-interrupt delivery. */
    2205                     rc2 = VINF_NO_CHANGE;
    2206                 }
    2207                 else if (   VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
    2208                          && CPUMIsGuestPhysIntrEnabled(pVCpu))
    2209                 {
    2210                     bool fInjected = false;
    2211                     Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
    2212 
    2213                     if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
    2214                         rc2 = emR3VmxNstGstIntrWindowExit(pVCpu);
    2215                     else if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx))
    2216                         rc2 = emR3SvmNstGstIntrIntercept(pVCpu);
    2217                     else
     2200                    /*
     2201                     * With VMX, virtual interrupts takes priority over physical interrupts.
     2202                     * With SVM, physical interrupts takes priority over virtual interrupts.
     2203                     */
     2204                    if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
     2205                        && CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
     2206                        && CPUMIsGuestVmxVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx))
     2207                    {
     2208                        /** @todo NSTVMX: virtual-interrupt delivery. */
    22182209                        rc2 = VINF_NO_CHANGE;
    2219 
    2220                     if (rc2 == VINF_NO_CHANGE)
     2210                    }
     2211                    else if (   VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
     2212                             && CPUMIsGuestPhysIntrEnabled(pVCpu))
    22212213                    {
    2222                         CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
    2223                         /** @todo this really isn't nice, should properly handle this */
    2224                         rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT, &fInjected);
    2225                         fWakeupPending = true;
    2226                         if (   pVM->em.s.fIemExecutesAll
    2227                             && (   rc2 == VINF_EM_RESCHEDULE_REM
    2228                                 || rc2 == VINF_EM_RESCHEDULE_HM
    2229                                 || rc2 == VINF_EM_RESCHEDULE_RAW))
     2214                        bool fInjected = false;
     2215                        Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
     2216
     2217                        if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
     2218                            rc2 = emR3VmxNstGstIntrWindowExit(pVCpu);
     2219                        else if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx))
     2220                            rc2 = emR3SvmNstGstIntrIntercept(pVCpu);
     2221                        else
     2222                            rc2 = VINF_NO_CHANGE;
     2223
     2224                        if (rc2 == VINF_NO_CHANGE)
    22302225                        {
     2226                            CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK);
     2227                            /** @todo this really isn't nice, should properly handle this */
     2228                            rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT, &fInjected);
     2229                            fWakeupPending = true;
     2230                            if (   pVM->em.s.fIemExecutesAll
     2231                                && (   rc2 == VINF_EM_RESCHEDULE_REM
     2232                                    || rc2 == VINF_EM_RESCHEDULE_HM
     2233                                    || rc2 == VINF_EM_RESCHEDULE_RAW))
     2234                            {
     2235                                rc2 = VINF_EM_RESCHEDULE;
     2236                            }
     2237                        }
     2238#ifdef VBOX_STRICT
     2239                        if (fInjected)
     2240                            rcIrq = rc2;
     2241#endif
     2242                        UPDATE_RC();
     2243                    }
     2244                    else if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
     2245                             && CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)
     2246                             && CPUMIsGuestSvmVirtIntrEnabled(pVCpu,  &pVCpu->cpum.GstCtx))
     2247                    {
     2248                        rc2 = emR3SvmNstGstVirtIntrIntercept(pVCpu);
     2249                        if (rc2 == VINF_NO_CHANGE)
     2250                        {
     2251                            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
     2252                            uint8_t const uNstGstVector = CPUMGetGuestSvmVirtIntrVector(&pVCpu->cpum.GstCtx);
     2253                            AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR %#x\n", uNstGstVector));
     2254                            TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
     2255                            Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));
    22312256                            rc2 = VINF_EM_RESCHEDULE;
     2257#ifdef VBOX_STRICT
     2258                            rcIrq = rc2;
     2259#endif
    22322260                        }
     2261                        UPDATE_RC();
    22332262                    }
    2234 #ifdef VBOX_STRICT
    2235                     if (fInjected)
    2236                         rcIrq = rc2;
    2237 #endif
    2238                     UPDATE_RC();
    2239                 }
    2240                 else if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)
    2241                          && CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)
    2242                          && CPUMIsGuestSvmVirtIntrEnabled(pVCpu,  &pVCpu->cpum.GstCtx))
    2243                 {
    2244                     rc2 = emR3SvmNstGstVirtIntrIntercept(pVCpu);
    2245                     if (rc2 == VINF_NO_CHANGE)
    2246                     {
    2247                         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
    2248                         uint8_t const uNstGstVector = CPUMGetGuestSvmVirtIntrVector(&pVCpu->cpum.GstCtx);
    2249                         AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR %#x\n", uNstGstVector));
    2250                         TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
    2251                         Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector));
    2252                         rc2 = VINF_EM_RESCHEDULE;
    2253 #ifdef VBOX_STRICT
    2254                         rcIrq = rc2;
    2255 #endif
    2256                     }
    2257                     UPDATE_RC();
    22582263                }
    22592264            }
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