VirtualBox

Changeset 42427 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Jul 26, 2012 11:48:01 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
79529
Message:

VMM: Fixed some selector arithmetic, introducing a new constand and renaming and old one to make things clearer. Also added CPUMGetGuestLdtrEx and make some (but not all) of SELM use this instead of shadow GDT.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/SELM.cpp

    r42418 r42427  
    10681068     */
    10691069    RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu);
    1070     if ((SelLdt & X86_SEL_MASK) == 0)
     1070    if (!(SelLdt & X86_SEL_MASK_OFF_RPL))
    10711071    {
    10721072        /* ldtr = 0 - update hyper LDTR and deregister any active handler. */
     
    10851085     * Get the LDT selector.
    10861086     */
     1087/** @todo this is wrong, use CPUMGetGuestLdtrEx */
    10871088    PX86DESC    pDesc    = &pVM->selm.s.paGdtR3[SelLdt >> X86_SEL_SHIFT];
    10881089    RTGCPTR     GCPtrLdt = X86DESC_BASE(pDesc);
     
    12931294    for (uint32_t iSReg = 0; iSReg < X86_SREG_COUNT; iSReg++)
    12941295    {
    1295         RTSEL const Sel = paSReg[iSReg].Sel & (X86_SEL_MASK | X86_SEL_LDT);
    1296         if (Sel & (X86_SEL_MASK | X86_SEL_LDT))
     1296        RTSEL const Sel = paSReg[iSReg].Sel;
     1297        if (Sel & X86_SEL_MASK_OFF_RPL)
    12971298        {
    12981299            /* Get the shadow descriptor entry corresponding to this. */
     
    15531554     *       make sure cbTss is 0.
    15541555     */
     1556/** @todo use the hidden bits, not shadow GDT. */
    15551557    CPUMSELREGHID   trHid;
    15561558    RTSEL           SelTss   = CPUMGetGuestTR(pVCpu, &trHid);
    15571559    RTGCPTR         GCPtrTss = trHid.u64Base;
    15581560    uint32_t        cbTss    = trHid.u32Limit;
    1559     Assert(     (SelTss & X86_SEL_MASK)
    1560            ||   (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */)
    1561            ||   (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */));
    1562     if (SelTss & X86_SEL_MASK)
     1561    Assert(   (SelTss & X86_SEL_MASK_OFF_RPL)
     1562           || (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */)
     1563           || (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */));
     1564    if (SelTss & X86_SEL_MASK_OFF_RPL)
    15631565    {
    15641566        Assert(!(SelTss & X86_SEL_LDT));
     
    17931795     */
    17941796    RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu);
    1795     if ((SelLdt & X86_SEL_MASK) == 0)
     1797    if ((SelLdt & X86_SEL_MASK_OFF_RPL) == 0)
    17961798        return VINF_SUCCESS;
     1799    Assert(!(SelLdt & X86_SEL_LDT));
    17971800    if (SelLdt > GDTR.cbGdt)
    17981801    {
     
    18861889    RTGCPTR         GCPtrTss = trHid.u64Base;
    18871890    uint32_t        cbTss    = trHid.u32Limit;
    1888     Assert(     (SelTss & X86_SEL_MASK)
    1889            ||   (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */)
    1890            ||   (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */));
    1891     if (SelTss & X86_SEL_MASK)
     1891    Assert(   (SelTss & X86_SEL_MASK_OFF_RPL)
     1892           || (cbTss == 0 && GCPtrTss == 0 && trHid.Attr.u == 0 /* TR=0 */)
     1893           || (cbTss == 0xffff && GCPtrTss == 0 && trHid.Attr.n.u1Present && trHid.Attr.n.u4Type == X86_SEL_TYPE_SYS_386_TSS_BUSY /* RESET */));
     1894    if (SelTss & X86_SEL_MASK_OFF_RPL)
    18921895    {
    18931896        AssertReturn(!(SelTss & X86_SEL_LDT), false);
     
    20072010
    20082011/**
    2009  * Returns flat address and limit of LDT by LDT selector from guest GDTR.
    2010  *
    2011  * Fully validate selector.
    2012  *
    2013  * @returns VBox status.
    2014  * @param   pVM       Pointer to the VM.
    2015  * @param   SelLdt    LDT selector.
    2016  * @param   ppvLdt    Where to store the flat address of LDT.
    2017  * @param   pcbLimit  Where to store LDT limit.
    2018  */
    2019 VMMDECL(int) SELMGetLDTFromSel(PVM pVM, RTSEL SelLdt, PRTGCPTR ppvLdt, unsigned *pcbLimit)
    2020 {
    2021     PVMCPU pVCpu = VMMGetCpu(pVM);
    2022 
    2023     /* Get guest GDTR. */
    2024     VBOXGDTR GDTR;
    2025     CPUMGetGuestGDTR(pVCpu, &GDTR);
    2026 
    2027     /* Check selector TI and GDT limit. */
    2028     if (   (SelLdt & X86_SEL_LDT)
    2029         || SelLdt > GDTR.cbGdt)
    2030         return VERR_INVALID_SELECTOR;
    2031 
    2032     /* Read descriptor from GC. */
    2033     X86DESC Desc;
    2034     int rc = PGMPhysSimpleReadGCPtr(pVCpu, (void *)&Desc, (RTGCPTR)(GDTR.pGdt + (SelLdt & X86_SEL_MASK)), sizeof(Desc));
    2035     if (RT_FAILURE(rc))
    2036     {
    2037         /* fatal */
    2038         Log(("Can't read LDT descriptor for selector=%04X\n", SelLdt));
    2039         return VERR_SELECTOR_NOT_PRESENT;
    2040     }
    2041 
    2042     /* Check if LDT descriptor is not present. */
    2043     if (Desc.Gen.u1Present == 0)
    2044         return VERR_SELECTOR_NOT_PRESENT;
    2045 
    2046     /* Check LDT descriptor type. */
    2047     if (    Desc.Gen.u1DescType == 1
    2048         ||  Desc.Gen.u4Type != X86_SEL_TYPE_SYS_LDT)
    2049         return VERR_INVALID_SELECTOR;
    2050 
    2051     /* LDT descriptor is ok. */
    2052     if (ppvLdt)
    2053     {
    2054         *ppvLdt = (RTGCPTR)X86DESC_BASE(&Desc);
    2055         *pcbLimit = X86DESC_LIMIT_G(&Desc);
    2056     }
    2057     return VINF_SUCCESS;
    2058 }
    2059 
    2060 
    2061 /**
    20622012 * Gets information about a 64-bit selector, SELMR3GetSelectorInfo helper.
    20632013 *
     
    20752025     * Read it from the guest descriptor table.
    20762026     */
     2027/** @todo this is bogus wrt the LDT/GDT limit on long selectors. */
    20772028    X86DESC64   Desc;
    2078     VBOXGDTR    Gdtr;
    20792029    RTGCPTR     GCPtrDesc;
    2080     CPUMGetGuestGDTR(pVCpu, &Gdtr);
    20812030    if (!(Sel & X86_SEL_LDT))
    20822031    {
    20832032        /* GDT */
    2084         if ((unsigned)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt)
     2033        VBOXGDTR Gdtr;
     2034        CPUMGetGuestGDTR(pVCpu, &Gdtr);
     2035        if ((Sel | X86_SEL_RPL_LDT) > Gdtr.cbGdt)
    20852036            return VERR_INVALID_SELECTOR;
    20862037        GCPtrDesc = Gdtr.pGdt + (Sel & X86_SEL_MASK);
     
    20882039    else
    20892040    {
    2090         /*
    2091          * LDT - must locate the LDT first.
    2092          */
    2093         RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu);
    2094         if (    (unsigned)(SelLdt & X86_SEL_MASK) < sizeof(X86DESC) /* the first selector is invalid, right? */ /** @todo r=bird: No, I don't think so */
    2095             ||  (unsigned)(SelLdt & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt)
     2041        /* LDT */
     2042        uint64_t GCPtrBase;
     2043        uint32_t cbLimit;
     2044        CPUMGetGuestLdtrEx(pVCpu, &GCPtrBase, &cbLimit);
     2045        if ((Sel | X86_SEL_RPL_LDT) > cbLimit)
    20962046            return VERR_INVALID_SELECTOR;
    2097         GCPtrDesc = Gdtr.pGdt + (SelLdt & X86_SEL_MASK);
    2098         int rc = PGMPhysSimpleReadGCPtr(pVCpu, &Desc, GCPtrDesc, sizeof(Desc));
    2099         if (RT_FAILURE(rc))
    2100             return rc;
    2101 
    2102         /* validate the LDT descriptor. */
    2103         if (Desc.Gen.u1Present == 0)
    2104             return VERR_SELECTOR_NOT_PRESENT;
    2105         if (    Desc.Gen.u1DescType == 1
    2106             ||  Desc.Gen.u4Type != AMD64_SEL_TYPE_SYS_LDT)
    2107             return VERR_INVALID_SELECTOR;
    2108 
    2109         uint32_t cbLimit = X86DESC_LIMIT_G(&Desc);
    2110         if ((uint32_t)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > cbLimit)
    2111             return VERR_INVALID_SELECTOR;
    21122047
    21132048        /* calc the descriptor location. */
    2114         GCPtrDesc = X86DESC64_BASE(&Desc);
    2115         GCPtrDesc += (Sel & X86_SEL_MASK);
     2049        GCPtrDesc = GCPtrBase + (Sel & X86_SEL_MASK);
    21162050    }
    21172051
     
    22552189    X86DESC Desc;
    22562190    if (    !(Sel & X86_SEL_LDT)
    2257         && (    pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_MASK)
    2258             ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_MASK)
    2259             ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_MASK)
    2260             ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_MASK)
    2261             ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_MASK))
     2191        && (    pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]         == (Sel & X86_SEL_RPL_LDT)
     2192            ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]         == (Sel & X86_SEL_RPL_LDT)
     2193            ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64]       == (Sel & X86_SEL_RPL_LDT)
     2194            ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS]        == (Sel & X86_SEL_RPL_LDT)
     2195            ||  pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_RPL_LDT))
    22622196       )
    22632197    {
     
    22802214        pSelInfo->fFlags = DBGFSELINFO_FLAGS_PROT_MODE;
    22812215
    2282         VBOXGDTR    Gdtr;
    22832216        RTGCPTR     GCPtrDesc;
    2284         CPUMGetGuestGDTR(pVCpu, &Gdtr);
    22852217        if (!(Sel & X86_SEL_LDT))
    22862218        {
    22872219            /* GDT */
    2288             if ((unsigned)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt)
     2220            VBOXGDTR Gdtr;
     2221            CPUMGetGuestGDTR(pVCpu, &Gdtr);
     2222            if ((Sel | X86_SEL_RPL_LDT) > Gdtr.cbGdt)
    22892223                return VERR_INVALID_SELECTOR;
    22902224            GCPtrDesc = Gdtr.pGdt + (Sel & X86_SEL_MASK);
     
    22922226        else
    22932227        {
    2294             /*
    2295              * LDT - must locate the LDT first...
    2296              */
    2297             RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu);
    2298             if (    (unsigned)(SelLdt & X86_SEL_MASK) < sizeof(X86DESC) /* the first selector is invalid, right? */ /** @todo r=bird: No, I don't think so */
    2299                 ||  (unsigned)(SelLdt & X86_SEL_MASK) + sizeof(X86DESC) - 1 > (unsigned)Gdtr.cbGdt)
     2228            /* LDT */
     2229            uint64_t GCPtrBase;
     2230            uint32_t cbLimit;
     2231            CPUMGetGuestLdtrEx(pVCpu, &GCPtrBase, &cbLimit);
     2232            if ((Sel | X86_SEL_RPL_LDT) > cbLimit)
    23002233                return VERR_INVALID_SELECTOR;
    2301             GCPtrDesc = Gdtr.pGdt + (SelLdt & X86_SEL_MASK);
    2302             int rc = PGMPhysSimpleReadGCPtr(pVCpu, &Desc, GCPtrDesc, sizeof(Desc));
    2303             if (RT_FAILURE(rc))
    2304                 return rc;
    2305 
    2306             /* validate the LDT descriptor. */
    2307             if (Desc.Gen.u1Present == 0)
    2308                 return VERR_SELECTOR_NOT_PRESENT;
    2309             if (    Desc.Gen.u1DescType == 1
    2310                 ||  Desc.Gen.u4Type != X86_SEL_TYPE_SYS_LDT)
    2311                 return VERR_INVALID_SELECTOR;
    2312 
    2313             uint32_t cbLimit = X86DESC_LIMIT_G(&Desc);
    2314             if ((uint32_t)(Sel & X86_SEL_MASK) + sizeof(X86DESC) - 1 > cbLimit)
    2315                 return VERR_INVALID_SELECTOR;
    23162234
    23172235            /* calc the descriptor location. */
    2318             GCPtrDesc = X86DESC_BASE(&Desc);
    2319             GCPtrDesc += (Sel & X86_SEL_MASK);
     2236            GCPtrDesc = GCPtrBase + (Sel & X86_SEL_MASK);
    23202237        }
    23212238
     
    24162333         */
    24172334        Desc = pVM->selm.s.paGdtR3[Sel >> X86_SEL_SHIFT];
    2418         pSelInfo->fFlags =    pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS] == (Sel & X86_SEL_MASK)
    2419                            || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS] == (Sel & X86_SEL_MASK)
    2420                            || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64] == (Sel & X86_SEL_MASK)
    2421                            || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] == (Sel & X86_SEL_MASK)
    2422                            || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_MASK)
     2335        pSelInfo->fFlags =    pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS]         == (Sel & X86_SEL_MASK_OFF_RPL)
     2336                           || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_DS]         == (Sel & X86_SEL_MASK_OFF_RPL)
     2337                           || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_CS64]       == (Sel & X86_SEL_MASK_OFF_RPL)
     2338                           || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS]        == (Sel & X86_SEL_MASK_OFF_RPL)
     2339                           || pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS_TRAP08] == (Sel & X86_SEL_MASK_OFF_RPL)
    24232340                         ? DBGFSELINFO_FLAGS_HYPER
    24242341                         : 0;
     
    26662583{
    26672584    /** @todo SMP support! */
    2668     PVMCPU      pVCpu = &pVM->aCpus[0];
    2669 
    2670     RTSEL SelLdt = CPUMGetGuestLDTR(pVCpu);
    2671     if (!(SelLdt & X86_SEL_MASK))
     2585    PVMCPU   pVCpu = &pVM->aCpus[0];
     2586
     2587    uint64_t GCPtrLdt;
     2588    uint32_t cbLdt;
     2589    RTSEL    SelLdt = CPUMGetGuestLdtrEx(pVCpu, &GCPtrLdt, &cbLdt);
     2590    if (!(SelLdt & X86_SEL_MASK_OFF_RPL))
    26722591    {
    26732592        pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x): Null-Selector\n", SelLdt);
     
    26752594    }
    26762595
    2677     RTGCPTR     GCPtrLdt;
    2678     unsigned    cbLdt;
    2679     int rc = SELMGetLDTFromSel(pVM, SelLdt, &GCPtrLdt, &cbLdt);
    2680     if (RT_FAILURE(rc))
    2681     {
    2682         pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x): rc=%Rrc\n", SelLdt, rc);
    2683         return;
    2684     }
    2685 
    2686     pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x GCAddr=%RGv limit=%x):\n", SelLdt, GCPtrLdt, cbLdt);
    2687     unsigned    cLdts  = (cbLdt + 1) >> X86_SEL_SHIFT;
     2596    pHlp->pfnPrintf(pHlp, "Guest LDT (Sel=%x GCAddr=%RX64 limit=%x):\n", SelLdt, GCPtrLdt, cbLdt);
     2597    unsigned cLdts  = (cbLdt + 1) >> X86_SEL_SHIFT;
    26882598    for (unsigned iLdt = 0; iLdt < cLdts; iLdt++, GCPtrLdt += sizeof(X86DESC))
    26892599    {
    26902600        X86DESC LdtE;
    2691         rc = PGMPhysSimpleReadGCPtr(pVCpu, &LdtE, GCPtrLdt, sizeof(LdtE));
     2601        int rc = PGMPhysSimpleReadGCPtr(pVCpu, &LdtE, GCPtrLdt, sizeof(LdtE));
    26922602        if (RT_SUCCESS(rc))
    26932603        {
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