Changeset 75830 in vbox for trunk/src/VBox
- Timestamp:
- Nov 30, 2018 9:30:58 AM (6 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
r75765 r75830 2649 2649 2650 2650 /** 2651 * Gets whether the guest or nested-guest's are ready to receive physical 2652 * interrupts. 2653 * 2654 * This function assumes there is no global 2655 * 2656 * @returns @c true if interrupts can be injected into the guest (or nested-guest), 2657 * @c false otherwise. 2651 * Returns whether the guest has physical interrupts enabled. 2652 * 2653 * @returns @c true if interrupts are enabled, @c false otherwise. 2658 2654 * @param pVCpu The cross context virtual CPU structure. 2659 */ 2660 DECLINLINE(bool) CPUMIsGuestPhysIntrsEnabled(PVMCPU pVCpu) 2661 { 2662 Assert(pVCpu->cpum.s.Guest.hwvirt.fGif); 2663 if ( !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.s.Guest) 2664 && !CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.s.Guest)) 2665 return RT_BOOL(pVCpu->cpum.s.Guest.rflags.Bits.u1IF); 2655 * 2656 * @remarks Warning! This function does -not- take into account the global-interrupt 2657 * flag (GIF). 2658 */ 2659 VMM_INT_DECL(bool) CPUMIsGuestPhysIntrEnabled(PVMCPU pVCpu) 2660 { 2661 if (!CPUMIsGuestInNestedHwvirtMode(&pVCpu->cpum.s.Guest)) 2662 { 2663 #ifdef VBOX_WITH_RAW_MODE_NOT_R0 2664 uint32_t const fEFlags = !pVCpu->cpum.s.fRawEntered ? pVCpu->cpum.s.Guest.eflags.u : CPUMRawGetEFlags(pVCpu); 2665 #else 2666 uint32_t const fEFlags = pVCpu->cpum.s.Guest.eflags.u; 2667 #endif 2668 return RT_BOOL(fEFlags & X86_EFL_IF); 2669 } 2666 2670 2667 2671 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.s.Guest)) 2668 return CPUMCanVmxNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.s.Guest); 2669 2670 return CPUMCanSvmNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.s.Guest); 2672 return CPUMIsGuestVmxPhysIntrEnabled(pVCpu, &pVCpu->cpum.s.Guest); 2673 2674 Assert(CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.s.Guest)); 2675 return CPUMIsGuestSvmPhysIntrEnabled(pVCpu, &pVCpu->cpum.s.Guest); 2676 } 2677 2678 2679 /** 2680 * Returns whether the nested-guest has virtual interrupts enabled. 2681 * 2682 * @returns @c true if interrupts are enabled, @c false otherwise. 2683 * @param pVCpu The cross context virtual CPU structure. 2684 * 2685 * @remarks Warning! This function does -not- take into account the global-interrupt 2686 * flag (GIF). 2687 */ 2688 VMM_INT_DECL(bool) CPUMIsGuestVirtIntrEnabled(PVMCPU pVCpu) 2689 { 2690 Assert(CPUMIsGuestInNestedHwvirtMode(&pVCpu->cpum.s.Guest)); 2691 2692 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.s.Guest)) 2693 return CPUMIsGuestVmxVirtIntrEnabled(pVCpu, &pVCpu->cpum.s.Guest); 2694 2695 Assert(CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.s.Guest)); 2696 return CPUMIsGuestSvmVirtIntrEnabled(pVCpu, &pVCpu->cpum.s.Guest); 2671 2697 } 2672 2698 … … 2681 2707 { 2682 2708 #if 1 2683 if (pVCpu->cpum.s.Guest.hwvirt.fGif) 2709 /* Global-interrupt flag blocks pretty much everything we care about here. */ 2710 if (CPUMGetGuestGif(&pVCpu->cpum.s.Guest)) 2684 2711 { 2685 /** @todo r=ramshankar: What about virtual-interrupt delivery to nested-guests? */ 2686 if (CPUMIsGuestPhysIntrsEnabled(pVCpu)) 2712 /* 2713 * Physical interrupts are primarily blocked using EFLAGS. However, we cannot access 2714 * it directly here. If and how EFLAGS are used depends on the context (nested-guest 2715 * or raw-mode). Hence we use the function below which handles the details. 2716 */ 2717 if ( CPUMIsGuestPhysIntrEnabled(pVCpu) 2718 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_BLOCK_NMIS | VMCPU_FF_INHIBIT_INTERRUPTS)) 2687 2719 { 2688 if (!VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_BLOCK_NMIS | VMCPU_FF_INHIBIT_INTERRUPTS)) 2720 if ( !CPUMIsGuestInNestedHwvirtMode(&pVCpu->cpum.s.Guest) 2721 || CPUMIsGuestVirtIntrEnabled(pVCpu)) 2689 2722 return CPUMINTERRUPTIBILITY_UNRESTRAINED; 2690 2723 2691 /** @todo does blocking NMIs mean interrupts are also inhibited? */ 2692 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) 2693 { 2694 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 2695 return CPUMINTERRUPTIBILITY_INT_INHIBITED; 2696 return CPUMINTERRUPTIBILITY_NMI_INHIBIT; 2697 } 2698 AssertFailed(); 2724 /* Physical interrupts are enabled, but nested-guest virtual interrupts are disabled. */ 2725 return CPUMINTERRUPTIBILITY_VIRT_INT_DISABLED; 2726 } 2727 2728 /* 2729 * Blocking the delivery of NMIs during an interrupt shadow is CPU implementation 2730 * specific. Therefore, in practice, we can't deliver an NMI in an interrupt shadow. 2731 * However, there is some uncertainity regarding the converse, i.e. whether 2732 * NMI-blocking until IRET blocks delivery of physical interrupts. 2733 * 2734 * See Intel spec. 25.4.1 "Event Blocking". 2735 */ 2736 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 2699 2737 return CPUMINTERRUPTIBILITY_NMI_INHIBIT; 2700 } 2701 else 2702 { 2703 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 2704 return CPUMINTERRUPTIBILITY_NMI_INHIBIT; 2705 return CPUMINTERRUPTIBILITY_INT_DISABLED; 2706 } 2738 2739 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) 2740 return CPUMINTERRUPTIBILITY_INT_INHIBITED; 2741 2742 return CPUMINTERRUPTIBILITY_INT_DISABLED; 2707 2743 } 2708 2744 return CPUMINTERRUPTIBILITY_GLOBAL_INHIBIT; … … 2751 2787 * @param pCtx The guest-CPU context. 2752 2788 */ 2753 VMM_INT_DECL(bool) CPUM CanVmxNstGstTakePhysIntr(PVMCPU pVCpu, PCCPUMCTX pCtx)2789 VMM_INT_DECL(bool) CPUMIsGuestVmxPhysIntrEnabled(PVMCPU pVCpu, PCCPUMCTX pCtx) 2754 2790 { 2755 2791 #ifdef IN_RC … … 2759 2795 RT_NOREF(pVCpu); 2760 2796 Assert(CPUMIsGuestInVmxNonRootMode(pCtx)); 2761 Assert(pCtx->hwvirt.fGif); /* Always true on Intel. */2762 2797 2763 2798 return RT_BOOL(pCtx->eflags.u & X86_EFL_IF); … … 2765 2800 } 2766 2801 2802 2767 2803 /** 2768 2804 * Checks whether the VMX nested-guest is in a state to receive virtual interrupts 2769 * (those injected with the "virtual -interrupt delivery" feature).2805 * (those injected with the "virtual interrupt delivery" feature). 2770 2806 * 2771 2807 * @returns VBox status code. … … 2775 2811 * @param pCtx The guest-CPU context. 2776 2812 */ 2777 VMM_INT_DECL(bool) CPUM CanVmxNstGstTakeVirtIntr(PVMCPU pVCpu, PCCPUMCTX pCtx)2813 VMM_INT_DECL(bool) CPUMIsGuestVmxVirtIntrEnabled(PVMCPU pVCpu, PCCPUMCTX pCtx) 2778 2814 { 2779 2815 #ifdef IN_RC … … 2783 2819 RT_NOREF2(pVCpu, pCtx); 2784 2820 Assert(CPUMIsGuestInVmxNonRootMode(pCtx)); 2785 Assert(pCtx->hwvirt.fGif); /* Always true on Intel. */2786 2821 2787 2822 if ( (pCtx->eflags.u & X86_EFL_IF) … … 2794 2829 2795 2830 /** 2796 * Checks whether the SVM nested-guest is in a state to receive physical (APIC) 2797 * interrupts. 2798 * 2799 * @returns VBox status code. 2800 * @retval true if it's ready, false otherwise. 2801 * 2831 * Checks whether the SVM nested-guest has physical interrupts enabled. 2832 * 2833 * @returns true if interrupts are enabled, false otherwise. 2802 2834 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 2803 2835 * @param pCtx The guest-CPU context. 2804 */ 2805 VMM_INT_DECL(bool) CPUMCanSvmNstGstTakePhysIntr(PVMCPU pVCpu, PCCPUMCTX pCtx) 2836 * 2837 * @remarks This does -not- take into account the global-interrupt flag. 2838 */ 2839 VMM_INT_DECL(bool) CPUMIsGuestSvmPhysIntrEnabled(PVMCPU pVCpu, PCCPUMCTX pCtx) 2806 2840 { 2807 2841 /** @todo Optimization: Avoid this function call and use a pointer to the … … 2812 2846 #else 2813 2847 Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx)); 2814 Assert(pCtx->hwvirt.fGif);2815 2848 2816 2849 X86EFLAGS fEFlags; … … 2835 2868 * @param pCtx The guest-CPU context. 2836 2869 */ 2837 VMM_INT_DECL(bool) CPUM CanSvmNstGstTakeVirtIntr(PVMCPU pVCpu, PCCPUMCTX pCtx)2870 VMM_INT_DECL(bool) CPUMIsGuestSvmVirtIntrEnabled(PVMCPU pVCpu, PCCPUMCTX pCtx) 2838 2871 { 2839 2872 #ifdef IN_RC … … 2842 2875 #else 2843 2876 Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx)); 2844 Assert(pCtx->hwvirt.fGif);2845 2877 2846 2878 PCSVMVMCBCTRL pVmcbCtrl = &pCtx->hwvirt.svm.CTX_SUFF(pVmcb)->ctrl; … … 2863 2895 2864 2896 /** 2865 * Gets the pending SVM nested-guest interrupt .2897 * Gets the pending SVM nested-guest interruptvector. 2866 2898 * 2867 2899 * @returns The nested-guest interrupt to inject. 2868 2900 * @param pCtx The guest-CPU context. 2869 2901 */ 2870 VMM_INT_DECL(uint8_t) CPUMGet SvmNstGstInterrupt(PCCPUMCTX pCtx)2902 VMM_INT_DECL(uint8_t) CPUMGetGuestSvmVirtIntrVector(PCCPUMCTX pCtx) 2871 2903 { 2872 2904 #ifdef IN_RC -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r75683 r75830 14292 14292 /** @todo Can we centralize this under CPUMCanInjectInterrupt()? */ 14293 14293 #if defined(VBOX_WITH_NESTED_HWVIRT_SVM) 14294 bool fIntrEnabled = pVCpu->cpum.GstCtx.hwvirt.fGif;14294 bool fIntrEnabled = CPUMGetGuestGif(&pVCpu->cpum.GstCtx); 14295 14295 if (fIntrEnabled) 14296 14296 { 14297 14297 if (CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu))) 14298 fIntrEnabled = CPUM CanSvmNstGstTakePhysIntr(pVCpu, IEM_GET_CTX(pVCpu));14298 fIntrEnabled = CPUMIsGuestSvmPhysIntrEnabled(pVCpu, IEM_GET_CTX(pVCpu)); 14299 14299 else 14300 14300 fIntrEnabled = pVCpu->cpum.GstCtx.eflags.Bits.u1IF; -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplSvmInstr.cpp.h
r75759 r75830 139 139 140 140 /* 141 * Disable the global 142 */ 143 pVCpu->cpum.GstCtx.hwvirt.fGif = false;141 * Disable the global-interrupt flag to prevent interrupts during the 'atomic' world switch. 142 */ 143 CPUMSetGuestGif(&pVCpu->cpum.GstCtx, false); 144 144 145 145 /* … … 757 757 758 758 /* 759 * Clear global interrupt flagsto allow interrupts in the guest.760 */ 761 pVCpu->cpum.GstCtx.hwvirt.fGif = true;759 * Set the global-interrupt flag to allow interrupts in the guest. 760 */ 761 CPUMSetGuestGif(&pVCpu->cpum.GstCtx, true); 762 762 763 763 /* … … 1242 1242 } 1243 1243 1244 pVCpu->cpum.GstCtx.hwvirt.fGif = false;1244 CPUMSetGuestGif(&pVCpu->cpum.GstCtx, false); 1245 1245 iemRegAddToRipAndClearRF(pVCpu, cbInstr); 1246 1246 … … 1271 1271 } 1272 1272 1273 pVCpu->cpum.GstCtx.hwvirt.fGif = true;1273 CPUMSetGuestGif(&pVCpu->cpum.GstCtx, true); 1274 1274 iemRegAddToRipAndClearRF(pVCpu, cbInstr); 1275 1275 -
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r75829 r75830 2457 2457 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.svm.u32Features & X86_CPUID_SVM_FEATURE_EDX_VGIF); /* Hardware supports it. */ 2458 2458 Assert(HMSvmIsVGifActive(pVCpu->CTX_SUFF(pVM))); /* VM has configured it. */ 2459 pVmcb->ctrl.IntCtrl.n.u1VGif = pCtx->hwvirt.fGif;2459 pVmcb->ctrl.IntCtrl.n.u1VGif = CPUMGetGuestGif(pCtx); 2460 2460 } 2461 2461 #endif … … 2810 2810 Assert(!CPUMIsGuestInSvmNestedHwVirtMode(pCtx)); /* We don't yet support passing VGIF feature to the guest. */ 2811 2811 Assert(HMSvmIsVGifActive(pVCpu->CTX_SUFF(pVM))); /* VM has configured it. */ 2812 pCtx->hwvirt.fGif = pVmcbCtrl->IntCtrl.n.u1VGif;2812 CPUMSetGuestGif(pCtx, pVmcbCtrl->IntCtrl.n.u1VGif); 2813 2813 } 2814 2814 } … … 3743 3743 Assert(pVmcb); 3744 3744 3745 bool const fGif = pCtx->hwvirt.fGif;3745 bool const fGif = CPUMGetGuestGif(pCtx); 3746 3746 bool const fIntShadow = hmR0SvmIsIntrShadowActive(pVCpu); 3747 3747 bool const fBlockNmi = VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS); … … 3803 3803 if ( fGif 3804 3804 && !fIntShadow 3805 && CPUM CanSvmNstGstTakePhysIntr(pVCpu, pCtx))3805 && CPUMIsGuestSvmPhysIntrEnabled(pVCpu, pCtx)) 3806 3806 { 3807 3807 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_INTR)) … … 3863 3863 Assert(pVmcb); 3864 3864 3865 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 3866 bool const fGif = pCtx->hwvirt.fGif; 3867 #else 3868 bool const fGif = true; 3869 #endif 3865 bool const fGif = CPUMGetGuestGif(pCtx); 3870 3866 bool const fIntShadow = hmR0SvmIsIntrShadowActive(pVCpu); 3871 3867 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF); … … 3974 3970 */ 3975 3971 if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx)) 3976 fAllowInt = CPUM CanSvmNstGstTakePhysIntr(pVCpu, pCtx) || CPUMCanSvmNstGstTakeVirtIntr(pVCpu, pCtx);3972 fAllowInt = CPUMIsGuestSvmPhysIntrEnabled(pVCpu, pCtx) || CPUMIsGuestSvmVirtIntrEnabled(pVCpu, pCtx); 3977 3973 else 3978 3974 fAllowInt = RT_BOOL(pCtx->eflags.u32 & X86_EFL_IF); -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r75649 r75830 618 618 { 619 619 Assert(!TRPMHasTrap(pVCpu)); 620 Assert( enmInterruptibility > CPUMINTERRUPTIBILITY_INVALID 621 && enmInterruptibility < CPUMINTERRUPTIBILITY_END); 620 622 621 623 /* … … 625 627 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_INTERRUPT_NMI)) 626 628 { 627 if (enmInterruptibility <= CPUMINTERRUPTIBILITY_ INT_INHIBITED)629 if (enmInterruptibility <= CPUMINTERRUPTIBILITY_UNRESTRAINED) 628 630 { 629 631 uint8_t u8Interrupt = 0; … … 659 661 } 660 662 } 663 /* 664 * Nested-guest virtual interrupt. 665 */ 666 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST)) 667 { 668 if (enmInterruptibility < CPUMINTERRUPTIBILITY_VIRT_INT_DISABLED) 669 { 670 /** @todo NSTVMX: NSTSVM: Remember, we might have to check and perform VM-exits 671 * here before injecting the virtual interrupt. See emR3ForcedActions 672 * for details. */ 673 return VINF_EM_HALT; 674 } 675 } 661 676 662 677 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UNHALT)) … … 730 745 | VMCPU_FF_REQUEST | VMCPU_FF_DBGF | VMCPU_FF_HM_UPDATE_CR3 731 746 | VMCPU_FF_HM_UPDATE_PAE_PDPES | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL 732 | VMCPU_FF_TO_R3 | VMCPU_FF_IOM | VMCPU_FF_INTERRUPT_NESTED_GUEST /*?*/ 733 | VMCPU_FF_VMX_PREEMPT_TIMER /*?*/ | VMCPU_FF_VMX_APIC_WRITE /*?*/ | VMCPU_FF_VMX_MTF /*?*/ 747 | VMCPU_FF_TO_R3 | VMCPU_FF_IOM 734 748 #ifdef VBOX_WITH_RAW_MODE 735 749 | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_SELM_SYNC_GDT … … 746 760 if ( pVCpu->vmm.s.fMayHaltInRing0 747 761 && !TRPMHasTrap(pVCpu) 748 && ( enmInterruptibility <= CPUMINTERRUPTIBILITY_INT_INHIBITED762 && ( enmInterruptibility == CPUMINTERRUPTIBILITY_UNRESTRAINED 749 763 || uMWait > 1)) 750 764 { … … 758 772 APICUpdatePendingInterrupts(pVCpu); 759 773 760 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC 761 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT)) 774 /* 775 * Flags that wake up from the halted state. 776 */ 777 uint64_t const fIntMask = VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_INTERRUPT_NESTED_GUEST 778 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT; 779 780 if (VMCPU_FF_IS_ANY_SET(pVCpu, fIntMask)) 762 781 return vmmR0DoHaltInterrupt(pVCpu, uMWait, enmInterruptibility); 763 782 ASMNopPause(); … … 775 794 APICUpdatePendingInterrupts(pVCpu); 776 795 777 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC 778 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT)) 796 if (VMCPU_FF_IS_ANY_SET(pVCpu, fIntMask)) 779 797 return vmmR0DoHaltInterrupt(pVCpu, uMWait, enmInterruptibility); 780 798 … … 813 831 } 814 832 ASMNopPause(); 815 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC 816 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT)) 833 if (VMCPU_FF_IS_ANY_SET(pVCpu, fIntMask)) 817 834 { 818 835 STAM_REL_COUNTER_INC(&pVCpu->vmm.s.StatR0HaltExecFromSpin); … … 853 870 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC)) 854 871 APICUpdatePendingInterrupts(pVCpu); 855 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC 856 | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_UNHALT)) 872 if (VMCPU_FF_IS_ANY_SET(pVCpu, fIntMask)) 857 873 { 858 874 STAM_REL_COUNTER_INC(&pVCpu->vmm.s.StatR0HaltExecFromBlock); -
trunk/src/VBox/VMM/VMMR3/CPUM.cpp
r75611 r75830 1955 1955 * Hardware virtualization state. 1956 1956 */ 1957 pCtx->hwvirt.fGif = true;1957 CPUMSetGuestGif(pCtx, true); 1958 1958 Assert(!pVM->cpum.ro.GuestFeatures.fVmx || !pVM->cpum.ro.GuestFeatures.fSvm); /* Paranoia. */ 1959 1959 if (pVM->cpum.ro.GuestFeatures.fVmx) -
trunk/src/VBox/VMM/VMMR3/EM.cpp
r75759 r75830 1712 1712 1713 1713 /** 1714 * Helper for emR3ForcedActions() for injecting interrupts into the 1715 * guest. 1714 * Helper for emR3ForcedActions() for VMX interrupt-window VM-exits. 1716 1715 * 1717 1716 * @returns VBox status code. 1718 * @param pVCpu The cross context virtual CPU structure. 1719 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1720 * pending. 1721 * @param pfInjected Where to store whether an interrupt was injected. 1722 */ 1723 DECLINLINE(int) emR3GstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1724 { 1725 CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_RFLAGS); 1726 *pfWakeupPending = false; 1727 *pfInjected = false; 1728 1729 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) 1717 * @param pVCpu The cross context virtual CPU structure. 1718 */ 1719 static int emR3VmxNstGstIntrWindowExit(PVMCPU pVCpu) 1720 { 1721 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 1722 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)); 1723 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT)) 1724 { 1725 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK); 1726 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitIntWindow(pVCpu); 1727 if (RT_SUCCESS(rcStrict)) 1728 { 1729 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1730 Assert(rcStrict != VINF_VMX_VMEXIT); 1731 return VBOXSTRICTRC_VAL(rcStrict); 1732 } 1733 AssertMsgFailed(("Interrupt-window Vm-exit failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1734 return VINF_EM_TRIPLE_FAULT; 1735 } 1736 #else 1737 RT_NOREF(pVCpu); 1738 #endif 1739 return VINF_NO_CHANGE; 1740 } 1741 1742 1743 /** 1744 * Helper for emR3ForcedActions() for SVM interrupt intercept. 1745 * 1746 * @returns VBox status code. 1747 * @param pVCpu The cross context virtual CPU structure. 1748 */ 1749 static int emR3SvmNstGstIntrIntercept(PVMCPU pVCpu) 1750 { 1730 1751 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1731 && pVCpu->cpum.GstCtx.hwvirt.fGif 1732 #endif 1733 #ifdef VBOX_WITH_RAW_MODE 1734 && !PATMIsPatchGCAddr(pVCpu->CTX_SUFF(pVM), pVCpu->cpum.GstCtx.eip) 1735 #endif 1736 && pVCpu->cpum.GstCtx.eflags.Bits.u1IF) 1737 { 1738 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1739 /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */ 1740 /** @todo this really isn't nice, should properly handle this */ 1741 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 1742 int rc2 = TRPMR3InjectEvent(pVCpu->CTX_SUFF(pVM), pVCpu, TRPM_HARDWARE_INT); 1743 Assert(rc2 != VINF_VMX_VMEXIT && rc2 != VINF_SVM_VMEXIT); 1744 Log(("EM: TRPMR3InjectEvent -> %d\n", rc2)); 1745 *pfWakeupPending = true; 1746 *pfInjected = true; 1747 return rc2; 1748 } 1749 1752 Assert(CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)); 1753 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR)) 1754 { 1755 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1756 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0); 1757 if (RT_SUCCESS(rcStrict)) 1758 { 1759 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1760 Assert(rcStrict != VINF_SVM_VMEXIT); 1761 return VBOXSTRICTRC_VAL(rcStrict); 1762 } 1763 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1764 return VINF_EM_TRIPLE_FAULT; 1765 } 1766 #else 1767 NOREF(pVCpu); 1768 #endif 1750 1769 return VINF_NO_CHANGE; 1751 1770 } 1752 1771 1753 1772 1754 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 1755 /** 1756 * Helper for emR3ForcedActions() for injecting interrupts into the 1757 * VMX nested-guest. 1773 /** 1774 * Helper for emR3ForcedActions() for SVM virtual interrupt intercept. 1758 1775 * 1759 1776 * @returns VBox status code. 1760 * @param pVCpu The cross context virtual CPU structure. 1761 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1762 * pending. 1763 * @param pfInjected Where to store whether an interrrupt was injected. 1764 */ 1765 static int emR3VmxNstGstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1766 { 1767 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)); 1768 *pfWakeupPending = false; 1769 *pfInjected = false; 1770 1771 /** @todo NSTVMX: Interrupt-window VM-exits currently only trigger when an 1772 * interrupt is pending but in reality it should happen as soon as the 1773 * guest is ready to receive interrupts even if no interrupt is pending. 1774 * Doing it before checking the VMCPU_FF_INTERRUPT_APIC or 1775 * VMCPU_FF_INTERRUPT_PIC here doesn't help as the caller already checks for 1776 * it earlier as part of the high-priority pre-mask anyway. */ 1777 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) 1778 && CPUMCanVmxNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1779 { 1780 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1781 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); 1782 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT)) 1783 { 1784 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK); 1785 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitIntWindow(pVCpu); 1786 if (RT_SUCCESS(rcStrict)) 1787 { 1788 *pfWakeupPending = true; 1789 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1790 if (rcStrict == VINF_VMX_VMEXIT) 1791 return VINF_SUCCESS; 1792 return VBOXSTRICTRC_VAL(rcStrict); 1793 } 1794 AssertMsgFailed(("Interrupt-window Vm-exit failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1795 return VINF_EM_TRIPLE_FAULT; 1796 } 1797 1798 int rc = emR3GstInjectIntr(pVCpu, pfWakeupPending, pfInjected); 1799 if (rc == VINF_VMX_VMEXIT) 1800 rc = VINF_SUCCESS; 1801 return rc; 1802 } 1803 1804 /** @todo NSTVMX: Virtual interrupt injection, virtual-interrupt delivery. */ 1805 1777 * @param pVCpu The cross context virtual CPU structure. 1778 */ 1779 static int emR3SvmNstGstVirtIntrIntercept(PVMCPU pVCpu) 1780 { 1781 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1782 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR)) 1783 { 1784 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1785 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0); 1786 if (RT_SUCCESS(rcStrict)) 1787 { 1788 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1789 Assert(rcStrict != VINF_SVM_VMEXIT); 1790 return VBOXSTRICTRC_VAL(rcStrict); 1791 } 1792 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1793 return VINF_EM_TRIPLE_FAULT; 1794 } 1795 #else 1796 NOREF(pVCpu); 1797 #endif 1806 1798 return VINF_NO_CHANGE; 1807 1799 } 1808 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */ 1809 1810 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 1811 /** 1812 * Helper for emR3ForcedActions() for injecting interrupts into the 1813 * SVM nested-guest. 1814 * 1815 * @returns VBox status code. 1816 * @param pVCpu The cross context virtual CPU structure. 1817 * @param pfWakeupPending Where to store whether a wake up from HLT state is 1818 * pending. 1819 * @param pfInjected Where to store whether an interrupt was injected. 1820 */ 1821 static int emR3SvmNstGstInjectIntr(PVMCPU pVCpu, bool *pfWakeupPending, bool *pfInjected) 1822 { 1823 Assert(CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)); 1824 *pfWakeupPending = false; 1825 *pfInjected = false; 1826 1827 PVM pVM = pVCpu->CTX_SUFF(pVM); 1828 bool fGif = pVCpu->cpum.GstCtx.hwvirt.fGif; 1829 #ifdef VBOX_WITH_RAW_MODE 1830 fGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip); 1831 #endif 1832 if (fGif) 1833 { 1834 if (CPUMCanSvmNstGstTakePhysIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1835 { 1836 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 1837 if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 1838 { 1839 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_INTR)) 1840 { 1841 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1842 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_INTR, 0, 0); 1843 if (RT_SUCCESS(rcStrict)) 1844 { 1845 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1846 * doesn't intercept HLT but intercepts INTR? */ 1847 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1848 if (rcStrict == VINF_SVM_VMEXIT) 1849 rcStrict = VINF_SUCCESS; 1850 *pfWakeupPending = true; 1851 return VBOXSTRICTRC_VAL(rcStrict); 1852 } 1853 1854 AssertMsgFailed(("INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1855 return VINF_EM_TRIPLE_FAULT; 1856 } 1857 1858 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 1859 /** @todo this really isn't nice, should properly handle this */ 1860 int rc = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT); 1861 Assert(rc != VINF_PGM_CHANGE_MODE); 1862 if (rc == VINF_SVM_VMEXIT) 1863 rc = VINF_SUCCESS; 1864 *pfWakeupPending = true; 1865 *pfInjected = true; 1866 return rc; 1867 } 1868 } 1869 1870 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 1871 && CPUMCanSvmNstGstTakeVirtIntr(pVCpu, &pVCpu->cpum.GstCtx)) 1872 { 1873 if (CPUMIsGuestSvmCtrlInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, SVM_CTRL_INTERCEPT_VINTR)) 1874 { 1875 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK); 1876 VBOXSTRICTRC rcStrict = IEMExecSvmVmexit(pVCpu, SVM_EXIT_VINTR, 0, 0); 1877 if (RT_SUCCESS(rcStrict)) 1878 { 1879 /** @todo r=ramshankar: Do we need to signal a wakeup here? If a nested-guest 1880 * doesn't intercept HLT but intercepts VINTR? */ 1881 Assert(rcStrict != VINF_PGM_CHANGE_MODE); 1882 if (rcStrict == VINF_SVM_VMEXIT) 1883 rcStrict = VINF_SUCCESS; 1884 *pfWakeupPending = true; 1885 return VBOXSTRICTRC_VAL(rcStrict); 1886 } 1887 1888 AssertMsgFailed(("VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 1889 return VINF_EM_TRIPLE_FAULT; 1890 } 1891 1892 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST); 1893 uint8_t const uNstGstVector = CPUMGetSvmNstGstInterrupt(&pVCpu->cpum.GstCtx); 1894 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR vector %#x\n", uNstGstVector)); 1895 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT); 1896 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector)); 1897 1898 *pfWakeupPending = true; 1899 *pfInjected = true; 1900 return VINF_EM_RESCHEDULE; 1901 } 1902 } 1903 1904 return VINF_SUCCESS; 1905 } 1906 #endif /* VBOX_WITH_NESTED_HWVIRT_SVM */ 1800 1907 1801 1908 1802 /** … … 2227 2121 { 2228 2122 Assert(!HMR3IsEventPending(pVCpu)); 2229 2230 bool fInjected; 2231 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 2232 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)) 2233 rc2 = emR3VmxNstGstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2234 else 2235 #endif 2236 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 2237 if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)) 2238 rc2 = emR3SvmNstGstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2239 else 2240 #endif 2123 bool fGif = CPUMGetGuestGif(&pVCpu->cpum.GstCtx); 2124 #ifdef VBOX_WITH_RAW_MODE 2125 fGif &= !PATMIsPatchGCAddr(pVM, pVCpu->cpum.GstCtx.eip); 2126 #endif 2127 if (fGif) 2241 2128 { 2242 rc2 = emR3GstInjectIntr(pVCpu, &fWakeupPending, &fInjected); 2243 } 2244 if (rc2 != VINF_NO_CHANGE) 2245 { 2246 if ( pVM->em.s.fIemExecutesAll 2247 && ( rc2 == VINF_EM_RESCHEDULE_REM 2248 || rc2 == VINF_EM_RESCHEDULE_HM 2249 || rc2 == VINF_EM_RESCHEDULE_RAW)) 2129 /* In VMX, virtual interrupt takes priority over physical interrupts. */ 2130 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 2131 && CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx) 2132 && CPUMIsGuestVmxVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx)) 2250 2133 { 2251 rc2 = VINF_EM_RESCHEDULE; 2134 /** @todo NSTVMX: virtual interrupt delivery. */ 2135 rc2 = VINF_NO_CHANGE; 2252 2136 } 2137 /* In SVM, physical interrupts take priority over virtual interrupts. */ 2138 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC) 2139 && CPUMIsGuestPhysIntrEnabled(pVCpu)) 2140 { 2141 bool fInjected = false; 2142 Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI); 2143 2144 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)) 2145 rc2 = emR3VmxNstGstIntrWindowExit(pVCpu); 2146 else if (CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx)) 2147 rc2 = emR3SvmNstGstIntrIntercept(pVCpu); 2148 else 2149 rc2 = VINF_NO_CHANGE; 2150 2151 if (rc2 == VINF_NO_CHANGE) 2152 { 2153 CPUM_IMPORT_EXTRN_RET(pVCpu, IEM_CPUMCTX_EXTRN_XCPT_MASK); 2154 /** @todo this really isn't nice, should properly handle this */ 2155 rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT, &fInjected); 2156 fWakeupPending = true; 2157 if ( pVM->em.s.fIemExecutesAll 2158 && ( rc2 == VINF_EM_RESCHEDULE_REM 2159 || rc2 == VINF_EM_RESCHEDULE_HM 2160 || rc2 == VINF_EM_RESCHEDULE_RAW)) 2161 { 2162 rc2 = VINF_EM_RESCHEDULE; 2163 } 2164 } 2253 2165 #ifdef VBOX_STRICT 2254 if (fInjected) 2255 rcIrq = rc2; 2256 #endif 2257 UPDATE_RC(); 2166 if (fInjected) 2167 rcIrq = rc2; 2168 #endif 2169 UPDATE_RC(); 2170 } 2171 else if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST) 2172 && CPUMIsGuestInSvmNestedHwVirtMode(&pVCpu->cpum.GstCtx) 2173 && CPUMIsGuestSvmVirtIntrEnabled(pVCpu, &pVCpu->cpum.GstCtx)) 2174 { 2175 rc2 = emR3SvmNstGstVirtIntrIntercept(pVCpu); 2176 if (rc2 == VINF_NO_CHANGE) 2177 { 2178 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST); 2179 uint8_t const uNstGstVector = CPUMGetGuestSvmVirtIntrVector(&pVCpu->cpum.GstCtx); 2180 AssertMsg(uNstGstVector > 0 && uNstGstVector <= X86_XCPT_LAST, ("Invalid VINTR %#x\n", uNstGstVector)); 2181 TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT); 2182 Log(("EM: Asserting nested-guest virt. hardware intr: %#x\n", uNstGstVector)); 2183 rc2 = VINF_EM_RESCHEDULE; 2184 rcIrq = rc2; 2185 } 2186 UPDATE_RC(); 2187 } 2258 2188 } 2259 2189 } -
trunk/src/VBox/VMM/VMMR3/TRPM.cpp
r75767 r75830 1489 1489 1490 1490 /** 1491 * Inject event (such as external irq or trap) 1491 * Inject event (such as external irq or trap). 1492 1492 * 1493 1493 * @returns VBox status code. … … 1495 1495 * @param pVCpu The cross context virtual CPU structure. 1496 1496 * @param enmEvent Trpm event type 1497 */ 1498 VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent) 1497 * @param pfInjected Where to store whether the event was injected or not. 1498 */ 1499 VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent, bool *pfInjected) 1499 1500 { 1500 1501 #ifdef VBOX_WITH_RAW_MODE … … 1503 1504 #endif 1504 1505 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)); 1506 Assert(pfInjected); 1507 *pfInjected = false; 1505 1508 1506 1509 /* Currently only useful for external hardware interrupts. */ … … 1602 1605 } 1603 1606 #endif 1607 *pfInjected = true; 1604 1608 if (!VM_IS_NEM_ENABLED(pVM)) 1605 1609 {
Note:
See TracChangeset
for help on using the changeset viewer.