Changeset 72569 in vbox
- Timestamp:
- Jun 15, 2018 7:04:01 PM (6 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/em.h
r72565 r72569 238 238 #define EMEXIT_F_KIND_XCPT UINT32_C(0x00004000) /**< Exception numbers (raw-mode). */ 239 239 #define EMEXIT_F_KIND_MASK UINT32_C(0x00007000) 240 #define EMEXIT_F_CS_EIP UINT32_C(0x000 08000) /**< The PC is EIP in the low dword and CS in the high. */241 #define EMEXIT_F_UNFLATTENED_PC UINT32_C(0x000 10000) /**< The PC hasn't had CS.BASE added to it. */240 #define EMEXIT_F_CS_EIP UINT32_C(0x00010000) /**< The PC is EIP in the low dword and CS in the high. */ 241 #define EMEXIT_F_UNFLATTENED_PC UINT32_C(0x00020000) /**< The PC hasn't had CS.BASE added to it. */ 242 242 /** Combines flags and exit type into EMHistoryAddExit() input. */ 243 243 #define EMEXIT_MAKE_FLAGS_AND_TYPE(a_fFlags, a_uType) ((a_fFlags) | (uint32_t)(a_uType)) … … 246 246 typedef enum EMEXITACTION 247 247 { 248 /** The record is free. */ 249 EMEXITACTION_FREE_RECORD = 0, 248 250 /** Take normal action on the exit. */ 249 EMEXITACTION_NORMAL = 0, 250 EMEXITACTION_TODO 251 EMEXITACTION_NORMAL, 252 /** Take normal action on the exit, already probed and found nothing. */ 253 EMEXITACTION_NORMAL_PROBED, 254 /** Do a probe execution. */ 255 EMEXITACTION_EXEC_PROBE, 256 /** Execute using EMEXITREC::cMaxInstructionsWithoutExit. */ 257 EMEXITACTION_EXEC_WITH_MAX 251 258 } EMEXITACTION; 252 259 AssertCompileSize(EMEXITACTION, 4); 253 260 254 VMM_INT_DECL(EMEXITACTION) EMHistoryAddExit(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp); 261 /** 262 * Accumulative exit record. 263 * 264 * This could perhaps be squeezed down a bit, but there isn't too much point. 265 * We'll probably need more data as time goes by. 266 */ 267 typedef struct EMEXITREC 268 { 269 /** The flat PC of the exit. */ 270 uint64_t uFlatPC; 271 /** Flags and type, see EMEXIT_MAKE_FLAGS_AND_TYPE. */ 272 uint32_t uFlagsAndType; 273 /** The action to take (EMEXITACTION). */ 274 uint8_t enmAction; 275 uint8_t bUnused; 276 /** Maximum number of instructions to execute without hitting an exit. */ 277 uint16_t cMaxInstructionsWithoutExit; 278 /** The exit number (EMCPU::iNextExit) at which it was last updated. */ 279 uint64_t uLastExitNo; 280 /** Number of hits. */ 281 uint64_t cHits; 282 } EMEXITREC; 283 AssertCompileSize(EMEXITREC, 32); 284 /** Pointer to an accumulative exit record. */ 285 typedef EMEXITREC *PEMEXITREC; 286 /** Pointer to a const accumulative exit record. */ 287 typedef EMEXITREC const *PCEMEXITREC; 288 289 VMM_INT_DECL(PCEMEXITREC) EMHistoryAddExit(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp); 255 290 #ifdef IN_RC 256 291 VMMRC_INT_DECL(void) EMRCHistoryAddExitCsEip(PVMCPU pVCpu, uint32_t uFlagsAndType, uint16_t uCs, uint32_t uEip, … … 260 295 VMMR0_INT_DECL(void) EMR0HistoryUpdatePC(PVMCPU pVCpu, uint64_t uFlatPC, bool fFlattened); 261 296 #endif 262 VMM_INT_DECL(EMEXITACTION) EMHistoryUpdateFlagsAndType(PVMCPU pVCpu, uint32_t uFlagsAndType); 263 VMM_INT_DECL(EMEXITACTION) EMHistoryUpdateFlagsAndTypeAndPC(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC); 297 VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndType(PVMCPU pVCpu, uint32_t uFlagsAndType); 298 VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndTypeAndPC(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC); 299 VMM_INT_DECL(VBOXSTRICTRC) EMHistoryExec(PVMCPU pVCpu, PCEMEXITREC pExitRec, uint32_t fWillExit); 264 300 265 301 -
trunk/include/VBox/vmm/iem.h
r72493 r72569 210 210 uint32_t *pcbWritten); 211 211 VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPU pVCpu, uint32_t *pcInstructions); 212 /** Statistics returned by IEMExecForExits. */ 213 typedef struct IEMEXECFOREXITSTATS 214 { 215 uint32_t cInstructions; 216 uint32_t cExits; 217 uint32_t cMaxExitDistance; 218 uint32_t cReserved; 219 } IEMEXECFOREXITSTATS; 220 /** Pointer to statistics returned by IEMExecForExits. */ 221 typedef IEMEXECFOREXITSTATS *PIEMEXECFOREXITSTATS; 222 VMMDECL(VBOXSTRICTRC) IEMExecForExits(PVMCPU pVCpu, uint32_t fWillExit, uint32_t cMinInstructions, uint32_t cMaxInstructions, 223 uint32_t cMaxInstructionsWithoutExits, PIEMEXECFOREXITSTATS pStats); 212 224 VMMDECL(VBOXSTRICTRC) IEMInjectTrpmEvent(PVMCPU pVCpu); 213 225 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2, -
trunk/include/VBox/vmm/vm.h
r72555 r72569 290 290 struct EMCPU s; 291 291 #endif 292 uint8_t padding[ 8192]; /* multiple of 4096 */292 uint8_t padding[40960]; /* multiple of 4096 */ 293 293 } em; 294 294 } VMCPU; -
trunk/include/VBox/vmm/vm.mac
r72555 r72569 83 83 .cpum resb 4096 84 84 alignb 4096 85 .em resb 819285 .em resb 40960 86 86 alignb 4096 87 87 endstruc -
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r72565 r72569 404 404 405 405 /** 406 * Execute using history. 407 * 408 * This function will be called when EMHistoryAddExit() and friends returns a 409 * non-NULL result. This happens in response to probing or when probing has 410 * uncovered adjacent exits which can more effectively be reached by using IEM 411 * than restarting execution using the main execution engine and fielding an 412 * regular exit. 413 * 414 * @returns VBox strict status code, see IEMExecForExits. 415 * @param pVCpu The cross context virtual CPU structure. 416 * @param pExitRec The exit record return by a previous history add 417 * or update call. 418 * @param fWillExit Flags indicating to IEM what will cause exits, TBD. 419 */ 420 VMM_INT_DECL(VBOXSTRICTRC) EMHistoryExec(PVMCPU pVCpu, PCEMEXITREC pExitRec, uint32_t fWillExit) 421 { 422 Assert(pExitRec); 423 VMCPU_ASSERT_EMT(pVCpu); 424 IEMEXECFOREXITSTATS ExecStats; 425 switch (pExitRec->enmAction) 426 { 427 /* 428 * Executes multiple instruction stopping only when we've gone a given 429 * number without perceived exits. 430 */ 431 case EMEXITACTION_EXEC_WITH_MAX: 432 { 433 LogFlow(("EMHistoryExec/EXEC_WITH_MAX: %RX64, max %u\n", pExitRec->uFlatPC, pExitRec->cMaxInstructionsWithoutExit)); 434 VBOXSTRICTRC rcStrict = IEMExecForExits(pVCpu, fWillExit, 435 pExitRec->cMaxInstructionsWithoutExit /* cMinInstructions*/, 436 4096 /*cMaxInstructions*/, 437 pExitRec->cMaxInstructionsWithoutExit, 438 &ExecStats); 439 LogFlow(("EMHistoryExec/EXEC_WITH_MAX: %Rrc cExits=%u cMaxExitDistance=%u cInstructions=%u\n", 440 VBOXSTRICTRC_VAL(rcStrict), ExecStats.cExits, ExecStats.cMaxExitDistance, ExecStats.cInstructions)); 441 return rcStrict; 442 } 443 444 /* 445 * Probe a exit for close by exits. 446 */ 447 case EMEXITACTION_EXEC_PROBE: 448 { 449 LogFlow(("EMHistoryExec/EXEC_PROBE: %RX64, max %u\n", pExitRec->uFlatPC)); 450 PEMEXITREC pExitRecUnconst = (PEMEXITREC)pExitRec; 451 VBOXSTRICTRC rcStrict = IEMExecForExits(pVCpu, fWillExit, 452 64 /*cMinInstructions*/, 453 4096 /*cMaxInstructions*/, 454 32 /*cMaxInstructionsWithoutExit*/, 455 &ExecStats); 456 LogFlow(("EMHistoryExec/EXEC_PROBE: %Rrc cExits=%u cMaxExitDistance=%u cInstructions=%u\n", 457 VBOXSTRICTRC_VAL(rcStrict), ExecStats.cExits, ExecStats.cMaxExitDistance, ExecStats.cInstructions)); 458 if (ExecStats.cExits >= 2) 459 { 460 Assert(ExecStats.cMaxExitDistance > 0 && ExecStats.cMaxExitDistance <= 32); 461 pExitRecUnconst->cMaxInstructionsWithoutExit = ExecStats.cMaxExitDistance; 462 pExitRecUnconst->enmAction = EMEXITACTION_EXEC_WITH_MAX; 463 LogFlow(("EMHistoryExec/EXEC_PROBE: -> EXEC_WITH_MAX %u\n", ExecStats.cMaxExitDistance)); 464 } 465 else 466 { 467 pExitRecUnconst->enmAction = EMEXITACTION_NORMAL_PROBED; 468 LogFlow(("EMHistoryExec/EXEC_PROBE: -> PROBED\n")); 469 /** @todo check for return to ring-3 and such and optimize/reprobe. */ 470 } 471 return rcStrict; 472 } 473 474 /* We shouldn't ever see these here! */ 475 case EMEXITACTION_FREE_RECORD: 476 case EMEXITACTION_NORMAL: 477 case EMEXITACTION_NORMAL_PROBED: 478 break; 479 480 /* No default case, want compiler warnings. */ 481 } 482 AssertLogRelFailedReturn(VERR_EM_INTERNAL_ERROR); 483 } 484 485 486 DECL_FORCE_INLINE(PCEMEXITREC) emHistoryRecordInit(PEMEXITREC pExitRec, uint64_t uFlatPC, uint32_t uFlagsAndType, uint64_t uExitNo) 487 { 488 pExitRec->uFlatPC = uFlatPC; 489 pExitRec->uFlagsAndType = uFlagsAndType; 490 pExitRec->enmAction = EMEXITACTION_NORMAL; 491 pExitRec->bUnused = 0; 492 pExitRec->cMaxInstructionsWithoutExit = 64; 493 pExitRec->uLastExitNo = uExitNo; 494 pExitRec->cHits = 1; 495 return NULL; 496 } 497 498 499 DECL_FORCE_INLINE(PCEMEXITREC) emHistoryRecordInitNew(PVMCPU pVCpu, PEMEXITENTRY pHistEntry, uintptr_t idxSlot, 500 PEMEXITREC pExitRec, uint64_t uFlatPC, 501 uint32_t uFlagsAndType, uint64_t uExitNo) 502 { 503 pHistEntry->idxSlot = (uint32_t)idxSlot; 504 pVCpu->em.s.cExitRecordUsed++; 505 LogFlow(("emHistoryRecordInitNew: [%#x] = %#07x %016RX64; (%u of %u used)\n", idxSlot, uFlagsAndType, uFlatPC, 506 pVCpu->em.s.cExitRecordUsed, RT_ELEMENTS(pVCpu->em.s.aExitRecords) )); 507 return emHistoryRecordInit(pExitRec, uFlatPC, uFlagsAndType, uExitNo); 508 } 509 510 511 /** 512 * Adds or updates the EMEXITREC for this PC/type and decide on an action. 513 * 514 * @returns Pointer to an exit record if special action should be taken using 515 * EMHistoryExec(). Take normal exit action when NULL. 516 * 517 * @param pVCpu The cross context virtual CPU structure. 518 * @param uFlagsAndType Combined flags and type, EMEXIT_F_KIND_EM set and 519 * both EMEXIT_F_CS_EIP and EMEXIT_F_UNFLATTENED_PC are clear. 520 * @param uFlatPC The flattened program counter. 521 * @param pHistEntry The exit history entry. 522 * @param uExitNo The current exit number. 523 */ 524 static PCEMEXITREC emHistoryAddOrUpdateRecord(PVMCPU pVCpu, uint64_t uFlagsAndType, uint64_t uFlatPC, 525 PEMEXITENTRY pHistEntry, uint64_t uExitNo) 526 { 527 /* 528 * Work the hash table. 529 */ 530 AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitRecords) == 1024); 531 #define EM_EXIT_RECORDS_IDX_MASK 1023 532 uintptr_t idxSlot = ((uintptr_t)uFlatPC >> 1) & EM_EXIT_RECORDS_IDX_MASK; 533 PEMEXITREC pExitRec = &pVCpu->em.s.aExitRecords[idxSlot]; 534 if (pExitRec->uFlatPC == uFlatPC) 535 { 536 Assert(pExitRec->enmAction != EMEXITACTION_FREE_RECORD); 537 pHistEntry->idxSlot = (uint32_t)idxSlot; 538 if (pExitRec->uFlagsAndType == uFlagsAndType) 539 pExitRec->uLastExitNo = uExitNo; 540 else 541 return emHistoryRecordInit(pExitRec, uFlatPC, uFlagsAndType, uExitNo); 542 } 543 else if (pExitRec->enmAction == EMEXITACTION_FREE_RECORD) 544 return emHistoryRecordInitNew(pVCpu, pHistEntry, idxSlot, pExitRec, uFlatPC, uFlagsAndType, uExitNo); 545 else 546 { 547 /* 548 * Collision. Figure out later. 549 */ 550 return NULL; 551 } 552 553 554 /* 555 * Found an existing record. 556 */ 557 switch (pExitRec->enmAction) 558 { 559 case EMEXITACTION_NORMAL: 560 { 561 uint64_t const cHits = ++pExitRec->cHits; 562 if (cHits < 256) 563 return NULL; 564 LogFlow(("emHistoryAddOrUpdateRecord: [%#x] %#07x %16RX64: -> EXEC_PROBE\n", idxSlot, uFlagsAndType, uFlatPC)); 565 pExitRec->enmAction = EMEXITACTION_EXEC_PROBE; 566 return pExitRec; 567 } 568 569 case EMEXITACTION_NORMAL_PROBED: 570 pExitRec->cHits += 1; 571 return NULL; 572 573 default: 574 pExitRec->cHits += 1; 575 return pExitRec; 576 577 /* This will happen if the caller ignores or cannot serve the probe 578 request (forced to ring-3, whatever). We retry this 256 times. */ 579 case EMEXITACTION_EXEC_PROBE: 580 { 581 uint64_t const cHits = ++pExitRec->cHits; 582 if (cHits < 512) 583 return pExitRec; 584 pExitRec->enmAction = EMEXITACTION_NORMAL_PROBED; 585 LogFlow(("emHistoryAddOrUpdateRecord: [%#x] %#07x %16RX64: -> PROBED\n", idxSlot, uFlagsAndType, uFlatPC)); 586 return NULL; 587 } 588 } 589 } 590 591 592 /** 406 593 * Adds an exit to the history for this CPU. 407 594 * 408 * @returns Suggested action to take. 595 * @returns Pointer to an exit record if special action should be taken using 596 * EMHistoryExec(). Take normal exit action when NULL. 597 * 409 598 * @param pVCpu The cross context virtual CPU structure. 410 599 * @param uFlagsAndType Combined flags and type (see EMEXIT_MAKE_FLAGS_AND_TYPE). … … 413 602 * @thread EMT(pVCpu) 414 603 */ 415 VMM_INT_DECL( EMEXITACTION) EMHistoryAddExit(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp)604 VMM_INT_DECL(PCEMEXITREC) EMHistoryAddExit(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp) 416 605 { 417 606 VMCPU_ASSERT_EMT(pVCpu); … … 421 610 */ 422 611 AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256); 423 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)(pVCpu->em.s.iNextExit++) & 0xff]; 612 uint64_t uExitNo = pVCpu->em.s.iNextExit++; 613 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)uExitNo & 0xff]; 424 614 pHistEntry->uFlatPC = uFlatPC; 425 615 pHistEntry->uTimestamp = uTimestamp; … … 428 618 429 619 /* 430 * If common exit type, we will insert/update the exit into the shared hash table.620 * If common exit type, we will insert/update the exit into the exit record hash table. 431 621 */ 432 if ((uFlagsAndType & EMEXIT_F_KIND_MASK) == EMEXIT_F_KIND_EM) 433 { 434 /** @todo later */ 435 } 436 437 return EMEXITACTION_NORMAL; 622 if ( (uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM 623 && uFlatPC != UINT64_MAX) 624 return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, uFlatPC, pHistEntry, uExitNo); 625 return NULL; 438 626 } 439 627 … … 476 664 { 477 665 AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256); 478 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[((uintptr_t)pVCpu->em.s.iNextExit - 1) & 0xff]; 666 uint64_t uExitNo = pVCpu->em.s.iNextExit - 1; 667 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)uExitNo & 0xff]; 479 668 pHistEntry->uFlatPC = uFlatPC; 480 669 if (fFlattened) … … 489 678 * Interface for convering a engine specific exit to a generic one and get guidance. 490 679 * 680 * @returns Pointer to an exit record if special action should be taken using 681 * EMHistoryExec(). Take normal exit action when NULL. 682 * 491 683 * @param pVCpu The cross context virtual CPU structure. 492 684 * @param uFlagsAndType Combined flags and type (see EMEXIT_MAKE_FLAGS_AND_TYPE). 493 685 * @thread EMT(pVCpu) 494 686 */ 495 VMM_INT_DECL( EMEXITACTION) EMHistoryUpdateFlagsAndType(PVMCPU pVCpu, uint32_t uFlagsAndType)687 VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndType(PVMCPU pVCpu, uint32_t uFlagsAndType) 496 688 { 497 689 VMCPU_ASSERT_EMT(pVCpu); … … 501 693 */ 502 694 AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256); 503 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[((uintptr_t)pVCpu->em.s.iNextExit - 1) & 0xff]; 695 uint64_t uExitNo = pVCpu->em.s.iNextExit - 1; 696 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)uExitNo & 0xff]; 504 697 pHistEntry->uFlagsAndType = uFlagsAndType | (pHistEntry->uFlagsAndType & (EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)); 505 698 506 699 /* 507 * If common exit type, we will insert/update the exit into the shared hash table.700 * If common exit type, we will insert/update the exit into the exit record hash table. 508 701 */ 509 if ((uFlagsAndType & EMEXIT_F_KIND_MASK) == EMEXIT_F_KIND_EM) 510 { 511 /** @todo later */ 512 } 513 514 return EMEXITACTION_NORMAL; 702 if ( (uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM 703 && pHistEntry->uFlatPC != UINT64_MAX) 704 return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, pHistEntry->uFlatPC, pHistEntry, uExitNo); 705 return NULL; 515 706 } 516 707 … … 519 710 * Interface for convering a engine specific exit to a generic one and get 520 711 * guidance, supplying flattened PC too. 712 * 713 * @returns Pointer to an exit record if special action should be taken using 714 * EMHistoryExec(). Take normal exit action when NULL. 521 715 * 522 716 * @param pVCpu The cross context virtual CPU structure. … … 525 719 * @thread EMT(pVCpu) 526 720 */ 527 VMM_INT_DECL( EMEXITACTION) EMHistoryUpdateFlagsAndTypeAndPC(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC)721 VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndTypeAndPC(PVMCPU pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC) 528 722 { 529 723 VMCPU_ASSERT_EMT(pVCpu); 724 Assert(uFlatPC != UINT64_MAX); 530 725 531 726 /* … … 533 728 */ 534 729 AssertCompile(RT_ELEMENTS(pVCpu->em.s.aExitHistory) == 256); 535 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[((uintptr_t)pVCpu->em.s.iNextExit - 1) & 0xff]; 730 uint64_t uExitNo = pVCpu->em.s.iNextExit - 1; 731 PEMEXITENTRY pHistEntry = &pVCpu->em.s.aExitHistory[(uintptr_t)uExitNo & 0xff]; 536 732 pHistEntry->uFlagsAndType = uFlagsAndType; 537 733 pHistEntry->uFlatPC = uFlatPC; 538 734 539 735 /* 540 * If common exit type, we will insert/update the exit into the shared hash table.736 * If common exit type, we will insert/update the exit into the exit record hash table. 541 737 */ 542 if ((uFlagsAndType & EMEXIT_F_KIND_MASK) == EMEXIT_F_KIND_EM) 543 { 544 /** @todo later */ 545 } 546 547 return EMEXITACTION_NORMAL; 738 if ((uFlagsAndType & (EMEXIT_F_KIND_MASK | EMEXIT_F_CS_EIP | EMEXIT_F_UNFLATTENED_PC)) == EMEXIT_F_KIND_EM) 739 return emHistoryAddOrUpdateRecord(pVCpu, uFlagsAndType, uFlatPC, pHistEntry, uExitNo); 740 return NULL; 548 741 } 549 742 -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r72563 r72569 14152 14152 14153 14153 14154 /** 14155 * Interface used by EMExecuteExec, does exit statistics and limits. 14156 * 14157 * @returns Strict VBox status code. 14158 * @param pVCpu The cross context virtual CPU structure. 14159 * @param fWillExit To be defined. 14160 * @param cMinInstructions Minimum number of instructions to execute before checking for FFs. 14161 * @param cMaxInstructions Maximum number of instructions to execute. 14162 * @param cMaxInstructionsWithoutExits 14163 * The max number of instructions without exits. 14164 * @param pStats Where to return statistics. 14165 */ 14166 VMMDECL(VBOXSTRICTRC) IEMExecForExits(PVMCPU pVCpu, uint32_t fWillExit, uint32_t cMinInstructions, uint32_t cMaxInstructions, 14167 uint32_t cMaxInstructionsWithoutExits, PIEMEXECFOREXITSTATS pStats) 14168 { 14169 NOREF(fWillExit); /** @todo define flexible exit crits */ 14170 14171 /* 14172 * Initialize return stats. 14173 */ 14174 pStats->cInstructions = 0; 14175 pStats->cExits = 0; 14176 pStats->cMaxExitDistance = 0; 14177 pStats->cReserved = 0; 14178 14179 /* 14180 * Initial decoder init w/ prefetch, then setup setjmp. 14181 */ 14182 VBOXSTRICTRC rcStrict = iemInitDecoderAndPrefetchOpcodes(pVCpu, false); 14183 if (rcStrict == VINF_SUCCESS) 14184 { 14185 uint32_t cInstructionSinceLastExit = 0; 14186 14187 #ifdef IEM_WITH_SETJMP 14188 jmp_buf JmpBuf; 14189 jmp_buf *pSavedJmpBuf = pVCpu->iem.s.CTX_SUFF(pJmpBuf); 14190 pVCpu->iem.s.CTX_SUFF(pJmpBuf) = &JmpBuf; 14191 pVCpu->iem.s.cActiveMappings = 0; 14192 if ((rcStrict = setjmp(JmpBuf)) == 0) 14193 #endif 14194 { 14195 /* 14196 * The run loop. We limit ourselves to 4096 instructions right now. 14197 */ 14198 PVM pVM = pVCpu->CTX_SUFF(pVM); 14199 for (;;) 14200 { 14201 /* 14202 * Log the state. 14203 */ 14204 #ifdef LOG_ENABLED 14205 iemLogCurInstr(pVCpu, true); 14206 #endif 14207 14208 /* 14209 * Do the decoding and emulation. 14210 */ 14211 uint32_t const cPotentialExits = pVCpu->iem.s.cPotentialExits; 14212 14213 uint8_t b; IEM_OPCODE_GET_NEXT_U8(&b); 14214 rcStrict = FNIEMOP_CALL(g_apfnOneByteMap[b]); 14215 14216 if ( cPotentialExits != pVCpu->iem.s.cPotentialExits 14217 && cInstructionSinceLastExit > 0 /* don't count the first */ ) 14218 { 14219 pStats->cExits += 1; 14220 if (cInstructionSinceLastExit > pStats->cMaxExitDistance) 14221 pStats->cMaxExitDistance = cInstructionSinceLastExit; 14222 cInstructionSinceLastExit = 0; 14223 } 14224 14225 if (RT_LIKELY(rcStrict == VINF_SUCCESS)) 14226 { 14227 Assert(pVCpu->iem.s.cActiveMappings == 0); 14228 pVCpu->iem.s.cInstructions++; 14229 pStats->cInstructions++; 14230 cInstructionSinceLastExit++; 14231 if (RT_LIKELY(pVCpu->iem.s.rcPassUp == VINF_SUCCESS)) 14232 { 14233 uint32_t fCpu = pVCpu->fLocalForcedActions 14234 & ( VMCPU_FF_ALL_MASK & ~( VMCPU_FF_PGM_SYNC_CR3 14235 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL 14236 | VMCPU_FF_TLB_FLUSH 14237 #ifdef VBOX_WITH_RAW_MODE 14238 | VMCPU_FF_TRPM_SYNC_IDT 14239 | VMCPU_FF_SELM_SYNC_TSS 14240 | VMCPU_FF_SELM_SYNC_GDT 14241 | VMCPU_FF_SELM_SYNC_LDT 14242 #endif 14243 | VMCPU_FF_INHIBIT_INTERRUPTS 14244 | VMCPU_FF_BLOCK_NMIS 14245 | VMCPU_FF_UNHALT )); 14246 14247 if (RT_LIKELY( ( ( !fCpu 14248 || ( !(fCpu & ~(VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)) 14249 && !pVCpu->cpum.GstCtx.rflags.Bits.u1IF)) 14250 && !VM_FF_IS_PENDING(pVM, VM_FF_ALL_MASK) ) 14251 || pStats->cInstructions < cMinInstructions)) 14252 { 14253 if (cMaxInstructions-- > 0) 14254 { 14255 if (cInstructionSinceLastExit <= cMaxInstructionsWithoutExits) 14256 { 14257 Assert(pVCpu->iem.s.cActiveMappings == 0); 14258 iemReInitDecoder(pVCpu); 14259 continue; 14260 } 14261 } 14262 } 14263 } 14264 Assert(pVCpu->iem.s.cActiveMappings == 0); 14265 } 14266 else if (pVCpu->iem.s.cActiveMappings > 0) 14267 iemMemRollback(pVCpu); 14268 rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict); 14269 break; 14270 } 14271 } 14272 #ifdef IEM_WITH_SETJMP 14273 else 14274 { 14275 if (pVCpu->iem.s.cActiveMappings > 0) 14276 iemMemRollback(pVCpu); 14277 pVCpu->iem.s.cLongJumps++; 14278 } 14279 pVCpu->iem.s.CTX_SUFF(pJmpBuf) = pSavedJmpBuf; 14280 #endif 14281 14282 /* 14283 * Assert hidden register sanity (also done in iemInitDecoder and iemReInitDecoder). 14284 */ 14285 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.cs)); 14286 Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pVCpu->cpum.GstCtx.ss)); 14287 } 14288 else 14289 { 14290 if (pVCpu->iem.s.cActiveMappings > 0) 14291 iemMemRollback(pVCpu); 14292 14293 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 14294 /* 14295 * When a nested-guest causes an exception intercept (e.g. #PF) when fetching 14296 * code as part of instruction execution, we need this to fix-up VINF_SVM_VMEXIT. 14297 */ 14298 rcStrict = iemExecStatusCodeFiddling(pVCpu, rcStrict); 14299 #endif 14300 } 14301 14302 /* 14303 * Maybe re-enter raw-mode and log. 14304 */ 14305 #ifdef IN_RC 14306 rcStrict = iemRCRawMaybeReenter(pVCpu, rcStrict); 14307 #endif 14308 if (rcStrict != VINF_SUCCESS) 14309 LogFlow(("IEMExecForExits: cs:rip=%04x:%08RX64 ss:rsp=%04x:%08RX64 EFL=%06x - rcStrict=%Rrc; ins=%u exits=%u maxdist=%u\n", 14310 pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.ss.Sel, pVCpu->cpum.GstCtx.rsp, 14311 pVCpu->cpum.GstCtx.eflags.u, VBOXSTRICTRC_VAL(rcStrict), pStats->cInstructions, pStats->cExits, pStats->cMaxExitDistance)); 14312 return rcStrict; 14313 } 14314 14154 14315 14155 14316 /** -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r72553 r72569 6801 6801 6802 6802 iemRegAddToRipAndClearRF(pVCpu, cbInstr); 6803 pVCpu->iem.s.cPotentialExits++; 6803 6804 return VINF_SUCCESS; 6804 6805 } -
trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
r72555 r72569 2293 2293 pCtx->rdi = pExit->IoPortAccess.Rdi; 2294 2294 pCtx->rsi = pExit->IoPortAccess.Rsi; 2295 # ifdef IN_RING02296 rcStrict = nemR0WinImportStateStrict(pGVCpu->pGVM, pGVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM, "IOExit");2297 if (rcStrict != VINF_SUCCESS)2298 return rcStrict;2299 # else2300 2295 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2301 2296 AssertRCReturn(rc, rc); 2302 # endif2303 2297 2304 2298 Log4(("IOExit/%u: %04x:%08RX64/%s: %s%s %#x LB %u (emulating)\n", … … 2477 2471 * function and make everyone use it. 2478 2472 */ 2479 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID), 2480 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2481 2482 /** @todo Combine implementations into IEMExecDecodedCpuId as this will 2483 * only get weirder with nested VT-x and AMD-V support. */ 2473 PCEMEXITREC pExitRec = EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FLAGS_AND_TYPE(EMEXIT_F_KIND_EM, EMEXITTYPE_CPUID), 2474 pExit->VpContext.Rip + pExit->VpContext.Cs.Base, ASMReadTSC()); 2484 2475 nemR3WinCopyStateFromX64Header(pVCpu, pCtx, &pExit->VpContext); 2485 2486 /* Copy in the low register values (top is always cleared). */ 2487 pCtx->rax = (uint32_t)pExit->CpuidAccess.Rax; 2488 pCtx->rcx = (uint32_t)pExit->CpuidAccess.Rcx; 2489 pCtx->rdx = (uint32_t)pExit->CpuidAccess.Rdx; 2490 pCtx->rbx = (uint32_t)pExit->CpuidAccess.Rbx; 2476 if (!pExitRec) 2477 { 2478 /** @todo Combine implementations into IEMExecDecodedCpuId as this will 2479 * only get weirder with nested VT-x and AMD-V support. */ 2480 2481 /* Copy in the low register values (top is always cleared). */ 2482 pCtx->rax = (uint32_t)pExit->CpuidAccess.Rax; 2483 pCtx->rcx = (uint32_t)pExit->CpuidAccess.Rcx; 2484 pCtx->rdx = (uint32_t)pExit->CpuidAccess.Rdx; 2485 pCtx->rbx = (uint32_t)pExit->CpuidAccess.Rbx; 2486 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2487 2488 /* Get the correct values. */ 2489 CPUMGetGuestCpuId(pVCpu, pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx); 2490 2491 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n", 2492 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2493 pExit->CpuidAccess.Rax, pExit->CpuidAccess.Rcx, pExit->CpuidAccess.Rdx, pExit->CpuidAccess.Rbx, 2494 pCtx->eax, pCtx->ecx, pCtx->edx, pCtx->ebx, 2495 pExit->CpuidAccess.DefaultResultRax, pExit->CpuidAccess.DefaultResultRcx, pExit->CpuidAccess.DefaultResultRdx, pExit->CpuidAccess.DefaultResultRbx)); 2496 2497 /* Move RIP and we're done. */ 2498 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext); 2499 2500 RT_NOREF_PV(pVM); 2501 return VINF_SUCCESS; 2502 } 2503 2504 /* Get state and call EMHistoryExec. */ 2505 pCtx->rax = pExit->CpuidAccess.Rax; 2506 pCtx->rcx = pExit->CpuidAccess.Rcx; 2507 pCtx->rdx = pExit->CpuidAccess.Rdx; 2508 pCtx->rbx = pExit->CpuidAccess.Rbx; 2491 2509 pCtx->fExtrn &= ~(CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX); 2492 2493 /* Get the correct values. */ 2494 CPUMGetGuestCpuId(pVCpu, pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx); 2495 2496 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 -> %08RX32 / %08RX32 / %08RX32 / %08RX32 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64)\n", 2510 Log4(("CpuIdExit/%u: %04x:%08RX64/%s: rax=%08RX64 / rcx=%08RX64 / rdx=%08RX64 / rbx=%08RX64 (hv: %08RX64 / %08RX64 / %08RX64 / %08RX64) ==> EMHistoryExec\n", 2497 2511 pVCpu->idCpu, pExit->VpContext.Cs.Selector, pExit->VpContext.Rip, nemR3WinExecStateToLogStr(&pExit->VpContext), 2498 2512 pExit->CpuidAccess.Rax, pExit->CpuidAccess.Rcx, pExit->CpuidAccess.Rdx, pExit->CpuidAccess.Rbx, 2499 pCtx->eax, pCtx->ecx, pCtx->edx, pCtx->ebx,2500 2513 pExit->CpuidAccess.DefaultResultRax, pExit->CpuidAccess.DefaultResultRcx, pExit->CpuidAccess.DefaultResultRdx, pExit->CpuidAccess.DefaultResultRbx)); 2501 2514 2502 /* Move RIP and we're done. */2503 nemR3WinAdvanceGuestRipAndClearRF(pVCpu, pCtx, &pExit->VpContext);2504 2505 RT_NOREF_PV(pVM);2506 return VINF_SUCCESS;2515 int rc = nemHCWinCopyStateFromHyperV(pVM, pVCpu, pCtx, NEM_WIN_CPUMCTX_EXTRN_MASK_FOR_IEM); 2516 AssertRCReturn(rc, rc); 2517 2518 VBOXSTRICTRC rcStrict = EMHistoryExec(pVCpu, pExitRec, 0); 2519 return rcStrict; 2507 2520 } 2508 2521 #endif /* IN_RING3 && !NEM_WIN_USE_OUR_OWN_RUN_API */ -
trunk/src/VBox/VMM/include/EMInternal.h
r72560 r72569 493 493 R3PTRTYPE(PAVLGCPTRNODECORE) pCliStatTree; 494 494 STAMCOUNTER StatTotalClis; 495 #if 0 496 /** 64-bit Visual C++ rounds the struct size up to 16 byte. */ 495 #if HC_ARCH_BITS == 32 497 496 uint64_t padding1; 498 497 #endif … … 505 504 /** Exit history table (6KB). */ 506 505 EMEXITENTRY aExitHistory[256]; 506 /** Number of exit records in use. */ 507 uint32_t cExitRecordUsed; 508 /** Number of exit records collisions. */ 509 uint32_t cExitRecordCollisions; 510 /** Exit records (32KB). (Aligned on 32 byte boundrary.) */ 511 EMEXITREC aExitRecords[1024]; 507 512 } EMCPU; 508 513 /** Pointer to EM VM instance data. */ -
trunk/src/VBox/VMM/include/NEMInternal.h
r72555 r72569 45 45 */ 46 46 # define NEM_WIN_USE_HYPERCALLS_FOR_PAGES 47 # define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS48 # define NEM_WIN_USE_OUR_OWN_RUN_API47 //# define NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS 48 //# define NEM_WIN_USE_OUR_OWN_RUN_API 49 49 # if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) 50 50 # error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS" -
trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp
r70918 r72569 415 415 CHECK_MEMBER_ALIGNMENT(EM, CritSectREM, sizeof(uintptr_t)); 416 416 #endif 417 CHECK_MEMBER_ALIGNMENT(EMCPU, aExitRecords, sizeof(EMEXITREC)); 417 418 CHECK_MEMBER_ALIGNMENT(PGM, CritSectX, sizeof(uintptr_t)); 418 419 CHECK_MEMBER_ALIGNMENT(PDM, CritSect, sizeof(uintptr_t));
Note:
See TracChangeset
for help on using the changeset viewer.