VirtualBox

Changeset 77295 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Feb 13, 2019 10:55:28 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128813
Message:

VMM/IEM: Nested VMX: bugref:9180 Fix CR3 VM-exits to work when CR3-target count is 0. Fix assertion during VM-entry with interrupt inhibition flag being already set.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r77169 r77295  
    915915 * @param   puValue         Where to store the CR3-target value.
    916916 */
    917 DECLINLINE(uint64_t) iemVmxVmcsGetCr3TargetValue(PCVMXVVMCS pVmcs, uint8_t idxCr3Target)
     917IEM_STATIC uint64_t iemVmxVmcsGetCr3TargetValue(PCVMXVVMCS pVmcs, uint8_t idxCr3Target)
    918918{
    919919    Assert(idxCr3Target < VMX_V_CR3_TARGET_COUNT);
     
    927927    uint8_t  const *pbField        = pbVmcs + offField;
    928928    uint64_t const uCr3TargetValue = *(uint64_t *)pbField;
    929 
    930929    return uCr3TargetValue;
    931930}
     
    28172816    /* Update the VM-exit reason, the other relevant data fields are expected to be updated by the caller already. */
    28182817    pVmcs->u32RoExitReason = uExitReason;
    2819     Log3(("vmexit: uExitReason=%#RX32 uExitQual=%#RX64\n", uExitReason, pVmcs->u64RoExitQual));
     2818    Log3(("vmexit: uExitReason=%#RX32 uExitQual=%#RX64 cs:rip=%04x:%#RX64\n", uExitReason, pVmcs->u64RoExitQual,
     2819          IEM_GET_CTX(pVCpu)->cs.Sel,  IEM_GET_CTX(pVCpu)->rip));
    28202820
    28212821    /*
     
    32503250            ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    32513251            ExitInfo.cbInstr = cbInstr;
    3252 
    32533252            ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 0) /* CR0 */
    32543253                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_CLTS);
     
    32863285    Assert(puNewCrX);
    32873286    Assert(iCrReg == 0 || iCrReg == 4);
     3287    Assert(iGReg < X86_GREG_COUNT);
    32883288
    32893289    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     
    33243324        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    33253325        ExitInfo.cbInstr = cbInstr;
    3326 
    33273326        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, iCrReg)
    33283327                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
     
    33553354    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    33563355    Assert(pVmcs);
     3356    Assert(iGReg < X86_GREG_COUNT);
    33573357    IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
    33583358
     
    33693369        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    33703370        ExitInfo.cbInstr = cbInstr;
    3371 
    33723371        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 3) /* CR3 */
    33733372                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_READ)
     
    33943393    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    33953394    Assert(pVmcs);
     3395    Assert(iGReg < X86_GREG_COUNT);
    33963396
    33973397    /*
     
    34033403    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_CR3_LOAD_EXIT)
    34043404    {
    3405         uint32_t uCr3TargetCount = pVmcs->u32Cr3TargetCount;
     3405        uint32_t const uCr3TargetCount = pVmcs->u32Cr3TargetCount;
    34063406        Assert(uCr3TargetCount <= VMX_V_CR3_TARGET_COUNT);
    34073407
    3408         for (uint32_t idxCr3Target = 0; idxCr3Target < uCr3TargetCount; idxCr3Target++)
    3409         {
    3410             uint64_t const uCr3TargetValue = iemVmxVmcsGetCr3TargetValue(pVmcs, idxCr3Target);
    3411             if (uNewCr3 != uCr3TargetValue)
     3408        /* If the CR3-target count is 0, we must always cause a VM-exit. */
     3409        bool fIntercept = RT_BOOL(uCr3TargetCount == 0);
     3410        if (!fIntercept)
     3411        {
     3412            for (uint32_t idxCr3Target = 0; idxCr3Target < uCr3TargetCount; idxCr3Target++)
    34123413            {
    3413                 Log2(("mov_Cr_Rd: (CR3) Guest intercept -> VM-exit\n"));
    3414 
    3415                 VMXVEXITINFO ExitInfo;
    3416                 RT_ZERO(ExitInfo);
    3417                 ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    3418                 ExitInfo.cbInstr = cbInstr;
    3419 
    3420                 ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 3) /* CR3 */
    3421                                  | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
    3422                                  | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG,   iGReg);
    3423                 return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     3414                uint64_t const uCr3TargetValue = iemVmxVmcsGetCr3TargetValue(pVmcs, idxCr3Target);
     3415                if (uNewCr3 != uCr3TargetValue)
     3416                {
     3417                    fIntercept = true;
     3418                    break;
     3419                }
    34243420            }
     3421        }
     3422
     3423        if (fIntercept)
     3424        {
     3425            Log2(("mov_Cr_Rd: (CR3) Guest intercept -> VM-exit\n"));
     3426
     3427            VMXVEXITINFO ExitInfo;
     3428            RT_ZERO(ExitInfo);
     3429            ExitInfo.uReason = VMX_EXIT_MOV_CRX;
     3430            ExitInfo.cbInstr = cbInstr;
     3431            ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 3) /* CR3 */
     3432                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
     3433                             | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG,   iGReg);
     3434            return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
    34253435        }
    34263436    }
     
    34423452    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    34433453    Assert(pVmcs);
     3454    Assert(iGReg < X86_GREG_COUNT);
    34443455
    34453456    /*
     
    34553466        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    34563467        ExitInfo.cbInstr = cbInstr;
    3457 
    34583468        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 8) /* CR8 */
    34593469                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_READ)
     
    34793489    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    34803490    Assert(pVmcs);
     3491    Assert(iGReg < X86_GREG_COUNT);
    34813492
    34823493    /*
     
    34923503        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
    34933504        ExitInfo.cbInstr = cbInstr;
    3494 
    34953505        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 8) /* CR8 */
    34963506                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
     
    35213531    Assert(iDrReg <= 7);
    35223532    Assert(uInstrId == VMXINSTRID_MOV_TO_DRX || uInstrId == VMXINSTRID_MOV_FROM_DRX);
     3533    Assert(iGReg < X86_GREG_COUNT);
    35233534
    35243535    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     
    69356946     */
    69366947    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     6948
     6949    /*
     6950     * If VM-entry is not vectoring, block-by-STI and block-by-MovSS state must be loaded.
     6951     * If VM-entry is vectoring, there is no block-by-STI or block-by-MovSS.
     6952     *
     6953     * See Intel spec. 26.6.1 "Interruptibility State".
     6954     */
    69376955    bool const fEntryVectoring = HMVmxIsVmentryVectoring(pVmcs->u32EntryIntInfo, NULL /* puEntryIntInfoType */);
    6938     if (!fEntryVectoring)
    6939     {
    6940         if (pVmcs->u32GuestIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
    6941             EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
    6942         else
    6943             Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
    6944 
    6945         /* SMI blocking is irrelevant. We don't support SMIs yet. */
    6946     }
    6947     else
    6948     {
    6949         /* When the VM-entry is not vectoring, there is no blocking by STI or Mov-SS. */
    6950         if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    6951             VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    6952     }
     6956    if (   !fEntryVectoring
     6957        && (pVmcs->u32GuestIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)))
     6958        EMSetInhibitInterruptsPC(pVCpu, pVmcs->u64GuestRip.u);
     6959    else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     6960        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    69536961
    69546962    /* NMI blocking. */
     
    69566964        && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
    69576965        VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     6966
     6967    /* SMI blocking is irrelevant. We don't support SMIs yet. */
    69586968
    69596969    /* Loading PDPTEs will be taken care when we switch modes. We don't support EPT yet. */
     
    73417351    }
    73427352
    7343     /** @todo Distinguish block-by-MOV-SS from block-by-STI. Currently we
     7353    /** @todo Distinguish block-by-MovSS from block-by-STI. Currently we
    73447354     *        use block-by-STI here which is not quite correct. */
    73457355    if (   VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
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