VirtualBox

Changeset 85974 in vbox


Ignore:
Timestamp:
Sep 1, 2020 10:03:09 AM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
140169
Message:

VMM/HMVMX.cpp: Optimize hmR0VmxExportGuestSegReg and hmR0VmxImportGuestSegReg. GCC 10 now inlines these two, it didn't when we used the translation tables.

Location:
trunk
Files:
2 edited

Legend:

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

    r82968 r85974  
    17571757#define VMX_VMCS16_GUEST_FS_SEL                                 0x0808
    17581758#define VMX_VMCS16_GUEST_GS_SEL                                 0x080a
     1759#define VMX_VMCS16_GUEST_SEG_SEL(a_iSegReg)                     (VMX_VMCS16_GUEST_ES_SEL + (a_iSegReg) * 2)
    17591760#define VMX_VMCS16_GUEST_LDTR_SEL                               0x080c
    17601761#define VMX_VMCS16_GUEST_TR_SEL                                 0x080e
     
    18941895#define VMX_VMCS32_GUEST_FS_LIMIT                               0x4808
    18951896#define VMX_VMCS32_GUEST_GS_LIMIT                               0x480a
     1897#define VMX_VMCS32_GUEST_SEG_LIMIT(a_iSegReg)                   (VMX_VMCS32_GUEST_ES_LIMIT + (a_iSegReg) * 2)
    18961898#define VMX_VMCS32_GUEST_LDTR_LIMIT                             0x480c
    18971899#define VMX_VMCS32_GUEST_TR_LIMIT                               0x480e
     
    19041906#define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS                       0x481c
    19051907#define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS                       0x481e
     1908#define VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(a_iSegReg)           (VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS + (a_iSegReg) * 2)
    19061909#define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS                     0x4820
    19071910#define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS                       0x4822
     
    19431946#define VMX_VMCS_GUEST_FS_BASE                                  0x680e
    19441947#define VMX_VMCS_GUEST_GS_BASE                                  0x6810
     1948#define VMX_VMCS_GUEST_SEG_BASE(a_iSegReg)                      (VMX_VMCS_GUEST_ES_BASE + (a_iSegReg) * 2)
    19451949#define VMX_VMCS_GUEST_LDTR_BASE                                0x6812
    19461950#define VMX_VMCS_GUEST_TR_BASE                                  0x6814
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r85970 r85974  
    691691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
    692692
     693#ifdef VBOX_STRICT
    693694static const uint32_t g_aVmcsSegBase[] =
    694695{
     
    731732AssertCompile(RT_ELEMENTS(g_aVmcsSegBase)  == X86_SREG_COUNT);
    732733AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr)  == X86_SREG_COUNT);
     734#endif /* VBOX_STRICT */
    733735
    734736#ifdef HMVMX_USE_FUNCTION_TABLE
     
    62626264 * @remarks No-long-jump zone!!!
    62636265 */
    6264 static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
     6266static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
    62656267{
    62666268    Assert(iSegReg < X86_SREG_COUNT);
    6267     uint32_t const idxSel   = g_aVmcsSegSel[iSegReg];
    6268     uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
    6269     uint32_t const idxBase  = g_aVmcsSegBase[iSegReg];
    6270     uint32_t const idxAttr  = g_aVmcsSegAttr[iSegReg];
    62716269
    62726270    uint32_t u32Access = pSelReg->Attr.u;
    6273     if (pVmcsInfo->RealMode.fRealOnV86Active)
    6274     {
    6275         /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
    6276         u32Access = 0xf3;
    6277         Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
    6278         Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
    6279         RT_NOREF_PV(pVCpu);
    6280     }
    6281     else
     6271    if (!pVmcsInfo->RealMode.fRealOnV86Active)
    62826272    {
    62836273        /*
     
    62886278         * NULL selectors loaded in protected-mode have their attribute as 0.
    62896279         */
    6290         if (!u32Access)
     6280        if (u32Access)
     6281        { }
     6282        else
    62916283            u32Access = X86DESCATTR_UNUSABLE;
     6284    }
     6285    else
     6286    {
     6287        /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
     6288        u32Access = 0xf3;
     6289        Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
     6290        Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
     6291        RT_NOREF_PV(pVCpu);
    62926292    }
    62936293
    62946294    /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
    62956295    AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
    6296               ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
     6296              ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
    62976297
    62986298    /*
    62996299     * Commit it to the VMCS.
    63006300     */
    6301     int rc = VMXWriteVmcs32(idxSel,   pSelReg->Sel);        AssertRC(rc);
    6302     rc     = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);   AssertRC(rc);
    6303     rc     = VMXWriteVmcsNw(idxBase,  pSelReg->u64Base);    AssertRC(rc);
    6304     rc     = VMXWriteVmcs32(idxAttr,  u32Access);           AssertRC(rc);
     6301    Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg)           == g_aVmcsSegSel[iSegReg]);
     6302    Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg)         == g_aVmcsSegLimit[iSegReg]);
     6303    Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
     6304    Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg)            == g_aVmcsSegBase[iSegReg]);
     6305    int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg),           pSelReg->Sel);      AssertRC(rc);
     6306    rc     = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg),         pSelReg->u32Limit); AssertRC(rc);
     6307    rc     = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg),            pSelReg->u64Base);  AssertRC(rc);
     6308    rc     = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access);         AssertRC(rc);
    63056309    return VINF_SUCCESS;
    63066310}
     
    72277231 * @param   pVCpu       The cross context virtual CPU structure.
    72287232 * @param   pSelReg     The segment register that needs fixing.
    7229  * @param   idxSel      The VMCS field for the corresponding segment register.
    7230  */
    7231 static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
     7233 * @param   pszRegName  The register name (for logging and assertions).
     7234 */
     7235static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
    72327236{
    72337237    Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
     
    72617265#ifdef VBOX_STRICT
    72627266    VMMRZCallRing3Disable(pVCpu);
    7263     Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
     7267    Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
    72647268# ifdef DEBUG_bird
    72657269    AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
    7266               ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
    7267                idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
     7270              ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
     7271               pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
    72687272# endif
    72697273    VMMRZCallRing3Enable(pVCpu);
    72707274    NOREF(uAttr);
    72717275#endif
    7272     RT_NOREF2(pVCpu, idxSel);
     7276    RT_NOREF2(pVCpu, pszRegName);
    72737277}
    72747278
     
    72837287 * @remarks Called with interrupts and/or preemption disabled.
    72847288 */
    7285 static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
     7289static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
    72867290{
    72877291    Assert(iSegReg < X86_SREG_COUNT);
    7288 
    7289 /** @todo r=bird: Aren't these translation tables a complete wast of time and
    7290  *        memory accesses?  As far as I can tell, the constants are in segment
    7291  *        order with a 2+ stepping.  Adding 4 macro functions to hm_vmx.h that
    7292  *        does the translation, like: @code
    7293  * #define VMX_VMCS_GUEST_SEG_BASE(a_iSegReg) \
    7294  *      (VMX_VMCS_GUEST_ES_BASE + (a_iSegReg) * 2)
    7295  *        @endcode
    7296  * The tables are in two different cache lines two, due to their size, so not
    7297  * great for locality either.
    7298  */
    7299     uint32_t const idxSel   = g_aVmcsSegSel[iSegReg];
    7300     uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
    7301     uint32_t const idxAttr  = g_aVmcsSegAttr[iSegReg];
    7302     uint32_t const idxBase  = g_aVmcsSegBase[iSegReg];
     7292    Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg)           == g_aVmcsSegSel[iSegReg]);
     7293    Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg)         == g_aVmcsSegLimit[iSegReg]);
     7294    Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
     7295    Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg)            == g_aVmcsSegBase[iSegReg]);
     7296
     7297    PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
    73037298
    73047299    uint16_t u16Sel;
    7305     uint64_t u64Base;
    7306     uint32_t u32Limit, u32Attr;
    7307     int rc = VMXReadVmcs16(idxSel,   &u16Sel);      AssertRC(rc);
    7308     rc     = VMXReadVmcs32(idxLimit, &u32Limit);    AssertRC(rc);
    7309     rc     = VMXReadVmcs32(idxAttr,  &u32Attr);     AssertRC(rc);
    7310     rc     = VMXReadVmcsNw(idxBase,  &u64Base);     AssertRC(rc);
    7311 
    7312     PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
     7300    int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel);   AssertRC(rc);
    73137301    pSelReg->Sel      = u16Sel;
    73147302    pSelReg->ValidSel = u16Sel;
    7315     pSelReg->fFlags   = CPUMSELREG_FLAGS_VALID;
    7316     pSelReg->u32Limit = u32Limit;
    7317 #ifdef DEBUG_bird
    7318     if (pSelReg->u64Base != u64Base)
    7319         Log7(("HM: %.2s: base %RX64 -> %RX64\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg->u64Base, u64Base));
    7320 #endif
    7321     pSelReg->u64Base  = u64Base;
     7303
     7304    rc     = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
     7305    rc     = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base);     AssertRC(rc);
     7306
     7307    uint32_t u32Attr;
     7308    rc     = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr);   AssertRC(rc);
    73227309    pSelReg->Attr.u   = u32Attr;
    73237310    if (u32Attr & X86DESCATTR_UNUSABLE)
    7324         hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
     7311        hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
     7312
     7313    pSelReg->fFlags   = CPUMSELREG_FLAGS_VALID;
    73257314}
    73267315
     
    73507339    pVCpu->cpum.GstCtx.ldtr.Attr.u   = u32Attr;
    73517340    if (u32Attr & X86DESCATTR_UNUSABLE)
    7352         hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
     7341        hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
    73537342}
    73547343
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