VirtualBox

Changeset 9678 in vbox


Ignore:
Timestamp:
Jun 13, 2008 11:42:02 AM (16 years ago)
Author:
vboxsync
Message:

Rewrote SELMToFlatEx for long mode.

Location:
trunk
Files:
4 edited

Legend:

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

    r9675 r9678  
    200200 * @returns VBox status
    201201 * @param   pVM         VM Handle.
     202 * @param   SelReg      Selector register
     203 * @param   pCtxCore    CPU context
     204 * @param   Addr        Address part.
     205 * @param   fFlags      SELMTOFLAT_FLAGS_*
     206 *                      GDT entires are valid.
     207 * @param   ppvGC       Where to store the GC flat address.
     208 */
     209SELMDECL(int) SELMToFlatEx(PVM pVM, DIS_SELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC);
     210
     211/**
     212 * Converts a GC selector based address to a flat address.
     213 *
     214 * Some basic checking is done, but not all kinds yet.
     215 *
     216 * Note: Obsolete: DO NOT USE
     217 *
     218 * @returns VBox status
     219 * @param   pVM         VM Handle.
    202220 * @param   eflags      Current eflags
    203221 * @param   Sel         Selector part.
     
    210228 *                      the selector. NULL is allowed.
    211229 */
    212 SELMDECL(int) SELMToFlatEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, PCPUMSELREGHID pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb);
     230SELMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb);
    213231
    214232/**
  • trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp

    r9659 r9678  
    345345        /* Convert source address ds:esi. */
    346346        RTGCUINTPTR pu8Virt;
    347         rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
     347        rc = SELMToFlatEx(pVM, DIS_SELREG_DS, pRegFrame, (RTGCPTR)pRegFrame->esi,
    348348                          SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
    349                           (PRTGCPTR)&pu8Virt, NULL);
     349                          (PRTGCPTR)&pu8Virt);
    350350        if (VBOX_SUCCESS(rc))
    351351        {
     
    404404        /* Convert destination address. */
    405405        RTGCUINTPTR pu8Virt;
    406         rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
    407                                 SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
    408                                 (RTGCPTR *)&pu8Virt, NULL);
     406        rc = SELMToFlatEx(pVM, DIS_SELREG_ES, pRegFrame, (RTGCPTR)pRegFrame->edi,
     407                          SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
     408                          (RTGCPTR *)&pu8Virt);
    409409        if (VBOX_FAILURE(rc))
    410410            return VINF_EM_RAW_GUEST_TRAP;
     
    13191319    /* Convert destination address es:edi. */
    13201320    RTGCPTR GCPtrDst;
    1321     int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->es, (RTGCPTR)pRegFrame->edi, &pRegFrame->esHid,
     1321    int rc = SELMToFlatEx(pVM, DIS_SELREG_ES, pRegFrame, (RTGCPTR)pRegFrame->edi,
    13221322                          SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
    1323                           &GCPtrDst, NULL);
     1323                          &GCPtrDst);
    13241324    if (VBOX_FAILURE(rc))
    13251325    {
     
    14741474    /* Convert source address ds:esi. */
    14751475    RTGCPTR GCPtrSrc;
    1476     int rc = SELMToFlatEx(pVM, pRegFrame->eflags, pRegFrame->ds, (RTGCPTR)pRegFrame->esi, &pRegFrame->dsHid,
     1476    int rc = SELMToFlatEx(pVM, DIS_SELREG_DS, pRegFrame, (RTGCPTR)pRegFrame->esi,
    14771477                          SELMTOFLAT_FLAGS_HYPER | SELMTOFLAT_FLAGS_NO_PL,
    1478                           &GCPtrSrc, NULL);
     1478                          &GCPtrSrc);
    14791479    if (VBOX_FAILURE(rc))
    14801480    {
  • trunk/src/VBox/VMM/VMMAll/SELMAll.cpp

    r9675 r9678  
    5252SELMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr)
    5353{
    54     Assert(!CPUMAreHiddenSelRegsValid(pVM));
     54    Assert(!CPUMIsGuestInLongMode(pVM));    /** DON'T USE! */
    5555
    5656    /** @todo check the limit. */
     
    131131}
    132132
     133
     134/**
     135 * Converts a GC selector based address to a flat address.
     136 *
     137 * Some basic checking is done, but not all kinds yet.
     138 *
     139 * @returns VBox status
     140 * @param   pVM         VM Handle.
     141 * @param   SelReg      Selector register
     142 * @param   pCtxCore    CPU context
     143 * @param   Addr        Address part.
     144 * @param   fFlags      SELMTOFLAT_FLAGS_*
     145 *                      GDT entires are valid.
     146 * @param   ppvGC       Where to store the GC flat address.
     147 */
     148SELMDECL(int) SELMToFlatEx(PVM pVM, DIS_SELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC)
     149{
     150    PCPUMSELREGHID pHiddenSel;
     151    RTSEL          Sel;
     152    int            rc;
     153
     154    rc = DISFetchRegSegEx(pCtxCore, SelReg, &Sel, &pHiddenSel); AssertRC(rc);
     155
     156    /*
     157     * Deal with real & v86 mode first.
     158     */
     159    if (    CPUMIsGuestInRealMode(pVM)
     160        ||  pCtxCore->eflags.Bits.u1VM)
     161    {
     162        RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
     163        if (ppvGC)
     164        {
     165            if (    pHiddenSel
     166                &&  CPUMAreHiddenSelRegsValid(pVM))
     167                *ppvGC = (RTGCPTR)(pHiddenSel->u64Base + uFlat);
     168            else
     169                *ppvGC = (RTGCPTR)(((RTGCUINTPTR)Sel << 4) + uFlat);
     170        }
     171        return VINF_SUCCESS;
     172    }
     173
     174
     175    uint32_t    u32Limit;
     176    RTGCPTR     pvFlat;
     177    uint32_t    u1Present, u1DescType, u1Granularity, u4Type;
     178
     179    /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
     180#ifndef IN_GC
     181    if (    pHiddenSel
     182        &&  CPUMAreHiddenSelRegsValid(pVM))
     183    {
     184        bool fCheckLimit = true;
     185
     186        u1Present     = pHiddenSel->Attr.n.u1Present;
     187        u1Granularity = pHiddenSel->Attr.n.u1Granularity;
     188        u1DescType    = pHiddenSel->Attr.n.u1DescType;
     189        u4Type        = pHiddenSel->Attr.n.u4Type;
     190
     191        u32Limit      = pHiddenSel->u32Limit;
     192
     193        /* 64 bits mode: CS, DS, ES and SS are treated as if each segment base is 0 (Intel® 64 and IA-32 Architectures Software Developer's Manual: 3.4.2.1). */
     194        if (    CPUMIsGuestInLongMode(pVM)
     195            &&  pCtxCore->csHid.Attr.n.u1Long)
     196        {
     197            fCheckLimit = false;
     198            switch (SelReg)
     199            {
     200            case DIS_SELREG_FS:
     201                pvFlat = (CPUMGetGuestFSBASE(pVM) + Addr);
     202                break;
     203
     204            case DIS_SELREG_GS:
     205                pvFlat = (CPUMGetGuestGSBASE(pVM) + Addr);
     206                break;
     207
     208            default:
     209                pvFlat = Addr;
     210                break;
     211            }
     212        }
     213        else
     214            pvFlat = (RTGCPTR)(pHiddenSel->u64Base + (RTGCUINTPTR)Addr);
     215
     216        /*
     217        * Check if present.
     218        */
     219        if (u1Present)
     220        {
     221            /*
     222            * Type check.
     223            */
     224            switch (u4Type)
     225            {
     226
     227                /** Read only selector type. */
     228                case X86_SEL_TYPE_RO:
     229                case X86_SEL_TYPE_RO_ACC:
     230                case X86_SEL_TYPE_RW:
     231                case X86_SEL_TYPE_RW_ACC:
     232                case X86_SEL_TYPE_EO:
     233                case X86_SEL_TYPE_EO_ACC:
     234                case X86_SEL_TYPE_ER:
     235                case X86_SEL_TYPE_ER_ACC:
     236                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     237                    {
     238                        /** @todo fix this mess */
     239                    }
     240                    /* check limit. */
     241                    if (fCheckLimit && (RTGCUINTPTR)Addr > u32Limit)
     242                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     243                    /* ok */
     244                    if (ppvGC)
     245                        *ppvGC = pvFlat;
     246                    return VINF_SUCCESS;
     247
     248                case X86_SEL_TYPE_EO_CONF:
     249                case X86_SEL_TYPE_EO_CONF_ACC:
     250                case X86_SEL_TYPE_ER_CONF:
     251                case X86_SEL_TYPE_ER_CONF_ACC:
     252                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     253                    {
     254                        /** @todo fix this mess */
     255                    }
     256                    /* check limit. */
     257                    if (fCheckLimit && (RTGCUINTPTR)Addr > u32Limit)
     258                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     259                    /* ok */
     260                    if (ppvGC)
     261                        *ppvGC = pvFlat;
     262                    return VINF_SUCCESS;
     263
     264                case X86_SEL_TYPE_RO_DOWN:
     265                case X86_SEL_TYPE_RO_DOWN_ACC:
     266                case X86_SEL_TYPE_RW_DOWN:
     267                case X86_SEL_TYPE_RW_DOWN_ACC:
     268                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     269                    {
     270                        /** @todo fix this mess */
     271                    }
     272                    /* check limit. */
     273                    if (fCheckLimit)
     274                    {
     275                        if (!u1Granularity && (RTGCUINTPTR)Addr > (RTGCUINTPTR)0xffff)
     276                            return VERR_OUT_OF_SELECTOR_BOUNDS;
     277                        if ((RTGCUINTPTR)Addr <= u32Limit)
     278                            return VERR_OUT_OF_SELECTOR_BOUNDS;
     279                    }
     280                    /* ok */
     281                    if (ppvGC)
     282                        *ppvGC = pvFlat;
     283                    return VINF_SUCCESS;
     284
     285                default:
     286                    return VERR_INVALID_SELECTOR;
     287
     288            }
     289        }
     290    }
     291    else
     292#endif /* !IN_GC */
     293#ifndef IN_RING0
     294    {
     295        VBOXDESC Desc;
     296
     297        if (!(Sel & X86_SEL_LDT))
     298        {
     299            if (   !(fFlags & SELMTOFLAT_FLAGS_HYPER)
     300                && (unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.GuestGdtr.cbGdt)
     301                return VERR_INVALID_SELECTOR;
     302            Desc = pVM->selm.s.CTXSUFF(paGdt)[Sel >> X86_SEL_SHIFT];
     303        }
     304        else
     305        {
     306            if ((unsigned)(Sel & X86_SEL_MASK) >= pVM->selm.s.cbLdtLimit)
     307                return VERR_INVALID_SELECTOR;
     308
     309            /** @todo handle LDT page(s) not present! */
     310#ifdef IN_GC
     311            PVBOXDESC    paLDT = (PVBOXDESC)((char *)pVM->selm.s.GCPtrLdt + pVM->selm.s.offLdtHyper);
     312#else
     313            PVBOXDESC    paLDT = (PVBOXDESC)((char *)pVM->selm.s.HCPtrLdt + pVM->selm.s.offLdtHyper);
     314#endif
     315            Desc = paLDT[Sel >> X86_SEL_SHIFT];
     316        }
     317
     318        /* calc limit. */
     319        u32Limit = X86DESC_LIMIT(Desc);
     320        if (Desc.Gen.u1Granularity)
     321            u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK;
     322
     323        /* calc address assuming straight stuff. */
     324        pvFlat = (RTGCPTR)((RTGCUINTPTR)Addr + X86DESC_BASE(Desc));
     325
     326        u1Present     = Desc.Gen.u1Present;
     327        u1Granularity = Desc.Gen.u1Granularity;
     328        u1DescType    = Desc.Gen.u1DescType;
     329        u4Type        = Desc.Gen.u4Type;
     330
     331        /*
     332        * Check if present.
     333        */
     334        if (u1Present)
     335        {
     336            /*
     337            * Type check.
     338            */
     339#define BOTH(a, b) ((a << 16) | b)
     340            switch (BOTH(u1DescType, u4Type))
     341            {
     342
     343                /** Read only selector type. */
     344                case BOTH(1,X86_SEL_TYPE_RO):
     345                case BOTH(1,X86_SEL_TYPE_RO_ACC):
     346                case BOTH(1,X86_SEL_TYPE_RW):
     347                case BOTH(1,X86_SEL_TYPE_RW_ACC):
     348                case BOTH(1,X86_SEL_TYPE_EO):
     349                case BOTH(1,X86_SEL_TYPE_EO_ACC):
     350                case BOTH(1,X86_SEL_TYPE_ER):
     351                case BOTH(1,X86_SEL_TYPE_ER_ACC):
     352                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     353                    {
     354                        /** @todo fix this mess */
     355                    }
     356                    /* check limit. */
     357                    if ((RTGCUINTPTR)Addr > u32Limit)
     358                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     359                    /* ok */
     360                    if (ppvGC)
     361                        *ppvGC = pvFlat;
     362                    return VINF_SUCCESS;
     363
     364                case BOTH(1,X86_SEL_TYPE_EO_CONF):
     365                case BOTH(1,X86_SEL_TYPE_EO_CONF_ACC):
     366                case BOTH(1,X86_SEL_TYPE_ER_CONF):
     367                case BOTH(1,X86_SEL_TYPE_ER_CONF_ACC):
     368                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     369                    {
     370                        /** @todo fix this mess */
     371                    }
     372                    /* check limit. */
     373                    if ((RTGCUINTPTR)Addr > u32Limit)
     374                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     375                    /* ok */
     376                    if (ppvGC)
     377                        *ppvGC = pvFlat;
     378                    return VINF_SUCCESS;
     379
     380                case BOTH(1,X86_SEL_TYPE_RO_DOWN):
     381                case BOTH(1,X86_SEL_TYPE_RO_DOWN_ACC):
     382                case BOTH(1,X86_SEL_TYPE_RW_DOWN):
     383                case BOTH(1,X86_SEL_TYPE_RW_DOWN_ACC):
     384                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     385                    {
     386                        /** @todo fix this mess */
     387                    }
     388                    /* check limit. */
     389                    if (!u1Granularity && (RTGCUINTPTR)Addr > (RTGCUINTPTR)0xffff)
     390                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     391                    if ((RTGCUINTPTR)Addr <= u32Limit)
     392                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     393
     394                    /* ok */
     395                    if (ppvGC)
     396                        *ppvGC = pvFlat;
     397                    return VINF_SUCCESS;
     398
     399                case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_AVAIL):
     400                case BOTH(0,X86_SEL_TYPE_SYS_LDT):
     401                case BOTH(0,X86_SEL_TYPE_SYS_286_TSS_BUSY):
     402                case BOTH(0,X86_SEL_TYPE_SYS_286_CALL_GATE):
     403                case BOTH(0,X86_SEL_TYPE_SYS_TASK_GATE):
     404                case BOTH(0,X86_SEL_TYPE_SYS_286_INT_GATE):
     405                case BOTH(0,X86_SEL_TYPE_SYS_286_TRAP_GATE):
     406                case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_AVAIL):
     407                case BOTH(0,X86_SEL_TYPE_SYS_386_TSS_BUSY):
     408                case BOTH(0,X86_SEL_TYPE_SYS_386_CALL_GATE):
     409                case BOTH(0,X86_SEL_TYPE_SYS_386_INT_GATE):
     410                case BOTH(0,X86_SEL_TYPE_SYS_386_TRAP_GATE):
     411                    if (!(fFlags & SELMTOFLAT_FLAGS_NO_PL))
     412                    {
     413                        /** @todo fix this mess */
     414                    }
     415                    /* check limit. */
     416                    if ((RTGCUINTPTR)Addr > u32Limit)
     417                        return VERR_OUT_OF_SELECTOR_BOUNDS;
     418                    /* ok */
     419                    if (ppvGC)
     420                        *ppvGC = pvFlat;
     421                    return VINF_SUCCESS;
     422
     423                default:
     424                    return VERR_INVALID_SELECTOR;
     425
     426            }
     427#undef BOTH
     428        }
     429    }
     430#endif /* !IN_RING0 */
     431    return VERR_SELECTOR_NOT_PRESENT;
     432}
    133433
    134434/**
     
    149449 *                      the selector. NULL is allowed.
    150450 */
    151 SELMDECL(int) SELMToFlatEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
    152 {
    153     Assert(!CPUMIsGuestInLongMode(pVM));    /** @todo */
     451SELMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
     452{
     453    Assert(!CPUMIsGuestInLongMode(pVM));    /** DON'T USE! */
     454
    154455    /*
    155456     * Deal with real & v86 mode first.
  • trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp

    r9412 r9678  
    555555                        || !ss_r0
    556556                        || (ss_r0 & X86_SEL_RPL) != ((dpl == 0) ? 1 : dpl)
    557                         || SELMToFlatEx(pVM, fakeflags, ss_r0, (RTGCPTR)esp_r0, NULL, SELMTOFLAT_FLAGS_CPL1, (PRTGCPTR)&pTrapStackGC, NULL) != VINF_SUCCESS
     557                        || SELMToFlatBySelEx(pVM, fakeflags, ss_r0, (RTGCPTR)esp_r0, NULL, SELMTOFLAT_FLAGS_CPL1, (PRTGCPTR)&pTrapStackGC, NULL) != VINF_SUCCESS
    558558                       )
    559559                    {
     
    569569
    570570                    if (    eflags.Bits.u1VM    /* illegal */
    571                         ||  SELMToFlatEx(pVM, fakeflags, ss_r0, (RTGCPTR)esp_r0, NULL, SELMTOFLAT_FLAGS_CPL1, (PRTGCPTR)&pTrapStackGC, NULL) != VINF_SUCCESS)
     571                        ||  SELMToFlatBySelEx(pVM, fakeflags, ss_r0, (RTGCPTR)esp_r0, NULL, SELMTOFLAT_FLAGS_CPL1, (PRTGCPTR)&pTrapStackGC, NULL) != VINF_SUCCESS)
    572572                    {
    573573                        AssertMsgFailed(("Invalid stack %04X:%VRv??? (VM=%d)\n", ss_r0, esp_r0, eflags.Bits.u1VM));
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