Changeset 45276 in vbox for trunk/src/VBox/VMM/VMMR3/SELM.cpp
- Timestamp:
- Apr 2, 2013 8:17:11 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 84670
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/SELM.cpp
r44528 r45276 80 80 #include <iprt/string.h> 81 81 82 83 /**84 * Enable or disable tracking of Shadow GDT/LDT/TSS.85 * @{86 */87 #define SELM_TRACK_SHADOW_GDT_CHANGES88 #define SELM_TRACK_SHADOW_LDT_CHANGES89 #define SELM_TRACK_SHADOW_TSS_CHANGES90 /** @} */91 82 92 83 … … 565 556 * Uninstall guest GDT/LDT/TSS write access handlers. 566 557 */ 567 int rc ;558 int rc = VINF_SUCCESS; 568 559 if (pVM->selm.s.GuestGdtr.pGdt != RTRCPTR_MAX && pVM->selm.s.fGDTRangeRegistered) 569 560 { 561 #ifdef SELM_TRACK_GUEST_GDT_CHANGES 570 562 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GuestGdtr.pGdt); 571 563 AssertRC(rc); 564 #endif 572 565 pVM->selm.s.GuestGdtr.pGdt = RTRCPTR_MAX; 573 566 pVM->selm.s.GuestGdtr.cbGdt = 0; … … 576 569 if (pVM->selm.s.GCPtrGuestLdt != RTRCPTR_MAX) 577 570 { 571 #ifdef SELM_TRACK_GUEST_LDT_CHANGES 578 572 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestLdt); 579 573 AssertRC(rc); 574 #endif 580 575 pVM->selm.s.GCPtrGuestLdt = RTRCPTR_MAX; 581 576 } 582 577 if (pVM->selm.s.GCPtrGuestTss != RTRCPTR_MAX) 583 578 { 579 #ifdef SELM_TRACK_GUEST_TSS_CHANGES 584 580 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestTss); 585 581 AssertRC(rc); 582 #endif 586 583 pVM->selm.s.GCPtrGuestTss = RTRCPTR_MAX; 587 584 pVM->selm.s.GCSelTss = RTSEL_MAX; … … 619 616 if (pVM->selm.s.GuestGdtr.pGdt != RTRCPTR_MAX && pVM->selm.s.fGDTRangeRegistered) 620 617 { 618 #ifdef SELM_TRACK_GUEST_GDT_CHANGES 621 619 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GuestGdtr.pGdt); 622 620 AssertRC(rc); 621 #endif 623 622 pVM->selm.s.GuestGdtr.pGdt = RTRCPTR_MAX; 624 623 pVM->selm.s.GuestGdtr.cbGdt = 0; … … 627 626 if (pVM->selm.s.GCPtrGuestLdt != RTRCPTR_MAX) 628 627 { 628 #ifdef SELM_TRACK_GUEST_LDT_CHANGES 629 629 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestLdt); 630 630 AssertRC(rc); 631 #endif 631 632 pVM->selm.s.GCPtrGuestLdt = RTRCPTR_MAX; 632 633 } 633 634 if (pVM->selm.s.GCPtrGuestTss != RTRCPTR_MAX) 634 635 { 636 #ifdef SELM_TRACK_GUEST_TSS_CHANGES 635 637 rc = PGMHandlerVirtualDeregister(pVM, pVM->selm.s.GCPtrGuestTss); 636 638 AssertRC(rc); 639 #endif 637 640 pVM->selm.s.GCPtrGuestTss = RTRCPTR_MAX; 638 641 pVM->selm.s.GCSelTss = RTSEL_MAX; … … 953 956 } 954 957 958 #ifdef VBOX_WITH_SAFE_STR 959 /** Use the guest's TR selector to plug the str virtualization hole. */ 960 if (CPUMGetGuestTR(pVCpu, NULL) != 0) 961 { 962 Log(("SELM: Use guest TSS selector %x\n", CPUMGetGuestTR(pVCpu, NULL))); 963 aHyperSel[SELM_HYPER_SEL_TSS] = CPUMGetGuestTR(pVCpu, NULL); 964 } 965 #endif 966 955 967 /* 956 968 * Work thru the copied GDT entries adjusting them for correct virtualization. … … 960 972 { 961 973 if (pGDTE->Gen.u1Present) 962 selmGuestToShadowDesc(p GDTE);974 selmGuestToShadowDesc(pVM, pGDTE); 963 975 964 976 /* Next GDT entry. */ … … 990 1002 VMR3Relocate(pVM, 0); 991 1003 } 992 else if (cbEffLimit >= SELM_HYPER_DEFAULT_BASE) 1004 else 1005 #ifdef VBOX_WITH_SAFE_STR 1006 if ( cbEffLimit >= SELM_HYPER_DEFAULT_BASE 1007 || CPUMGetGuestTR(pVCpu, NULL) != 0) /* Our shadow TR entry was overwritten when we synced the guest's GDT. */ 1008 #else 1009 if (cbEffLimit >= SELM_HYPER_DEFAULT_BASE) 1010 #endif 993 1011 /* We overwrote all entries above, so we have to save them again. */ 994 1012 selmR3SetupHyperGDTSelectors(pVM); … … 1011 1029 { 1012 1030 Log(("SELMR3UpdateFromCPUM: Guest's GDT is changed to pGdt=%016RX64 cbGdt=%08X\n", GDTR.pGdt, GDTR.cbGdt)); 1013 1031 #ifdef SELM_TRACK_GUEST_GDT_CHANGES 1014 1032 /* 1015 1033 * [Re]Register write virtual handler for guest's GDT. … … 1025 1043 0, selmR3GuestGDTWriteHandler, "selmRCGuestGDTWriteHandler", 0, 1026 1044 "Guest GDT write access handler"); 1045 # ifdef VBOX_WITH_RAW_RING1 1046 /* Some guest OSes (QNX) share code and the GDT on the same page; PGMR3HandlerVirtualRegister doesn't support more than one handler, so we kick out the 1047 * PATM handler as this one is more important. 1048 * @todo fix this properly in PGMR3HandlerVirtualRegister 1049 */ 1050 if (rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT) 1051 { 1052 LogRel(("selmR3UpdateShadowGdt: Virtual handler conflict %RGv -> kick out PATM handler for the higher priority GDT page monitor\n", GDTR.pGdt)); 1053 rc = PGMHandlerVirtualDeregister(pVM, GDTR.pGdt & PAGE_BASE_GC_MASK); 1054 AssertRC(rc); 1055 1056 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, 1057 GDTR.pGdt, GDTR.pGdt + GDTR.cbGdt /* already inclusive */, 1058 0, selmR3GuestGDTWriteHandler, "selmRCGuestGDTWriteHandler", 0, 1059 "Guest GDT write access handler"); 1060 } 1061 # endif 1027 1062 if (RT_FAILURE(rc)) 1028 1063 return rc; 1029 1064 #endif 1030 1065 /* Update saved Guest GDTR. */ 1031 1066 pVM->selm.s.GuestGdtr = GDTR; … … 1137 1172 pVM->selm.s.GCPtrGuestLdt, pVM->selm.s.cbLdtLimit, GCPtrLdt, cbLdt, pVM->selm.s.GuestGdtr.pGdt, pVM->selm.s.GuestGdtr.cbGdt)); 1138 1173 1174 #ifdef SELM_TRACK_GUEST_LDT_CHANGES 1139 1175 /* 1140 1176 * [Re]Register write virtual handler for guest's GDT. … … 1146 1182 AssertRC(rc); 1147 1183 } 1148 # ifdef DEBUG1184 # ifdef DEBUG 1149 1185 if (pDesc->Gen.u1Present) 1150 1186 Log(("LDT selector marked not present!!\n")); 1151 # endif1187 # endif 1152 1188 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrLdt, GCPtrLdt + cbLdt /* already inclusive */, 1153 1189 0, selmR3GuestLDTWriteHandler, "selmRCGuestLDTWriteHandler", 0, "Guest LDT write access handler"); … … 1166 1202 return rc; 1167 1203 } 1168 1204 #else 1205 pVM->selm.s.GCPtrGuestLdt = GCPtrLdt; 1206 #endif 1169 1207 pVM->selm.s.cbLdtLimit = cbLdt; 1170 1208 } … … 1205 1243 /** @todo investigate how intel handle various operations on half present cross page entries. */ 1206 1244 off = GCPtrLdt & (sizeof(X86DESC) - 1); 1207 AssertMsg(!off, ("LDT is not aligned on entry size! GCPtrLdt=%08x\n", GCPtrLdt));1245 //// AssertMsg(!off, ("LDT is not aligned on entry size! GCPtrLdt=%08x\n", GCPtrLdt)); 1208 1246 1209 1247 /* Note: Do not skip the first selector; unlike the GDT, a zero LDT selector is perfectly valid. */ … … 1239 1277 { 1240 1278 if (pLDTE->Gen.u1Present) 1241 selmGuestToShadowDesc(p LDTE);1279 selmGuestToShadowDesc(pVM, pLDTE); 1242 1280 1243 1281 /* Next LDT entry. */ … … 1438 1476 } 1439 1477 1440 1478 #ifdef SELM_TRACK_GUEST_GDT_CHANGES 1441 1479 /** 1442 1480 * \#PF Handler callback for virtual access handler ranges. … … 1465 1503 return VINF_PGM_HANDLER_DO_DEFAULT; 1466 1504 } 1467 1468 1505 #endif 1506 1507 #ifdef SELM_TRACK_GUEST_LDT_CHANGES 1469 1508 /** 1470 1509 * \#PF Handler callback for virtual access handler ranges. … … 1493 1532 return VINF_PGM_HANDLER_DO_DEFAULT; 1494 1533 } 1495 1496 1534 #endif 1535 1536 1537 #ifdef SELM_TRACK_GUEST_TSS_CHANGES 1497 1538 /** 1498 1539 * \#PF Handler callback for virtual access handler ranges. … … 1526 1567 return VINF_PGM_HANDLER_DO_DEFAULT; 1527 1568 } 1528 1569 #endif 1529 1570 1530 1571 /** … … 1675 1716 selmSetRing1Stack(pVM, Tss.ss0 | 1, Tss.esp0); 1676 1717 pVM->selm.s.fSyncTSSRing0Stack = fNoRing1Stack = false; 1718 1719 #ifdef VBOX_WITH_RAW_RING1 1720 /* Update our TSS structure for the guest's ring 2 stack */ 1721 selmSetRing2Stack(pVM, (Tss.ss1 & ~1) | 2, Tss.esp1); 1722 1723 if ( (pVM->selm.s.Tss.ss2 != ((Tss.ss1 & ~2) | 1)) 1724 || pVM->selm.s.Tss.esp2 != Tss.esp1) 1725 { 1726 Log(("SELMR3SyncTSS: Updating TSS ring 1 stack to %04X:%08X from %04X:%08X\n", Tss.ss1, Tss.esp1, (pVM->selm.s.Tss.ss2 & ~2) | 1, pVM->selm.s.Tss.esp2)); 1727 } 1728 #endif 1677 1729 } 1678 1730 } … … 1711 1763 if (cbMonitoredTss != 0) 1712 1764 { 1765 #ifdef SELM_TRACK_GUEST_TSS_CHANGES 1713 1766 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrTss, GCPtrTss + cbMonitoredTss - 1, 1714 1767 0, selmR3GuestTSSWriteHandler, … … 1716 1769 if (RT_FAILURE(rc)) 1717 1770 { 1771 # ifdef VBOX_WITH_RAW_RING1 1772 /* Some guest OSes (QNX) share code and the TSS on the same page; PGMR3HandlerVirtualRegister doesn't support more than one handler, so we kick out the 1773 * PATM handler as this one is more important. 1774 * @todo fix this properly in PGMR3HandlerVirtualRegister 1775 */ 1776 if (rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT) 1777 { 1778 LogRel(("SELMR3SyncTSS: Virtual handler conflict %RGv -> kick out PATM handler for the higher priority TSS page monitor\n", GCPtrTss)); 1779 rc = PGMHandlerVirtualDeregister(pVM, GCPtrTss & PAGE_BASE_GC_MASK); 1780 AssertRC(rc); 1781 1782 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtrTss, GCPtrTss + cbMonitoredTss - 1, 1783 0, selmR3GuestTSSWriteHandler, 1784 "selmRCGuestTSSWriteHandler", 0, "Guest TSS write access handler"); 1785 if (RT_FAILURE(rc)) 1786 { 1787 STAM_PROFILE_STOP(&pVM->selm.s.StatUpdateFromCPUM, a); 1788 return rc; 1789 } 1790 } 1791 # else 1718 1792 STAM_PROFILE_STOP(&pVM->selm.s.StatUpdateFromCPUM, a); 1719 1793 return rc; 1720 } 1721 1794 # endif 1795 } 1796 #endif 1722 1797 /* Update saved Guest TSS info. */ 1723 1798 pVM->selm.s.GCPtrGuestTss = GCPtrTss; … … 1888 1963 VMMR3DECL(bool) SELMR3CheckTSS(PVM pVM) 1889 1964 { 1890 #if def VBOX_STRICT1965 #if defined(VBOX_STRICT) && defined(SELM_TRACK_GUEST_TSS_CHANGES) 1891 1966 PVMCPU pVCpu = VMMGetCpu(pVM); 1892 1967 … … 2019 2094 #endif /* !VBOX_STRICT */ 2020 2095 } 2096 2097 # ifdef VBOX_WITH_SAFE_STR 2098 /** 2099 * Validates the RawR0 TR shadow GDT entry 2100 * 2101 * @returns true if it matches. 2102 * @returns false and assertions on mismatch.. 2103 * @param pVM Pointer to the VM. 2104 */ 2105 VMMR3DECL(bool) SELMR3CheckShadowTR(PVM pVM) 2106 { 2107 # ifdef VBOX_STRICT 2108 PX86DESC paGdt = pVM->selm.s.paGdtR3; 2109 2110 /* 2111 * TSS descriptor 2112 */ 2113 PX86DESC pDesc = &paGdt[pVM->selm.s.aHyperSel[SELM_HYPER_SEL_TSS] >> 3]; 2114 RTRCPTR RCPtrTSS = VM_RC_ADDR(pVM, &pVM->selm.s.Tss); 2115 2116 if ( pDesc->Gen.u16BaseLow != RT_LOWORD(RCPtrTSS) 2117 || pDesc->Gen.u8BaseHigh1 != RT_BYTE3(RCPtrTSS) 2118 || pDesc->Gen.u8BaseHigh2 != RT_BYTE4(RCPtrTSS) 2119 || pDesc->Gen.u16LimitLow != sizeof(VBOXTSS) - 1 2120 || pDesc->Gen.u4LimitHigh != 0 2121 || (pDesc->Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_AVAIL && pDesc->Gen.u4Type != X86_SEL_TYPE_SYS_386_TSS_BUSY) 2122 || pDesc->Gen.u1DescType != 0 /* system */ 2123 || pDesc->Gen.u2Dpl != 0 /* supervisor */ 2124 || pDesc->Gen.u1Present != 1 2125 || pDesc->Gen.u1Available != 0 2126 || pDesc->Gen.u1Long != 0 2127 || pDesc->Gen.u1DefBig != 0 2128 || pDesc->Gen.u1Granularity != 0 /* byte limit */ 2129 ) 2130 { 2131 AssertFailed(); 2132 return false; 2133 } 2134 # endif 2135 return true; 2136 } 2137 # endif 2021 2138 2022 2139 #endif /* VBOX_WITH_RAW_MODE */
Note:
See TracChangeset
for help on using the changeset viewer.