Changeset 37039 in vbox
- Timestamp:
- May 11, 2011 3:04:25 PM (13 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
-
IEMAll.cpp (modified) (16 diffs)
-
IEMAllCImpl.cpp.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r37034 r37039 537 537 * Internal Functions * 538 538 *******************************************************************************/ 539 static VBOXSTRICTRC iemRaiseTaskSwitchFaultCurrentTSS(PIEMCPU pIemCpu); 540 static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr); 541 static VBOXSTRICTRC iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr); 539 542 static VBOXSTRICTRC iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu); 540 543 static VBOXSTRICTRC iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess); … … 542 545 static VBOXSTRICTRC iemRaiseSelectorNotPresent(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess); 543 546 static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc); 547 static VBOXSTRICTRC iemMemFetchDataU32(PIEMCPU pIemCpu, uint32_t *pu32Dst, uint8_t iSegReg, RTGCPTR GCPtrMem); 548 static VBOXSTRICTRC iemMemFetchDataU64(PIEMCPU pIemCpu, uint64_t *pu64Dst, uint8_t iSegReg, RTGCPTR GCPtrMem); 549 static VBOXSTRICTRC iemMemFetchSelDesc(PIEMCPU pIemCpu, PIEMSELDESC pDesc, uint16_t uSel); 550 static VBOXSTRICTRC iemMemStackPushCommitSpecial(PIEMCPU pIemCpu, void *pvMem, uint64_t uNewRsp); 551 static VBOXSTRICTRC iemMemStackPushBeginSpecial(PIEMCPU pIemCpu, size_t cbMem, void **ppvMem, uint64_t *puNewRsp); 552 544 553 #ifdef IEM_VERIFICATION_MODE 545 554 static PIEMVERIFYEVTREC iemVerifyAllocRecord(PIEMCPU pIemCpu); … … 1196 1205 */ 1197 1206 1207 /** @name IEM_XCPT_FLAGS_XXX - flags for iemRaiseXcptOrInt. 1208 * @{ */ 1209 /** CPU exception. */ 1210 #define IEM_XCPT_FLAGS_T_CPU_XCPT RT_BIT_32(0) 1211 /** External interrupt (from PIC, APIC, whatever). */ 1212 #define IEM_XCPT_FLAGS_T_EXT_INT RT_BIT_32(1) 1213 /** Software interrupt (int, into or bound). */ 1214 #define IEM_XCPT_FLAGS_T_SOFT_INT RT_BIT_32(2) 1215 /** Takes an error code. */ 1216 #define IEM_XCPT_FLAGS_ERR RT_BIT_32(3) 1217 /** Takes a CR2. */ 1218 #define IEM_XCPT_FLAGS_CR2 RT_BIT_32(4) 1219 /** Generated by the breakpoint instruction. */ 1220 #define IEM_XCPT_FLAGS_BP_INSTR RT_BIT_32(5) 1221 /** Mask out the nesting level. */ 1222 #define IEM_XCPT_FLAGS_NESTING_MASK UINT32_C(0xff000000) 1223 /** Shift count for the nesting level. */ 1224 #define IEM_XCPT_FLAGS_NESTING_SHIFT 24 1225 /** Mask out the nesting level after shifting. */ 1226 #define IEM_XCPT_FLAGS_NESTING_SMASK UINT32_C(0x000000ff) 1227 /** @} */ 1228 1229 /** 1230 * Loads the specified stack far pointer from the TSS. 1231 * 1232 * @returns VBox strict status code. 1233 * @param pIemCpu The IEM per CPU instance data. 1234 * @param pCtx The CPU context. 1235 * @param uCpl The CPL to load the stack for. 1236 * @param pSelSS Where to return the new stack segment. 1237 * @param puEsp Where to return the new stack pointer. 1238 */ 1239 static VBOXSTRICTRC iemRaiseLoadStackFromTss32Or16(PIEMCPU pIemCpu, PCCPUMCTX pCtx, uint8_t uCpl, 1240 PRTSEL pSelSS, uint32_t *puEsp) 1241 { 1242 VBOXSTRICTRC rcStrict; 1243 Assert(uCpl < 4); 1244 1245 switch (pCtx->trHid.Attr.n.u4Type) 1246 { 1247 /* 1248 * 16-bit TSS (X86TSS16). 1249 */ 1250 case X86_SEL_TYPE_SYS_286_TSS_AVAIL: AssertFailed(); 1251 case X86_SEL_TYPE_SYS_286_TSS_BUSY: 1252 { 1253 uint32_t off = uCpl * 4 + 2; 1254 if (off + 4 > pCtx->trHid.u32Limit) 1255 { 1256 Log(("LoadStackFromTss32Or16: out of bounds! uCpl=%d, u32Limit=%#x TSS16\n", uCpl, pCtx->trHid.u32Limit)); 1257 return iemRaiseTaskSwitchFaultCurrentTSS(pIemCpu); 1258 } 1259 1260 uint32_t u32Tmp; 1261 rcStrict = iemMemFetchDataU32(pIemCpu, &u32Tmp, UINT8_MAX, pCtx->trHid.u64Base + off); 1262 if (rcStrict == VINF_SUCCESS) 1263 { 1264 *puEsp = RT_LOWORD(u32Tmp); 1265 *pSelSS = RT_HIWORD(u32Tmp); 1266 return VINF_SUCCESS; 1267 } 1268 break; 1269 } 1270 1271 /* 1272 * 32-bit TSS (X86TSS32). 1273 */ 1274 case X86_SEL_TYPE_SYS_386_TSS_AVAIL: AssertFailed(); 1275 case X86_SEL_TYPE_SYS_386_TSS_BUSY: 1276 { 1277 uint32_t off = uCpl * 8 + 4; 1278 if (off + 7 > pCtx->trHid.u32Limit) 1279 { 1280 Log(("LoadStackFromTss32Or16: out of bounds! uCpl=%d, u32Limit=%#x TSS16\n", uCpl, pCtx->trHid.u32Limit)); 1281 return iemRaiseTaskSwitchFaultCurrentTSS(pIemCpu); 1282 } 1283 1284 uint64_t u64Tmp; 1285 rcStrict = iemMemFetchDataU64(pIemCpu, &u64Tmp, UINT8_MAX, pCtx->trHid.u64Base + off); 1286 if (rcStrict == VINF_SUCCESS) 1287 { 1288 *puEsp = u64Tmp & UINT32_MAX; 1289 *pSelSS = (RTSEL)(u64Tmp >> 32); 1290 return VINF_SUCCESS; 1291 } 1292 break; 1293 } 1294 1295 default: 1296 AssertFailedReturn(VERR_INTERNAL_ERROR_2); 1297 } 1298 return rcStrict; 1299 } 1300 1301 1302 /** 1303 * Adjust the CPU state according to the exception being raised. 1304 * 1305 * @param pCtx The CPU context. 1306 * @param u8Vector The exception that has been raised. 1307 */ 1308 DECLINLINE(void) iemRaiseXcptAdjustState(PCPUMCTX pCtx, uint8_t u8Vector) 1309 { 1310 switch (u8Vector) 1311 { 1312 case X86_XCPT_DB: 1313 pCtx->dr[7] &= ~X86_DR7_GD; 1314 break; 1315 /** @todo Read the AMD and Intel exception reference... */ 1316 } 1317 } 1318 1319 1320 /** 1321 * Implements exceptions and interrupts for real mode. 1322 * 1323 * @returns VBox strict status code. 1324 * @param pIemCpu The IEM per CPU instance data. 1325 * @param pCtx The CPU context. 1326 * @param cbInstr The number of bytes to offset rIP by in the return 1327 * address. 1328 * @param u8Vector The interrupt / exception vector number. 1329 * @param fFlags The flags. 1330 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1331 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1332 */ 1333 static VBOXSTRICTRC 1334 iemRaiseXcptOrIntInRealMode(PIEMCPU pIemCpu, 1335 PCPUMCTX pCtx, 1336 uint8_t cbInstr, 1337 uint8_t u8Vector, 1338 uint32_t fFlags, 1339 uint16_t uErr, 1340 uint64_t uCr2) 1341 { 1342 AssertReturn(pIemCpu->enmCpuMode == IEMMODE_16BIT, VERR_INTERNAL_ERROR_3); 1343 1344 /* 1345 * Read the IDT entry. 1346 */ 1347 if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3) 1348 { 1349 Log(("RaiseXcptOrIntInRealMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt)); 1350 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1351 } 1352 RTFAR16 Idte; 1353 VBOXSTRICTRC rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX, 1354 pCtx->idtr.pIdt + UINT32_C(4) * u8Vector); 1355 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1356 return rcStrict; 1357 1358 /* 1359 * Push the stack frame. 1360 */ 1361 uint16_t *pu16Frame; 1362 uint64_t uNewRsp; 1363 rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp); 1364 if (rcStrict != VINF_SUCCESS) 1365 return rcStrict; 1366 1367 pu16Frame[2] = (uint16_t)pCtx->eflags.u; 1368 pu16Frame[1] = (uint16_t)pCtx->cs; 1369 pu16Frame[0] = pCtx->ip + cbInstr; 1370 rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp); 1371 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1372 return rcStrict; 1373 1374 /* 1375 * Load the vector address into cs:ip and make exception specific state 1376 * adjustments. 1377 */ 1378 pCtx->cs = Idte.sel; 1379 pCtx->csHid.u64Base = (uint32_t)Idte.sel << 4; 1380 /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */ 1381 pCtx->rip = Idte.off; 1382 pCtx->eflags.Bits.u1IF = 0; 1383 1384 /** @todo do we actually do this in real mode? */ 1385 if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT) 1386 iemRaiseXcptAdjustState(pCtx, u8Vector); 1387 1388 return VINF_SUCCESS; 1389 } 1390 1391 1392 /** 1393 * Implements exceptions and interrupts for protected mode. 1394 * 1395 * @returns VBox strict status code. 1396 * @param pIemCpu The IEM per CPU instance data. 1397 * @param pCtx The CPU context. 1398 * @param cbInstr The number of bytes to offset rIP by in the return 1399 * address. 1400 * @param u8Vector The interrupt / exception vector number. 1401 * @param fFlags The flags. 1402 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1403 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1404 */ 1405 static VBOXSTRICTRC 1406 iemRaiseXcptOrIntInProtMode(PIEMCPU pIemCpu, 1407 PCPUMCTX pCtx, 1408 uint8_t cbInstr, 1409 uint8_t u8Vector, 1410 uint32_t fFlags, 1411 uint16_t uErr, 1412 uint64_t uCr2) 1413 { 1414 /* 1415 * Read the IDT entry. 1416 */ 1417 if (pCtx->idtr.cbIdt < UINT32_C(8) * u8Vector + 7) 1418 { 1419 Log(("RaiseXcptOrIntInProtMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt)); 1420 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1421 } 1422 X86DESC Idte; 1423 VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pIemCpu, &Idte.u, UINT8_MAX, 1424 pCtx->idtr.pIdt + UINT32_C(8) * u8Vector); 1425 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1426 return rcStrict; 1427 1428 /* 1429 * Check the descriptor type, DPL and such. 1430 * ASSUMES this is done in the same order as described for call-gate calls. 1431 */ 1432 if (Idte.Gate.u1DescType) 1433 { 1434 Log(("RaiseXcptOrIntInProtMode %#x - not system selector (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type)); 1435 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1436 } 1437 uint32_t fEflToClear = X86_EFL_TF | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM; 1438 switch (Idte.Gate.u4Type) 1439 { 1440 case X86_SEL_TYPE_SYS_UNDEFINED: 1441 case X86_SEL_TYPE_SYS_286_TSS_AVAIL: 1442 case X86_SEL_TYPE_SYS_LDT: 1443 case X86_SEL_TYPE_SYS_286_TSS_BUSY: 1444 case X86_SEL_TYPE_SYS_286_CALL_GATE: 1445 case X86_SEL_TYPE_SYS_UNDEFINED2: 1446 case X86_SEL_TYPE_SYS_386_TSS_AVAIL: 1447 case X86_SEL_TYPE_SYS_UNDEFINED3: 1448 case X86_SEL_TYPE_SYS_386_TSS_BUSY: 1449 case X86_SEL_TYPE_SYS_386_CALL_GATE: 1450 case X86_SEL_TYPE_SYS_UNDEFINED4: 1451 { 1452 /** @todo check what actually happens when the type is wrong... 1453 * esp. call gates. */ 1454 Log(("RaiseXcptOrIntInProtMode %#x - invalid type (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type)); 1455 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1456 } 1457 1458 case X86_SEL_TYPE_SYS_286_INT_GATE: 1459 case X86_SEL_TYPE_SYS_386_INT_GATE: 1460 fEflToClear |= X86_EFL_IF; 1461 break; 1462 1463 case X86_SEL_TYPE_SYS_TASK_GATE: 1464 /** @todo task gates. */ 1465 AssertFailedReturn(VERR_NOT_SUPPORTED); 1466 1467 case X86_SEL_TYPE_SYS_286_TRAP_GATE: 1468 case X86_SEL_TYPE_SYS_386_TRAP_GATE: 1469 break; 1470 1471 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 1472 } 1473 1474 /* Check DPL against CPL if applicable. */ 1475 if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 1476 { 1477 if (pIemCpu->uCpl > Idte.Gate.u2Dpl) 1478 { 1479 Log(("RaiseXcptOrIntInProtMode %#x - CPL (%d) > DPL (%d) -> #GP\n", u8Vector, pIemCpu->uCpl, Idte.Gate.u2Dpl)); 1480 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1481 } 1482 } 1483 1484 /* Is it there? */ 1485 if (!Idte.Gate.u1Present) 1486 { 1487 Log(("RaiseXcptOrIntInProtMode %#x - not present -> #NP\n", u8Vector)); 1488 return iemRaiseSelectorNotPresentWithErr(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1489 } 1490 1491 /* A null CS is bad. */ 1492 RTSEL NewCS = Idte.Gate.u16Sel; 1493 if (!(NewCS & (X86_SEL_MASK | X86_SEL_LDT))) 1494 { 1495 Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x -> #GP\n", u8Vector, NewCS)); 1496 return iemRaiseGeneralProtectionFault0(pIemCpu); 1497 } 1498 1499 /* Fetch the descriptor for the new CS. */ 1500 IEMSELDESC DescCS; 1501 rcStrict = iemMemFetchSelDesc(pIemCpu, &DescCS, NewCS); 1502 if (rcStrict != VINF_SUCCESS) 1503 return rcStrict; 1504 1505 /* Must be a code segment. */ 1506 if (!DescCS.Legacy.Gen.u1DescType) 1507 { 1508 Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - system selector (%#x) -> #GP\n", u8Vector, NewCS, DescCS.Legacy.Gen.u4Type)); 1509 return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT)); 1510 } 1511 if (!(DescCS.Legacy.Gen.u4Type & X86_SEL_TYPE_CODE)) 1512 { 1513 Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - data selector (%#x) -> #GP\n", u8Vector, NewCS, DescCS.Legacy.Gen.u4Type)); 1514 return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT)); 1515 } 1516 1517 /* Don't allow lowering the privilege level. */ 1518 /** @todo Does the lowering of privileges apply to software interrupts 1519 * only? This has bearings on the more-privileged or 1520 * same-privilege stack behavior further down. A testcase would 1521 * be nice. */ 1522 if (DescCS.Legacy.Gen.u2Dpl > pIemCpu->uCpl) 1523 { 1524 Log(("RaiseXcptOrIntInProtMode %#x - CS=%#x - DPL (%d) > CPL (%d) -> #GP\n", 1525 u8Vector, NewCS, DescCS.Legacy.Gen.u2Dpl, pIemCpu->uCpl)); 1526 return iemRaiseGeneralProtectionFault(pIemCpu, NewCS & (X86_SEL_MASK | X86_SEL_LDT)); 1527 } 1528 /** @todo is the RPL of the interrupt/trap gate descriptor checked? */ 1529 1530 /* 1531 * If the privilege level changes, we need to get a new stack from the TSS. 1532 */ 1533 uint8_t const uNewCpl = DescCS.Legacy.Gen.u4Type & X86_SEL_TYPE_CONF 1534 ? pIemCpu->uCpl : DescCS.Legacy.Gen.u2Dpl; 1535 if (uNewCpl != pIemCpu->uCpl) 1536 { 1537 uint32_t uNewEsp; 1538 RTSEL uNewSs; 1539 rcStrict = iemRaiseLoadStackFromTss32Or16(pIemCpu, pCtx, uNewCpl, &uNewSs, &uNewEsp); 1540 if (rcStrict != VINF_SUCCESS) 1541 return rcStrict; 1542 1543 } 1544 1545 return VERR_NOT_IMPLEMENTED; 1546 } 1547 1548 1549 /** 1550 * Implements exceptions and interrupts for V8086 mode. 1551 * 1552 * @returns VBox strict status code. 1553 * @param pIemCpu The IEM per CPU instance data. 1554 * @param pCtx The CPU context. 1555 * @param cbInstr The number of bytes to offset rIP by in the return 1556 * address. 1557 * @param u8Vector The interrupt / exception vector number. 1558 * @param fFlags The flags. 1559 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1560 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1561 */ 1562 static VBOXSTRICTRC 1563 iemRaiseXcptOrIntInV8086Mode(PIEMCPU pIemCpu, 1564 PCPUMCTX pCtx, 1565 uint8_t cbInstr, 1566 uint8_t u8Vector, 1567 uint32_t fFlags, 1568 uint16_t uErr, 1569 uint64_t uCr2) 1570 { 1571 AssertMsgFailed(("V8086 exception / interrupt dispatching\n")); 1572 return VERR_NOT_IMPLEMENTED; 1573 } 1574 1575 1576 /** 1577 * Implements exceptions and interrupts for long mode. 1578 * 1579 * @returns VBox strict status code. 1580 * @param pIemCpu The IEM per CPU instance data. 1581 * @param pCtx The CPU context. 1582 * @param cbInstr The number of bytes to offset rIP by in the return 1583 * address. 1584 * @param u8Vector The interrupt / exception vector number. 1585 * @param fFlags The flags. 1586 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1587 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1588 */ 1589 static VBOXSTRICTRC 1590 iemRaiseXcptOrIntInLongMode(PIEMCPU pIemCpu, 1591 PCPUMCTX pCtx, 1592 uint8_t cbInstr, 1593 uint8_t u8Vector, 1594 uint32_t fFlags, 1595 uint16_t uErr, 1596 uint64_t uCr2) 1597 { 1598 AssertMsgFailed(("long mode exception / interrupt dispatching\n")); 1599 return VERR_NOT_IMPLEMENTED; 1600 } 1601 1602 1603 /** 1604 * Implements exceptions and interrupts. 1605 * 1606 * All exceptions and interrupts goes thru this function! 1607 * 1608 * @returns VBox strict status code. 1609 * @param pIemCpu The IEM per CPU instance data. 1610 * @param cbInstr The number of bytes to offset rIP by in the return 1611 * address. 1612 * @param u8Vector The interrupt / exception vector number. 1613 * @param fFlags The flags. 1614 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1615 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1616 */ 1617 static VBOXSTRICTRC 1618 iemRaiseXcptOrInt(PIEMCPU pIemCpu, 1619 uint8_t cbInstr, 1620 uint8_t u8Vector, 1621 uint32_t fFlags, 1622 uint16_t uErr, 1623 uint64_t uCr2) 1624 { 1625 /* 1626 * Do recursion accounting. 1627 */ 1628 uint8_t uPrevXcpt = pIemCpu->uCurXcpt; 1629 if (pIemCpu->cXcptRecursions > 0) 1630 { 1631 /** @todo double and tripple faults. */ 1632 AssertReturn(pIemCpu->cXcptRecursions < 3, VERR_NOT_IMPLEMENTED); 1633 } 1634 pIemCpu->cXcptRecursions++; 1635 pIemCpu->uCurXcpt = u8Vector; 1636 1637 /* 1638 * Call mode specific worker function. 1639 */ 1640 VBOXSTRICTRC rcStrict; 1641 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 1642 if (!(pCtx->cr0 & X86_CR0_PE)) 1643 rcStrict = iemRaiseXcptOrIntInRealMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1644 else if (pCtx->msrEFER & MSR_K6_EFER_LMA) 1645 rcStrict = iemRaiseXcptOrIntInLongMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1646 else if (!pCtx->eflags.Bits.u1VM) 1647 rcStrict = iemRaiseXcptOrIntInProtMode( pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1648 else 1649 rcStrict = iemRaiseXcptOrIntInV8086Mode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1650 1651 /* 1652 * Unwind. 1653 */ 1654 pIemCpu->cXcptRecursions--; 1655 pIemCpu->uCurXcpt = uPrevXcpt; 1656 return rcStrict; 1657 } 1658 1659 1660 /** \#DE - 00. */ 1198 1661 static VBOXSTRICTRC iemRaiseDivideError(PIEMCPU pIemCpu) 1199 1662 { … … 1202 1665 } 1203 1666 1667 1668 /** \#DB - 01. */ 1204 1669 static VBOXSTRICTRC iemRaiseDebugException(PIEMCPU pIemCpu) 1205 1670 { … … 1208 1673 } 1209 1674 1675 1676 /** \#UD - 06. */ 1210 1677 static VBOXSTRICTRC iemRaiseUndefinedOpcode(PIEMCPU pIemCpu) 1678 { 1679 AssertFailed(/** @todo implement X86_XCPT_UD */); 1680 return VERR_NOT_IMPLEMENTED; 1681 } 1682 1683 1684 /** \#NM - 07. */ 1685 static VBOXSTRICTRC iemRaiseDeviceNotAvailable(PIEMCPU pIemCpu) 1211 1686 { 1212 1687 AssertFailed(/** @todo implement this */); … … 1215 1690 1216 1691 1217 static VBOXSTRICTRC iemRaiseDeviceNotAvailable(PIEMCPU pIemCpu) 1692 /** \#TS(err) - 0a. */ 1693 static VBOXSTRICTRC iemRaiseTaskSwitchFaultWithErr(PIEMCPU pIemCpu, uint16_t uErr) 1218 1694 { 1219 1695 AssertFailed(/** @todo implement this */); … … 1222 1698 1223 1699 1224 static VBOXSTRICTRC iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr) 1700 /** \#TS(tr) - 0a. */ 1701 static VBOXSTRICTRC iemRaiseTaskSwitchFaultCurrentTSS(PIEMCPU pIemCpu) 1702 { 1703 return iemRaiseTaskSwitchFaultWithErr(pIemCpu, pIemCpu->CTX_SUFF(pCtx)->tr); 1704 } 1705 1706 1707 /** \#NP(err) - 0b. */ 1708 static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr) 1225 1709 { 1226 1710 AssertFailed(/** @todo implement this */); … … 1229 1713 1230 1714 1231 static VBOXSTRICTRC iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu) 1715 /** \#NP(seg) - 0b. */ 1716 static VBOXSTRICTRC iemRaiseSelectorNotPresentBySegReg(PIEMCPU pIemCpu, uint32_t iSegReg) 1232 1717 { 1233 1718 AssertFailed(/** @todo implement this */); … … 1236 1721 1237 1722 1238 static VBOXSTRICTRC iemRaiseNotCanonical(PIEMCPU pIemCpu) 1723 /** \#NP(sel) - 0b. */ 1724 static VBOXSTRICTRC iemRaiseSelectorNotPresentBySelector(PIEMCPU pIemCpu, uint16_t uSel) 1239 1725 { 1240 1726 AssertFailed(/** @todo implement this */); … … 1243 1729 1244 1730 1245 static VBOXSTRICTRC iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess) 1731 /** \#GP(n) - 0d. */ 1732 static VBOXSTRICTRC iemRaiseGeneralProtectionFault(PIEMCPU pIemCpu, uint16_t uErr) 1246 1733 { 1247 1734 AssertFailed(/** @todo implement this */); … … 1250 1737 1251 1738 1252 static VBOXSTRICTRC iemRaiseSelectorInvalidAccess(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess) 1739 /** \#GP(0) - 0d. */ 1740 static VBOXSTRICTRC iemRaiseGeneralProtectionFault0(PIEMCPU pIemCpu) 1741 { 1742 return iemRaiseGeneralProtectionFault(pIemCpu, 0); 1743 } 1744 1745 1746 /** \#GP(0) - 0d. */ 1747 static VBOXSTRICTRC iemRaiseNotCanonical(PIEMCPU pIemCpu) 1253 1748 { 1254 1749 AssertFailed(/** @todo implement this */); … … 1257 1752 1258 1753 1259 static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr) 1754 /** \#GP(sel) - 0d. */ 1755 static VBOXSTRICTRC iemRaiseSelectorBounds(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess) 1260 1756 { 1261 1757 AssertFailed(/** @todo implement this */); … … 1264 1760 1265 1761 1266 static VBOXSTRICTRC iemRaiseSelectorNotPresentBySegReg(PIEMCPU pIemCpu, uint32_t iSegReg) 1762 /** \#GP(sel) - 0d. */ 1763 static VBOXSTRICTRC iemRaiseSelectorInvalidAccess(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess) 1267 1764 { 1268 1765 AssertFailed(/** @todo implement this */); … … 1271 1768 1272 1769 1273 static VBOXSTRICTRC iemRaiseSelectorNotPresentBySelector(PIEMCPU pIemCpu, uint16_t uSel) 1770 /** \#PF(n) - 0e. */ 1771 static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc) 1274 1772 { 1275 1773 AssertFailed(/** @todo implement this */); … … 1278 1776 1279 1777 1280 static VBOXSTRICTRC iemRaisePageFault(PIEMCPU pIemCpu, RTGCPTR GCPtrWhere, uint32_t fAccess, int rc) 1281 { 1282 AssertFailed(/** @todo implement this */); 1283 return VERR_NOT_IMPLEMENTED; 1284 } 1285 1286 1778 /** \#MF(n) - 10. */ 1287 1779 static VBOXSTRICTRC iemRaiseMathFault(PIEMCPU pIemCpu) 1288 1780 { … … 5365 5857 } 5366 5858 5367 return iem CImpl_RaiseXcptOrInt(&pVCpu->iem.s, 0, u8TrapNo, fFlags, uErrCode, uCr2);5368 } 5369 5859 return iemRaiseXcptOrInt(&pVCpu->iem.s, 0, u8TrapNo, fFlags, uErrCode, uCr2); 5860 } 5861 -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r37034 r37039 1115 1115 1116 1116 1117 /** @name IEM_XCPT_FLAGS_XXX - flags for iemCImpl_RaiseXcptOrInt.1118 * @{ */1119 /** CPU exception. */1120 #define IEM_XCPT_FLAGS_T_CPU_XCPT RT_BIT_32(0)1121 /** External interrupt (from PIC, APIC, whatever). */1122 #define IEM_XCPT_FLAGS_T_EXT_INT RT_BIT_32(1)1123 /** Software interrupt (int, into or bound). */1124 #define IEM_XCPT_FLAGS_T_SOFT_INT RT_BIT_32(2)1125 /** Takes an error code. */1126 #define IEM_XCPT_FLAGS_ERR RT_BIT_32(3)1127 /** Takes a CR2. */1128 #define IEM_XCPT_FLAGS_CR2 RT_BIT_32(4)1129 /** Generated by the breakpoint instruction. */1130 #define IEM_XCPT_FLAGS_BP_INSTR RT_BIT_32(5)1131 /** Mask out the nesting level. */1132 #define IEM_XCPT_FLAGS_NESTING_MASK UINT32_C(0xff000000)1133 /** Shift count for the nesting level. */1134 #define IEM_XCPT_FLAGS_NESTING_SHIFT 241135 /** Mask out the nesting level after shifting. */1136 #define IEM_XCPT_FLAGS_NESTING_SMASK UINT32_C(0x000000ff)1137 /** @} */1138 1139 1140 /**1141 * Adjust the CPU state according to the exception being raised.1142 *1143 * @param pCtx The CPU context.1144 * @param u8Vector The exception that has been raised.1145 */1146 DECLINLINE(void) iemCImpl_RaiseXcptAdjustState(PCPUMCTX pCtx, uint8_t u8Vector)1147 {1148 switch (u8Vector)1149 {1150 case X86_XCPT_DB:1151 pCtx->dr[7] &= ~X86_DR7_GD;1152 break;1153 /** @todo Read the AMD and Intel exception reference... */1154 }1155 }1156 1157 1158 /**1159 * Implements exceptions and interrupts for real mode.1160 *1161 * @returns VBox strict status code.1162 * @param pIemCpu The IEM per CPU instance data.1163 * @param pCtx The CPU context.1164 * @param cbInstr The number of bytes to offset rIP by in the return1165 * address.1166 * @param u8Vector The interrupt / exception vector number.1167 * @param fFlags The flags.1168 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set.1169 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set.1170 */1171 static VBOXSTRICTRC1172 iemCImpl_RaiseXcptOrIntInRealMode(PIEMCPU pIemCpu,1173 PCPUMCTX pCtx,1174 uint8_t cbInstr,1175 uint8_t u8Vector,1176 uint32_t fFlags,1177 uint16_t uErr,1178 uint64_t uCr2)1179 {1180 AssertReturn(pIemCpu->enmCpuMode == IEMMODE_16BIT, VERR_INTERNAL_ERROR_3);1181 1182 /*1183 * Read the IDT entry.1184 */1185 if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3)1186 {1187 Log(("RaiseXcptOrIntInRealMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));1188 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));1189 }1190 RTFAR16 Idte;1191 VBOXSTRICTRC rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX,1192 pCtx->idtr.pIdt + UINT32_C(4) * u8Vector);1193 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))1194 return rcStrict;1195 1196 /*1197 * Push the stack frame.1198 */1199 uint16_t *pu16Frame;1200 uint64_t uNewRsp;1201 rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp);1202 if (rcStrict != VINF_SUCCESS)1203 return rcStrict;1204 1205 pu16Frame[2] = (uint16_t)pCtx->eflags.u;1206 pu16Frame[1] = (uint16_t)pCtx->cs;1207 pu16Frame[0] = pCtx->ip + cbInstr;1208 rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp);1209 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))1210 return rcStrict;1211 1212 /*1213 * Load the vector address into cs:ip and make exception specific state1214 * adjustments.1215 */1216 pCtx->cs = Idte.sel;1217 pCtx->csHid.u64Base = (uint32_t)Idte.sel << 4;1218 /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */1219 pCtx->rip = Idte.off;1220 pCtx->eflags.Bits.u1IF = 0;1221 1222 /** @todo do we actually do this in real mode? */1223 if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT)1224 iemCImpl_RaiseXcptAdjustState(pCtx, u8Vector);1225 1226 return VINF_SUCCESS;1227 }1228 1229 1230 /**1231 * Implements exceptions and interrupts for protected mode.1232 *1233 * @returns VBox strict status code.1234 * @param pIemCpu The IEM per CPU instance data.1235 * @param pCtx The CPU context.1236 * @param cbInstr The number of bytes to offset rIP by in the return1237 * address.1238 * @param u8Vector The interrupt / exception vector number.1239 * @param fFlags The flags.1240 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set.1241 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set.1242 */1243 static VBOXSTRICTRC1244 iemCImpl_RaiseXcptOrIntInProtMode(PIEMCPU pIemCpu,1245 PCPUMCTX pCtx,1246 uint8_t cbInstr,1247 uint8_t u8Vector,1248 uint32_t fFlags,1249 uint16_t uErr,1250 uint64_t uCr2)1251 {1252 /*1253 * Read the IDT entry.1254 */1255 if (pCtx->idtr.cbIdt < UINT32_C(8) * u8Vector + 7)1256 {1257 Log(("RaiseXcptOrIntInProtMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt));1258 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));1259 }1260 X86DESC Idte;1261 VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pIemCpu, &Idte.u, UINT8_MAX,1262 pCtx->idtr.pIdt + UINT32_C(8) * u8Vector);1263 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))1264 return rcStrict;1265 1266 /*1267 * Check the descriptor type, DPL and such.1268 * ASSUMES this is done in the same order as described for selectors.1269 */1270 if (Idte.Gate.u1DescType)1271 {1272 Log(("RaiseXcptOrIntInProtMode %#x - not system selector (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));1273 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));1274 }1275 uint32_t fEflToClear = X86_EFL_TF | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM;1276 switch (Idte.Gate.u4Type)1277 {1278 case X86_SEL_TYPE_SYS_UNDEFINED:1279 case X86_SEL_TYPE_SYS_286_TSS_AVAIL:1280 case X86_SEL_TYPE_SYS_LDT:1281 case X86_SEL_TYPE_SYS_286_TSS_BUSY:1282 case X86_SEL_TYPE_SYS_286_CALL_GATE:1283 case X86_SEL_TYPE_SYS_UNDEFINED2:1284 case X86_SEL_TYPE_SYS_386_TSS_AVAIL:1285 case X86_SEL_TYPE_SYS_UNDEFINED3:1286 case X86_SEL_TYPE_SYS_386_TSS_BUSY:1287 case X86_SEL_TYPE_SYS_386_CALL_GATE:1288 case X86_SEL_TYPE_SYS_UNDEFINED4:1289 {1290 /** @todo check what actually happens when the type is wrong...1291 * esp. call gates. */1292 Log(("RaiseXcptOrIntInProtMode %#x - invalid type (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type));1293 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));1294 }1295 1296 case X86_SEL_TYPE_SYS_286_INT_GATE:1297 case X86_SEL_TYPE_SYS_386_INT_GATE:1298 fEflToClear |= X86_EFL_IF;1299 break;1300 1301 case X86_SEL_TYPE_SYS_TASK_GATE:1302 case X86_SEL_TYPE_SYS_286_TRAP_GATE:1303 case X86_SEL_TYPE_SYS_386_TRAP_GATE:1304 break;1305 1306 IEM_NOT_REACHED_DEFAULT_CASE_RET();1307 }1308 1309 /* Check DPL against CPL if applicable. */1310 if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT)1311 {1312 #if 0 /** @todo continue here */1313 if (pIemCpu->uCpl > Desc.Legacy.Gen.u2Dpl)1314 {1315 Log(("load sreg%u, %#x - CPL (%d) is greater than DPL (%d) -> #GP\n",1316 iSegReg, uSel, pIemCpu->uCpl, Desc.Legacy.Gen.u2Dpl));1317 return iemRaiseGeneralProtectionFault(pIemCpu, uSel & (X86_SEL_MASK | X86_SEL_LDT));1318 }1319 #endif1320 }1321 1322 /* Is it there? */1323 if (!Idte.Gate.u1Present)1324 {1325 Log(("RaiseXcptOrIntInProtMode %#x - not present -> #NP\n", u8Vector));1326 return iemRaiseSelectorNotPresentWithErr(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT));1327 }1328 1329 return VERR_NOT_IMPLEMENTED;1330 }1331 1332 1333 /**1334 * Implements exceptions and interrupts for long mode.1335 *1336 * @returns VBox strict status code.1337 * @param pIemCpu The IEM per CPU instance data.1338 * @param pCtx The CPU context.1339 * @param cbInstr The number of bytes to offset rIP by in the return1340 * address.1341 * @param u8Vector The interrupt / exception vector number.1342 * @param fFlags The flags.1343 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set.1344 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set.1345 */1346 static VBOXSTRICTRC1347 iemCImpl_RaiseXcptOrIntInLongMode(PIEMCPU pIemCpu,1348 PCPUMCTX pCtx,1349 uint8_t cbInstr,1350 uint8_t u8Vector,1351 uint32_t fFlags,1352 uint16_t uErr,1353 uint64_t uCr2)1354 {1355 AssertMsgFailed(("long mode exception / interrupt dispatching\n"));1356 return VERR_NOT_IMPLEMENTED;1357 }1358 1359 1360 /**1361 * Implements exceptions and interrupts.1362 *1363 * All exceptions and interrupts goes thru this function!1364 *1365 * @returns VBox strict status code.1366 * @param pIemCpu The IEM per CPU instance data.1367 * @param cbInstr The number of bytes to offset rIP by in the return1368 * address.1369 * @param u8Vector The interrupt / exception vector number.1370 * @param fFlags The flags.1371 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set.1372 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set.1373 */1374 static VBOXSTRICTRC1375 iemCImpl_RaiseXcptOrInt(PIEMCPU pIemCpu,1376 uint8_t cbInstr,1377 uint8_t u8Vector,1378 uint32_t fFlags,1379 uint16_t uErr,1380 uint64_t uCr2)1381 {1382 /*1383 * Do recursion accounting.1384 */1385 uint8_t uPrevXcpt = pIemCpu->uCurXcpt;1386 if (pIemCpu->cXcptRecursions > 0)1387 {1388 /** @todo double and tripple faults. */1389 AssertReturn(pIemCpu->cXcptRecursions < 3, VERR_NOT_IMPLEMENTED);1390 }1391 pIemCpu->cXcptRecursions++;1392 pIemCpu->uCurXcpt = u8Vector;1393 1394 /*1395 * Call mode specific worker function.1396 */1397 VBOXSTRICTRC rcStrict;1398 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);1399 if (!(pCtx->cr0 & X86_CR0_PE))1400 rcStrict = iemCImpl_RaiseXcptOrIntInRealMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);1401 else if (pCtx->msrEFER & MSR_K6_EFER_LMA)1402 rcStrict = iemCImpl_RaiseXcptOrIntInLongMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);1403 else1404 rcStrict = iemCImpl_RaiseXcptOrIntInProtMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2);1405 1406 /*1407 * Unwind.1408 */1409 pIemCpu->cXcptRecursions--;1410 pIemCpu->uCurXcpt = uPrevXcpt;1411 return rcStrict;1412 }1413 1414 1415 1117 /** 1416 1118 * Implements int3 and int XX. … … 1422 1124 { 1423 1125 Assert(pIemCpu->cXcptRecursions == 0); 1424 return iem CImpl_RaiseXcptOrInt(pIemCpu,1425 cbInstr,1426 u8Int,1427 (fIsBpInstr ? IEM_XCPT_FLAGS_BP_INSTR : 0) | IEM_XCPT_FLAGS_T_SOFT_INT,1428 0,1429 0);1126 return iemRaiseXcptOrInt(pIemCpu, 1127 cbInstr, 1128 u8Int, 1129 (fIsBpInstr ? IEM_XCPT_FLAGS_BP_INSTR : 0) | IEM_XCPT_FLAGS_T_SOFT_INT, 1130 0, 1131 0); 1430 1132 } 1431 1133
Note:
See TracChangeset
for help on using the changeset viewer.

