VirtualBox

Changeset 1939 in vbox for trunk


Ignore:
Timestamp:
Apr 4, 2007 4:00:01 PM (18 years ago)
Author:
vboxsync
Message:

Support segment prefixes in our instruction emulator.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r1929 r1939  
    5454DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize);
    5555
     56/* Enable to allow segment prefix support */
     57#define EM_ALLOW_SEG_PREFIX
    5658
    5759/**
     
    107109inline int emDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
    108110{
    109     return DISCoreOneEx(InstrGC, pCpu->mode, EMReadBytes, pVM, pCpu, pOpsize);
     111    return DISCoreOneEx(InstrGC, pCpu->mode, EMReadBytes, pVM, pCpu,  pOpsize);
    110112}
    111113
     
    282284
    283285
    284 inline int emRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb)
     286inline int emRamRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, void *pDest, RTGCPTR GCSrc, uint32_t cb)
    285287{
    286288#ifdef IN_GC
     
    300302}
    301303
    302 inline int emRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb)
     304inline int emRamWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, RTGCPTR GCDest, void *pSrc, uint32_t cb)
    303305{
    304306#ifdef IN_GC
     
    317319}
    318320
     321/* Convert sel:addr to a flat GC address */
     322static RTGCPTR emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, POP_PARAMETER pParam, RTGCPTR pvAddr)
     323{
     324#ifdef EM_ALLOW_SEG_PREFIX
     325    int   prefix_seg;
     326    RTSEL sel = 0;
     327    CPUMSELREGHID *pSelHidReg;
     328   
     329    prefix_seg = DISDetectSegReg(pCpu, pParam);
     330    DISFetchRegSegEx(pRegFrame, prefix_seg, &sel, &pSelHidReg);
     331    return SELMToFlat(pVM, pRegFrame->eflags, sel, pSelHidReg, pvAddr);
     332#else
     333    return pvAddr;
     334#endif
     335}
     336
    319337/**
    320338 * XCHG instruction emulation.
     
    351369            case PARMTYPE_ADDRESS:
    352370                pParam1 = (RTGCPTR)param1.val.val32;
     371                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    353372#ifdef IN_GC
    354373                /* Safety check (in theory it could cross a page boundary and fault there though) */
    355                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    356 #endif
    357                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     374                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     375#endif
     376                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
    358377                if (VBOX_FAILURE(rc))
    359378                {
     
    372391            case PARMTYPE_ADDRESS:
    373392                pParam2 = (RTGCPTR)param2.val.val32;
     393                pParam2 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param2, pParam2);
    374394#ifdef IN_GC
    375395                /* Safety check (in theory it could cross a page boundary and fault there though) */
    376                 AssertReturn(pParam2 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    377 #endif
    378                 rc = emRamRead(pVM, &valpar2, pParam2, param2.size);
     396                AssertReturn(pParam2 == pvFault, VERR_EM_INTERPRETER);
     397#endif
     398                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar2, pParam2, param2.size);
    379399                if (VBOX_FAILURE(rc))
    380400                {
     
    409429            else
    410430            {
    411                 rc = emRamWrite(pVM, pParam1, &valpar2, param1.size);
     431                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar2, param1.size);
    412432                if (VBOX_FAILURE(rc))
    413433                {
     
    434454            else
    435455            {
    436                 rc = emRamWrite(pVM, pParam2, &valpar1, param2.size);
     456                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam2, &valpar1, param2.size);
    437457                if (VBOX_FAILURE(rc))
    438458                {
     
    475495            {
    476496                pParam1 = (RTGCPTR)param1.val.val32;
     497                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    477498#ifdef IN_GC
    478499                /* Safety check (in theory it could cross a page boundary and fault there though) */
    479                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    480 #endif
    481                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     500                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     501#endif
     502                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
    482503                if (VBOX_FAILURE(rc))
    483504                {
     
    500521
    501522            /* Write result back */
    502             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     523            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    503524            if (VBOX_FAILURE(rc))
    504525            {
     
    550571                return VERR_EM_INTERPRETER;
    551572
    552             rc = emRamRead(pVM, &valpar1, pStackVal, param1.size);
     573            rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pStackVal, param1.size);
    553574            if (VBOX_FAILURE(rc))
    554575            {
     
    568589                   )
    569590                   pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + param1.size);
     591
     592                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    570593               
    571594#ifdef IN_GC
    572595                /* Safety check (in theory it could cross a page boundary and fault there though) */
    573                 AssertMsgReturn(pParam1 == (RTGCPTR)pvFault, ("%VGv != %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
    574 #endif
    575                 rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     596                AssertMsgReturn(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, ("%VGv != %VGv ss:esp=%04X:%VGv\n", pParam1, pvFault, pRegFrame->ss, pRegFrame->esp), VERR_EM_INTERPRETER);
     597#endif
     598                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    576599                if (VBOX_FAILURE(rc))
    577600                {
     
    640663            {
    641664                pParam1 = (RTGCPTR)param1.val.val32;
     665                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    642666
    643667#ifdef IN_GC
    644668                /* Safety check (in theory it could cross a page boundary and fault there though) */
    645                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    646 #endif
    647                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     669                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     670#endif
     671                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
    648672                if (VBOX_FAILURE(rc))
    649673                {
     
    678702
    679703            /* And write it back */
    680             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     704            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    681705            if (VBOX_SUCCESS(rc))
    682706            {
     
    731755            {
    732756                pParam1 = (RTGCPTR)param1.val.val32;
     757                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    733758
    734759#ifdef IN_GC
    735760                /* Safety check (in theory it could cross a page boundary and fault there though) */
    736                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    737 #endif
    738                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     761                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     762#endif
     763                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
    739764                if (VBOX_FAILURE(rc))
    740765                {
     
    769794
    770795            /* And write it back */
    771             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     796            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    772797            if (VBOX_SUCCESS(rc))
    773798            {
     
    822847            {
    823848                pParam1 = (RTGCPTR)param1.val.val32;
     849                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    824850
    825851#ifdef IN_GC
     
    827853                AssertMsgReturn(pParam1 == pvFault, ("pParam1 = %VGv pvFault = %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
    828854#endif
    829                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     855                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
    830856                if (VBOX_FAILURE(rc))
    831857                {
     
    862888
    863889            /* And write it back */
    864             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     890            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    865891            if (VBOX_SUCCESS(rc))
    866892            {
     
    915941            {
    916942                pParam1 = (RTGCPTR)param1.val.val32;
     943                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    917944
    918945#ifdef IN_GC
    919946                /* Safety check (in theory it could cross a page boundary and fault there though) */
    920                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    921 #endif
    922                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     947                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     948#endif
     949                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
    923950                if (VBOX_FAILURE(rc))
    924951                {
     
    955982
    956983            /* And write it back */
    957             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     984            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    958985            if (VBOX_SUCCESS(rc))
    959986            {
     
    10091036            {
    10101037                pParam1 = (RTGCPTR)param1.val.val32;
     1038                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    10111039
    10121040#ifdef IN_GC
    10131041                /* Safety check (in theory it could cross a page boundary and fault there though) */
    1014                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    1015 #endif
    1016                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     1042                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     1043#endif
     1044                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
    10171045                if (VBOX_FAILURE(rc))
    10181046                {
     
    10541082
    10551083            /* And write it back */
    1056             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     1084            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    10571085            if (VBOX_SUCCESS(rc))
    10581086            {
     
    11071135            {
    11081136                pParam1 = (RTGCPTR)param1.val.val32;
     1137                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    11091138
    11101139#ifdef IN_GC
    11111140                /* Safety check (in theory it could cross a page boundary and fault there though) */
    1112                 AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
    1113 #endif
    1114                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
     1141                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
     1142#endif
     1143                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
    11151144                if (VBOX_FAILURE(rc))
    11161145                {
     
    11471176
    11481177            /* And write it back */
    1149             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
     1178            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
    11501179            if (VBOX_SUCCESS(rc))
    11511180            {
     
    11971226            case PARMTYPE_ADDRESS:
    11981227                pDest = (RTGCPTR)param1.val.val32;
     1228                pDest = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pDest);
    11991229                break;
    12001230
     
    12181248            Assert(param2.size <= 4 && param2.size > 0);
    12191249
    1220             rc = emRamWrite(pVM, pDest, &val32, param2.size);
     1250#ifdef IN_GC
     1251            /* Safety check (in theory it could cross a page boundary and fault there though) */
     1252            AssertReturn(pDest == pvFault, VERR_EM_INTERPRETER);
     1253#endif
     1254            rc = emRamWrite(pVM, pRegFrame, pCpu, pDest, &val32, param2.size);
    12211255            if (VBOX_FAILURE(rc))
    12221256                return VERR_EM_INTERPRETER;
     
    12391273            case PARMTYPE_ADDRESS:
    12401274                pSrc = (RTGCPTR)param2.val.val32;
     1275                pSrc = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param2, pSrc);
    12411276                break;
    12421277
     
    12461281
    12471282            Assert(param1.size <= 4 && param1.size > 0);
    1248             rc = emRamRead(pVM, &val32, pSrc, param1.size);
     1283#ifdef IN_GC
     1284            /* Safety check (in theory it could cross a page boundary and fault there though) */
     1285            AssertReturn(pSrc == pvFault, VERR_EM_INTERPRETER);
     1286#endif
     1287            rc = emRamRead(pVM, pRegFrame, pCpu, &val32, pSrc, param1.size);
    12491288            if (VBOX_FAILURE(rc))
    12501289                return VERR_EM_INTERPRETER;
     
    12931332    int         rc;
    12941333
    1295     rc  = emRamRead(pVM, &eip,      (RTGCPTR)pIretStack    , 4);
    1296     rc |= emRamRead(pVM, &cs,       (RTGCPTR)(pIretStack + 4), 4);
    1297     rc |= emRamRead(pVM, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
     1334    rc  = emRamRead(pVM, NULL, NULL, &eip,      (RTGCPTR)pIretStack      , 4);
     1335    rc |= emRamRead(pVM, NULL, NULL, &cs,       (RTGCPTR)(pIretStack + 4), 4);
     1336    rc |= emRamRead(pVM, NULL, NULL, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
    12981337    AssertRCReturn(rc, VERR_EM_INTERPRETER);
    12991338    AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
    13001339
    1301     rc |= emRamRead(pVM, &esp,      (RTGCPTR)(pIretStack + 12), 4);
    1302     rc |= emRamRead(pVM, &ss,       (RTGCPTR)(pIretStack + 16), 4);
    1303     rc |= emRamRead(pVM, &es,       (RTGCPTR)(pIretStack + 20), 4);
    1304     rc |= emRamRead(pVM, &ds,       (RTGCPTR)(pIretStack + 24), 4);
    1305     rc |= emRamRead(pVM, &fs,       (RTGCPTR)(pIretStack + 28), 4);
    1306     rc |= emRamRead(pVM, &gs,       (RTGCPTR)(pIretStack + 32), 4);
     1340    rc |= emRamRead(pVM, NULL, NULL, &esp,      (RTGCPTR)(pIretStack + 12), 4);
     1341    rc |= emRamRead(pVM, NULL, NULL, &ss,       (RTGCPTR)(pIretStack + 16), 4);
     1342    rc |= emRamRead(pVM, NULL, NULL, &es,       (RTGCPTR)(pIretStack + 20), 4);
     1343    rc |= emRamRead(pVM, NULL, NULL, &ds,       (RTGCPTR)(pIretStack + 24), 4);
     1344    rc |= emRamRead(pVM, NULL, NULL, &fs,       (RTGCPTR)(pIretStack + 28), 4);
     1345    rc |= emRamRead(pVM, NULL, NULL, &gs,       (RTGCPTR)(pIretStack + 32), 4);
    13071346    AssertRCReturn(rc, VERR_EM_INTERPRETER);
    13081347
     
    18531892    }
    18541893
     1894#ifdef EM_ALLOW_SEG_PREFIX
     1895    if (pCpu->prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_LOCK))
     1896#else
    18551897    /* Out emulation above can't cope with 16 bits code yet. */
    18561898    if (!SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid))
    18571899        return VERR_EM_INTERPRETER;
    18581900
    1859     /** @note we could ignore PREFIX_LOCK here. Need to take special precautions when/if we support SMP in the guest.
    1860      */
    18611901    if (pCpu->prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG | PREFIX_LOCK))
     1902#endif
    18621903    {
    18631904        //Log(("EMInterpretInstruction: wrong prefix!!\n"));
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