Changeset 22343 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Aug 19, 2009 12:40:16 PM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PGMInternal.h
r22170 r22343 1609 1609 #endif 1610 1610 RTGCPHYS GCPhys; 1611 1612 /** Access handler statistics to determine whether the guest is (re)initializing a page table. */ 1613 RTGCPTR pvLastAccessHandlerRip; 1614 RTGCPTR pvLastAccessHandlerFault; 1615 uint64_t cLastAccessHandlerCount; 1616 1611 1617 /** The kind of page we're shadowing. (This is really a PGMPOOLKIND enum.) */ 1612 1618 uint8_t enmKind; … … 1792 1798 /** Profiling the pgmPoolFlushPage calls made from the RC/R0 access handler. */ 1793 1799 STAMPROFILE StatMonitorRZFlushPage; 1800 /* Times we've detected a page table reinit. */ 1801 STAMCOUNTER StatMonitorRZFlushReinit; 1794 1802 /** Times we've detected fork(). */ 1795 1803 STAMCOUNTER StatMonitorRZFork; … … 1811 1819 /** Profiling the pgmPoolFlushPage calls made from the R3 access handler. */ 1812 1820 STAMPROFILE StatMonitorR3FlushPage; 1821 /* Times we've detected a page table reinit. */ 1822 STAMCOUNTER StatMonitorR3FlushReinit; 1813 1823 /** Times we've detected fork(). */ 1814 1824 STAMCOUNTER StatMonitorR3Fork; … … 2729 2739 uint8_t abDisStatePadding[DISCPUSTATE_PADDING_SIZE]; 2730 2740 }; 2741 2742 /* Count the number of pgm pool access handler calls. */ 2743 uint64_t cPoolAccessHandler; 2731 2744 2732 2745 /** @name Release Statistics -
trunk/src/VBox/VMM/PGMPool.cpp
r20764 r22343 344 344 STAM_REG(pVM, &pPool->StatMonitorRZEmulateInstr, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/RZ/EmulateInstr", STAMUNIT_OCCURENCES, "Times we've failed interpreting the instruction."); 345 345 STAM_REG(pVM, &pPool->StatMonitorRZFlushPage, STAMTYPE_PROFILE, "/PGM/Pool/Monitor/RZ/FlushPage", STAMUNIT_TICKS_PER_CALL, "Profiling the pgmPoolFlushPage calls made from the RC/R0 access handler."); 346 STAM_REG(pVM, &pPool->StatMonitorRZFlushReinit, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/RZ/FlushReinit", STAMUNIT_OCCURENCES, "Times we've detected a page table reinit."); 346 347 STAM_REG(pVM, &pPool->StatMonitorRZFork, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/RZ/Fork", STAMUNIT_OCCURENCES, "Times we've detected fork()."); 347 348 STAM_REG(pVM, &pPool->StatMonitorRZHandled, STAMTYPE_PROFILE, "/PGM/Pool/Monitor/RZ/Handled", STAMUNIT_TICKS_PER_CALL, "Profiling the RC/R0 access we've handled (except REP STOSD)."); … … 353 354 STAM_REG(pVM, &pPool->StatMonitorR3EmulateInstr, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/R3/EmulateInstr", STAMUNIT_OCCURENCES, "Times we've failed interpreting the instruction."); 354 355 STAM_REG(pVM, &pPool->StatMonitorR3FlushPage, STAMTYPE_PROFILE, "/PGM/Pool/Monitor/R3/FlushPage", STAMUNIT_TICKS_PER_CALL, "Profiling the pgmPoolFlushPage calls made from the R3 access handler."); 356 STAM_REG(pVM, &pPool->StatMonitorR3FlushReinit, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/R3/FlushReinit", STAMUNIT_OCCURENCES, "Times we've detected a page table reinit."); 355 357 STAM_REG(pVM, &pPool->StatMonitorR3Fork, STAMTYPE_COUNTER, "/PGM/Pool/Monitor/R3/Fork", STAMUNIT_OCCURENCES, "Times we've detected fork()."); 356 358 STAM_REG(pVM, &pPool->StatMonitorR3Handled, STAMTYPE_PROFILE, "/PGM/Pool/Monitor/R3/Handled", STAMUNIT_TICKS_PER_CALL, "Profiling the R3 access we've handled (except REP STOSD)."); -
trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp
r22337 r22343 820 820 * @returns false if we consider it to still be a paging page. 821 821 * @param pVM VM Handle. 822 * @param pVCpu VMCPU Handle. 822 823 * @param pRegFrame Trap register frame. 823 824 * @param pDis The disassembly info for the faulting instruction. … … 826 827 * @remark The REP prefix check is left to the caller because of STOSD/W. 827 828 */ 828 DECLINLINE(bool) pgmPoolMonitorIsReused(PVM pVM, P CPUMCTXCORE pRegFrame, PDISCPUSTATE pDis, RTGCPTR pvFault)829 DECLINLINE(bool) pgmPoolMonitorIsReused(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pDis, RTGCPTR pvFault) 829 830 { 830 831 #ifndef IN_RC … … 840 841 NOREF(pVM); NOREF(pvFault); 841 842 #endif 843 844 LogFlow(("Reused instr %RGv %d at %RGv param1.flags=%x param1.reg=%d\n", pRegFrame->rip, pDis->pCurInstr->opcode, pvFault, pDis->param1.flags, pDis->param1.base.reg_gen)); 845 846 /* Non-supervisor mode write means it's used for something else. */ 847 if (CPUMGetGuestCPL(pVCpu, pRegFrame) != 0) 848 return true; 842 849 843 850 switch (pDis->pCurInstr->opcode) … … 961 968 PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, RTGCPTR pvFault) 962 969 { 963 unsigned uIncrement ;970 unsigned uIncrement = pDis->param1.size; 964 971 965 972 Assert(pDis->mode == CPUMODE_32BIT || pDis->mode == CPUMODE_64BIT); 966 973 Assert(pRegFrame->rcx <= 0x20); 967 974 968 if (pDis->mode == CPUMODE_32BIT) 969 uIncrement = 4; 975 #ifdef VBOX_STRICT 976 if (pDis->opmode == CPUMODE_32BIT) 977 Assert(uIncrement == 4); 970 978 else 971 uIncrement = 8; 979 Assert(uIncrement == 8); 980 #endif 972 981 973 982 Log3(("pgmPoolAccessHandlerSTOSD\n")); … … 1107 1116 PPGMPOOLPAGE pPage = (PPGMPOOLPAGE)pvUser; 1108 1117 PVMCPU pVCpu = VMMGetCpu(pVM); 1118 unsigned cMaxModifications; 1109 1119 1110 1120 LogFlow(("pgmPoolAccessHandler: pvFault=%RGv pPage=%p:{.idx=%d} GCPhysFault=%RGp\n", pvFault, pPage, pPage->idx, GCPhysFault)); … … 1135 1145 Assert(pPage->iMonitoredPrev == NIL_PGMPOOL_IDX); 1136 1146 1147 /* Maximum nr of modifications depends on the guest mode. */ 1148 if (pDis->mode == CPUMODE_32BIT) 1149 cMaxModifications = 32; 1150 else 1151 cMaxModifications = 16; 1152 1153 /* 1154 * Incremental page table updates should weight more than random ones. 1155 * (Only applies when started from offset 0) 1156 */ 1157 pVCpu->pgm.s.cPoolAccessHandler++; 1158 if ( pPage->pvLastAccessHandlerRip >= pRegFrame->rip - 0x40 /* observed loops in Windows 7 x64 */ 1159 && pPage->pvLastAccessHandlerRip < pRegFrame->rip + 0x40 1160 && pvFault == (pPage->pvLastAccessHandlerFault + pDis->param1.size) 1161 && pVCpu->pgm.s.cPoolAccessHandler == (pPage->cLastAccessHandlerCount + 1)) 1162 { 1163 Log(("Possible page reuse cMods=%d -> %d\n", pPage->cModifications, (pPage->cModifications + 2) * 2)); 1164 pPage->cModifications = (pPage->cModifications + 1) * 2; 1165 pPage->pvLastAccessHandlerFault = pvFault; 1166 pPage->cLastAccessHandlerCount = pVCpu->pgm.s.cPoolAccessHandler; 1167 if (pPage->cModifications > cMaxModifications) 1168 STAM_COUNTER_INC(&pPool->CTX_MID_Z(StatMonitor,FlushReinit)); 1169 } 1170 1137 1171 /* 1138 1172 * Check if it's worth dealing with. 1139 1173 */ 1140 1174 bool fReused = false; 1141 if ( ( pPage->cModifications < 48/** @todo #define */ /** @todo need to check that it's not mapping EIP. */ /** @todo adjust this! */1175 if ( ( pPage->cModifications < cMaxModifications /** @todo #define */ /** @todo need to check that it's not mapping EIP. */ /** @todo adjust this! */ 1142 1176 || pgmPoolIsPageLocked(&pVM->pgm.s, pPage) 1143 1177 ) 1144 && !(fReused = pgmPoolMonitorIsReused(pVM, p RegFrame, pDis, pvFault))1178 && !(fReused = pgmPoolMonitorIsReused(pVM, pVCpu, pRegFrame, pDis, pvFault)) 1145 1179 && !pgmPoolMonitorIsForking(pPool, pDis, GCPhysFault & PAGE_OFFSET_MASK)) 1146 1180 { … … 1151 1185 { 1152 1186 rc = pgmPoolAccessHandlerSimple(pVM, pVCpu, pPool, pPage, pDis, pRegFrame, GCPhysFault, pvFault); 1187 1188 /* A mov instruction to change the first page table entry will be remembered so we can detect 1189 * full page table changes early on. This will reduce the amount of unnecessary traps we'll take. 1190 */ 1191 if ( rc == VINF_SUCCESS 1192 && pDis->pCurInstr->opcode == OP_MOV 1193 && (pvFault & PAGE_OFFSET_MASK) == 0) 1194 { 1195 pPage->pvLastAccessHandlerFault = pvFault; 1196 pPage->cLastAccessHandlerCount = pVCpu->pgm.s.cPoolAccessHandler; 1197 pPage->pvLastAccessHandlerRip = pRegFrame->rip; 1198 } 1199 else 1200 if (pPage->pvLastAccessHandlerFault == pvFault) 1201 { 1202 /* ignore the 2nd write to this page table entry. */ 1203 pPage->cLastAccessHandlerCount = pVCpu->pgm.s.cPoolAccessHandler; 1204 } 1205 else 1206 { 1207 pPage->pvLastAccessHandlerFault = 0; 1208 pPage->pvLastAccessHandlerRip = 0; 1209 } 1210 1153 1211 STAM_PROFILE_STOP_EX(&pVM->pgm.s.CTX_SUFF(pPool)->CTX_SUFF_Z(StatMonitor), &pPool->CTX_MID_Z(StatMonitor,Handled), a); 1154 1212 pgmUnlock(pVM); … … 1161 1219 */ 1162 1220 if ( pDis->pCurInstr->opcode == OP_STOSWD 1163 && CPUMGetGuestCPL(pVCpu, pRegFrame) == 01164 1221 && !pRegFrame->eflags.Bits.u1DF 1165 1222 && pDis->opmode == pDis->mode … … 1183 1240 && pDis->prefix == (PREFIX_REP | PREFIX_REX) 1184 1241 && pRegFrame->rcx <= 0x20 1185 && pRegFrame->rcx * 4<= PAGE_SIZE - ((uintptr_t)pvFault & PAGE_OFFSET_MASK)1186 && !((uintptr_t)pvFault & 3)1242 && pRegFrame->rcx * 8 <= PAGE_SIZE - ((uintptr_t)pvFault & PAGE_OFFSET_MASK) 1243 && !((uintptr_t)pvFault & 7) 1187 1244 && (pRegFrame->rax == 0 || pRegFrame->rax == 0x80) /* the two values observed. */ 1188 1245 ) … … 4162 4219 pPage->cPresent = 0; 4163 4220 pPage->iFirstPresent = ~0; 4221 pPage->pvLastAccessHandlerFault = 0; 4222 pPage->cLastAccessHandlerCount = 0; 4223 pPage->pvLastAccessHandlerRip = 0; 4164 4224 4165 4225 /*
Note:
See TracChangeset
for help on using the changeset viewer.