VirtualBox

Changeset 67136 in vbox for trunk


Ignore:
Timestamp:
May 30, 2017 7:58:21 AM (7 years ago)
Author:
vboxsync
Message:

HostDrivers/Support, VMM: bugref:8864: On Linux 4.12 the GDT is mapped read-only. The writable-mapped GDT is available and is used for clearing the TSS BUSY descriptor bit and for LTR.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/sup.h

    r64364 r67136  
    101101 */
    102102/** GDT is read-only. */
    103 #define SUPKERNELFEATURES_GDT_READ_ONLY     RT_BIT(0)
     103#define SUPKERNELFEATURES_GDT_READ_ONLY       RT_BIT(0)
    104104/** SMAP is possibly enabled. */
    105 #define SUPKERNELFEATURES_SMAP              RT_BIT(1)
     105#define SUPKERNELFEATURES_SMAP                RT_BIT(1)
     106/** GDT is read-only but the writable GDT can be fetched by SUPR0GetCurrentGdtRw(). */
     107#define SUPKERNELFEATURES_GDT_NEED_WRITABLE   RT_BIT(2)
    106108/** @} */
    107109
     
    18941896SUPR0DECL(int) SUPR0GetSvmUsability(bool fInitSvm);
    18951897SUPR0DECL(int) SUPR0GetVmxUsability(bool *pfIsSmxModeAmbiguous);
     1898SUPR0DECL(int) SUPR0GetCurrentGdtRw(RTHCUINTPTR *pGdtRw);
    18961899SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps);
    18971900SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
  • trunk/include/VBox/vmm/hm_vmx.h

    r64143 r67136  
    112112#define VMX_RESTORE_HOST_GDT_READ_ONLY        RT_BIT(7)
    113113#define VMX_RESTORE_HOST_REQUIRED             RT_BIT(8)
     114#define VMX_RESTORE_HOST_GDT_NEED_WRITABLE    RT_BIT(9)
    114115/** @} */
    115116
     
    127128    RTSEL       uHostSelTR;     /* 0x08 */
    128129    uint8_t     abPadding0[4];
    129     X86XDTR64   HostGdtr;       /**< 0x0e - should be aligned by it's 64-bit member.  */
     130    X86XDTR64   HostGdtr;       /**< 0x0e - should be aligned by it's 64-bit member. */
    130131    uint8_t     abPadding1[6];
    131     X86XDTR64   HostIdtr;       /**< 0x1e - should be aligned by it's 64-bit member. */
    132     uint64_t    uHostFSBase;    /* 0x28 */
    133     uint64_t    uHostGSBase;    /* 0x30 */
     132    X86XDTR64   HostGdtrRw;     /**< 0x1e - should be aligned by it's 64-bit member. */
     133    uint8_t     abPadding2[6];
     134    X86XDTR64   HostIdtr;       /**< 0x2e - should be aligned by it's 64-bit member. */
     135    uint64_t    uHostFSBase;    /* 0x38 */
     136    uint64_t    uHostGSBase;    /* 0x40 */
    134137} VMXRESTOREHOST;
    135138/** Pointer to VMXRESTOREHOST. */
     
    137140AssertCompileSize(X86XDTR64, 10);
    138141AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr.uAddr, 16);
    139 AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr.uAddr, 32);
    140 AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    40);
    141 AssertCompileSize(VMXRESTOREHOST, 56);
     142AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtrRw.uAddr, 32);
     143AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr.uAddr, 48);
     144AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    56);
     145AssertCompileSize(VMXRESTOREHOST, 72);
    142146AssertCompileSizeAlignment(VMXRESTOREHOST, 8);
    143147
  • trunk/include/VBox/vmm/hm_vmx.mac

    r62476 r67136  
    161161%define VMX_RESTORE_HOST_GDT_READ_ONLY                          80h   ;RT_BIT(7)
    162162%define VMX_RESTORE_HOST_REQUIRED                              100h   ;RT_BIT(8)
     163%define VMX_RESTORE_HOST_GDT_NEED_WRITABLE                     200h   ;RT_BIT(9)
    163164
    164165;; C version hm_vmx.h.
     
    172173    .HostGdtr           resb    10
    173174    .abPadding1         resb    6
     175    .HostGdtrRw         resb    10
     176    .abPadding2         resb    6
    174177    .HostIdtr           resb    10
    175178    .uHostFSBase        resq    1
     
    177180endstruc
    178181AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtr,     16-2)
    179 AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr,     32-2)
    180 AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    40)
    181 AssertCompileSize(VMXRESTOREHOST, 56)
     182AssertCompileMemberOffset(VMXRESTOREHOST, HostGdtrRw,   32-2)
     183AssertCompileMemberOffset(VMXRESTOREHOST, HostIdtr,     48-2)
     184AssertCompileMemberOffset(VMXRESTOREHOST, uHostFSBase,    56)
     185AssertCompileSize(VMXRESTOREHOST, 72)
    182186
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp

    r66581 r67136  
    199199    { "SUPR0SuspendVTxOnCpu",                   (void *)(uintptr_t)SUPR0SuspendVTxOnCpu },
    200200    { "SUPR0ResumeVTxOnCpu",                    (void *)(uintptr_t)SUPR0ResumeVTxOnCpu },
     201    { "SUPR0GetCurrentGdtRw",                   (void *)(uintptr_t)SUPR0GetCurrentGdtRw },
    201202    { "SUPR0GetKernelFeatures",                 (void *)(uintptr_t)SUPR0GetKernelFeatures },
    202203    { "SUPR0GetPagingMode",                     (void *)(uintptr_t)SUPR0GetPagingMode },
     
    38773878
    38783879
     3880SUPR0DECL(int) SUPR0GetCurrentGdtRw(RTHCUINTPTR *pGdtRw)
     3881{
     3882#ifdef RT_OS_LINUX
     3883    return supdrvOSetCurrentGdtRw(pGdtRw);
     3884#else
     3885    return VERR_NOT_IMPLEMENTED;
     3886#endif
     3887}
     3888
     3889
    38793890/**
    38803891 * Checks if Intel VT-x feature is usable on this CPU.
  • trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h

    r64872 r67136  
    842842bool VBOXCALL   supdrvOSSuspendVTxOnCpu(void);
    843843void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended);
     844int  VBOXCALL   supdrvOSetCurrentGdtRw(RTHCUINTPTR *pGdtRw);
    844845
    845846/**
  • trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c

    r62694 r67136  
    6161# include <asm/msr.h>
    6262#endif
     63
     64#include <asm/desc.h>
    6365
    6466#include <iprt/asm-amd64-x86.h>
     
    14011403    fFlags |= SUPKERNELFEATURES_GDT_READ_ONLY;
    14021404#endif
     1405#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
     1406    fFlags |= SUPKERNELFEATURES_GDT_NEED_WRITABLE;
     1407#endif
    14031408#if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV)
    14041409    fFlags |= SUPKERNELFEATURES_SMAP;
     
    14111416
    14121417
     1418int supdrvOSetCurrentGdtRw(RTHCUINTPTR *pGdtRw)
     1419{
     1420#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
     1421    *pGdtRw = (RTHCUINTPTR)get_current_gdt_rw();
     1422    return VINF_SUCCESS;
     1423#else
     1424    return VERR_NOT_IMPLEMENTED;
     1425#endif
     1426}
     1427
     1428
    14131429module_init(VBoxDrvLinuxInit);
    14141430module_exit(VBoxDrvLinuxUnload);
  • trunk/src/VBox/VMM/VMMR0/HMR0A.asm

    r66878 r67136  
    285285    mov         ax, dx
    286286    and         eax, X86_SEL_MASK_OFF_RPL                       ; Mask away TI and RPL bits leaving only the descriptor offset.
     287    test        edi, VMX_RESTORE_HOST_GDT_READ_ONLY | VMX_RESTORE_HOST_GDT_NEED_WRITABLE
     288    jnz         .gdt_readonly
    287289    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2]  ; xAX <- descriptor offset + GDTR.pGdt.
    288     test        edi, VMX_RESTORE_HOST_GDT_READ_ONLY
    289     jnz         .gdt_readonly
    290290    and         dword [rax + 4], ~RT_BIT(9)                     ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
    291291    ltr         dx
    292292    jmp short   .test_fs
    293293.gdt_readonly:
     294    test        edi, VMX_RESTORE_HOST_GDT_NEED_WRITABLE
     295    jnz         .gdt_readonly_need_writable
    294296    mov         rcx, cr0
    295297    mov         r9, rcx
     298    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2]  ; xAX <- descriptor offset + GDTR.pGdt.
    296299    and         rcx, ~X86_CR0_WP
    297300    mov         cr0, rcx
     
    299302    ltr         dx
    300303    mov         cr0, r9
     304    jmp short   .test_fs
     305.gdt_readonly_need_writable:
     306    add         rax, qword [rsi + VMXRESTOREHOST.HostGdtrRw + 2]  ; xAX <- descriptor offset + GDTR.pGdtRw.
     307    and         dword [rax + 4], ~RT_BIT(9)                     ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
     308    lgdt        [rsi + VMXRESTOREHOST.HostGdtrRw]
     309    ltr         dx
     310    lgdt        [rsi + VMXRESTOREHOST.HostGdtr]                 ; Load the original GDT
    301311
    302312.test_fs:
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r67050 r67136  
    30383038     */
    30393039    if (Gdtr.cbGdt != 0xffff)
    3040     {
    30413040        pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
    3042         AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
    3043         memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
    3044     }
    30453041
    30463042    /*
     
    30943090            pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
    30953091        pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
    3096 
    3097         /* Store the GDTR here as we need it while restoring TR. */
     3092    }
     3093
     3094    /*
     3095     * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
     3096     */
     3097    if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
     3098    {
     3099        AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
    30983100        memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
     3101        if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
     3102        {
     3103            /* The GDT is read-only but the writable GDT is available. */
     3104            pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
     3105            pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
     3106            rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
     3107            AssertRCReturn(rc, rc);
     3108        }
    30993109    }
    31003110#else
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