VirtualBox

Changeset 54650 in vbox for trunk/src


Ignore:
Timestamp:
Mar 5, 2015 1:42:10 PM (10 years ago)
Author:
vboxsync
Message:

SUPDrv/VMMR0: properly handle the CR4 shadow register on Linux >= 4.0

Location:
trunk/src/VBox
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r54467 r54650  
    159159    { "SUPR0ContAlloc",                         (void *)SUPR0ContAlloc },
    160160    { "SUPR0ContFree",                          (void *)SUPR0ContFree },
     161    { "SUPR0ChangeCR4",                         (void *)SUPR0ChangeCR4 },
    161162    { "SUPR0EnableVTx",                         (void *)SUPR0EnableVTx },
    162163    { "SUPR0SuspendVTxOnCpu",                   (void *)SUPR0SuspendVTxOnCpu },
     
    36683669
    36693670/**
     3671 * Change CR4 and take care of the kernel CR4 shadow if applicable.
     3672 *
     3673 * CR4 shadow handling is required for Linux >= 4.0. Calling this function
     3674 * instead of ASMSetCR4() is only necessary for semi-permanent CR4 changes
     3675 * for code with interrupts enabled.
     3676 *
     3677 * @returns the old CR4 value.
     3678 *
     3679 * @param   fOrMask         bits to be set in CR4.
     3680 * @param   fAndMask        bits to be cleard in CR4.
     3681 *
     3682 * @remarks Must be called with preemption/interrupts disabled.
     3683 */
     3684SUPR0DECL(RTCCUINTREG) SUPR0ChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
     3685{
     3686#ifdef RT_OS_LINUX
     3687    return supdrvOSChangeCR4(fOrMask, fAndMask);
     3688#else
     3689    RTCCUINTREG uOld = ASMReadCR4();
     3690    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
     3691    if (uNew != uOld)
     3692        ASMSetCR4(uNew);
     3693    return uOld;
     3694#endif
     3695}
     3696
     3697
     3698/**
    36703699 * Enables or disabled hardware virtualization extensions using native OS APIs.
    36713700 *
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r54467 r54650  
    215215 *          - (nothing)
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x001f0003
     217#define SUPDRV_IOC_VERSION                              0x001f0004
    218218
    219219/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r54581 r54650  
    808808bool VBOXCALL   supdrvOSAreTscDeltasInSync(void);
    809809int  VBOXCALL   supdrvOSEnableVTx(bool fEnabled);
     810RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask);
    810811bool VBOXCALL   supdrvOSSuspendVTxOnCpu(void);
    811812void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended);
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r54467 r54650  
    280280        CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    281281        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001f0000
    282                                    ? 0x001f0003
     282                                   ? 0x001f0004
    283283                                   : SUPDRV_IOC_VERSION & 0xffff0000;
    284284        CookieReq.u.In.u32MinVersion = uMinVersion;
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r54581 r54650  
    6969# define SUPDRV_LINUX_HAS_SAFE_MSR_API
    7070# include <asm/msr.h>
    71 # include <iprt/asm-amd64-x86.h>
    72 #endif
     71#endif
     72#include <iprt/asm-amd64-x86.h>
    7373
    7474
     
    823823
    824824
     825RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
     826{
     827#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
     828    RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4);
     829    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
     830    if (uNew != uOld)
     831    {
     832        this_cpu_write(cpu_tlbstate.cr4, uNew);
     833        __write_cr4(uNew);
     834    }
     835#else
     836    RTCCUINTREG uOld = ASMGetCR4();
     837    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
     838    if (uNew != uOld)
     839        ASMSetCR4(uNew);
     840#endif
     841    return uOld;
     842}
     843
     844
    825845void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
    826846{
  • trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h

    r50077 r54650  
    141141#endif
    142142
     143/* for cr4_init_shadow() / cpu_tlbstate. */
     144#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
     145# include <asm/tlbflush.h>
     146#endif
     147
    143148#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
    144149# ifndef page_to_pfn
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r54384 r54650  
    773773
    774774    /* Enable the VMX bit in CR4 if necessary. */
    775     RTCCUINTREG uCr4 = ASMGetCR4();
    776     if (!(uCr4 & X86_CR4_VMXE))
    777         ASMSetCR4(uCr4 | X86_CR4_VMXE);
     775    RTCCUINTREG uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, ~0);
    778776
    779777    /* Enter VMX root mode. */
    780778    int rc = VMXEnable(HCPhysCpuPage);
    781     if (RT_FAILURE(rc))
    782         ASMSetCR4(uCr4);
     779    if (   RT_FAILURE(rc)
     780        && !(uOldCr4 & X86_CR4_VMXE))
     781        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
    783782
    784783    /* Restore interrupts. */
     
    808807        /* Exit VMX root mode and clear the VMX bit in CR4. */
    809808        VMXDisable();
    810         ASMSetCR4(uHostCR4 & ~X86_CR4_VMXE);
     809        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
    811810        rc = VINF_SUCCESS;
    812811    }
     
    52165215    VMXDisable();
    52175216
    5218     ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
     5217    SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
    52195218
    52205219    CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
     
    52315230    /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
    52325231    /* Make sure the VMX instructions don't cause #UD faults. */
    5233     ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);
     5232    SUPR0ChangeCR4(X86_CR4_VMXE, ~0);
    52345233
    52355234    /* Re-enter VMX Root Mode */
     
    52375236    if (RT_FAILURE(rc2))
    52385237    {
    5239         ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
     5238        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
    52405239        ASMSetFlags(uOldEflags);
    52415240        return rc2;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette