VirtualBox

Changeset 20846 in vbox for trunk/src/VBox/VMM/VMMR0


Ignore:
Timestamp:
Jun 23, 2009 2:57:46 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
48985
Message:

If an active trap is already pending, then we must forward it first!

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

Legend:

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

    r20838 r20846  
    426426    }
    427427
    428     if (VMCPU_FF_TESTANDCLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI_BIT))
    429     {
    430         SVM_EVENT Event;
    431 
    432         Log(("CPU%d: injecting #NMI\n", pVCpu->idCpu));
    433         Event.n.u8Vector     = X86_XCPT_NMI;
    434         Event.n.u1Valid      = 1;
    435         Event.n.u32ErrorCode = 0;
    436         Event.n.u3Type       = SVM_EVENT_NMI;
    437 
    438         SVMR0InjectEvent(pVCpu, pVMCB, pCtx, &Event);
    439         return VINF_SUCCESS;
    440     }
    441 
    442     /* @todo SMI interrupts. */
    443 
    444     /* When external interrupts are pending, we should exit the VM when IF is set. */
    445     if (    !TRPMHasTrap(pVCpu)
    446         &&  VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)))
    447     {
    448         if (    !(pCtx->eflags.u32 & X86_EFL_IF)
    449             ||  VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    450         {
    451             if (!pVMCB->ctrl.IntCtrl.n.u1VIrqValid)
     428    /* If an active trap is already pending, then we must forward it first! */
     429    if (!TRPMHasTrap(pVCpu))
     430    {
     431        if (VMCPU_FF_TESTANDCLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI_BIT))
     432        {
     433            SVM_EVENT Event;
     434
     435            Log(("CPU%d: injecting #NMI\n", pVCpu->idCpu));
     436            Event.n.u8Vector     = X86_XCPT_NMI;
     437            Event.n.u1Valid      = 1;
     438            Event.n.u32ErrorCode = 0;
     439            Event.n.u3Type       = SVM_EVENT_NMI;
     440
     441            SVMR0InjectEvent(pVCpu, pVMCB, pCtx, &Event);
     442            return VINF_SUCCESS;
     443        }
     444
     445        /* @todo SMI interrupts. */
     446
     447        /* When external interrupts are pending, we should exit the VM when IF is set. */
     448        if (VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)))
     449        {
     450            if (    !(pCtx->eflags.u32 & X86_EFL_IF)
     451                ||  VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    452452            {
    453                 if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    454                     LogFlow(("Enable irq window exit!\n"));
    455                 else
    456                     Log(("Pending interrupt blocked at %RGv by VM_FF_INHIBIT_INTERRUPTS -> irq window exit\n", (RTGCPTR)pCtx->rip));
    457 
    458                 /** @todo use virtual interrupt method to inject a pending irq; dispatched as soon as guest.IF is set. */
    459                 pVMCB->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_VINTR;
    460                 pVMCB->ctrl.IntCtrl.n.u1VIrqValid    = 1;
    461                 pVMCB->ctrl.IntCtrl.n.u8VIrqVector   = 0; /* don't care */
    462             }
    463         }
    464         else
    465         {
    466             uint8_t u8Interrupt;
    467 
    468             rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
    469             Log(("Dispatch interrupt: u8Interrupt=%x (%d) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc));
    470             if (RT_SUCCESS(rc))
    471             {
    472                 rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
    473                 AssertRC(rc);
     453                if (!pVMCB->ctrl.IntCtrl.n.u1VIrqValid)
     454                {
     455                    if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     456                        LogFlow(("Enable irq window exit!\n"));
     457                    else
     458                        Log(("Pending interrupt blocked at %RGv by VM_FF_INHIBIT_INTERRUPTS -> irq window exit\n", (RTGCPTR)pCtx->rip));
     459
     460                    /** @todo use virtual interrupt method to inject a pending irq; dispatched as soon as guest.IF is set. */
     461                    pVMCB->ctrl.u32InterceptCtrl1 |= SVM_CTRL1_INTERCEPT_VINTR;
     462                    pVMCB->ctrl.IntCtrl.n.u1VIrqValid    = 1;
     463                    pVMCB->ctrl.IntCtrl.n.u8VIrqVector   = 0; /* don't care */
     464                }
    474465            }
    475466            else
    476467            {
    477                 /* Can only happen in rare cases where a pending interrupt is cleared behind our back */
    478                 Assert(!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)));
    479                 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchGuestIrq);
    480                 /* Just continue */
     468                uint8_t u8Interrupt;
     469
     470                rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
     471                Log(("Dispatch interrupt: u8Interrupt=%x (%d) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc));
     472                if (RT_SUCCESS(rc))
     473                {
     474                    rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
     475                    AssertRC(rc);
     476                }
     477                else
     478                {
     479                    /* Can only happen in rare cases where a pending interrupt is cleared behind our back */
     480                    Assert(!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)));
     481                    STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchGuestIrq);
     482                    /* Just continue */
     483                }
    481484            }
    482485        }
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r20838 r20846  
    754754    }
    755755
    756     if (VMCPU_FF_TESTANDCLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI_BIT))
    757     {
    758         RTGCUINTPTR intInfo;
    759 
    760         Log(("CPU%d: injecting #NMI\n", pVCpu->idCpu));
    761 
    762         intInfo  = X86_XCPT_NMI;
    763         intInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    764         intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    765 
    766         rc = VMXR0InjectEvent(pVM, pVCpu, pCtx, intInfo, 0, 0);
    767         AssertRC(rc);
    768 
    769         return VINF_SUCCESS;
    770     }
    771 
    772     /* @todo SMI interrupts. */
    773 
    774     /* When external interrupts are pending, we should exit the VM when IF is set. */
    775     if (    !TRPMHasTrap(pVCpu)
    776         &&  VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)))
    777     {
    778         if (!(pCtx->eflags.u32 & X86_EFL_IF))
    779         {
    780             if (!(pVCpu->hwaccm.s.vmx.proc_ctls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT))
     756    /* If an active trap is already pending, then we must forward it first! */
     757    if (!TRPMHasTrap(pVCpu))
     758    {
     759        if (VMCPU_FF_TESTANDCLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI_BIT))
     760        {
     761            RTGCUINTPTR intInfo;
     762
     763            Log(("CPU%d: injecting #NMI\n", pVCpu->idCpu));
     764
     765            intInfo  = X86_XCPT_NMI;
     766            intInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     767            intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     768
     769            rc = VMXR0InjectEvent(pVM, pVCpu, pCtx, intInfo, 0, 0);
     770            AssertRC(rc);
     771
     772            return VINF_SUCCESS;
     773        }
     774
     775        /* @todo SMI interrupts. */
     776
     777        /* When external interrupts are pending, we should exit the VM when IF is set. */
     778        if (VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)))
     779        {
     780            if (!(pCtx->eflags.u32 & X86_EFL_IF))
    781781            {
    782                 LogFlow(("Enable irq window exit!\n"));
    783                 pVCpu->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT;
    784                 rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
    785                 AssertRC(rc);
    786             }
    787             /* else nothing to do but wait */
    788         }
    789         else
    790         if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    791         {
    792             uint8_t u8Interrupt;
    793 
    794             rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
    795             Log(("CPU%d: Dispatch interrupt: u8Interrupt=%x (%d) rc=%Rrc cs:rip=%04X:%RGv\n", pVCpu->idCpu, u8Interrupt, u8Interrupt, rc, pCtx->cs, (RTGCPTR)pCtx->rip));
    796             if (RT_SUCCESS(rc))
    797             {
    798                 rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
    799                 AssertRC(rc);
     782                if (!(pVCpu->hwaccm.s.vmx.proc_ctls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT))
     783                {
     784                    LogFlow(("Enable irq window exit!\n"));
     785                    pVCpu->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT;
     786                    rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
     787                    AssertRC(rc);
     788                }
     789                /* else nothing to do but wait */
    800790            }
    801791            else
     792            if (!VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    802793            {
    803                 /* Can only happen in rare cases where a pending interrupt is cleared behind our back */
    804                 Assert(!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)));
    805                 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchGuestIrq);
    806                 /* Just continue */
     794                uint8_t u8Interrupt;
     795
     796                rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
     797                Log(("CPU%d: Dispatch interrupt: u8Interrupt=%x (%d) rc=%Rrc cs:rip=%04X:%RGv\n", pVCpu->idCpu, u8Interrupt, u8Interrupt, rc, pCtx->cs, (RTGCPTR)pCtx->rip));
     798                if (RT_SUCCESS(rc))
     799                {
     800                    rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
     801                    AssertRC(rc);
     802                }
     803                else
     804                {
     805                    /* Can only happen in rare cases where a pending interrupt is cleared behind our back */
     806                    Assert(!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)));
     807                    STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatSwitchGuestIrq);
     808                    /* Just continue */
     809                }
    807810            }
    808         }
    809         else
    810             Log(("Pending interrupt blocked at %RGv by VM_FF_INHIBIT_INTERRUPTS!!\n", (RTGCPTR)pCtx->rip));
     811            else
     812                Log(("Pending interrupt blocked at %RGv by VM_FF_INHIBIT_INTERRUPTS!!\n", (RTGCPTR)pCtx->rip));
     813        }
    811814    }
    812815
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette