Changeset 21653 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jul 16, 2009 3:18:07 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 50188
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/EMHandleRCTmpl.h
r21222 r21653 220 220 rc = HWACCMR3EmulateIoBlock(pVM, pCtx); 221 221 break; 222 223 case VINF_EM_HWACCM_PATCH_TPR_INSTR: 224 rc = HWACCMR3PatchTprInstr(pVM, pVCpu, pCtx); 225 break; 222 226 #endif 223 227 -
trunk/src/VBox/VMM/HWACCM.cpp
r21652 r21653 1431 1431 1432 1432 /** 1433 * Emulate simple mov tpr instruction 1434 * 1435 * @returns VBox status code. 1436 * @param pVCpu The VM CPU to operate on. 1437 * @param pDis Disassembly state 1438 * @param pCtx CPU context 1439 * @param cbOp Opcode size 1440 */ 1441 static int hwaccmR0EmulateTprMov(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTX pCtx, unsigned cbOp) 1442 { 1443 int rc; 1444 1445 if (pDis->param1.flags == USE_DISPLACEMENT32) 1446 { 1447 /* write */ 1448 uint8_t u8Tpr; 1449 1450 /* Fetch the new TPR value */ 1451 if (pDis->param2.flags == USE_REG_GEN32) 1452 { 1453 uint32_t val; 1454 1455 rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pDis->param2.base.reg_gen, &val); 1456 AssertRC(rc); 1457 u8Tpr = val; 1458 } 1459 else 1460 if (pDis->param2.flags == USE_IMMEDIATE32) 1461 { 1462 u8Tpr = (uint8_t)pDis->param2.parval; 1463 } 1464 else 1465 return VERR_EM_INTERPRETER; 1466 1467 rc = PDMApicSetTPR(pVCpu, u8Tpr); 1468 AssertRC(rc); 1469 1470 Log(("Emulated write successfully\n")); 1471 pCtx->rip += cbOp; 1472 return VINF_SUCCESS; 1473 } 1474 else 1475 if (pDis->param2.flags == USE_DISPLACEMENT32) 1476 { 1477 /* read */ 1478 bool fPending; 1479 uint8_t u8Tpr; 1480 1481 /* TPR caching in CR8 */ 1482 rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending); 1483 AssertRC(rc); 1484 1485 rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pDis->param1.base.reg_gen, u8Tpr); 1486 AssertRC(rc); 1487 1488 Log(("Emulated read successfully\n")); 1489 pCtx->rip += cbOp; 1490 return VINF_SUCCESS; 1491 } 1492 return VERR_EM_INTERPRETER; 1493 } 1494 1495 /** 1496 * Callback to patch a TPR instruction 1497 * 1498 * @returns VBox status code. 1499 * @param pVM The VM handle. 1500 * @param pVCpu The VMCPU for the EMT we're being called on. 1501 * @param pvUser User specified CPU context 1502 * 1503 */ 1504 DECLCALLBACK(int) hwaccmR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, void *pvUser) 1505 { 1506 PCPUMCTX pCtx = (PCPUMCTX)pvUser; 1507 RTGCPTR oldrip = pCtx->rip; 1508 PDISCPUSTATE pDis = &pVCpu->hwaccm.s.DisState; 1509 unsigned cbOp; 1510 1511 Log(("Replace TPR access at %RGv\n", pCtx->rip)); 1512 1513 int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp); 1514 AssertRC(rc); 1515 if ( rc == VINF_SUCCESS 1516 && pDis->pCurInstr->opcode == OP_MOV) 1517 { 1518 if (pVM->hwaccm.s.svm.cPatches < RT_ELEMENTS(pVM->hwaccm.s.svm.aPatches)) 1519 { 1520 uint8_t aVMMCall[3] = { 0xf, 0x1, 0xd9}; 1521 uint32_t idx = pVM->hwaccm.s.svm.cPatches; 1522 PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.svm.aPatches[idx]; 1523 1524 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp); 1525 AssertRC(rc); 1526 1527 pPatch->cbOp = cbOp; 1528 1529 if (pDis->param1.flags == USE_DISPLACEMENT32) 1530 { 1531 /* write. */ 1532 if (pDis->param2.flags == USE_REG_GEN32) 1533 { 1534 pPatch->enmType = HWACCMTPRINSTR_WRITE_REG; 1535 pPatch->uSrcOperand = pDis->param2.base.reg_gen; 1536 } 1537 else 1538 { 1539 Assert(pDis->param2.flags == USE_IMMEDIATE32); 1540 pPatch->enmType = HWACCMTPRINSTR_WRITE_IMM; 1541 pPatch->uSrcOperand = pDis->param2.parval; 1542 } 1543 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall)); 1544 AssertRC(rc); 1545 } 1546 else 1547 { 1548 RTGCPTR oldrip = pCtx->rip; 1549 uint32_t oldcbOp = cbOp; 1550 uint32_t uMmioReg = pDis->param1.base.reg_gen; 1551 1552 /* read */ 1553 Assert(pDis->param1.flags == USE_REG_GEN32); 1554 1555 /* Found: 1556 * mov eax, dword [fffe0080] (5 bytes) 1557 * Check if next instruction is: 1558 * shr eax, 4 1559 */ 1560 pCtx->rip += cbOp; 1561 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp); 1562 pCtx->rip = oldrip; 1563 if ( rc == VINF_SUCCESS 1564 && pDis->pCurInstr->opcode == OP_SHR 1565 && pDis->param1.flags == USE_REG_GEN32 1566 && pDis->param1.base.reg_gen == uMmioReg 1567 && pDis->param2.flags == USE_IMMEDIATE8 1568 && pDis->param2.parval == 4 1569 && oldcbOp + cbOp < sizeof(pVM->hwaccm.s.svm.aPatches[idx])) 1570 { 1571 uint8_t szInstr[15]; 1572 1573 /* Replacing two instructions now. */ 1574 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp); 1575 AssertRC(rc); 1576 1577 pPatch->cbOp = oldcbOp + cbOp; 1578 1579 /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */ 1580 szInstr[0] = 0xF0; 1581 szInstr[1] = 0x0F; 1582 szInstr[2] = 0x20; 1583 szInstr[3] = 0xC0 | pDis->param1.base.reg_gen; 1584 for (unsigned i = 4; i < 5+cbOp; i++) 1585 szInstr[i] = 0x90; /* nop */ 1586 1587 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp); 1588 AssertRC(rc); 1589 1590 Log(("Acceptable read/shr candidate!\n")); 1591 pPatch->enmType = HWACCMTPRINSTR_READ_SHR4; 1592 } 1593 else 1594 { 1595 pPatch->enmType = HWACCMTPRINSTR_READ; 1596 pPatch->uDstOperand = pDis->param1.base.reg_gen; 1597 1598 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall)); 1599 AssertRC(rc); 1600 } 1601 } 1602 1603 pPatch->Core.Key = pCtx->eip; 1604 rc = RTAvloU32Insert(&pVM->hwaccm.s.svm.PatchTree, &pPatch->Core); 1605 AssertRC(rc); 1606 1607 pVM->hwaccm.s.svm.cPatches++; 1608 return VINF_SUCCESS; 1609 } 1610 return hwaccmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp); 1611 } 1612 return VERR_ACCESS_DENIED; 1613 } 1614 1615 /** 1616 * Attempt to patch TPR mmio instructions 1617 * 1618 * @returns VBox status code. 1619 * @param pVM The VM to operate on. 1620 * @param pVCpu The VM CPU to operate on. 1621 * @param pCtx CPU context 1622 */ 1623 VMMR3DECL(int) HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) 1624 { 1625 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, hwaccmR3PatchTprInstr, pCtx); 1626 AssertRC(rc); 1627 return rc; 1628 } 1629 1630 /** 1433 1631 * Force execution of the current IO code in the recompiler 1434 1632 * -
trunk/src/VBox/VMM/VMM.cpp
r21649 r21653 383 383 STAM_REG(pVM, &pVM->vmm.s.StatRZRetPGMChangeMode, STAMTYPE_COUNTER, "/VMM/RZRet/PGMChangeMode", STAMUNIT_OCCURENCES, "Number of VINF_PGM_CHANGE_MODE returns."); 384 384 STAM_REG(pVM, &pVM->vmm.s.StatRZRetPendingRequest, STAMTYPE_COUNTER, "/VMM/RZRet/PendingRequest", STAMUNIT_OCCURENCES, "Number of VINF_EM_PENDING_REQUEST returns."); 385 385 STAM_REG(pVM, &pVM->vmm.s.StatRZRetPatchTPR, STAMTYPE_COUNTER, "/VMM/RZRet/PatchTPR", STAMUNIT_OCCURENCES, "Number of VINF_EM_HWACCM_PATCH_TPR_INSTR returns."); 386 386 STAM_REG(pVM, &pVM->vmm.s.StatRZRetCallRing3, STAMTYPE_COUNTER, "/VMM/RZCallR3/Misc", STAMUNIT_OCCURENCES, "Number of Other ring-3 calls."); 387 387 STAM_REG(pVM, &pVM->vmm.s.StatRZCallPDMLock, STAMTYPE_COUNTER, "/VMM/RZCallR3/PDMLock", STAMUNIT_OCCURENCES, "Number of VMMCALLRING3_PDM_LOCK calls."); -
trunk/src/VBox/VMM/VMMInternal.h
r21196 r21653 364 364 STAMCOUNTER StatRZRetPGMChangeMode; 365 365 STAMCOUNTER StatRZRetPendingRequest; 366 STAMCOUNTER StatRZRetPatchTPR; 366 367 STAMCOUNTER StatRZCallPDMLock; 367 368 STAMCOUNTER StatRZCallLogFlush; -
trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
r21649 r21653 54 54 *******************************************************************************/ 55 55 static int svmR0InterpretInvpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uASID); 56 static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);57 56 static int svmR0EmulateTprVMMCall(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx); 58 57 … … 1747 1746 if (uFaultAddress == GCPhysApicBase + 0x80) 1748 1747 { 1749 rc = svmR0ReplaceTprInstr(pVM, pVCpu, pCtx); 1750 if (rc == VINF_SUCCESS) 1751 { 1752 STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x); 1753 goto ResumeExecution; 1754 } 1755 1756 rc = IOMMMIOPhysHandler(pVM, errCode, CPUMCTX2CORE(pCtx), uFaultAddress); 1757 if (rc == VINF_SUCCESS) 1758 { 1759 STAM_PROFILE_ADV_STOP(&pVCpu->hwaccm.s.StatExit1, x); 1760 goto ResumeExecution; /* rip already updated */ 1761 } 1748 rc = VINF_EM_HWACCM_PATCH_TPR_INSTR; 1749 break; 1762 1750 } 1763 1751 } … … 2385 2373 * 2386 2374 * @returns VBox status code. 2387 * @param pVCpu The VM CPU to operate on.2388 * @param pDis Disassembly state2389 * @param pCtx CPU context2390 * @param cbOp Opcode size2391 */2392 static int svmR0EmulateTprMov(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTX pCtx, unsigned cbOp)2393 {2394 int rc;2395 2396 if (pDis->param1.flags == USE_DISPLACEMENT32)2397 {2398 /* write */2399 uint8_t u8Tpr;2400 2401 /* Fetch the new TPR value */2402 if (pDis->param2.flags == USE_REG_GEN32)2403 {2404 uint32_t val;2405 2406 rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pDis->param2.base.reg_gen, &val);2407 AssertRC(rc);2408 u8Tpr = val;2409 }2410 else2411 if (pDis->param2.flags == USE_IMMEDIATE32)2412 {2413 u8Tpr = (uint8_t)pDis->param2.parval;2414 }2415 else2416 return VERR_EM_INTERPRETER;2417 2418 rc = PDMApicSetTPR(pVCpu, u8Tpr);2419 AssertRC(rc);2420 2421 Log(("Emulated write successfully\n"));2422 pCtx->rip += cbOp;2423 return VINF_SUCCESS;2424 }2425 else2426 if (pDis->param2.flags == USE_DISPLACEMENT32)2427 {2428 /* read */2429 bool fPending;2430 uint8_t u8Tpr;2431 2432 /* TPR caching in CR8 */2433 rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending);2434 AssertRC(rc);2435 2436 rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pDis->param1.base.reg_gen, u8Tpr);2437 AssertRC(rc);2438 2439 Log(("Emulated read successfully\n"));2440 pCtx->rip += cbOp;2441 return VINF_SUCCESS;2442 }2443 return VERR_EM_INTERPRETER;2444 }2445 2446 /**2447 * Emulate simple mov tpr instruction2448 *2449 * @returns VBox status code.2450 2375 * @param pVM The VM to operate on. 2451 2376 * @param pVCpu The VM CPU to operate on. … … 2505 2430 } 2506 2431 2507 /**2508 * Attempt to patch TPR mmio instructions2509 *2510 * @returns VBox status code.2511 * @param pVM The VM to operate on.2512 * @param pVCpu The VM CPU to operate on.2513 * @param pCtx CPU context2514 */2515 static int svmR0ReplaceTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)2516 {2517 RTGCPTR oldrip = pCtx->rip;2518 PDISCPUSTATE pDis = &pVCpu->hwaccm.s.DisState;2519 unsigned cbOp;2520 2521 Log(("Replace TPR access at %RGv\n", pCtx->rip));2522 2523 int rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);2524 AssertRC(rc);2525 if ( rc == VINF_SUCCESS2526 && pDis->pCurInstr->opcode == OP_MOV)2527 {2528 if (pVM->hwaccm.s.svm.cPatches < RT_ELEMENTS(pVM->hwaccm.s.svm.aPatches))2529 {2530 uint8_t aVMMCall[3] = { 0xf, 0x1, 0xd9};2531 uint32_t idx = pVM->hwaccm.s.svm.cPatches;2532 PHWACCMTPRPATCH pPatch = &pVM->hwaccm.s.svm.aPatches[idx];2533 2534 rc = PGMPhysSimpleReadGCPtr(pVCpu, pPatch->aOpcode, pCtx->rip, cbOp);2535 AssertRC(rc);2536 2537 pPatch->cbOp = cbOp;2538 2539 if (pDis->param1.flags == USE_DISPLACEMENT32)2540 {2541 /* write. */2542 if (pDis->param2.flags == USE_REG_GEN32)2543 {2544 pPatch->enmType = HWACCMTPRINSTR_WRITE_REG;2545 pPatch->uSrcOperand = pDis->param2.base.reg_gen;2546 }2547 else2548 {2549 Assert(pDis->param2.flags == USE_IMMEDIATE32);2550 pPatch->enmType = HWACCMTPRINSTR_WRITE_IMM;2551 pPatch->uSrcOperand = pDis->param2.parval;2552 }2553 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));2554 AssertRC(rc);2555 }2556 else2557 {2558 RTGCPTR oldrip = pCtx->rip;2559 uint32_t oldcbOp = cbOp;2560 uint32_t uMmioReg = pDis->param1.base.reg_gen;2561 2562 /* read */2563 Assert(pDis->param1.flags == USE_REG_GEN32);2564 2565 /* Found:2566 * mov eax, dword [fffe0080] (5 bytes)2567 * Check if next instruction is:2568 * shr eax, 42569 */2570 pCtx->rip += cbOp;2571 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), pDis, &cbOp);2572 pCtx->rip = oldrip;2573 if ( rc == VINF_SUCCESS2574 && pDis->pCurInstr->opcode == OP_SHR2575 && pDis->param1.flags == USE_REG_GEN322576 && pDis->param1.base.reg_gen == uMmioReg2577 && pDis->param2.flags == USE_IMMEDIATE82578 && pDis->param2.parval == 42579 && oldcbOp + cbOp < sizeof(pVM->hwaccm.s.svm.aPatches[idx]))2580 {2581 uint8_t szInstr[15];2582 2583 /* Replacing two instructions now. */2584 rc = PGMPhysSimpleReadGCPtr(pVCpu, &pPatch->aOpcode, pCtx->rip, oldcbOp + cbOp);2585 AssertRC(rc);2586 2587 pPatch->cbOp = oldcbOp + cbOp;2588 2589 /* 0xF0, 0x0F, 0x20, 0xC0 = mov eax, cr8 */2590 szInstr[0] = 0xF0;2591 szInstr[1] = 0x0F;2592 szInstr[2] = 0x20;2593 szInstr[3] = 0xC0 | pDis->param1.base.reg_gen;2594 for (unsigned i = 4; i < 5+cbOp; i++)2595 szInstr[i] = 0x90; /* nop */2596 2597 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, szInstr, 5+cbOp);2598 AssertRC(rc);2599 2600 Log(("Acceptable read/shr candidate!\n"));2601 pPatch->enmType = HWACCMTPRINSTR_READ_SHR4;2602 }2603 else2604 {2605 pPatch->enmType = HWACCMTPRINSTR_READ;2606 pPatch->uDstOperand = pDis->param1.base.reg_gen;2607 2608 rc = PGMPhysSimpleWriteGCPtr(pVCpu, pCtx->rip, aVMMCall, sizeof(aVMMCall));2609 AssertRC(rc);2610 }2611 }2612 2613 pPatch->Core.Key = pCtx->eip;2614 rc = RTAvloU32Insert(&pVM->hwaccm.s.svm.PatchTree, &pPatch->Core);2615 AssertRC(rc);2616 2617 pVM->hwaccm.s.svm.cPatches++;2618 return VINF_SUCCESS;2619 }2620 return svmR0EmulateTprMov(pVCpu, pDis, pCtx, cbOp);2621 }2622 return VERR_ACCESS_DENIED;2623 }2624 2432 2625 2433 /** -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r21196 r21653 468 468 STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetPendingRequest); 469 469 break; 470 case VINF_EM_HWACCM_PATCH_TPR_INSTR: 471 STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetPatchTPR); 472 break; 470 473 default: 471 474 STAM_COUNTER_INC(&pVM->vmm.s.StatRZRetMisc);
Note:
See TracChangeset
for help on using the changeset viewer.