- Timestamp:
- Oct 21, 2007 3:57:23 AM (17 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/TRPM.cpp
r5395 r5396 518 518 STAM_REG(pVM, &pVM->trpm.s.StatForwardProfHC, STAMTYPE_PROFILE_ADV, "/TRPM/ForwardRaw/Prof/HC", STAMUNIT_TICKS_PER_CALL, "Profiling TRPMForwardTrap."); 519 519 520 STAM_REG(pVM, &pVM->trpm.s.StatTrap0dDisasm, STAMTYPE_PROFILE_ADV, "/TRPM/Trap0d/Prof/Disasm", STAMUNIT_TICKS_PER_CALL, "Profiling trpmGCTrap0dHandler."); 521 STAM_REG(pVM, &pVM->trpm.s.StatTrap0dRing0RdTsc, STAMTYPE_COUNTER, "/TRPM/Trap0d/RdTsc-R0", STAMUNIT_OCCURENCES, "Number of RDTSC #GPs from guest ring-0."); 522 STAM_REG(pVM, &pVM->trpm.s.StatTrap0dRing3RdTsc, STAMTYPE_COUNTER, "/TRPM/Trap0d/RdTsc-R3", STAMUNIT_OCCURENCES, "Number of RDTSC #GPs from guest ring-3."); 520 STAM_REG(pVM, &pVM->trpm.s.StatTrap0dDisasm, STAMTYPE_PROFILE, "/TRPM/GC/Traps/0d/Disasm", STAMUNIT_TICKS_PER_CALL, "Profiling disassembly part of trpmGCTrap0dHandler."); 521 STAM_REG(pVM, &pVM->trpm.s.StatTrap0dRdTsc, STAMTYPE_COUNTER, "/TRPM/GC/Traps/0d/RdTsc", STAMUNIT_OCCURENCES, "Number of RDTSC #GPs."); 523 522 524 523 /* -
trunk/src/VBox/VMM/TRPMInternal.h
r5395 r5396 174 174 STAMPROFILEADV StatForwardProfGC; 175 175 STAMPROFILEADV StatForwardProfHC; 176 STAMPROFILEADV StatTrap0dDisasm; 177 STAMCOUNTER StatTrap0dRing0RdTsc; /**< Number of RDTSC #GPs from guest ring-0. */ 178 STAMCOUNTER StatTrap0dRing3RdTsc; /**< Number of RDTSC #GPs from guest ring-3. */ 176 STAMPROFILE StatTrap0dDisasm; 177 STAMCOUNTER StatTrap0dRdTsc; /**< Number of RDTSC #GPs. */ 179 178 180 179 /* R3: Statistics for interrupt handlers (allocated on the hypervisor heap). */ -
trunk/src/VBox/VMM/TRPMInternal.mac
r5395 r5396 63 63 .StatForwardProfGC resb STAMPROFILEADV_size 64 64 .StatForwardProfHC resb STAMPROFILEADV_size 65 .StatTrap0dDisasm resb STAMPROFILEADV_size 66 .StatTrap0dRing0RdTsc resb STAMCOUNTER_size 67 .StatTrap0dRing3RdTsc resb STAMCOUNTER_size 65 .StatTrap0dDisasm resb STAMPROFILE_size 66 .StatTrap0dRdTsc resb STAMCOUNTER_size 68 67 69 68 .paStatForwardedIRQR3 RTR3PTR_RES 1 -
trunk/src/VBox/VMM/VMMAll/SELMAll.cpp
r4776 r5396 321 321 322 322 /** 323 * Validates and converts a GC selector based code address to a flat address. 324 * 325 * @returns Flat address. 323 * Validates and converts a GC selector based code address to a flat 324 * address when in real or v8086 mode. 325 * 326 * @returns VINF_SUCCESS. 327 * @param pVM VM Handle. 328 * @param SelCS Selector part. 329 * @param pHidCS The hidden CS register part. Optional. 330 * @param Addr Address part. 331 * @param ppvFlat Where to store the flat address. 332 */ 333 DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVM pVM, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat) 334 { 335 RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff; 336 if (!pHidCS || !CPUMAreHiddenSelRegsValid(pVM)) 337 uFlat += ((RTGCUINTPTR)SelCS << 4); 338 else 339 uFlat += pHidCS->u32Base; 340 *ppvFlat = (RTGCPTR)uFlat; 341 return VINF_SUCCESS; 342 } 343 344 345 /** 346 * Validates and converts a GC selector based code address to a flat 347 * address when in protected/long mode using the standard algorithm. 348 * 349 * @returns VBox status code. 326 350 * @param pVM VM Handle. 327 351 * @param SelCPL Current privilege level. Get this from SS - CS might be conforming! … … 330 354 * @param Addr Address part. 331 355 * @param ppvFlat Where to store the flat address. 332 */ 333 static int selmValidateAndConvertCSAddr(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat) 356 * @param pcBits Where to store the segment bitness (16/32/64). Optional. 357 */ 358 DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits) 334 359 { 335 360 Assert(!CPUMAreHiddenSelRegsValid(pVM)); … … 378 403 if ((RTGCUINTPTR)Addr <= u32Limit) 379 404 { 380 if (ppvFlat) 381 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr 382 + ( (Desc.Gen.u8BaseHigh2 << 24) 383 | (Desc.Gen.u8BaseHigh1 << 16) 384 | Desc.Gen.u16BaseLow) 385 ); 405 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr 406 + ( (Desc.Gen.u8BaseHigh2 << 24) 407 | (Desc.Gen.u8BaseHigh1 << 16) 408 | Desc.Gen.u16BaseLow) 409 ); 410 if (pcBits) 411 *pcBits = Desc.Gen.u1DefBig ? 32 : 16; /** @todo GUEST64 */ 386 412 return VINF_SUCCESS; 387 413 } … … 397 423 398 424 /** 425 * Validates and converts a GC selector based code address to a flat 426 * address when in protected/long mode using the standard algorithm. 427 * 428 * @returns VBox status code. 429 * @param pVM VM Handle. 430 * @param SelCPL Current privilege level. Get this from SS - CS might be conforming! 431 * A full selector can be passed, we'll only use the RPL part. 432 * @param SelCS Selector part. 433 * @param Addr Address part. 434 * @param ppvFlat Where to store the flat address. 435 * @param pcBits Where to store the segment bitness (16/32/64). Optional. 436 */ 437 DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVM pVM, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat) 438 { 439 /* 440 * Check if present. 441 */ 442 if (pHidCS->Attr.n.u1Present) 443 { 444 /* 445 * Type check. 446 */ 447 if ( pHidCS->Attr.n.u1DescType == 1 448 && (pHidCS->Attr.n.u4Type & X86_SEL_TYPE_CODE)) 449 { 450 /* 451 * Check level. 452 */ 453 unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL); 454 if ( !(pHidCS->Attr.n.u4Type & X86_SEL_TYPE_CONF) 455 ? uLevel <= pHidCS->Attr.n.u2Dpl 456 : uLevel >= pHidCS->Attr.n.u2Dpl /* hope I got this right now... */ 457 ) 458 { 459 /* 460 * Limit check. 461 */ 462 uint32_t u32Limit = pHidCS->u32Limit; 463 /** @todo correct with hidden limit value?? */ 464 if (pHidCS->Attr.n.u1Granularity) 465 u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK; 466 if ((RTGCUINTPTR)Addr <= u32Limit) 467 { 468 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr + pHidCS->u32Base ); 469 return VINF_SUCCESS; 470 } 471 return VERR_OUT_OF_SELECTOR_BOUNDS; 472 } 473 return VERR_INVALID_RPL; 474 } 475 return VERR_NOT_CODE_SELECTOR; 476 } 477 return VERR_SELECTOR_NOT_PRESENT; 478 } 479 480 481 /** 399 482 * Validates and converts a GC selector based code address to a flat address. 400 483 * 401 * @returns Flat address. 484 * This is like SELMValidateAndConvertCSAddr + SELMIsSelector32Bit but with 485 * invalid hidden CS data. It's customized for dealing efficiently with CS 486 * at GC trap time. 487 * 488 * @returns VBox status code. 489 * @param pVM VM Handle. 490 * @param eflags Current eflags 491 * @param SelCPL Current privilege level. Get this from SS - CS might be conforming! 492 * A full selector can be passed, we'll only use the RPL part. 493 * @param SelCS Selector part. 494 * @param Addr Address part. 495 * @param ppvFlat Where to store the flat address. 496 * @param pcBits Where to store the 64-bit/32-bit/16-bit indicator. 497 */ 498 SELMDECL(int) SELMValidateAndConvertCSAddrGCTrap(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits) 499 { 500 if ( CPUMIsGuestInRealMode(pVM) 501 || eflags.Bits.u1VM) 502 { 503 *pcBits = 16; 504 return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, NULL, Addr, ppvFlat); 505 } 506 return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, pcBits); 507 } 508 509 510 /** 511 * Validates and converts a GC selector based code address to a flat address. 512 * 513 * @returns VBox status code. 402 514 * @param pVM VM Handle. 403 515 * @param eflags Current eflags … … 411 523 SELMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat) 412 524 { 413 /*414 * Deal with real & v86 mode first.415 */416 525 if ( CPUMIsGuestInRealMode(pVM) 417 526 || eflags.Bits.u1VM) 418 { 419 if (ppvFlat) 420 { 421 RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff; 422 423 if (!CPUMAreHiddenSelRegsValid(pVM)) 424 uFlat += ((RTGCUINTPTR)SelCS << 4); 425 else 426 uFlat += pHiddenCSSel->u32Base; 427 428 *ppvFlat = (RTGCPTR)uFlat; 429 } 430 return VINF_SUCCESS; 431 } 432 433 /** @todo when we're in 16 bits mode, we should cut off the address as well.. */ 434 527 return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, pHiddenCSSel, Addr, ppvFlat); 528 529 /** @todo when we're in 16 bits mode, we should cut off the address as well? (like in selmValidateAndConvertCSAddrRealMode) */ 435 530 if (!CPUMAreHiddenSelRegsValid(pVM)) 436 return selmValidateAndConvertCSAddr(pVM, SelCPL, SelCS, Addr, ppvFlat); 437 438 /* 439 * Check if present. 440 */ 441 if (pHiddenCSSel->Attr.n.u1Present) 442 { 443 /* 444 * Type check. 445 */ 446 if ( pHiddenCSSel->Attr.n.u1DescType == 1 447 && (pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CODE)) 448 { 449 /* 450 * Check level. 451 */ 452 unsigned uLevel = RT_MAX(SelCPL & X86_SEL_RPL, SelCS & X86_SEL_RPL); 453 if ( !(pHiddenCSSel->Attr.n.u4Type & X86_SEL_TYPE_CONF) 454 ? uLevel <= pHiddenCSSel->Attr.n.u2Dpl 455 : uLevel >= pHiddenCSSel->Attr.n.u2Dpl /* hope I got this right now... */ 456 ) 457 { 458 /* 459 * Limit check. 460 */ 461 uint32_t u32Limit = pHiddenCSSel->u32Limit; 462 /** @todo correct with hidden limit value?? */ 463 if (pHiddenCSSel->Attr.n.u1Granularity) 464 u32Limit = (u32Limit << PAGE_SHIFT) | PAGE_OFFSET_MASK; 465 if ((RTGCUINTPTR)Addr <= u32Limit) 466 { 467 if (ppvFlat) 468 *ppvFlat = (RTGCPTR)( (RTGCUINTPTR)Addr + pHiddenCSSel->u32Base ); 469 470 return VINF_SUCCESS; 471 } 472 return VERR_OUT_OF_SELECTOR_BOUNDS; 473 } 474 return VERR_INVALID_RPL; 475 } 476 return VERR_NOT_CODE_SELECTOR; 477 } 478 return VERR_SELECTOR_NOT_PRESENT; 531 return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, NULL); 532 return selmValidateAndConvertCSAddrHidden(pVM, SelCPL, SelCS, pHiddenCSSel, Addr, ppvFlat); 479 533 } 480 534 -
trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp
r5395 r5396 525 525 switch (pCpu->pCurInstr->opcode) 526 526 { 527 /*528 * Since we're usually trapping RDTSC there may be a high volume529 * of these instructions. So, put it first and go straight to530 * the emulation function to save time.531 */532 case OP_RDTSC:533 STAM_COUNTER_INC(&pVM->trpm.s.StatTrap0dRing0RdTsc);534 rc = EMInterpretRdtsc(pVM, pRegFrame);535 if (RT_SUCCESS(rc))536 pRegFrame->eip += pCpu->opsize;537 else if (rc == VERR_EM_INTERPRETER)538 rc = VINF_EM_RAW_EXCEPTION_PRIVILEGED;539 return trpmGCExitTrap(pVM, rc, pRegFrame);540 541 527 case OP_INT3: 542 528 /* … … 599 585 case OP_LLDT: 600 586 case OP_STI: 587 case OP_RDTSC: /* just in case */ 601 588 case OP_CLTS: 602 589 { … … 675 662 676 663 /* 677 * Handle virtualized TSC reads. 678 * Call the emulation function directly to skip unnecessary overhead. 664 * Handle virtualized TSC reads, just in case. 679 665 */ 680 666 case OP_RDTSC: 681 STAM_COUNTER_INC(&pVM->trpm.s.StatTrap0dRing3RdTsc); 682 rc = EMInterpretRdtsc(pVM, pRegFrame); 683 if (RT_SUCCESS(rc)) 667 { 668 uint32_t cbIgnored; 669 rc = EMInterpretInstructionCPU(pVM, pCpu, pRegFrame, PC, &cbIgnored); 670 if (VBOX_SUCCESS(rc)) 684 671 pRegFrame->eip += pCpu->opsize; 685 672 else if (rc == VERR_EM_INTERPRETER) 686 673 rc = VINF_EM_RAW_EXCEPTION_PRIVILEGED; 687 674 return trpmGCExitTrap(pVM, rc, pRegFrame); 675 } 688 676 689 677 /* … … 712 700 713 701 /** 702 * Emulates RDTSC for the \#GP handler. 703 * 704 * @returns VINF_SUCCESS or VINF_EM_RAW_EMULATE_INSTR. 705 * 706 * @param pVM Pointer to the shared VM structure. 707 * @param pRegFrame Pointer to the registre frame for the trap. 708 * This will be updated on successful return. 709 */ 710 DECLINLINE(int) trpmGCTrap0dHandlerRDTSC(PVM pVM, PCPUMCTXCORE pRegFrame) 711 { 712 STAM_COUNTER_INC(&pVM->trpm.s.StatTrap0dRdTsc); 713 714 if (CPUMGetGuestCR4(pVM) & X86_CR4_TSD) 715 return trpmGCExitTrap(pVM, VINF_EM_RAW_EMULATE_INSTR, pRegFrame); /* will trap (optimize later). */ 716 717 uint64_t uTicks = TMCpuTickGet(pVM); 718 pRegFrame->eax = uTicks; 719 pRegFrame->edx = uTicks >> 32; 720 pRegFrame->eip += 2; 721 return trpmGCExitTrap(pVM, VINF_SUCCESS, pRegFrame); 722 } 723 724 725 /** 714 726 * \#GP (General Protection Fault) handler. 715 727 * … … 726 738 LogFlow(("trpmGCTrap0dHandler: cs:eip=%RTsel:%VGv uErr=%RX32\n", pRegFrame->ss, pRegFrame->eip, pTrpm->uActiveErrorCode)); 727 739 728 #if 0 /* not right for iret. Shouldn't really be needed as SELMValidateAndConvertCSAddr deals with invalid cs. */ 729 /* 730 * Filter out selector problems first as these may mean that the 731 * instruction isn't safe to read. If we're here because CS is NIL 732 * the flattening of cs:eip will deal with that. 733 */ 734 if ( !(pTrpm->uActiveErrorCode & (X86_TRAP_ERR_IDT | X86_TRAP_ERR_EXTERNAL)) 735 && (pTrpm->uActiveErrorCode & X86_TRAP_ERR_SEL_MASK)) 736 { 737 /* It's a guest trap. */ 738 return trpmGCExitTrap(pVM, VINF_EM_RAW_GUEST_TRAP, pRegFrame); 739 } 740 #endif 741 742 STAM_PROFILE_ADV_START(&pVM->trpm.s.StatTrap0dDisasm, a); 743 /* 744 * Decode the instruction. 745 */ 740 /* 741 * Convert and validate CS. 742 */ 743 STAM_PROFILE_START(&pVM->trpm.s.StatTrap0dDisasm, a); 746 744 RTGCPTR PC; 747 int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC); 748 if (VBOX_FAILURE(rc)) 749 { 750 Log(("trpmGCTrap0dHandler: Failed to convert %RTsel:%RX32 (cpl=%d) - rc=%Vrc !!\n", 745 uint32_t cBits; 746 int rc = SELMValidateAndConvertCSAddrGCTrap(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, 747 (RTGCPTR)pRegFrame->eip, &PC, &cBits); 748 if (RT_FAILURE(rc)) 749 { 750 Log(("trpmGCTrap0dHandler: Failed to convert %RTsel:%RX32 (cpl=%d) - rc=%Rrc !!\n", 751 751 pRegFrame->cs, pRegFrame->eip, pRegFrame->ss & X86_SEL_RPL, rc)); 752 STAM_PROFILE_ ADV_STOP(&pVM->trpm.s.StatTrap0dDisasm, a);752 STAM_PROFILE_STOP(&pVM->trpm.s.StatTrap0dDisasm, a); 753 753 return trpmGCExitTrap(pVM, VINF_EM_RAW_EMULATE_INSTR, pRegFrame); 754 754 } 755 755 756 /* 757 * Optimize RDTSC traps. 758 * Some guests (like Solaris) is using RDTSC all over the place and 759 * will end up trapping a *lot* because of that. 760 */ 761 if ( !pRegFrame->eflags.Bits.u1VM 762 && ((uint8_t *)PC)[0] == 0x0f 763 && ((uint8_t *)PC)[1] == 0x31) 764 { 765 STAM_PROFILE_STOP(&pVM->trpm.s.StatTrap0dDisasm, a); 766 return trpmGCTrap0dHandlerRDTSC(pVM, pRegFrame); 767 } 768 769 /* 770 * Disassemble the instruction. 771 */ 756 772 DISCPUSTATE Cpu; 757 773 uint32_t cbOp; 758 rc = EMInterpretDisasOneEx(pVM, (RTGCUINTPTR)PC, pRegFrame, &Cpu, &cbOp); 759 if (VBOX_FAILURE(rc)) 760 { 761 STAM_PROFILE_ADV_STOP(&pVM->trpm.s.StatTrap0dDisasm, a); 774 rc = DISCoreOneEx((RTGCUINTPTR)PC, cBits == 32 ? CPUMODE_32BIT : cBits == 16 ? CPUMODE_16BIT : CPUMODE_64BIT, 775 NULL, NULL, &Cpu, &cbOp); 776 if (RT_FAILURE(rc)) 777 { 778 AssertMsgFailed(("DISCoreOneEx failed to PC=%VGv rc=%Vrc\n", PC, rc)); 779 STAM_PROFILE_STOP(&pVM->trpm.s.StatTrap0dDisasm, a); 762 780 return trpmGCExitTrap(pVM, VINF_EM_RAW_EMULATE_INSTR, pRegFrame); 763 781 } 764 STAM_PROFILE_ ADV_STOP(&pVM->trpm.s.StatTrap0dDisasm, a);782 STAM_PROFILE_STOP(&pVM->trpm.s.StatTrap0dDisasm, a); 765 783 766 784 /* … … 773 791 return trpmGCExitTrap(pVM, rc, pRegFrame); 774 792 } 775 776 793 777 794 /* … … 790 807 /* 791 808 * Deal with v86 code. 792 */ 793 794 /* We always set IOPL to zero which makes e.g. pushf fault in V86 mode. The guest might use IOPL=3 and therefor not expect a #GP. 795 * Simply fall back to the recompiler to emulate this instruction. 796 */ 797 /* Retrieve the eflags including the virtualized bits. */ 798 /** @note hackish as the cpumctxcore structure doesn't contain the right value */ 809 * 810 * We always set IOPL to zero which makes e.g. pushf fault in V86 811 * mode. The guest might use IOPL=3 and therefore not expect a #GP. 812 * Simply fall back to the recompiler to emulate this instruction if 813 * that's the case. To get the correct we must use CPUMRawGetEFlags. 814 */ 799 815 X86EFLAGS eflags; 800 eflags.u32 = CPUMRawGetEFlags(pVM, pRegFrame); 816 eflags.u32 = CPUMRawGetEFlags(pVM, pRegFrame); /* Get the correct value. */ 801 817 if (eflags.Bits.u2IOPL != 3) 802 818 {
Note:
See TracChangeset
for help on using the changeset viewer.