VirtualBox

Changeset 78977 in vbox


Ignore:
Timestamp:
Jun 5, 2019 6:24:38 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131105
Message:

VMM/IEM: Nested VMX: bugref:9180 Add interface for exception or NMI VM-exit handling with event info. Use CPUMIsGuestVmxXcptInterceptSet.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/iem.h

    r78951 r78977  
    335335VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitPreemptTimer(PVMCPU pVCpu);
    336336VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitExtInt(PVMCPU pVCpu, uint8_t uVector, bool fIntPending);
    337 VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitNmi(PVMCPU pVCpu);
     337VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitXcpt(PVMCPU pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo);
     338VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitXcptNmi(PVMCPU pVCpu);
    338339VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitTripleFault(PVMCPU pVCpu);
    339340VMM_INT_DECL(VBOXSTRICTRC)  IEMExecVmxVmexitStartupIpi(PVMCPU pVCpu, uint8_t uVector);
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r78958 r78977  
    1580515805 * @retval  VINF_VMX_VMEXIT if the access causes a VM-exit.
    1580615806 *
    15807  * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
     15807 * @param   pVCpu           The cross context virtual CPU structure of the calling EMT.
    1580815808 * @param   pExitInfo       Pointer to the VM-exit information.
    1580915809 * @param   pExitEventInfo  Pointer to the VM-exit event information.
     
    1587215872
    1587315873/**
     15874 * Interface for HM and EM to emulate VM-exit due to exceptions (incl. NMIs).
     15875 *
     15876 * @returns Strict VBox status code.
     15877 * @param   pVCpu           The cross context virtual CPU structure of the calling EMT.
     15878 * @param   pExitInfo       Pointer to the VM-exit information.
     15879 * @param   pExitEventInfo  Pointer to the VM-exit event information.
     15880 * @thread  EMT(pVCpu)
     15881 */
     15882VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitXcpt(PVMCPU pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo)
     15883{
     15884    Assert(pExitInfo);
     15885    Assert(pExitEventInfo);
     15886    VBOXSTRICTRC rcStrict = iemVmxVmexitEventWithInfo(pVCpu, pExitInfo, pExitEventInfo);
     15887    Assert(!pVCpu->iem.s.cActiveMappings);
     15888    return iemExecStatusCodeFiddling(pVCpu, rcStrict);
     15889}
     15890
     15891
     15892/**
    1587415893 * Interface for HM and EM to emulate VM-exit due to NMIs.
    1587515894 *
     
    1587815897 * @thread  EMT(pVCpu)
    1587915898 */
    15880 VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitNmi(PVMCPU pVCpu)
    15881 {
    15882     VBOXSTRICTRC rcStrict = iemVmxVmexitNmi(pVCpu);
     15899VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitXcptNmi(PVMCPU pVCpu)
     15900{
     15901    VMXVEXITINFO ExitInfo;
     15902    RT_ZERO(ExitInfo);
     15903    VMXVEXITEVENTINFO ExitEventInfo;
     15904    RT_ZERO(ExitInfo);
     15905    ExitEventInfo.uExitIntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,  1)
     15906                               | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,   VMX_EXIT_INT_INFO_TYPE_NMI)
     15907                               | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, X86_XCPT_NMI);
     15908
     15909    VBOXSTRICTRC rcStrict = iemVmxVmexitEventWithInfo(pVCpu, &ExitInfo, &ExitEventInfo);
    1588315910    Assert(!pVCpu->iem.s.cActiveMappings);
    1588415911    return iemExecStatusCodeFiddling(pVCpu, rcStrict);
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r78959 r78977  
    38553855
    38563856/**
    3857  * VMX VM-exit handler for VM-exits due to NMIs.
    3858  *
    3859  * @returns VBox strict status code.
    3860  * @param   pVCpu           The cross context virtual CPU structure.
    3861  *
    3862  * @remarks This function might import externally kept DR6 if necessary.
    3863  */
    3864 IEM_STATIC VBOXSTRICTRC iemVmxVmexitNmi(PVMCPU pVCpu)
    3865 {
    3866     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    3867     Assert(pVmcs);
    3868     Assert(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT);
    3869     Assert(pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents);
    3870     NOREF(pVmcs);
    3871     return iemVmxVmexitEvent(pVCpu, X86_XCPT_NMI, IEM_XCPT_FLAGS_T_CPU_XCPT, 0 /* uErrCode */, 0 /* uCr2 */, 0 /* cbInstr */);
    3872 }
    3873 
    3874 
    3875 /**
    38763857 * VMX VM-exit handler for VM-exits due to startup-IPIs (SIPI).
    38773858 *
     
    39343915
    39353916/**
     3917 * VMX VM-exit handler for VM-exit due to delivery of an events.
     3918 *
     3919 * This is intended for VM-exit due to exceptions or NMIs where the caller provides
     3920 * all the relevant VM-exit information.
     3921 *
     3922 * @returns VBox strict status code.
     3923 * @param   pVCpu               The cross context virtual CPU structure.
     3924 * @param   pExitInfo           Pointer to the VM-exit information.
     3925 * @param   pExitEventInfo      Pointer to the VM-exit event information.
     3926 */
     3927IEM_STATIC VBOXSTRICTRC iemVmxVmexitEventWithInfo(PVMCPU pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo)
     3928{
     3929    Assert(pExitInfo);
     3930    Assert(pExitEventInfo);
     3931    Assert(VMX_EXIT_INT_INFO_IS_VALID(pExitEventInfo->uExitIntInfo));
     3932
     3933    iemVmxVmcsSetExitQual(pVCpu, pExitInfo->u64Qual);
     3934    iemVmxVmcsSetExitInstrLen(pVCpu, pExitInfo->cbInstr);
     3935    iemVmxVmcsSetExitIntInfo(pVCpu, pExitEventInfo->uExitIntInfo);
     3936    iemVmxVmcsSetExitIntErrCode(pVCpu, pExitEventInfo->uExitIntErrCode);
     3937    iemVmxVmcsSetIdtVectoringInfo(pVCpu, pExitEventInfo->uIdtVectoringInfo);
     3938    iemVmxVmcsSetIdtVectoringErrCode(pVCpu, pExitEventInfo->uIdtVectoringErrCode);
     3939    return iemVmxVmexit(pVCpu, VMX_EXIT_XCPT_OR_NMI);
     3940}
     3941
     3942
     3943/**
    39363944 * VMX VM-exit handler for VM-exits due to delivery of an event.
    39373945 *
     
    39903998    /*
    39913999     * Evaluate intercepts for hardware exceptions, software exceptions (#BP, #OF),
    3992      * and privileged software exceptions (#DB generated by INT1/ICEBP).
     4000     * and privileged software exceptions (#DB generated by INT1/ICEBP) and software
     4001     * interrupts.
    39934002     */
    39944003    Assert(fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT));
    3995     bool fIntercept = false;
    3996     bool fIsHwXcpt  = false;
     4004    bool fIntercept;
    39974005    if (   !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)
    39984006        ||  (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR)))
    39994007    {
    4000         fIsHwXcpt = true;
    4001 
    4002         /* NMIs have a dedicated VM-execution control for causing VM-exits. */
    4003         if (uVector == X86_XCPT_NMI)
    4004         {
    4005             if (pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT)
    4006                 fIntercept = true;
    4007         }
    4008         else
    4009         {
    4010             /* Page-faults are subject to masking using its error code. */
    4011             uint32_t fXcptBitmap = pVmcs->u32XcptBitmap;
    4012             if (uVector == X86_XCPT_PF)
    4013             {
    4014                 uint32_t const fXcptPFMask  = pVmcs->u32XcptPFMask;
    4015                 uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch;
    4016                 if ((uErrCode & fXcptPFMask) != fXcptPFMatch)
    4017                     fXcptBitmap ^= RT_BIT(X86_XCPT_PF);
    4018             }
    4019 
    4020             /* Consult the exception bitmap for all other hardware exceptions. */
    4021             Assert(uVector <= X86_XCPT_LAST);
    4022             if (fXcptBitmap & RT_BIT(uVector))
    4023                 fIntercept = true;
    4024         }
    4025     }
    4026     /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */
    4027 
    4028     /*
    4029      * Now that we've determined whether the software interrupt or hardware exception
    4030      * causes a VM-exit, we need to construct the relevant VM-exit information and
    4031      * cause the VM-exit.
     4008        fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uVector, uErrCode);
     4009    }
     4010    else
     4011    {
     4012        /* Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */
     4013        fIntercept = false;
     4014    }
     4015
     4016    /*
     4017     * Now that we've determined whether the event causes a VM-exit, we need to construct the
     4018     * relevant VM-exit information and cause the VM-exit.
    40324019     */
    40334020    if (fIntercept)
     
    40364023
    40374024        /* Construct the rest of the event related information fields and cause the VM-exit. */
    4038         uint64_t uExitQual = 0;
    4039         if (fIsHwXcpt)
    4040         {
    4041             if (uVector == X86_XCPT_PF)
    4042             {
    4043                 Assert(fFlags & IEM_XCPT_FLAGS_CR2);
    4044                 uExitQual = uCr2;
    4045             }
    4046             else if (uVector == X86_XCPT_DB)
    4047             {
    4048                 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR6);
    4049                 uExitQual = pVCpu->cpum.GstCtx.dr[6] & VMX_VMCS_EXIT_QUAL_VALID_MASK;
    4050             }
    4051         }
     4025        uint64_t uExitQual;
     4026        if (uVector == X86_XCPT_PF)
     4027        {
     4028            Assert(fFlags & IEM_XCPT_FLAGS_CR2);
     4029            uExitQual = uCr2;
     4030        }
     4031        else if (uVector == X86_XCPT_DB)
     4032        {
     4033            IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_DR6);
     4034            uExitQual = pVCpu->cpum.GstCtx.dr[6] & VMX_VMCS_EXIT_QUAL_VALID_MASK;
     4035        }
     4036        else
     4037            uExitQual = 0;
    40524038
    40534039        uint8_t  const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     
    40644050
    40654051        /*
    4066          * For VM exits due to software exceptions (those generated by INT3 or INTO) or privileged
     4052         * For VM-exits due to software exceptions (those generated by INT3 or INTO) or privileged
    40674053         * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
    40684054         * length.
     
    41494135                                                       PCVMXVEXITEVENTINFO pExitEventInfo)
    41504136{
    4151     Assert(pExitInfo);
    4152     Assert(pExitEventInfo);
    4153 
    41544137    /* VM-exit interruption information should not be valid for APIC-access VM-exits. */
    41554138    Assert(!VMX_EXIT_INT_INFO_IS_VALID(pExitEventInfo->uExitIntInfo));
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