Changeset 79751 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jul 13, 2019 9:00:45 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r79750 r79751 84 84 #define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7) 85 85 /** @} */ 86 87 /** All the VMCS fields required for our processing of exception/NMI VM-exits. */ 88 #define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \ 89 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \ 90 | HMVMX_READ_EXIT_INSTR_LEN \ 91 | HMVMX_READ_IDT_VECTORING_INFO \ 92 | HMVMX_READ_IDT_VECTORING_ERROR_CODE) 86 93 87 94 /** … … 13625 13632 Assert(!pVCpu->hm.s.Event.fPending); 13626 13633 13634 #ifdef VBOX_STRICT 13635 /* 13636 * Validate we have read the required fields from the VMCS. 13637 */ 13638 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); 13639 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 13640 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO); 13641 #endif 13642 13627 13643 /* 13628 13644 * Construct a pending event from IDT vectoring information. … … 13756 13772 VBOXSTRICTRC rcStrict = VINF_SUCCESS; 13757 13773 13758 /* Read the IDT vectoring info. and VM-exit interruption info. */ 13759 { 13760 int rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 13761 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 13762 AssertRCReturn(rc, rc); 13763 } 13774 #ifdef VBOX_STRICT 13775 /* 13776 * Validate we have read the required fields from the VMCS. 13777 */ 13778 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); 13779 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 13780 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO); 13781 #endif 13764 13782 13765 13783 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo; … … 13851 13869 uint32_t u32ErrCode; 13852 13870 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo)) 13853 {13854 int rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);13855 AssertRCReturn(rc, rc);13856 13871 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode; 13857 }13858 13872 else 13859 13873 u32ErrCode = 0; … … 14342 14356 /** 14343 14357 * VM-exit exception handler for \#PF (Page-fault exception). 14358 * 14359 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14344 14360 */ 14345 14361 static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14348 14364 PVM pVM = pVCpu->CTX_SUFF(pVM); 14349 14365 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 14350 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);14351 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);14352 14366 AssertRCReturn(rc, rc); 14353 14367 … … 14441 14455 /** 14442 14456 * VM-exit exception handler for \#MF (Math Fault: floating point exception). 14457 * 14458 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14443 14459 */ 14444 14460 static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14463 14479 } 14464 14480 14465 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);14466 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);14467 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);14468 AssertRCReturn(rc, rc);14469 14470 14481 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr, 14471 14482 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */); 14472 return rc;14483 return VINF_SUCCESS; 14473 14484 } 14474 14485 … … 14476 14487 /** 14477 14488 * VM-exit exception handler for \#BP (Breakpoint exception). 14489 * 14490 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14478 14491 */ 14479 14492 static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14485 14498 AssertRCReturn(rc, rc); 14486 14499 14487 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;14488 14500 if (!pVmxTransient->fIsNestedGuest) 14489 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE( pCtx));14501 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx)); 14490 14502 else 14491 14503 rc = VINF_EM_RAW_GUEST_TRAP; 14492 14504 if (rc == VINF_EM_RAW_GUEST_TRAP) 14493 14505 { 14494 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);14495 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);14496 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);14497 AssertRCReturn(rc, rc);14498 14499 14506 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr, 14500 14507 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */); … … 14508 14515 /** 14509 14516 * VM-exit exception handler for \#AC (Alignment-check exception). 14517 * 14518 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14510 14519 */ 14511 14520 static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14514 14523 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); 14515 14524 14516 /* 14517 * Re-inject it. We'll detect any nesting before getting here. 14518 */ 14519 int rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 14520 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 14521 AssertRCReturn(rc, rc); 14522 Assert(ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead) & HMVMX_READ_EXIT_INTERRUPTION_INFO); 14523 14525 /* Re-inject it. We'll detect any nesting before getting here. */ 14524 14526 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr, 14525 14527 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */); … … 14530 14532 /** 14531 14533 * VM-exit exception handler for \#DB (Debug exception). 14534 * 14535 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14532 14536 */ 14533 14537 static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14540 14544 */ 14541 14545 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 14546 AssertRCReturn(rc, rc); 14542 14547 14543 14548 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */ … … 14594 14599 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection". 14595 14600 */ 14596 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);14597 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);14598 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);14599 AssertRCReturn(rc, rc);14600 14601 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr, 14601 14602 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */); … … 14684 14685 /** 14685 14686 * VM-exit exception handler for \#GP (General-protection exception). 14687 * 14688 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14686 14689 */ 14687 14690 static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14690 14693 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); 14691 14694 14692 PCPUMCTX pCtx= &pVCpu->cpum.GstCtx;14695 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx; 14693 14696 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 14694 14697 if (pVmcsInfo->RealMode.fRealOnV86Active) … … 14703 14706 * executing a nested-guest, reflect #GP to the guest or nested-guest. 14704 14707 */ 14705 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 14706 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 14707 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 14708 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); 14708 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); 14709 14709 AssertRCReturn(rc, rc); 14710 14710 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip, … … 14767 14767 * This simply re-injects the exception back into the VM without any special 14768 14768 * processing. 14769 * 14770 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS. 14769 14771 */ 14770 14772 static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient) … … 14784 14786 * would have been handled while checking exits due to event delivery. 14785 14787 */ 14786 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);14787 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);14788 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);14789 AssertRCReturn(rc, rc);14790 14791 14788 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo); 14792 14789 14793 14790 #ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS 14794 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);14791 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP); 14795 14792 AssertRCReturn(rc, rc); 14796 14793 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip)); … … 14842 14839 DECL_FORCE_INLINE(VBOXSTRICTRC) hmR0VmxExitXcptAll(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uVector) 14843 14840 { 14841 /* 14842 * Validate we have read the required fields from the VMCS. 14843 */ 14844 #ifdef VBOX_STRICT 14845 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); 14846 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); 14847 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO); 14848 #endif 14849 14844 14850 switch (uVector) 14845 14851 { … … 14890 14896 AssertRCReturn(rc, rc); 14891 14897 14892 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo); 14898 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo); 14899 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo); 14893 14900 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo)); 14894 14901 14895 14902 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 14896 14903 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT) 14897 && u IntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);14904 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT); 14898 14905 NOREF(pVmcsInfo); 14899 14906 14900 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI) 14907 VBOXSTRICTRC rcStrict; 14908 switch (uExitIntType) 14901 14909 { 14902 14910 /* 14903 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we 14904 * injected it ourselves and anything we inject is not going to cause a VM-exit directly 14905 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2]. 14911 * Host physical NMIs: 14912 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we 14913 * injected it ourselves and anything we inject is not going to cause a VM-exit directly 14914 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2]. 14906 14915 * 14907 * [1] --See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".14908 * [2] --See Intel spec. 27.5.5 "Updating Non-Register State".14916 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery". 14917 * See Intel spec. 27.5.5 "Updating Non-Register State". 14909 14918 */ 14910 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 14911 return hmR0VmxExitHostNmi(pVCpu, pVmcsInfo); 14912 } 14913 14914 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */ 14915 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 14916 if (RT_UNLIKELY(rcStrict == VINF_SUCCESS)) 14917 { /* likely */ } 14918 else 14919 { 14920 if (rcStrict == VINF_HM_DOUBLE_FAULT) 14921 { 14922 Assert(pVCpu->hm.s.Event.fPending); 14923 rcStrict = VINF_SUCCESS; 14924 } 14925 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 14926 return rcStrict; 14927 } 14928 14929 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo; 14930 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo); 14931 switch (uIntType) 14932 { 14933 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: /* Privileged software exception. (#DB from ICEBP) */ 14919 case VMX_EXIT_INT_INFO_TYPE_NMI: 14920 { 14921 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo); 14922 break; 14923 } 14924 14925 /* 14926 * Privileged software exceptions (#DB from ICEBP), 14927 * Software exceptions (#BP and #OF), 14928 * Hardware exceptions: 14929 * Process the required exceptions and resume guest execution if possible. 14930 */ 14931 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: 14934 14932 Assert(uVector == X86_XCPT_DB); 14935 14933 RT_FALL_THRU(); 14936 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: /* Software exception. (#BP or #OF) */14937 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || u IntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);14934 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: 14935 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT); 14938 14936 RT_FALL_THRU(); 14939 14937 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT: 14940 14938 { 14939 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 14940 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 14941 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 14942 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 14943 AssertRCReturn(rc, rc); 14944 14941 14945 /* 14942 * If there's any exception caused as a result of event injection, the resulting 14943 * secondary/final execption will be pending, we shall continue guest execution 14944 * after injecting the event. The page-fault case is complicated and we manually 14945 * handle any currently pending event in hmR0VmxExitXcptPF. 14946 * If this VM-exit occurred while delivering an event through the guest IDT, take 14947 * action based on the return code and additional hints (e.g. for page-faults) 14948 * that will be updated in the VMX transient structure. 14946 14949 */ 14947 if (!pVCpu->hm.s.Event.fPending) 14948 { /* likely */ } 14949 else if (uVector != X86_XCPT_PF) 14950 rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 14951 if (rcStrict == VINF_SUCCESS) 14950 14952 { 14953 /* 14954 * If an exception caused a VM-exit due to delivery of an event, the secondary 14955 * exception may be made pending for re-injection. We shall reinject it and 14956 * continue guest execution. However, the page-fault case is a complicated case 14957 * and needs additional processing done in hmR0VmxExitXcptPF. 14958 */ 14959 if ( !pVCpu->hm.s.Event.fPending 14960 || uVector == X86_XCPT_PF) 14961 rcStrict = hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector); 14962 } 14963 else if (rcStrict == VINF_HM_DOUBLE_FAULT) 14964 { 14965 Assert(pVCpu->hm.s.Event.fPending); 14951 14966 rcStrict = VINF_SUCCESS; 14952 break;14953 14967 } 14954 rcStrict = hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector);14955 14968 break; 14956 14969 } … … 14958 14971 default: 14959 14972 { 14960 pVCpu->hm.s.u32HMError = uExitIntInfo;14973 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo; 14961 14974 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE; 14962 AssertMsgFailed((" Unexpected interruption info %#x\n", VMX_EXIT_INT_INFO_TYPE(uExitIntInfo)));14975 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo)); 14963 14976 break; 14964 14977 } 14965 14978 } 14979 14966 14980 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 14967 14981 return rcStrict; … … 16290 16304 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess); 16291 16305 16292 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */ 16293 VBOXSTRICTRC rcStrict1 = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 16294 if (RT_LIKELY(rcStrict1 == VINF_SUCCESS)) 16306 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 16307 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 16308 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 16309 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 16310 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 16311 AssertRCReturn(rc, rc); 16312 16313 /* 16314 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. 16315 */ 16316 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 16317 if (RT_LIKELY(rcStrict == VINF_SUCCESS)) 16295 16318 { 16296 16319 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */ … … 16303 16326 else 16304 16327 { 16305 if (rcStrict1 == VINF_HM_DOUBLE_FAULT) 16306 { 16307 Assert(pVCpu->hm.s.Event.fPending); 16308 rcStrict1 = VINF_SUCCESS; 16309 } 16310 return rcStrict1; 16328 Assert(rcStrict != VINF_HM_DOUBLE_FAULT); 16329 return rcStrict; 16311 16330 } 16312 16331 16313 16332 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */ 16314 16333 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 16315 intrc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);16316 rc 16334 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK); 16335 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 16317 16336 AssertRCReturn(rc, rc); 16318 16337 16319 16338 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */ 16320 16339 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual); 16321 VBOXSTRICTRC rcStrict2;16322 16340 switch (uAccessType) 16323 16341 { … … 16337 16355 PVM pVM = pVCpu->CTX_SUFF(pVM); 16338 16356 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx; 16339 rcStrict 2= IOMMMIOPhysHandler(pVM, pVCpu,16340 16341 16342 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict 2)));16343 if ( rcStrict 2== VINF_SUCCESS16344 || rcStrict 2== VERR_PAGE_TABLE_NOT_PRESENT16345 || rcStrict 2== VERR_PAGE_NOT_PRESENT)16357 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu, 16358 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, 16359 CPUMCTX2CORE(pCtx), GCPhys); 16360 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 16361 if ( rcStrict == VINF_SUCCESS 16362 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT 16363 || rcStrict == VERR_PAGE_NOT_PRESENT) 16346 16364 { 16347 16365 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS 16348 16366 | HM_CHANGED_GUEST_APIC_TPR); 16349 rcStrict 2= VINF_SUCCESS;16367 rcStrict = VINF_SUCCESS; 16350 16368 } 16351 16369 break; … … 16355 16373 { 16356 16374 Log4Func(("uAccessType=%#x\n", uAccessType)); 16357 rcStrict 2= VINF_EM_RAW_EMULATE_INSTR;16375 rcStrict = VINF_EM_RAW_EMULATE_INSTR; 16358 16376 break; 16359 16377 } 16360 16378 } 16361 16379 16362 if (rcStrict 2!= VINF_SUCCESS)16380 if (rcStrict != VINF_SUCCESS) 16363 16381 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3); 16364 return rcStrict 2;16382 return rcStrict; 16365 16383 } 16366 16384 … … 16465 16483 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging); 16466 16484 16467 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */ 16485 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 16486 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 16487 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 16488 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 16489 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 16490 AssertRCReturn(rc, rc); 16491 16492 /* 16493 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. 16494 */ 16468 16495 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 16469 16496 if (RT_LIKELY(rcStrict == VINF_SUCCESS)) … … 16489 16516 else 16490 16517 { 16491 if (rcStrict == VINF_HM_DOUBLE_FAULT) 16492 rcStrict = VINF_SUCCESS; 16518 Assert(rcStrict != VINF_HM_DOUBLE_FAULT); 16493 16519 return rcStrict; 16494 16520 } … … 16499 16525 RTGCPHYS GCPhys; 16500 16526 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 16501 int rc= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);16502 rc 16527 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys); 16528 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK); 16503 16529 AssertRCReturn(rc, rc); 16504 16530 … … 16557 16583 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging); 16558 16584 16559 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */ 16585 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 16586 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 16587 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 16588 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 16589 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 16590 AssertRCReturn(rc, rc); 16591 16592 /* 16593 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. 16594 */ 16560 16595 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient); 16561 16596 if (RT_LIKELY(rcStrict == VINF_SUCCESS)) … … 16570 16605 else 16571 16606 { 16572 if (rcStrict == VINF_HM_DOUBLE_FAULT) 16573 { 16574 Assert(pVCpu->hm.s.Event.fPending); 16575 rcStrict = VINF_SUCCESS; 16576 } 16607 Assert(rcStrict != VINF_HM_DOUBLE_FAULT); 16577 16608 return rcStrict; 16578 16609 } … … 16580 16611 RTGCPHYS GCPhys; 16581 16612 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 16582 intrc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);16583 rc 16584 rc 16613 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys); 16614 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 16615 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK); 16585 16616 AssertRCReturn(rc, rc); 16586 16617 … … 16998 17029 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient); 16999 17030 17000 int rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient); 17001 AssertRCReturn(rc, rc); 17002 17003 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 17031 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 17004 17032 AssertRCReturn(rc, rc); 17005 17033 … … 17012 17040 /* 17013 17041 * Physical NMIs: 17014 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.17042 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host. 17015 17043 */ 17016 17044 case VMX_EXIT_INT_INFO_TYPE_NMI: 17017 {17018 Assert(!pVCpu->hm.s.Event.fPending); /* An NMI cannot be caused by the delivery on another event. */17019 17045 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo); 17020 }17021 17046 17022 17047 /* … … 17024 17049 * Software exceptions, 17025 17050 * Privileged software exceptions: 17026 * Figure out if the exception must be delivered to the guest or the nested-guest. 17027 * 17028 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged 17029 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction 17030 * length. However, if delivery of a software interrupt, software exception or privileged 17031 * software exception causes a VM-exit, that too provides the VM-exit instruction length. 17032 * Hence, we read it for all exception types below to keep it simple. 17051 * Figure out if the exception must be delivered to the guest or the nested-guest. 17033 17052 */ 17034 17053 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: … … 17036 17055 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT: 17037 17056 { 17038 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 17039 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 17057 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 17058 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 17059 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 17060 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 17061 AssertRCReturn(rc, rc); 17062 17063 /* 17064 * If this VM-exit occurred while delivering an event through the nested-guest IDT, handle it accordingly. 17065 */ 17066 rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient); 17040 17067 AssertRCReturn(rc, rc); 17041 17068 … … 17048 17075 if (fIntercept) 17049 17076 { 17050 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 17051 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 17052 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 17077 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 17053 17078 AssertRCReturn(rc, rc); 17054 17079 17080 /* 17081 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged 17082 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction 17083 * length. However, if delivery of a software interrupt, software exception or privileged 17084 * software exception causes a VM-exit, that too provides the VM-exit instruction length. 17085 */ 17055 17086 VMXVEXITINFO ExitInfo; 17056 17087 RT_ZERO(ExitInfo); … … 17688 17719 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient); 17689 17720 17690 int rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient); 17721 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient); 17722 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient); 17723 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 17724 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 17725 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 17691 17726 AssertRCReturn(rc, rc); 17692 17727 17728 rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient); 17729 AssertRCReturn(rc, rc); 17730 17693 17731 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS)); 17694 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 17695 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient); 17696 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient); 17697 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient); 17732 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient); 17698 17733 AssertRCReturn(rc, rc); 17699 17734
Note:
See TracChangeset
for help on using the changeset viewer.