VirtualBox

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


Ignore:
Timestamp:
May 31, 2016 4:55:10 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
107611
Message:

CPUM,HM: CPUM must tell VT-x that it modified the host CR0 because it caches the value in the VMCS and state corruption may ensue if it restores it because we'll take a #NM when saving the guest state, probably ending up with the FPU state of the EMT instead.

Location:
trunk/src/VBox/VMM
Files:
9 edited

Legend:

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

    r61068 r61317  
    327327 * @retval VINF_SUCCESS           if the guest FPU state is loaded.
    328328 * @retval VINF_EM_RAW_GUEST_TRAP if it is a guest trap.
     329 * @retval VINF_CPUM_HOST_CR0_MODIFIED if we modified the host CR0.
    329330 *
    330331 * @param   pVM         The cross context VM structure.
     
    386387 * state into the CPU.
    387388 *
    388  * @returns VINF_SUCCESS (for CPUMR0Trap07Handler).
     389 * @returns VINF_SUCCESS on success, host CR0 unmodified.
     390 * @returns VINF_CPUM_HOST_CR0_MODIFIED on success when the host CR0 was
     391 *          modified and VT-x needs to update the value in the VMCS.
    389392 *
    390393 * @param   pVM     The cross context VM structure.
     
    393396VMMR0_INT_DECL(int) CPUMR0LoadGuestFPU(PVM pVM, PVMCPU pVCpu)
    394397{
     398    int rc = VINF_SUCCESS;
    395399    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
    396400    Assert(!(pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_GUEST));
     
    404408        /* Save the host state if necessary. */
    405409        if (!(pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_HOST))
    406             cpumRZSaveHostFPUState(&pVCpu->cpum.s);
     410            rc = cpumRZSaveHostFPUState(&pVCpu->cpum.s);
    407411
    408412        /* Restore the state on entry as we need to be in 64-bit mode to access the full state. */
     
    418422        {
    419423            Assert(!(pVCpu->cpum.s.fUseFlags & CPUM_USED_MANUAL_XMM_RESTORE));
    420             cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
     424            rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
    421425        }
    422426        else
     
    428432            uint64_t uHostEfer = ASMRdMsr(MSR_K6_EFER);
    429433            if (!(uHostEfer & MSR_K6_EFER_FFXSR))
    430                 cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
     434                rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
    431435            else
    432436            {
     
    434438                pVCpu->cpum.s.fUseFlags |= CPUM_USED_MANUAL_XMM_RESTORE;
    435439                ASMWrMsr(MSR_K6_EFER, uHostEfer & ~MSR_K6_EFER_FFXSR);
    436                 cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
     440                rc = cpumR0SaveHostRestoreGuestFPUState(&pVCpu->cpum.s);
    437441                ASMWrMsr(MSR_K6_EFER, uHostEfer | MSR_K6_EFER_FFXSR);
    438442                ASMSetFlags(uSavedFlags);
     
    442446               ==                            (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_HOST | CPUM_USED_FPU_SINCE_REM));
    443447    }
    444     return VINF_SUCCESS;
     448    return rc;
    445449}
    446450
  • trunk/src/VBox/VMM/VMMR0/CPUMR0A.asm

    r61144 r61317  
    6363; Saves the host FPU/SSE/AVX state and restores the guest FPU/SSE/AVX state.
    6464;
     65; @returns  VINF_SUCCESS (0) or VINF_CPUM_HOST_CR0_MODIFIED. (EAX)
    6566; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
    6667;
     
    156157        popf
    157158
     159%ifndef CPUM_CAN_USE_FPU_IN_R0
     160        test    ecx, ecx
     161        jnz     .modified_cr0
     162%endif
     163        xor     eax, eax
     164.return:
    158165%ifdef RT_ARCH_X86
    159166        pop     esi
     
    162169        leave
    163170        ret
     171
     172%ifndef CPUM_CAN_USE_FPU_IN_R0
     173.modified_cr0:
     174        mov     eax, VINF_CPUM_HOST_CR0_MODIFIED
     175        jmp     .return
     176%endif
    164177ENDPROC   cpumR0SaveHostRestoreGuestFPUState
    165178
  • trunk/src/VBox/VMM/VMMR0/HMR0.cpp

    r61144 r61317  
    15161516{
    15171517    HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
     1518}
     1519
     1520
     1521/**
     1522 * Notification from CPUM that it has modified the host CR0 (because of FPU).
     1523 *
     1524 * @param   pVCpu   The cross context virtual CPU structure of the calling EMT.
     1525 */
     1526VMMR0_INT_DECL(void) HMR0NotifyCpumModifiedHostCr0(PVMCPU pVCpu)
     1527{
     1528    HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    15181529}
    15191530
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r61155 r61317  
    31203120        && !CPUMIsGuestFPUStateActive(pVCpu))
    31213121    {
    3122         CPUMR0LoadGuestFPU(pVM, pVCpu);
     3122        CPUMR0LoadGuestFPU(pVM, pVCpu); /* (Ignore rc, no need to set HM_CHANGED_HOST_CONTEXT for SVM.) */
    31233123        HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
    31243124    }
     
    53885388        Assert(!pSvmTransient->fWasGuestFPUStateActive);
    53895389#endif
    5390         rc = CPUMR0Trap07Handler(pVCpu->CTX_SUFF(pVM), pVCpu);
    5391         Assert(rc == VINF_EM_RAW_GUEST_TRAP || (rc == VINF_SUCCESS && CPUMIsGuestFPUStateActive(pVCpu)));
     5390        rc = CPUMR0Trap07Handler(pVCpu->CTX_SUFF(pVM), pVCpu); /* (No need to set HM_CHANGED_HOST_CONTEXT for SVM.) */
     5391        Assert(   rc == VINF_EM_RAW_GUEST_TRAP
     5392               || ((rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED) && CPUMIsGuestFPUStateActive(pVCpu)));
    53925393    }
    53935394
     
    53955396    VMMRZCallRing3Enable(pVCpu);
    53965397
    5397     if (rc == VINF_SUCCESS)
     5398    if (rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED)
    53985399    {
    53995400        /* Guest FPU state was activated, we'll want to change CR0 FPU intercepts before the next VM-reentry. */
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r61156 r61317  
    86268626#ifdef HMVMX_ALWAYS_SWAP_FPU_STATE
    86278627    if (!CPUMIsGuestFPUStateActive(pVCpu))
    8628         CPUMR0LoadGuestFPU(pVM, pVCpu);
     8628        if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
     8629            HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    86298630    HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
    86308631#endif
     
    86338634        && !CPUMIsGuestFPUStateActive(pVCpu))
    86348635    {
    8635         CPUMR0LoadGuestFPU(pVM, pVCpu);
     8636        if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
     8637            HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    86368638        Assert(HMVMXCPU_GST_IS_UPDATED(pVCpu, HMVMX_UPDATED_GUEST_CR0));
    86378639        HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR0);
     
    1298812990#endif
    1298912991        rc = CPUMR0Trap07Handler(pVCpu->CTX_SUFF(pVM), pVCpu);
    12990         Assert(rc == VINF_EM_RAW_GUEST_TRAP || (rc == VINF_SUCCESS && CPUMIsGuestFPUStateActive(pVCpu)));
     12992        Assert(   rc == VINF_EM_RAW_GUEST_TRAP
     12993               || ((rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED) && CPUMIsGuestFPUStateActive(pVCpu)));
     12994        if (rc == VINF_CPUM_HOST_CR0_MODIFIED)
     12995            HMCPU_CF_SET(pVCpu, HM_CHANGED_HOST_CONTEXT);
    1299112996    }
    1299212997
     
    1299412999    VMMRZCallRing3Enable(pVCpu);
    1299513000
    12996     if (rc == VINF_SUCCESS)
     13001    if (rc == VINF_SUCCESS || rc == VINF_CPUM_HOST_CR0_MODIFIED)
    1299713002    {
    1299813003        /* Guest FPU state was activated, we'll want to change CR0 FPU intercepts before the next VM-reentry. */
  • trunk/src/VBox/VMM/VMMRZ/CPUMRZ.cpp

    r61147 r61317  
    4949    {
    5050        case 0:
     51#ifdef IN_RC
    5152            cpumRZSaveHostFPUState(&pVCpu->cpum.s);
    52 #ifdef IN_RC
    5353            VMCPU_FF_SET(pVCpu, VMCPU_FF_CPUM); /* Must recalc CR0 before executing more code! */
     54#else
     55            if (cpumRZSaveHostFPUState(&pVCpu->cpum.s) == VINF_CPUM_HOST_CR0_MODIFIED)
     56                HMR0NotifyCpumModifiedHostCr0(pVCpu);
    5457#endif
    5558            break;
  • trunk/src/VBox/VMM/VMMRZ/CPUMRZA.asm

    r61146 r61317  
    2525%include "iprt/x86.mac"
    2626%include "VBox/vmm/cpum.mac"
     27%include "VBox/err.mac"
    2728
    2829
     
    3839; re-evaluate the situation before executing more guest code.
    3940;
    40 ; @returns  VINF_SUCCESS (0) in EAX
     41; @returns  VINF_SUCCESS (0) or VINF_CPUM_HOST_CR0_MODIFIED. (EAX)
    4142; @param    pCpumCpu  x86:[ebp+8] gcc:rdi msc:rcx     CPUMCPU pointer
    4243;
     
    7879        ; leave it like that so IEM can use the FPU/SSE/AVX host CPU features directly.
    7980        ;
    80         SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX
     81        SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX               ; xCX must be preserved!
    8182        ;; @todo What about XCR0?
    8283 %ifdef IN_RING0
     
    9394        popf
    9495
     96%ifndef CPUM_CAN_USE_FPU_IN_R0
     97        ; Figure the return code.
     98        test    ecx, ecx
     99        jnz     .modified_cr0
     100%endif
     101        xor     eax, eax
     102.return:
     103
    95104%ifdef RT_ARCH_X86
    96105        pop     esi
     
    99108        leave
    100109        ret
     110
     111%ifndef CPUM_CAN_USE_FPU_IN_R0
     112.modified_cr0:
     113        mov     eax, VINF_CPUM_HOST_CR0_MODIFIED
     114        jmp     .return
     115%endif
    101116%undef pCpumCpu
    102117%undef pXState
  • trunk/src/VBox/VMM/include/CPUMInternal.h

    r61144 r61317  
    540540
    541541# ifdef IN_RING0
    542 DECLASM(void)       cpumR0SaveHostRestoreGuestFPUState(PCPUMCPU pCPUM);
     542DECLASM(int)        cpumR0SaveHostRestoreGuestFPUState(PCPUMCPU pCPUM);
    543543DECLASM(void)       cpumR0SaveGuestRestoreHostFPUState(PCPUMCPU pCPUM);
    544544#  if ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
     
    548548
    549549# if defined(IN_RC) || defined(IN_RING0)
    550 DECLASM(void)       cpumRZSaveHostFPUState(PCPUMCPU pCPUM);
     550DECLASM(int)        cpumRZSaveHostFPUState(PCPUMCPU pCPUM);
    551551DECLASM(void)       cpumRZSaveGuestFpuState(PCPUMCPU pCPUM, bool fLeaveFpuAccessible);
    552552DECLASM(void)       cpumRZSaveGuestSseRegisters(PCPUMCPU pCPUM);
  • trunk/src/VBox/VMM/include/CPUMInternal.mac

    r61162 r61317  
    4848%ifdef RT_OS_DARWIN
    4949 ; Intel Darwin kernels will load the FPU context of the current thread (user land).
    50  %define CPUM_CAN_USE_FPU_IN_R0 1
     50 ;; @todo we still need to check CR0 and tell HMVMX when CR0 changes!
     51 ;%define CPUM_CAN_USE_FPU_IN_R0 1
    5152%endif
    5253%ifdef RT_OS_LINUX
     
    5455 ; at least that what my LXR research on 2.6.18+ indicates.  It's possible this was
    5556 ; done differently at some point, I seems to recall issues with it ages and ages ago.
    56 ; %define CPUM_CAN_USE_FPU_IN_R0 1 - test me first
     57 ;; @todo We still need to check CR0 and tell HMVMX when CR0 changes!
     58 ;%define CPUM_CAN_USE_FPU_IN_R0 1
    5759%endif
    5860%ifndef IN_RING0
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