Changeset 100869 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Aug 14, 2023 12:37:33 PM (18 months ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp
r100803 r100869 458 458 * Allocate a translation block for threadeded recompilation. 459 459 * 460 * This is allocated with maxed out call table and storage for opcode bytes, 461 * because it's only supposed to be called once per EMT to allocate the TB 462 * pointed to by IEMCPU::pThrdCompileTbR3. 463 * 460 464 * @returns Pointer to the translation block on success, NULL on failure. 461 465 * @param pVM The cross context virtual machine structure. … … 467 471 static PIEMTB iemThreadedTbAlloc(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysPc, uint32_t fExtraFlags) 468 472 { 469 /*470 * Just using the heap for now. Will make this more efficient and471 * complicated later, don't worry. :-)472 */473 473 PIEMTB pTb = (PIEMTB)RTMemAlloc(sizeof(IEMTB)); 474 474 if (pTb) 475 475 { 476 unsigned const cCalls = 128;476 unsigned const cCalls = 256; 477 477 pTb->Thrd.paCalls = (PIEMTHRDEDCALLENTRY)RTMemAlloc(sizeof(IEMTHRDEDCALLENTRY) * cCalls); 478 478 if (pTb->Thrd.paCalls) 479 479 { 480 pTb->pabOpcodes = (uint8_t *)RTMemAlloc(cCalls * 16); /* This will be reallocated later. */480 pTb->pabOpcodes = (uint8_t *)RTMemAlloc(cCalls * 16); 481 481 if (pTb->pabOpcodes) 482 482 { … … 515 515 516 516 /** 517 * Frees pTb. 518 * 519 * @param pVM The cross context virtual machine structure. 520 * @param pVCpu The cross context virtual CPU structure of the calling 521 * thread. 522 * @param pTb The translation block to free.. 523 */ 524 static void iemThreadedTbFree(PVMCC pVM, PVMCPUCC pVCpu, PIEMTB pTb) 525 { 517 * Called on the TB that are dedicated for recompilation before it's reused. 518 * 519 * @param pVCpu The cross context virtual CPU structure of the calling 520 * thread. 521 * @param pTb The translation block to reuse. 522 * @param GCPhysPc The physical address corresponding to RIP + CS.BASE. 523 * @param fExtraFlags Extra flags (IEMTB_F_XXX). 524 */ 525 static void iemThreadedTbReuse(PVMCPUCC pVCpu, PIEMTB pTb, RTGCPHYS GCPhysPc, uint32_t fExtraFlags) 526 { 527 pTb->GCPhysPc = GCPhysPc; 528 pTb->fFlags = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags; 529 pTb->x86.fAttr = (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u; 530 pTb->Thrd.cCalls = 0; 531 pTb->cbOpcodes = 0; 532 pTb->cInstructions = 0; 533 534 /* Init the first opcode range. */ 535 pTb->cRanges = 1; 536 pTb->aRanges[0].cbOpcodes = 0; 537 pTb->aRanges[0].offOpcodes = 0; 538 pTb->aRanges[0].offPhysPage = GCPhysPc & GUEST_PAGE_OFFSET_MASK; 539 pTb->aRanges[0].u2Unused = 0; 540 pTb->aRanges[0].idxPhysPage = 0; 541 pTb->aGCPhysPages[0] = NIL_RTGCPHYS; 542 pTb->aGCPhysPages[1] = NIL_RTGCPHYS; 543 } 544 545 546 /** 547 * Used to duplicate a threded translation block after recompilation is done. 548 * 549 * @returns Pointer to the translation block on success, NULL on failure. 550 * @param pVM The cross context virtual machine structure. 551 * @param pVCpu The cross context virtual CPU structure of the calling 552 * thread. 553 * @param pTbSrc The TB to duplicate. 554 */ 555 static PIEMTB iemThreadedTbDuplicate(PVMCC pVM, PVMCPUCC pVCpu, PCIEMTB pTbSrc) 556 { 557 /* 558 * Just using the heap for now. Will make this more efficient and 559 * complicated later, don't worry. :-) 560 */ 561 PIEMTB pTb = (PIEMTB)RTMemAlloc(sizeof(IEMTB)); 562 if (pTb) 563 { 564 memcpy(pTb, pTbSrc, sizeof(*pTb)); 565 566 unsigned const cCalls = pTbSrc->Thrd.cCalls; 567 Assert(cCalls > 0); 568 pTb->Thrd.paCalls = (PIEMTHRDEDCALLENTRY)RTMemDup(pTbSrc->Thrd.paCalls, sizeof(IEMTHRDEDCALLENTRY) * cCalls); 569 if (pTb->Thrd.paCalls) 570 { 571 unsigned const cbOpcodes = pTbSrc->cbOpcodes; 572 Assert(cbOpcodes > 0); 573 pTb->pabOpcodes = (uint8_t *)RTMemDup(pTbSrc->pabOpcodes, cbOpcodes); 574 if (pTb->pabOpcodes) 575 { 576 pTb->Thrd.cAllocated = cCalls; 577 pTb->cbOpcodesAllocated = cbOpcodes; 578 pTb->pNext = NULL; 579 RTListInit(&pTb->LocalList); 580 pTb->fFlags = (pTbSrc->fFlags & ~IEMTB_F_STATE_MASK) | IEMTB_F_STATE_READY; 581 582 pVCpu->iem.s.cTbAllocs++; 583 return pTb; 584 } 585 RTMemFree(pTb->Thrd.paCalls); 586 } 587 RTMemFree(pTb); 588 } 526 589 RT_NOREF(pVM); 527 AssertPtr(pTb); 528 529 AssertCompile(IEMTB_F_STATE_OBSOLETE == IEMTB_F_STATE_MASK); 530 pTb->fFlags |= IEMTB_F_STATE_OBSOLETE; /* works, both bits set */ 531 532 /* Unlink it from the hash table: */ 533 uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, pTb->fFlags, pTb->GCPhysPc); 534 PIEMTB pTbCur = g_TbCache.apHash[idxHash]; 535 if (pTbCur == pTb) 536 g_TbCache.apHash[idxHash] = pTb->pNext; 537 else 538 while (pTbCur) 539 { 540 PIEMTB const pNextTb = pTbCur->pNext; 541 if (pNextTb == pTb) 542 { 543 pTbCur->pNext = pTb->pNext; 544 break; 545 } 546 pTbCur = pNextTb; 547 } 548 549 /* Free it. */ 550 RTMemFree(pTb->Thrd.paCalls); 551 pTb->Thrd.paCalls = NULL; 552 553 RTMemFree(pTb->pabOpcodes); 554 pTb->pabOpcodes = NULL; 555 556 RTMemFree(pTb); 557 pVCpu->iem.s.cTbFrees++; 590 return NULL; 591 558 592 } 559 593 560 594 561 595 /** 562 * Called by opcode verifier functions when they detect a problem. 563 */ 564 void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb) 565 { 566 iemThreadedTbFree(pVCpu->CTX_SUFF(pVM), pVCpu, pTb); 567 } 568 569 570 static PIEMTB iemThreadedTbLookup(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysPc, uint32_t fExtraFlags) IEM_NOEXCEPT_MAY_LONGJMP 571 { 572 uint32_t const fFlags = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags | IEMTB_F_STATE_READY; 573 uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, fFlags, GCPhysPc); 574 Log10(("TB lookup: idxHash=%#x fFlags=%#x GCPhysPc=%RGp\n", idxHash, fFlags, GCPhysPc)); 575 PIEMTB pTb = g_TbCache.apHash[idxHash]; 576 while (pTb) 577 { 578 if (pTb->GCPhysPc == GCPhysPc) 579 { 580 if (pTb->fFlags == fFlags) 581 { 582 if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u) 583 { 584 #ifdef VBOX_WITH_STATISTICS 585 pVCpu->iem.s.cTbLookupHits++; 586 #endif 587 return pTb; 588 } 589 Log11(("TB miss: CS: %#x, wanted %#x\n", pTb->x86.fAttr, (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)); 590 } 591 else 592 Log11(("TB miss: fFlags: %#x, wanted %#x\n", pTb->fFlags, fFlags)); 593 } 594 else 595 Log11(("TB miss: GCPhysPc: %#x, wanted %#x\n", pTb->GCPhysPc, GCPhysPc)); 596 597 pTb = pTb->pNext; 598 } 599 RT_NOREF(pVM); 600 pVCpu->iem.s.cTbLookupMisses++; 601 return pTb; 602 } 603 604 596 * Adds the given TB to the hash table. 597 * 598 * @param pVM The cross context virtual machine structure. 599 * @param pVCpu The cross context virtual CPU structure of the calling 600 * thread. 601 * @param pTb The translation block to add. 602 */ 605 603 static void iemThreadedTbAdd(PVMCC pVM, PVMCPUCC pVCpu, PIEMTB pTb) 606 604 { … … 622 620 } 623 621 RT_NOREF(pVM); 622 } 623 624 625 /** 626 * Frees the given TB. 627 * 628 * @param pVM The cross context virtual machine structure. 629 * @param pVCpu The cross context virtual CPU structure of the calling 630 * thread. 631 * @param pTb The translation block to free.. 632 */ 633 static void iemThreadedTbFree(PVMCC pVM, PVMCPUCC pVCpu, PIEMTB pTb) 634 { 635 RT_NOREF(pVM); 636 AssertPtr(pTb); 637 638 AssertCompile(IEMTB_F_STATE_OBSOLETE == IEMTB_F_STATE_MASK); 639 pTb->fFlags |= IEMTB_F_STATE_OBSOLETE; /* works, both bits set */ 640 641 /* Unlink it from the hash table: */ 642 uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, pTb->fFlags, pTb->GCPhysPc); 643 PIEMTB pTbCur = g_TbCache.apHash[idxHash]; 644 if (pTbCur == pTb) 645 g_TbCache.apHash[idxHash] = pTb->pNext; 646 else 647 while (pTbCur) 648 { 649 PIEMTB const pNextTb = pTbCur->pNext; 650 if (pNextTb == pTb) 651 { 652 pTbCur->pNext = pTb->pNext; 653 break; 654 } 655 pTbCur = pNextTb; 656 } 657 658 /* Free it. */ 659 RTMemFree(pTb->Thrd.paCalls); 660 pTb->Thrd.paCalls = NULL; 661 662 RTMemFree(pTb->pabOpcodes); 663 pTb->pabOpcodes = NULL; 664 665 RTMemFree(pTb); 666 pVCpu->iem.s.cTbFrees++; 667 } 668 669 670 /** 671 * Called by opcode verifier functions when they detect a problem. 672 */ 673 void iemThreadedTbObsolete(PVMCPUCC pVCpu, PIEMTB pTb) 674 { 675 iemThreadedTbFree(pVCpu->CTX_SUFF(pVM), pVCpu, pTb); 676 } 677 678 679 static PIEMTB iemThreadedTbLookup(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhysPc, uint32_t fExtraFlags) IEM_NOEXCEPT_MAY_LONGJMP 680 { 681 uint32_t const fFlags = (pVCpu->iem.s.fExec & IEMTB_F_IEM_F_MASK) | fExtraFlags | IEMTB_F_STATE_READY; 682 uint32_t const idxHash = IEMTBCACHE_HASH(&g_TbCache, fFlags, GCPhysPc); 683 Log10(("TB lookup: idxHash=%#x fFlags=%#x GCPhysPc=%RGp\n", idxHash, fFlags, GCPhysPc)); 684 PIEMTB pTb = g_TbCache.apHash[idxHash]; 685 while (pTb) 686 { 687 if (pTb->GCPhysPc == GCPhysPc) 688 { 689 if (pTb->fFlags == fFlags) 690 { 691 if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u) 692 { 693 #ifdef VBOX_WITH_STATISTICS 694 pVCpu->iem.s.cTbLookupHits++; 695 #endif 696 return pTb; 697 } 698 Log11(("TB miss: CS: %#x, wanted %#x\n", pTb->x86.fAttr, (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)); 699 } 700 else 701 Log11(("TB miss: fFlags: %#x, wanted %#x\n", pTb->fFlags, fFlags)); 702 } 703 else 704 Log11(("TB miss: GCPhysPc: %#x, wanted %#x\n", pTb->GCPhysPc, GCPhysPc)); 705 706 pTb = pTb->pNext; 707 } 708 RT_NOREF(pVM); 709 pVCpu->iem.s.cTbLookupMisses++; 710 return pTb; 624 711 } 625 712 … … 1362 1449 { 1363 1450 /* 1364 * Allocate a new translation block. 1365 */ 1366 PIEMTB pTb = iemThreadedTbAlloc(pVM, pVCpu, GCPhysPc, fExtraFlags | IEMTB_F_STATE_COMPILING); 1367 AssertReturn(pTb, VERR_IEM_TB_ALLOC_FAILED); 1451 * Get the TB we use for the recompiling. This is a maxed-out TB so 1452 * that'll we'll make a more efficient copy of when we're done compiling. 1453 */ 1454 PIEMTB pTb = pVCpu->iem.s.pThrdCompileTbR3; 1455 if (pTb) 1456 iemThreadedTbReuse(pVCpu, pTb, GCPhysPc, fExtraFlags | IEMTB_F_STATE_COMPILING); 1457 else 1458 { 1459 pTb = iemThreadedTbAlloc(pVM, pVCpu, GCPhysPc, fExtraFlags | IEMTB_F_STATE_COMPILING); 1460 AssertReturn(pTb, VERR_IEM_TB_ALLOC_FAILED); 1461 pVCpu->iem.s.pThrdCompileTbR3 = pTb; 1462 } 1368 1463 1369 1464 /* Set the current TB so iemThreadedCompileLongJumped and the CIMPL … … 1421 1516 1422 1517 pVCpu->iem.s.pCurTbR3 = NULL; 1423 iemThreadedTbFree(pVM, pVCpu, pTb);1424 1518 return iemExecStatusCodeFiddling(pVCpu, rcStrict); 1425 1519 } … … 1445 1539 1446 1540 /* 1447 * Complete the TB and link it. 1448 */ 1449 pTb->fFlags = (pTb->fFlags & ~IEMTB_F_STATE_MASK) | IEMTB_F_STATE_READY; 1541 * Duplicate the TB into a completed one and link it. 1542 */ 1543 pTb = iemThreadedTbDuplicate(pVM, pVCpu, pTb); 1544 AssertReturn(pTb, VERR_IEM_TB_ALLOC_FAILED); 1545 1450 1546 iemThreadedTbAdd(pVM, pVCpu, pTb); 1451 1547 -
trunk/src/VBox/VMM/include/IEMInternal.h
r100863 r100869 1177 1177 * This can either be one being executed or one being compiled. */ 1178 1178 R3PTRTYPE(PIEMTB) pCurTbR3; 1179 /** Fixed TB used for threaded recompilation. 1180 * This is allocated once with maxed-out sizes and re-used afterwards. */ 1181 R3PTRTYPE(PIEMTB) pThrdCompileTbR3; 1182 /** Fixed TB used for native recompilation. 1183 * This is allocated once and re-used afterwards, growing individual 1184 * components as needed. */ 1185 R3PTRTYPE(PIEMTB) pNativeCompileTbR3; 1179 1186 /** The PC (RIP) at the start of pCurTbR3/pCurTbR0. 1180 1187 * The TBs are based on physical addresses, so this is needed to correleated 1181 1188 * RIP to opcode bytes stored in the TB (AMD-V / VT-x). */ 1182 1189 uint64_t uCurTbStartPc; 1183 /** Statistics: Number of TB allocation calls. */1184 uint64_t cTbAllocs;1185 /** Statistics: Number of TB free calls. */1186 uint64_t cTbFrees;1187 1190 /** Statistics: Number of TB lookup misses. */ 1188 1191 uint64_t cTbLookupMisses; … … 1222 1225 uint64_t GCVirtTbBranchSrcBuf; 1223 1226 /* Alignment. */ 1227 uint64_t auAlignment10[6]; 1228 /** Statistics: Number of TB allocation calls. */ 1229 uint64_t cTbAllocs; 1230 /** Statistics: Number of TB free calls. */ 1231 uint64_t cTbFrees; 1224 1232 /** Statistics: Times TB execution was broken off before reaching the end. */ 1225 1233 STAMCOUNTER StatTbExecBreaks;
Note:
See TracChangeset
for help on using the changeset viewer.