VirtualBox

Changeset 72530 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Jun 12, 2018 4:40:46 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123017
Message:

VMM/HMVMXR0: Always preload FPU as done before with SVM"

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r72522 r72530  
    4949# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
    5050# define HMVMX_ALWAYS_TRAP_PF
    51 # define HMVMX_ALWAYS_SWAP_FPU_STATE
    5251# define HMVMX_ALWAYS_FLUSH_TLB
    5352# define HMVMX_ALWAYS_SWAP_EFER
     
    148147#define HMVMX_REAL_MODE_XCPT_MASK    (  RT_BIT(X86_XCPT_DE)  /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI)   \
    149148                                      | RT_BIT(X86_XCPT_BP)             | RT_BIT(X86_XCPT_OF)    | RT_BIT(X86_XCPT_BR)    \
    150                                       | RT_BIT(X86_XCPT_UD)            /* RT_BIT(X86_XCPT_NM) */ | RT_BIT(X86_XCPT_DF)    \
     149                                      | RT_BIT(X86_XCPT_UD)             | RT_BIT(X86_XCPT_NM)    | RT_BIT(X86_XCPT_DF)    \
    151150                                      | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS)    | RT_BIT(X86_XCPT_NP)    \
    152151                                      | RT_BIT(X86_XCPT_SS)             | RT_BIT(X86_XCPT_GP)   /* RT_BIT(X86_XCPT_PF) */ \
    153                                      /* RT_BIT(X86_XCPT_MF)    always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC)    \
     152                                      | RT_BIT(X86_XCPT_MF)  /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC)    \
    154153                                      | RT_BIT(X86_XCPT_XF))
    155154
     
    288287    uint32_t        fVmcsFieldsRead;
    289288
    290     /** Whether the guest FPU was active at the time of VM-exit. */
    291     bool            fWasGuestFPUStateActive;
    292289    /** Whether the guest debug state was active at the time of VM-exit. */
    293290    bool            fWasGuestDebugStateActive;
     
    303300    bool            fVectoringPF;
    304301} VMXTRANSIENT;
    305 AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason,             sizeof(uint64_t));
    306 AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo,            sizeof(uint64_t));
    307 AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo,           sizeof(uint64_t));
    308 AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestFPUStateActive, sizeof(uint64_t));
     302AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason,               sizeof(uint64_t));
     303AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo,              sizeof(uint64_t));
     304AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo,             sizeof(uint64_t));
     305AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
    309306AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
    310307/** Pointer to VMX transient state. */
     
    452449/** @} */
    453450
    454 static int          hmR0VmxExitXcptNM(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient);
    455451static int          hmR0VmxExitXcptPF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient);
    456452static int          hmR0VmxExitXcptMF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient);
     
    37773773static int hmR0VmxLoadSharedCR0(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    37783774{
     3775    Assert(CPUMIsGuestFPUStateActive(pVCpu));
     3776
    37793777    /*
    37803778     * Guest CR0.
     
    38263824         */
    38273825        u32GuestCR0 |= X86_CR0_NE;
    3828         bool fInterceptNM = false;
    3829         if (CPUMIsGuestFPUStateActive(pVCpu))
    3830         {
    3831             fInterceptNM = false;              /* Guest FPU active, no need to VM-exit on #NM. */
    3832             /* The guest should still get #NM exceptions when it expects it to, so we should not clear TS & MP bits here.
    3833                We're only concerned about -us- not intercepting #NMs when the guest-FPU is active. Not the guest itself! */
    3834         }
    3835         else
    3836         {
    3837             fInterceptNM = true;               /* Guest FPU inactive, VM-exit on #NM for lazy FPU loading. */
    3838             u32GuestCR0 |=  X86_CR0_TS         /* Guest can task switch quickly and do lazy FPU syncing. */
    3839                           | X86_CR0_MP;        /* FWAIT/WAIT should not ignore CR0.TS and should generate #NM. */
    3840         }
    38413826
    38423827        /* Catch floating point exceptions if we need to report them to the guest in a different way. */
     
    38513836            Assert(pVM->hm.s.vmx.pRealModeTSS);
    38523837            pVCpu->hm.s.vmx.u32XcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
    3853             fInterceptNM = true;
    3854             fInterceptMF = true;
    38553838        }
    38563839        else
     
    38583841            /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
    38593842            pVCpu->hm.s.vmx.u32XcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
     3843            if (fInterceptMF)
     3844                pVCpu->hm.s.vmx.u32XcptBitmap |= RT_BIT(X86_XCPT_MF);
    38603845        }
    38613846        HMCPU_CF_SET(pVCpu, HM_CHANGED_VMM_GUEST_XCPT_INTERCEPTS);
    3862 
    3863         if (fInterceptNM)
    3864             pVCpu->hm.s.vmx.u32XcptBitmap |= RT_BIT(X86_XCPT_NM);
    3865         else
    3866             pVCpu->hm.s.vmx.u32XcptBitmap &= ~RT_BIT(X86_XCPT_NM);
    3867 
    3868         if (fInterceptMF)
    3869             pVCpu->hm.s.vmx.u32XcptBitmap |= RT_BIT(X86_XCPT_MF);
    3870         else
    3871             pVCpu->hm.s.vmx.u32XcptBitmap &= ~RT_BIT(X86_XCPT_MF);
    38723847
    38733848        /* Additional intercepts for debugging, define these yourself explicitly. */
     
    39323907        if (pVM->hm.s.fNestedPaging)
    39333908            u32CR0Mask &= ~X86_CR0_WP;
    3934 
    3935         /* If the guest FPU state is active, don't need to VM-exit on writes to FPU related bits in CR0. */
    3936         if (fInterceptNM)
    3937         {
    3938             u32CR0Mask |=  X86_CR0_TS
    3939                          | X86_CR0_MP;
    3940         }
    39413909
    39423910        /* Write the CR0 mask into the VMCS and update the VCPU's copy of the current CR0 mask. */
     
    90859053    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
    90869054
    9087 #ifdef HMVMX_ALWAYS_SWAP_FPU_STATE
    90889055    if (!CPUMIsGuestFPUStateActive(pVCpu))
    9089     {
    9090         STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
    9091         if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
    9092             HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    9093         STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
    9094         STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
    9095     }
    9096     HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
    9097 #endif
    9098 
    9099     if (   pVCpu->hm.s.fPreloadGuestFpu
    9100         && !CPUMIsGuestFPUStateActive(pVCpu))
    91019056    {
    91029057        STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
     
    91539108        pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
    91549109    }
    9155     pVmxTransient->fWasGuestFPUStateActive = CPUMIsGuestFPUStateActive(pVCpu);
    91569110
    91579111    /*
     
    1168811642                case X86_XCPT_PF: rc = hmR0VmxExitXcptPF(pVCpu, pMixedCtx, pVmxTransient);      break;
    1168911643                case X86_XCPT_GP: rc = hmR0VmxExitXcptGP(pVCpu, pMixedCtx, pVmxTransient);      break;
    11690                 case X86_XCPT_NM: rc = hmR0VmxExitXcptNM(pVCpu, pMixedCtx, pVmxTransient);      break;
    1169111644                case X86_XCPT_MF: rc = hmR0VmxExitXcptMF(pVCpu, pMixedCtx, pVmxTransient);      break;
    1169211645                case X86_XCPT_DB: rc = hmR0VmxExitXcptDB(pVCpu, pMixedCtx, pVmxTransient);      break;
     
    1169411647                case X86_XCPT_AC: rc = hmR0VmxExitXcptAC(pVCpu, pMixedCtx, pVmxTransient);      break;
    1169511648
     11649                case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM);
     11650                                  rc = hmR0VmxExitXcptGeneric(pVCpu, pMixedCtx, pVmxTransient); break;
    1169611651                case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF);
    1169711652                                  rc = hmR0VmxExitXcptGeneric(pVCpu, pMixedCtx, pVmxTransient); break;
     
    1353813493    return rc;
    1353913494}
    13540 
    13541 
    13542 /**
    13543  * VM-exit exception handler for \#NM (Device-not-available exception: floating
    13544  * point exception).
    13545  */
    13546 static int hmR0VmxExitXcptNM(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient)
    13547 {
    13548     HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS();
    13549 
    13550     /* We require CR0 and EFER. EFER is always up-to-date. */
    13551     int rc = hmR0VmxSaveGuestCR0(pVCpu, pMixedCtx);
    13552     AssertRCReturn(rc, rc);
    13553 
    13554     /* We're playing with the host CPU state here, have to disable preemption or longjmp. */
    13555     VMMRZCallRing3Disable(pVCpu);
    13556     HM_DISABLE_PREEMPT();
    13557 
    13558     /* If the guest FPU was active at the time of the #NM VM-exit, then it's a guest fault. */
    13559     if (pVmxTransient->fWasGuestFPUStateActive)
    13560     {
    13561         rc = VINF_EM_RAW_GUEST_TRAP;
    13562         Assert(CPUMIsGuestFPUStateActive(pVCpu) || HMCPU_CF_IS_PENDING(pVCpu, HM_CHANGED_GUEST_CR0));
    13563     }
    13564     else
    13565     {
    13566 #ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
    13567         Assert(!pVmxTransient->fWasGuestFPUStateActive || pVCpu->hm.s.fUsingDebugLoop);
    13568 #endif
    13569         rc = CPUMR0Trap07Handler(pVCpu->CTX_SUFF(pVM), pVCpu);
    13570         Assert(   rc == VINF_EM_RAW_GUEST_TRAP
    13571                || ((rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED) && CPUMIsGuestFPUStateActive(pVCpu)));
    13572         if (rc == VINF_CPUM_HOST_CR0_MODIFIED)
    13573             HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    13574     }
    13575 
    13576     HM_RESTORE_PREEMPT();
    13577     VMMRZCallRing3Enable(pVCpu);
    13578 
    13579     if (rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED)
    13580     {
    13581         /* Guest FPU state was activated, we'll want to change CR0 FPU intercepts before the next VM-reentry. */
    13582         HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
    13583         STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowNM);
    13584         pVCpu->hm.s.fPreloadGuestFpu = true;
    13585     }
    13586     else
    13587     {
    13588         /* Forward #NM to the guest. */
    13589         Assert(rc == VINF_EM_RAW_GUEST_TRAP);
    13590         rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
    13591         AssertRCReturn(rc, rc);
    13592         hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
    13593                                pVmxTransient->cbInstr, 0 /* error code */, 0 /* GCPtrFaultAddress */);
    13594         STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM);
    13595     }
    13596 
    13597     return VINF_SUCCESS;
    13598 }
    13599 
    1360013495
    1360113496/**
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