Changeset 79100 in vbox
- Timestamp:
- Jun 12, 2019 8:17:21 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131262
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r79090 r79100 291 291 /** Pointer to VMX transient state. */ 292 292 typedef VMXTRANSIENT *PVMXTRANSIENT; 293 /** Pointer to a const VMX transient state. */ 294 typedef const VMXTRANSIENT *PCVMXTRANSIENT; 295 293 296 294 297 /** … … 743 746 744 747 /** 748 * Checks whether one of the given Pin-based VM-execution controls are set. 749 * 750 * @returns @c true if set, @c false otherwise. 751 * @param pVCpu The cross context virtual CPU structure. 752 * @param pVmxTransient The VMX-transient structure. 753 * @param uPinCtls The Pin-based VM-execution controls to check. 754 * 755 * @remarks This will not check merged controls when executing a nested-guest 756 * but the original control specified by the guest hypervisor. 757 */ 758 static bool hmR0VmxIsPinCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uPinCtls) 759 { 760 if (!pVmxTransient->fIsNestedGuest) 761 { 762 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 763 return RT_BOOL(pVmcsInfo->u32PinCtls & uPinCtls); 764 } 765 return CPUMIsGuestVmxPinCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uPinCtls); 766 } 767 768 769 /** 770 * Checks whether one of the given Processor-based VM-execution controls are set. 771 * 772 * @returns @c true if set, @c false otherwise. 773 * @param pVCpu The cross context virtual CPU structure. 774 * @param pVmxTransient The VMX-transient structure. 775 * @param uPinCtls The Processor-based VM-execution controls to check. 776 * 777 * @remarks This will not check merged controls when executing a nested-guest 778 * but the original control specified by the guest hypervisor. 779 */ 780 static bool hmR0VmxIsProcCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uProcCtls) 781 { 782 if (!pVmxTransient->fIsNestedGuest) 783 { 784 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 785 return RT_BOOL(pVmcsInfo->u32ProcCtls & uProcCtls); 786 } 787 return CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls); 788 } 789 790 791 /** 792 * Checks whether one of the given Secondary Processor-based VM-execution controls 793 * are set. 794 * 795 * @returns @c true if set, @c false otherwise. 796 * @param pVCpu The cross context virtual CPU structure. 797 * @param pVmxTransient The VMX-transient structure. 798 * @param uPinCtls The Secondary Processor-based VM-execution controls to 799 * check. 800 * 801 * @remarks This will not check merged controls when executing a nested-guest 802 * but the original control specified by the guest hypervisor. 803 */ 804 static bool hmR0VmxIsProcCtls2Set(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uProcCtls2) 805 { 806 if (!pVmxTransient->fIsNestedGuest) 807 { 808 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 809 return RT_BOOL(pVmcsInfo->u32ProcCtls2 & uProcCtls2); 810 } 811 return CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls2); 812 } 813 814 815 #if 0 816 /** 817 * Checks whether one of the given VM-entry controls are set. 818 * 819 * @returns @c true if set, @c false otherwise. 820 * @param pVCpu The cross context virtual CPU structure. 821 * @param pVmxTransient The VMX-transient structure. 822 * @param uPinCtls The VM-entry controls to check. 823 * 824 * @remarks This will not check merged controls when executing a nested-guest 825 * but the original control specified by the guest hypervisor. 826 */ 827 static bool hmR0VmxIsEntryCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uEntryCtls) 828 { 829 if (!pVmxTransient->fIsNestedGuest) 830 { 831 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 832 return RT_BOOL(pVmcsInfo->u32EntryCtls & uEntryCtls); 833 } 834 return CPUMIsGuestVmxEntryCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uEntryCtls); 835 } 836 837 838 /** 839 * Checks whether one of the given VM-exit controls are set. 840 * 841 * @returns @c true if set, @c false otherwise. 842 * @param pVCpu The cross context virtual CPU structure. 843 * @param pVmxTransient The VMX-transient structure. 844 * @param uPinCtls The VM-exit controls to check. 845 * 846 * @remarks This will not check merged controls when executing a nested-guest 847 * but the original control specified by the guest hypervisor. 848 */ 849 static bool hmR0VmxIsExitCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uExitCtls) 850 { 851 if (!pVmxTransient->fIsNestedGuest) 852 { 853 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 854 return RT_BOOL(pVmcsInfo->u32ExitCtls & uExitCtls); 855 } 856 return CPUMIsGuestVmxExitCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uExitCtls); 857 } 858 #endif 859 860 861 /** 745 862 * Adds one or more exceptions to the exception bitmap and commits it to the current 746 863 * VMCS. … … 4557 4674 * 4558 4675 * @returns Guest's interruptibility-state. 4559 * @param pVCpu The cross context virtual CPU structure.4560 * @param pVm csInfo The VMCS info. object.4676 * @param pVCpu The cross context virtual CPU structure. 4677 * @param pVmxTransient The VMX-transient structure. 4561 4678 * 4562 4679 * @remarks No-long-jump zone!!! 4563 4680 */ 4564 static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, P CVMXVMCSINFO pVmcsInfo)4681 static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) 4565 4682 { 4566 4683 /* … … 4605 4722 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}. 4606 4723 */ 4607 if ( (pVmcsInfo->u32PinCtls &VMX_PIN_CTLS_VIRT_NMI)4724 if ( hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI) 4608 4725 && CPUMIsGuestNmiBlocking(pVCpu)) 4609 4726 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI; … … 6101 6218 * @remarks No-long-jump zone!!! 6102 6219 */ 6103 DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, P VMXTRANSIENT pVmxTransient)6220 DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient) 6104 6221 { 6105 6222 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */ … … 7347 7464 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); 7348 7465 7349 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 7350 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS); 7466 CPUMSetGuestNmiBlocking(pVCpu, false); 7351 7467 } 7352 7468 else … … 7366 7482 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); 7367 7483 7368 if (u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI) 7369 { 7370 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 7371 VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS); 7372 } 7373 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 7374 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS); 7484 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI); 7485 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking); 7375 7486 } 7376 7487 } … … 8768 8879 8769 8880 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */ 8770 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVm csInfo);8881 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient); 8771 8882 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS); 8772 8883 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI); … … 10024 10135 static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst) 10025 10136 { 10026 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap); 10027 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap; 10028 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap; 10029 Assert(pu64MsrBitmapNstGst); 10030 Assert(pu64MsrBitmapGst); 10137 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE; 10138 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap; 10031 10139 Assert(pu64MsrBitmap); 10032 10140 … … 10035 10143 * MSR that is intercepted by the guest is also intercepted while executing the 10036 10144 * nested-guest using hardware-assisted VMX. 10145 * 10146 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a 10147 * nested-guest VM-exit even if the outer guest is not intercepting some 10148 * MSRs. We cannot assume the caller has initialized the nested-guest 10149 * MSR bitmap in this case. 10150 * 10151 * The guest hypervisor may also switch whether it uses MSR bitmaps for 10152 * each VM-entry, hence initializing it once per-VM while setting up the 10153 * nested-guest VMCS is not sufficient. 10037 10154 */ 10038 uint32_t const cFrags = X86_PAGE_4K_SIZE / sizeof(uint64_t); 10039 for (uint32_t i = 0; i < cFrags; i++) 10040 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i]; 10155 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 10156 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS) 10157 { 10158 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap); 10159 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap; 10160 Assert(pu64MsrBitmapNstGst); 10161 Assert(pu64MsrBitmapGst); 10162 10163 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t); 10164 for (uint32_t i = 0; i < cFrags; i++) 10165 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i]; 10166 } 10167 else 10168 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff)); 10041 10169 } 10042 10170 … … 10417 10545 /* 10418 10546 * Virtualize memory-mapped accesses to the physical APIC (may take locks). 10419 * We look at the guest VMCS control here as we always set it when supported by10420 * the physical CPU. Looking at the nested-guest control here would not be10421 * possible because they are not merged yet.10422 10547 */ 10423 10548 PVM pVM = pVCpu->CTX_SUFF(pVM); … … 10425 10550 Assert(pVmcsInfo); 10426 10551 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase 10427 && (pVmcsInfo->u32ProcCtls2 &VMX_PROC_CTLS2_VIRT_APIC_ACCESS)10552 && hmR0VmxIsProcCtls2Set(pVCpu, pVmxTransient, VMX_PROC_CTLS2_VIRT_APIC_ACCESS) 10428 10553 && PDMHasApic(pVM)) 10429 10554 { … … 11152 11277 * @param pDbgState The debug state to initialize. 11153 11278 */ 11154 static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, P VMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)11279 static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState) 11155 11280 { 11156 11281 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip; … … 12827 12952 static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) 12828 12953 { 12829 VBOXSTRICTRC rcStrict = VINF_SUCCESS;12830 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;12831 12832 12954 /* Read the IDT vectoring info. and VM-exit interruption info. */ 12833 12955 { … … 12837 12959 } 12838 12960 12961 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 12839 12962 uint32_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo); 12840 12963 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo)) … … 12902 13025 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception". See @bugref{7445}. 12903 13026 */ 12904 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS) 12905 && uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI 13027 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI 12906 13028 && ( enmRaise == IEMXCPTRAISE_PREV_EVENT 12907 13029 || (fRaiseInfo & IEMXCPTRAISEINFO_NMI_PF)) 12908 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)) 12909 { 12910 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS); 13030 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI) 13031 && CPUMIsGuestNmiBlocking(pVCpu)) 13032 { 13033 CPUMSetGuestNmiBlocking(pVCpu, false); 12911 13034 } 12912 13035 … … 12997 13120 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitIntInfo) 12998 13121 && uExitVector != X86_XCPT_DF 12999 && (pVmcsInfo->u32PinCtls &VMX_PIN_CTLS_VIRT_NMI))13122 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI)) 13000 13123 { 13001 13124 /* … … 13004 13127 * See Intel spec. 30.7.1.2 "Resuming guest software after handling an exception". 13005 13128 */ 13006 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS)) 13007 { 13008 Log4Func(("Setting VMCPU_FF_BLOCK_NMIS. fValid=%RTbool uExitReason=%u\n", 13009 VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo), pVmxTransient->uExitReason)); 13010 VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS); 13011 } 13129 CPUMSetGuestNmiBlocking(pVCpu, true); 13130 Log4Func(("Set NMI blocking. fValid=%RTbool uExitReason=%u\n", VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo), 13131 pVmxTransient->uExitReason)); 13012 13132 } 13013 13133 … … 13206 13326 } 13207 13327 13208 Assert(! VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS));13328 Assert(!CPUMIsGuestNmiBlocking(pVCpu)); 13209 13329 13210 13330 /* … … 13804 13924 13805 13925 #ifdef VBOX_STRICT 13806 if ( pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)13926 if (hmR0VmxIsProcCtlsSet(pVCpu, pVmxTransient, VMX_PROC_CTLS_USE_MSR_BITMAPS)) 13807 13927 { 13808 13928 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr) … … 13907 14027 13908 14028 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not supported. */ 13909 if (! (pVmcsInfo->u32ProcCtls &VMX_PROC_CTLS_USE_MSR_BITMAPS))14029 if (!hmR0VmxIsProcCtlsSet(pVCpu, pVmxTransient, VMX_PROC_CTLS_USE_MSR_BITMAPS)) 13910 14030 { 13911 14031 switch (idMsr) … … 15065 15185 { 15066 15186 #ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS 15067 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv );15187 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest); 15068 15188 #endif 15069 15189 /* If the guest is not in real-mode or we have unrestricted guest execution support, reflect #GP to the guest. */ … … 15076 15196 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel)); 15077 15197 15078 if ( !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv 15198 if ( pVmxTransient->fIsNestedGuest 15199 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv 15079 15200 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx)) 15080 15201 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), … … 15087 15208 Assert(CPUMIsGuestInRealModeEx(pCtx)); 15088 15209 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest); 15210 Assert(!pVmxTransient->fIsNestedGuest); 15089 15211 15090 15212 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); … … 15136 15258 #ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS 15137 15259 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 15138 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active ,15260 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest, 15139 15261 ("uVector=%#x u32XcptBitmap=%#X32\n", 15140 15262 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap)); … … 15142 15264 #endif 15143 15265 15144 /* Re-inject the exception into the guest. This cannot be a double-fault condition which would have been handled in 15145 hmR0VmxCheckExitDueToEventDelivery(). */ 15266 /* 15267 * Re-inject the exception into the guest. This cannot be a double-fault condition which 15268 * would have been handled while checking exits due to event delivery. 15269 */ 15146 15270 int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 15147 15271 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
Note:
See TracChangeset
for help on using the changeset viewer.