VirtualBox

Changeset 15584 in vbox


Ignore:
Timestamp:
Dec 16, 2008 1:59:05 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
41093
Message:

#3281: VT-x real mode disable itself quietly if PDMR3VMMDevHeapAlloc fails (because the VMMDev head is disabled in this version of the virtual hardware).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/HWACCM.cpp

    r15578 r15584  
    783783            /* Allocate three pages for the TSS we need for real mode emulation. (2 page for the IO bitmap) */
    784784            rc = PDMR3VMMDevHeapAlloc(pVM, HWACCM_VTX_TOTAL_DEVHEAP_MEM, (RTR3PTR *)&pVM->hwaccm.s.vmx.pRealModeTSS);
    785             AssertRC(rc);
    786             if (RT_FAILURE(rc))
    787                 return rc;
    788 
    789             /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. */
    790             ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS));
    791             pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS);
    792             /* Bit set to 0 means redirection enabled. */
    793             memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap));
    794             /* Allow all port IO, so the VT-x IO intercepts do their job. */
    795             memset(pVM->hwaccm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE*2);
    796             *((unsigned char *)pVM->hwaccm.s.vmx.pRealModeTSS + HWACCM_VTX_TSS_SIZE - 2) = 0xff;
    797 
    798             /* Construct a 1024 element page directory with 4 MB pages for the identity mapped page table used in
    799              * real and protected mode without paging with EPT.
    800              */
    801             pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hwaccm.s.vmx.pRealModeTSS + PAGE_SIZE * 3);
    802             for (unsigned i=0;i<X86_PG_ENTRIES;i++)
     785            if (RT_SUCCESS(rc))
    803786            {
    804                 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u  = _4M * i;
    805                 pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS | X86_PDE4M_G;
     787
     788                /* The I/O bitmap starts right after the virtual interrupt redirection bitmap. */
     789                ASMMemZero32(pVM->hwaccm.s.vmx.pRealModeTSS, sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS));
     790                pVM->hwaccm.s.vmx.pRealModeTSS->offIoBitmap = sizeof(*pVM->hwaccm.s.vmx.pRealModeTSS);
     791                /* Bit set to 0 means redirection enabled. */
     792                memset(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap, 0x0, sizeof(pVM->hwaccm.s.vmx.pRealModeTSS->IntRedirBitmap));
     793                /* Allow all port IO, so the VT-x IO intercepts do their job. */
     794                memset(pVM->hwaccm.s.vmx.pRealModeTSS + 1, 0, PAGE_SIZE*2);
     795                *((unsigned char *)pVM->hwaccm.s.vmx.pRealModeTSS + HWACCM_VTX_TSS_SIZE - 2) = 0xff;
     796
     797                /* Construct a 1024 element page directory with 4 MB pages for the identity mapped page table used in
     798                 * real and protected mode without paging with EPT.
     799                 */
     800                pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = (PX86PD)((char *)pVM->hwaccm.s.vmx.pRealModeTSS + PAGE_SIZE * 3);
     801                for (unsigned i=0;i<X86_PG_ENTRIES;i++)
     802                {
     803                    pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u  = _4M * i;
     804                    pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable->a[i].u |= X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A | X86_PDE4M_D | X86_PDE4M_PS | X86_PDE4M_G;
     805                }
     806
     807                /* We convert it here every time as pci regions could be reconfigured. */
     808                rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pRealModeTSS, &GCPhys);
     809                AssertRC(rc);
     810                LogRel(("HWACCM: Real Mode TSS guest physaddr  = %RGp\n", GCPhys));
     811
     812                rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
     813                AssertRC(rc);
     814                LogRel(("HWACCM: Non-Paging Mode EPT CR3       = %RGp\n", GCPhys));
    806815            }
    807 
    808             /* We convert it here every time as pci regions could be reconfigured. */
    809             rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pRealModeTSS, &GCPhys);
    810             AssertRC(rc);
    811             LogRel(("HWACCM: Real Mode TSS guest physaddr  = %RGp\n", GCPhys));
    812 
    813             rc = PDMVMMDevHeapR3ToGCPhys(pVM, pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
    814             AssertRC(rc);
    815             LogRel(("HWACCM: Non-Paging Mode EPT CR3       = %RGp\n", GCPhys));
     816            else
     817            {
     818                LogRel(("HWACCM: No real mode VT-x support (PDMR3VMMDevHeapAlloc returned %Rrc)\n", rc));
     819                pVM->hwaccm.s.vmx.pRealModeTSS = NULL;
     820                pVM->hwaccm.s.vmx.pNonPagingModeEPTPageTable = NULL;
     821            }
    816822
    817823            rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_HWACC_SETUP_VM, 0, NULL);
     
    11931199    /* Note! The context supplied by REM is partial. If we add more checks here, be sure to verify that REM provides this info! */
    11941200#ifdef HWACCM_VMX_EMULATE_REALMODE
    1195     if (CPUMIsGuestInRealModeEx(pCtx))
    1196     {
    1197         /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case.
    1198          * The base must also be equal to (sel << 4).
    1199          */
    1200         if (   (   pCtx->cs != (pCtx->csHid.u64Base >> 4)
    1201                 && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */)
    1202             || pCtx->ds != (pCtx->dsHid.u64Base >> 4)
    1203             || pCtx->es != (pCtx->esHid.u64Base >> 4)
    1204             || pCtx->fs != (pCtx->fsHid.u64Base >> 4)
    1205             || pCtx->gs != (pCtx->gsHid.u64Base >> 4)
    1206             || pCtx->ss != (pCtx->ssHid.u64Base >> 4))
    1207         {
    1208             return false;
    1209         }
    1210     }
    1211     else
    1212     {
    1213         PGMMODE enmGuestMode = PGMGetGuestMode(pVM);
    1214         /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch
    1215          * from real to protected mode. (all sorts of RPL & DPL assumptions)
    1216          */
    1217         PVMCPU pVCpu = VMMGetCpu(pVM);
    1218 
    1219         if (    pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL
    1220             &&  enmGuestMode >= PGMMODE_PROTECTED)
    1221         {
    1222             if (   (pCtx->cs & X86_SEL_RPL)
    1223                 || (pCtx->ds & X86_SEL_RPL)
    1224                 || (pCtx->es & X86_SEL_RPL)
    1225                 || (pCtx->fs & X86_SEL_RPL)
    1226                 || (pCtx->gs & X86_SEL_RPL)
    1227                 || (pCtx->ss & X86_SEL_RPL))
     1201    if (pVM->hwaccm.s.vmx.pRealModeTSS)
     1202    {
     1203        if (CPUMIsGuestInRealModeEx(pCtx))
     1204        {
     1205            /* VT-x will not allow high selector bases in v86 mode; fall back to the recompiler in that case.
     1206             * The base must also be equal to (sel << 4).
     1207             */
     1208            if (   (   pCtx->cs != (pCtx->csHid.u64Base >> 4)
     1209                    && pCtx->csHid.u64Base != 0xffff0000 /* we can deal with the BIOS code as it's also mapped into the lower region. */)
     1210                || pCtx->ds != (pCtx->dsHid.u64Base >> 4)
     1211                || pCtx->es != (pCtx->esHid.u64Base >> 4)
     1212                || pCtx->fs != (pCtx->fsHid.u64Base >> 4)
     1213                || pCtx->gs != (pCtx->gsHid.u64Base >> 4)
     1214                || pCtx->ss != (pCtx->ssHid.u64Base >> 4))
    12281215            {
    12291216                return false;
    12301217            }
    12311218        }
    1232     }
    1233 #else
    1234     if (!CPUMIsGuestInLongModeEx(pCtx))
    1235     {
    1236         /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
    1237         if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0)
    1238             return false;
    1239 
    1240         /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
    1241         /* Windows XP; switch to protected mode; all selectors are marked not present in the
    1242          * hidden registers (possible recompiler bug; see load_seg_vm) */
    1243         if (pCtx->csHid.Attr.n.u1Present == 0)
    1244             return false;
    1245         if (pCtx->ssHid.Attr.n.u1Present == 0)
    1246             return false;
    1247     }
    1248 #endif
     1219        else
     1220        {
     1221            PGMMODE enmGuestMode = PGMGetGuestMode(pVM);
     1222            /* Verify the requirements for executing code in protected mode. VT-x can't handle the CPU state right after a switch
     1223             * from real to protected mode. (all sorts of RPL & DPL assumptions)
     1224             */
     1225            PVMCPU pVCpu = VMMGetCpu(pVM);
     1226
     1227            if (    pVCpu->hwaccm.s.vmx.enmLastSeenGuestMode == PGMMODE_REAL
     1228                &&  enmGuestMode >= PGMMODE_PROTECTED)
     1229            {
     1230                if (   (pCtx->cs & X86_SEL_RPL)
     1231                    || (pCtx->ds & X86_SEL_RPL)
     1232                    || (pCtx->es & X86_SEL_RPL)
     1233                    || (pCtx->fs & X86_SEL_RPL)
     1234                    || (pCtx->gs & X86_SEL_RPL)
     1235                    || (pCtx->ss & X86_SEL_RPL))
     1236                {
     1237                    return false;
     1238                }
     1239            }
     1240        }
     1241    }
     1242    else
     1243#endif /* HWACCM_VMX_EMULATE_REALMODE */
     1244    {
     1245        if (!CPUMIsGuestInLongModeEx(pCtx))
     1246        {
     1247            /* Too early for VT-x; Solaris guests will fail with a guru meditation otherwise; same for XP. */
     1248            if (pCtx->idtr.pIdt == 0 || pCtx->idtr.cbIdt == 0 || pCtx->tr == 0)
     1249                return false;
     1250
     1251            /* The guest is about to complete the switch to protected mode. Wait a bit longer. */
     1252            /* Windows XP; switch to protected mode; all selectors are marked not present in the
     1253             * hidden registers (possible recompiler bug; see load_seg_vm) */
     1254            if (pCtx->csHid.Attr.n.u1Present == 0)
     1255                return false;
     1256            if (pCtx->ssHid.Attr.n.u1Present == 0)
     1257                return false;
     1258        }
     1259    }
    12491260
    12501261    if (pVM->hwaccm.s.vmx.fEnabled)
     
    12581269
    12591270#ifdef HWACCM_VMX_EMULATE_REALMODE
    1260         /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
    1261         mask &= ~(X86_CR0_PG|X86_CR0_PE);
    1262 #else
    1263         /* We support protected mode without paging using identity mapping. */
    1264         mask &= ~X86_CR0_PG;
     1271        if (pVM->hwaccm.s.vmx.pRealModeTSS)
     1272        {
     1273            /* Note: We ignore the PE & PG bits here on purpose; we emulate real and protected mode without paging. */
     1274            mask &= ~(X86_CR0_PG|X86_CR0_PE);
     1275        }
     1276        else
    12651277#endif
     1278        {
     1279            /* We support protected mode without paging using identity mapping. */
     1280            mask &= ~X86_CR0_PG;
     1281        }
    12661282        if ((pCtx->cr0 & mask) != mask)
    12671283            return false;
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