VirtualBox

Changeset 74660 in vbox


Ignore:
Timestamp:
Oct 8, 2018 6:39:49 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM, CPUM: Nested VMX: bugref:9180 VM-exit bits; I/O exit prep work. Also add missing allocation/de-allocation for the shadow VMCS during CPUM init.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpumctx.h

    r74542 r74660  
    644644                uint32_t                uMsrBitmapR3;
    645645#endif
    646                 /** 0x378 - Padding. */
    647                 uint8_t             abPadding[0x3f0 - 0x378];
     646                /** 0x378 - The I/O bitmap - R0 ptr. */
     647                R0PTRTYPE(void *)       pvIoBitmapR0;
     648#if HC_ARCH_BITS == 32
     649                uint32_t                uIoBitmapR0;
     650#endif
     651                /** 0x380 - The I/O bitmap - R3 ptr. */
     652                R3PTRTYPE(void *)       pvIoBitmapR3;
     653#if HC_ARCH_BITS == 32
     654                uint32_t                uIoBitmapR3;
     655#endif
     656                /** 0x388 - Padding. */
     657                uint8_t             abPadding[0x3f0 - 0x388];
    648658            } vmx;
    649659        } CPUM_UNION_NM(s);
     
    745755AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pAutoMsrAreaR0,         0x358);
    746756AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pAutoMsrAreaR3,         0x360);
     757AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvMsrBitmapR0,          0x368);
     758AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvMsrBitmapR3,          0x370);
     759AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvIoBitmapR0,           0x378);
     760AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvIoBitmapR3,           0x380);
    747761AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pVmcsR0,           8);
    748762AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pShadowVmcsR0,     8);
     
    752766AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pAutoMsrAreaR0,    8);
    753767AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvMsrBitmapR0,     8);
     768AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvIoBitmapR0,      8);
    754769AssertCompileMemberOffset(CPUMCTX, hwvirt.enmHwvirt,           0x3f0);
    755770AssertCompileMemberOffset(CPUMCTX, hwvirt.fLocalForcedActions, 0x3f4);
  • trunk/include/VBox/vmm/hm.h

    r74545 r74660  
    150150VMM_INT_DECL(int)               HMVmxEntryIntInfoInjectTrpmEvent(PVMCPU pVCpu, uint32_t uEntryIntInfo, uint32_t uErrCode,
    151151                                                                 uint32_t cbInstr, RTGCUINTPTR GCPtrFaultAddress);
    152 VMM_INT_DECL(int)               HMVmxGetMsrPermission(void *pvMsrBitmap, uint32_t idMsr, PVMXMSREXITREAD penmRead,
     152VMM_INT_DECL(int)               HMVmxGetMsrPermission(void const *pvMsrBitmap, uint32_t idMsr, PVMXMSREXITREAD penmRead,
    153153                                                      PVMXMSREXITWRITE penmWrite);
     154VMM_INT_DECL(bool)              HMVmxGetIoBitmapPermission(void const *pvIoBitmapA, void const *pvIoBitmapB, uint16_t uPort);
    154155/** @} */
    155156
  • trunk/include/VBox/vmm/hm_vmx.h

    r74648 r74660  
    25002500#define VMXINSTRID_VMREAD                                       (0x12 | VMXINSTRID_VALID)
    25012501#define VMXINSTRID_VMWRITE                                      (0x13 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
     2502#define VMXINSTRID_IO_IN                                        (0x14 | VMXINSTRID_VALID)
     2503#define VMXINSTRID_IO_OUT                                       (0x15 | VMXINSTRID_VALID)
    25022504/** @} */
    25032505
     
    27262728/** 16-31: IO Port (0-0xffff). */
    27272729#define VMX_EXIT_QUAL_IO_PORT(a)                                (((a) >> 16) & 0xffff)
    2728 /* Rest reserved. */
     2730
     2731/** Bit fields for Exit qualification for I/O instructions. */
     2732#define VMX_BF_EXIT_QUAL_IO_WIDTH_SHIFT                         0
     2733#define VMX_BF_EXIT_QUAL_IO_WIDTH_MASK                          UINT64_C(0x0000000000000007)
     2734#define VMX_BF_EXIT_QUAL_IO_DIRECTION_SHIFT                     3
     2735#define VMX_BF_EXIT_QUAL_IO_DIRECTION_MASK                      UINT64_C(0x0000000000000008)
     2736#define VMX_BF_EXIT_QUAL_IO_IS_STRING_SHIFT                     4
     2737#define VMX_BF_EXIT_QUAL_IO_IS_STRING_MASK                      UINT64_C(0x0000000000000010)
     2738#define VMX_BF_EXIT_QUAL_IO_IS_REP_SHIFT                        5
     2739#define VMX_BF_EXIT_QUAL_IO_IS_REP_MASK                         UINT64_C(0x0000000000000020)
     2740#define VMX_BF_EXIT_QUAL_IO_ENCODING_SHIFT                      6
     2741#define VMX_BF_EXIT_QUAL_IO_ENCODING_MASK                       UINT64_C(0x0000000000000040)
     2742#define VMX_BF_EXIT_QUAL_IO_RSVD_7_15_SHIFT                     7
     2743#define VMX_BF_EXIT_QUAL_IO_RSVD_7_15_MASK                      UINT64_C(0x000000000000ff80)
     2744#define VMX_BF_EXIT_QUAL_IO_PORT_SHIFT                          16
     2745#define VMX_BF_EXIT_QUAL_IO_PORT_MASK                           UINT64_C(0x00000000ffff0000)
     2746#define VMX_BF_EXIT_QUAL_IO_RSVD_32_63_SHIFT                    32
     2747#define VMX_BF_EXIT_QUAL_IO_RSVD_32_63_MASK                     UINT64_C(0xffffffff00000000)
     2748RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_IO_, UINT64_C(0), UINT64_MAX,
     2749                            (WIDTH, DIRECTION, IS_STRING, IS_REP, ENCODING, RSVD_7_15, PORT, RSVD_32_63));
    27292750/** @} */
    27302751
     
    30783099#define VMX_V_MSR_BITMAP_PAGES                                  1
    30793100
     3101/** The size of I/O bitmap A (in bytes). */
     3102#define VMX_V_IO_BITMAP_A_SIZE                                  X86_PAGE_4K_SIZE
     3103/** The size of I/O bitmap A (in pages). */
     3104#define VMX_V_IO_BITMAP_A_PAGES                                 1
     3105
     3106/** The size of I/O bitmap B (in bytes). */
     3107#define VMX_V_IO_BITMAP_B_SIZE                                  X86_PAGE_4K_SIZE
     3108/** The size of I/O bitmap B (in pages). */
     3109#define VMX_V_IO_BITMAP_B_PAGES                                 1
     3110
    30803111/** The size of the auto-load/store MSR area (in bytes). */
    30813112#define VMX_V_AUTOMSR_AREA_SIZE                                 ((512 * (VMX_V_AUTOMSR_COUNT_MAX + 1)) * sizeof(VMXAUTOMSR))
     
    31203151typedef const VMXVEXITINFO *PCVMXVEXITINFO;
    31213152AssertCompileMemberAlignment(VMXVEXITINFO, u64Qual, 8);
     3153
    31223154
    31233155/**
  • trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp

    r74545 r74660  
    890890 *                          NULL.
    891891 */
    892 VMM_INT_DECL(int) HMVmxGetMsrPermission(void *pvMsrBitmap, uint32_t idMsr, PVMXMSREXITREAD penmRead,
     892VMM_INT_DECL(int) HMVmxGetMsrPermission(void const *pvMsrBitmap, uint32_t idMsr, PVMXMSREXITREAD penmRead,
    893893                                        PVMXMSREXITWRITE penmWrite)
    894894{
     
    896896
    897897    int32_t iBit;
    898     uint8_t *pbMsrBitmap = (uint8_t *)pvMsrBitmap;
     898    uint8_t const *pbMsrBitmap = (uint8_t *)pvMsrBitmap;
    899899
    900900    /*
     
    955955}
    956956
     957
     958/**
     959 * Gets the permission bits for the specified I/O port from the given I/O bitmaps.
     960 *
     961 * @returns @c true if the I/O port access must cause a VM-exit, @c false otherwise.
     962 * @param   pvIoBitmapA     Pointer to I/O bitmap A.
     963 * @param   pvIoBitmapB     Pointer to I/O bitmap B.
     964 * @param   uPort           The I/O port being accessed.
     965 */
     966VMM_INT_DECL(bool) HMVmxGetIoBitmapPermission(void const *pvIoBitmapA, void const *pvIoBitmapB, uint16_t uPort)
     967{
     968    /* If the port is 0 or ffff ("wrap around"), we cause a VM-exit. */
     969    if (   uPort == 0x0000
     970        || uPort == 0xffff)
     971        return true;
     972
     973    /* Read the appropriate bit from the corresponding IO bitmap. */
     974    void const *pvIoBitmap = uPort < 0x8000 ? pvIoBitmapA : pvIoBitmapB;
     975    return ASMBitTest(pvIoBitmap, uPort);
     976}
     977
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74635 r74660  
    28612861
    28622862/**
     2863 * Checks whether an I/O instruction for the given port is intercepted (causes a
     2864 * VM-exit)  or not.
     2865 *
     2866 * @returns @c true if the instruction is intercepted, @c false otherwise.
     2867 * @param   pVCpu           The cross context virtual CPU structure.
     2868 * @param   uPort           The I/O port being accessed by the instruction.
     2869 */
     2870IEM_STATIC bool iemVmxIsIoInterceptSet(PVMCPU pVCpu, uint16_t uPort)
     2871{
     2872    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     2873    Assert(pVmcs);
     2874
     2875    /*
     2876     * Check whether the IO instruction must cause a VM-exit or not.
     2877     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
     2878     */
     2879    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT)
     2880        return true;
     2881
     2882    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS)
     2883    {
     2884        uint8_t const *pbIoBitmapA = (uint8_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvIoBitmap);
     2885        uint8_t const *pbIoBitmapB = (uint8_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvIoBitmap) + VMX_V_IO_BITMAP_A_SIZE;
     2886        Assert(pbIoBitmapA);
     2887        Assert(pbIoBitmapB);
     2888        return HMVmxGetIoBitmapPermission(pbIoBitmapA, pbIoBitmapB, uPort);
     2889    }
     2890
     2891    return false;
     2892}
     2893
     2894
     2895/**
    28632896 * VMX VM-exit handler for VM-exits due to INVLPG.
    28642897 *
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r74648 r74660  
    934934            pVCpu->cpum.s.Guest.hwvirt.vmx.pVmcsR3 = NULL;
    935935        }
     936        if (pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3)
     937        {
     938            SUPR3PageFreeEx(pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3, VMX_V_VMCS_PAGES);
     939            pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3 = NULL;
     940        }
    936941        if (pVCpu->cpum.s.Guest.hwvirt.vmx.pvVirtApicPageR3)
    937942        {
     
    958963            SUPR3PageFreeEx(pVCpu->cpum.s.Guest.hwvirt.vmx.pvMsrBitmapR3, VMX_V_MSR_BITMAP_PAGES);
    959964            pVCpu->cpum.s.Guest.hwvirt.vmx.pvMsrBitmapR3 = NULL;
     965        }
     966        if (pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3)
     967        {
     968            SUPR3PageFreeEx(pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3, VMX_V_IO_BITMAP_A_PAGES + VMX_V_IO_BITMAP_B_PAGES);
     969            pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3 = NULL;
    960970        }
    961971    }
     
    9951005
    9961006        /*
     1007         * Allocate the nested-guest shadow VMCS.
     1008         */
     1009        Assert(VMX_V_VMCS_PAGES == 1);
     1010        Assert(!pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3);
     1011        rc = SUPR3PageAllocEx(VMX_V_VMCS_PAGES, 0 /* fFlags */, (void **)&pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3,
     1012                              &pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR0, NULL /* paPages */);
     1013        if (RT_FAILURE(rc))
     1014        {
     1015            Assert(!pVCpu->cpum.s.Guest.hwvirt.vmx.pShadowVmcsR3);
     1016            LogRel(("CPUM%u: Failed to alloc %u pages for the nested-guest's shadow VMCS\n", pVCpu->idCpu, VMX_V_VMCS_PAGES));
     1017            break;
     1018        }
     1019
     1020        /*
    9971021         * Allocate the Virtual-APIC page.
    9981022         */
     
    10621086            LogRel(("CPUM%u: Failed to alloc %u pages for the nested-guest's MSR bitmap\n", pVCpu->idCpu,
    10631087                    VMX_V_MSR_BITMAP_PAGES));
     1088            break;
     1089        }
     1090
     1091        /*
     1092         * Allocate the I/O bitmaps (A and B).
     1093         */
     1094        Assert(!pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3);
     1095        rc = SUPR3PageAllocEx(VMX_V_IO_BITMAP_A_PAGES + VMX_V_IO_BITMAP_B_PAGES, 0 /* fFlags */,
     1096                              (void **)&pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3,
     1097                              &pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR0, NULL /* paPages */);
     1098        if (RT_FAILURE(rc))
     1099        {
     1100            Assert(!pVCpu->cpum.s.Guest.hwvirt.vmx.pvIoBitmapR3);
     1101            LogRel(("CPUM%u: Failed to alloc %u pages for the nested-guest's I/O bitmaps\n", pVCpu->idCpu,
     1102                    VMX_V_IO_BITMAP_A_PAGES + VMX_V_IO_BITMAP_B_PAGES));
    10641103            break;
    10651104        }
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