Changeset 100964 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Aug 24, 2023 2:45:42 PM (16 months ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
r99891 r100964 72 72 static int pgmShwSyncLongModePDPtr(PVMCPUCC pVCpu, RTGCPTR64 GCPtr, X86PGPAEUINT uGstPml4e, X86PGPAEUINT uGstPdpe, PX86PDPAE *ppPD); 73 73 static int pgmShwGetEPTPDPtr(PVMCPUCC pVCpu, RTGCPTR64 GCPtr, PEPTPDPT *ppPdpt, PEPTPD *ppPD); 74 #ifdef PGM_WITH_PAGE_ZEROING_DETECTION 75 static bool pgmHandlePageZeroingCode(PVMCPUCC pVCpu, PCPUMCTX pCtx); 76 #endif 74 77 75 78 … … 3931 3934 3932 3935 cch = pfnOutput(pvArgOutput, szTmp, cch); 3936 #if 0 3937 size_t cch2 = 0; 3938 szTmp[cch2++] = '('; 3939 cch2 += RTStrFormatNumber(&szTmp[cch2], (uintptr_t)pPage, 16, 18, 0, RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT); 3940 szTmp[cch2++] = ')'; 3941 szTmp[cch2] = '\0'; 3942 cch += pfnOutput(pvArgOutput, szTmp, cch2); 3943 #endif 3933 3944 } 3934 3945 else … … 4075 4086 } 4076 4087 4088 #ifdef PGM_WITH_PAGE_ZEROING_DETECTION 4089 4090 /** 4091 * Helper for checking whether XMM0 is zero, possibly retriving external state. 4092 */ 4093 static bool pgmHandlePageZeroingIsXmm0Zero(PVMCPUCC pVCpu, PCPUMCTX pCtx) 4094 { 4095 if (pCtx->fExtrn & CPUMCTX_EXTRN_SSE_AVX) 4096 { 4097 int rc = CPUMImportGuestStateOnDemand(pVCpu, CPUMCTX_EXTRN_SSE_AVX); 4098 AssertRCReturn(rc, false); 4099 } 4100 return pCtx->XState.x87.aXMM[0].au64[0] == 0 4101 && pCtx->XState.x87.aXMM[0].au64[1] == 0 4102 && pCtx->XState.x87.aXMM[0].au64[2] == 0 4103 && pCtx->XState.x87.aXMM[0].au64[3] == 0; 4104 } 4105 4106 4107 /** 4108 * Helper for comparing opcode bytes. 4109 */ 4110 static bool pgmHandlePageZeroingMatchOpcodes(PVMCPUCC pVCpu, PCPUMCTX pCtx, uint8_t const *pbOpcodes, uint32_t cbOpcodes) 4111 { 4112 uint8_t abTmp[64]; 4113 AssertMsgReturn(cbOpcodes <= sizeof(abTmp), ("cbOpcodes=%#x\n", cbOpcodes), false); 4114 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abTmp, pCtx->rip + pCtx->cs.u64Base, cbOpcodes); 4115 if (RT_SUCCESS(rc)) 4116 return memcmp(abTmp, pbOpcodes, cbOpcodes) == 0; 4117 return false; 4118 } 4119 4120 4121 /** 4122 * Called on faults on ZERO pages to check if the guest is trying to zero it. 4123 * 4124 * Since it's a waste of time to zero a ZERO page and it will cause an 4125 * unnecessary page allocation, we'd like to detect and avoid this. 4126 * If any known page zeroing code is detected, this function will update the CPU 4127 * state to pretend the page was zeroed by the code. 4128 * 4129 * @returns true if page zeroing code was detected and CPU state updated to skip 4130 * the code. 4131 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 4132 * @param pCtx The guest register context. 4133 */ 4134 static bool pgmHandlePageZeroingCode(PVMCPUCC pVCpu, PCPUMCTX pCtx) 4135 { 4136 CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER); 4137 4138 /* 4139 * Sort by mode first. 4140 */ 4141 if (CPUMIsGuestInLongModeEx(pCtx)) 4142 { 4143 if (CPUMIsGuestIn64BitCodeEx(pCtx)) 4144 { 4145 /* 4146 * 64-bit code. 4147 */ 4148 Log9(("pgmHandlePageZeroingCode: not page zeroing - 64-bit\n")); 4149 } 4150 else if (pCtx->cs.Attr.n.u1DefBig) 4151 Log9(("pgmHandlePageZeroingCode: not page zeroing - 32-bit lm\n")); 4152 else 4153 Log9(("pgmHandlePageZeroingCode: not page zeroing - 16-bit lm\n")); 4154 } 4155 else if (CPUMIsGuestInPagedProtectedModeEx(pCtx)) 4156 { 4157 if (pCtx->cs.Attr.n.u1DefBig) 4158 { 4159 /* 4160 * 32-bit paged protected mode code. 4161 */ 4162 CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RCX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RBX 4163 | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RBP | CPUMCTX_EXTRN_RSI | CPUMCTX_EXTRN_RDI 4164 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS); 4165 4166 /* 1. Generic 'rep stosd' detection. */ 4167 static uint8_t const s_abRepStosD[] = { 0xf3, 0xab }; 4168 if ( pCtx->eax == 0 4169 && pCtx->ecx == X86_PAGE_SIZE / 4 4170 && !(pCtx->edi & X86_PAGE_OFFSET_MASK) 4171 && pgmHandlePageZeroingMatchOpcodes(pVCpu, pCtx, s_abRepStosD, sizeof(s_abRepStosD))) 4172 { 4173 pCtx->ecx = 0; 4174 pCtx->edi += X86_PAGE_SIZE; 4175 Log9(("pgmHandlePageZeroingCode: REP STOSD: eip=%RX32 -> %RX32\n", pCtx->eip, pCtx->eip + sizeof(s_abRepStosD))); 4176 pCtx->eip += sizeof(s_abRepStosD); 4177 return true; 4178 } 4179 4180 /* 2. Windows 2000 sp4 KiXMMIZeroPageNoSave loop code: */ 4181 static uint8_t const s_abW2kSp4XmmZero[] = 4182 { 4183 0x0f, 0x2b, 0x01, 4184 0x0f, 0x2b, 0x41, 0x10, 4185 0x0f, 0x2b, 0x41, 0x20, 4186 0x0f, 0x2b, 0x41, 0x30, 4187 0x83, 0xc1, 0x40, 4188 0x48, 4189 0x75, 0xeb, 4190 }; 4191 if ( pCtx->eax == 64 4192 && !(pCtx->ecx & X86_PAGE_OFFSET_MASK) 4193 && pgmHandlePageZeroingMatchOpcodes(pVCpu, pCtx, s_abW2kSp4XmmZero, sizeof(s_abW2kSp4XmmZero)) 4194 && pgmHandlePageZeroingIsXmm0Zero(pVCpu, pCtx)) 4195 { 4196 pCtx->eax = 1; 4197 pCtx->ecx += X86_PAGE_SIZE; 4198 Log9(("pgmHandlePageZeroingCode: w2k sp4 xmm: eip=%RX32 -> %RX32\n", 4199 pCtx->eip, pCtx->eip + sizeof(s_abW2kSp4XmmZero) - 3)); 4200 pCtx->eip += sizeof(s_abW2kSp4XmmZero) - 3; 4201 return true; 4202 } 4203 Log9(("pgmHandlePageZeroingCode: not page zeroing - 32-bit\n")); 4204 } 4205 else if (!pCtx->eflags.Bits.u1VM) 4206 Log9(("pgmHandlePageZeroingCode: not page zeroing - 16-bit\n")); 4207 else 4208 Log9(("pgmHandlePageZeroingCode: not page zeroing - v86\n")); 4209 } 4210 return false; 4211 } 4212 4213 #endif /* PGM_WITH_PAGE_ZEROING_DETECTION */ -
trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
r100958 r100964 783 783 # endif 784 784 AssertFatalMsg(!PGM_PAGE_IS_BALLOONED(pPage), ("Unexpected ballooned page at %RGp\n", GCPhys)); 785 # ifdef PGM_WITH_PAGE_ZEROING_DETECTION 786 if ( PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ZERO 787 && (pvFault & X86_PAGE_OFFSET_MASK) == 0 788 && pgmHandlePageZeroingCode(pVCpu, pCtx)) 789 { 790 STAM_STATS({ pVCpu->pgmr0.s.pStatTrap0eAttributionR0 = &pVCpu->pgm.s.Stats.StatRZTrap0eTime2PageZeroing; }); 791 return VINF_SUCCESS; 792 } 793 # endif 785 794 STAM_STATS({ pVCpu->pgmr0.s.pStatTrap0eAttributionR0 = &pVCpu->pgm.s.Stats.StatRZTrap0eTime2MakeWritable; }); 786 795 … … 1313 1322 /* This is a read-only page. */ 1314 1323 AssertFatalMsg(!PGM_PAGE_IS_BALLOONED(pPage), ("Unexpected ballooned page at %RGp\n", GCPhysPage)); 1324 #ifdef PGM_WITH_PAGE_ZEROING_DETECTION 1325 if ( PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ZERO 1326 && (GCPhysNestedFault & X86_PAGE_OFFSET_MASK) == 0 1327 && pgmHandlePageZeroingCode(pVCpu, pCtx)) 1328 { 1329 STAM_STATS({ pVCpu->pgmr0.s.pStatTrap0eAttributionR0 = &pVCpu->pgm.s.Stats.StatRZTrap0eTime2PageZeroing; }); 1330 return VINF_SUCCESS; 1331 } 1332 #endif 1315 1333 STAM_STATS({ pVCpu->pgmr0.s.pStatTrap0eAttributionR0 = &pVCpu->pgm.s.Stats.StatRZTrap0eTime2MakeWritable; }); 1316 1334 … … 1679 1697 } 1680 1698 # else 1681 NOREF(GCPhysPage);1699 NOREF(GCPhysPage); 1682 1700 # endif 1683 1684 STAM_PROFILE_START(&pVM->pgm.s.Stats.StatTrackDeref, a);1685 LogFlow(("SyncPageWorkerTrackDeref: Damn HCPhys=%RHp pShwPage->idx=%#x!!!\n", HCPhys, pShwPage->idx));1686 1701 1687 1702 /** @todo If this turns out to be a bottle neck (*very* likely) two things can be done: 1688 1703 * 1. have a medium sized HCPhys -> GCPhys TLB (hash?) 1689 1704 * 2. write protect all shadowed pages. I.e. implement caching. 1690 */ 1705 * 1706 * 2023-08-24 bird: If we allow the ZeroPg to enter the shadow page tables, 1707 * this becomes a common occurence and we screw up. A better to the above would 1708 * be to have a parallel table that records the guest physical addresses of the 1709 * pages mapped by the shadow page table... For nested page tables, 1710 * we can easily correleate a table entry to a page entry, so it won't be 1711 * needed for those. 1712 */ 1713 # if PGM_TYPE_IS_NESTED_OR_EPT(PGM_SHW_TYPE) || !PGM_WITH_PAGING(PGM_GST_TYPE, PGM_SHW_TYPE) 1714 /* 1715 * For non-paged guest tables, EPT and nested tables we can figure out the 1716 * physical page corresponding to the entry and dereference it. 1717 * (This ASSUMES that shadow PTs won't be used ever be used out of place.) 1718 */ 1719 if ( pShwPage->enmKind == PGMPOOLKIND_EPT_PT_FOR_PHYS 1720 || pShwPage->enmKind == PGMPOOLKIND_PAE_PT_FOR_PHYS 1721 || pShwPage->enmKind == PGMPOOLKIND_32BIT_PT_FOR_PHYS) 1722 { 1723 RTGCPHYS GCPhysNestedEntry = pShwPage->GCPhys + ((uint32_t)iPte << X86_PAGE_SHIFT); 1724 if (!pShwPage->fA20Enabled) 1725 GCPhysNestedEntry &= ~(uint64_t)RT_BIT_64(20); 1726 PPGMPAGE const pPhysPage = pgmPhysGetPage(pVM, GCPhysNestedEntry); 1727 AssertRelease(pPhysPage); 1728 pgmTrackDerefGCPhys(pVM->pgm.s.CTX_SUFF(pPool), pShwPage, pPhysPage, iPte); 1729 } 1730 else 1731 AssertMsgFailed(("enmKind=%d GCPhys=%RGp\n", pShwPage->enmKind, pShwPage->GCPhys)); 1732 # endif 1733 1691 1734 /** @todo duplicated in the 2nd half of pgmPoolTracDerefGCPhysHint */ 1692 1735 … … 1694 1737 * Find the guest address. 1695 1738 */ 1739 STAM_PROFILE_START(&pVM->pgm.s.Stats.StatTrackDeref, a); 1740 LogFlow(("SyncPageWorkerTrackDeref(%d,%d): Damn HCPhys=%RHp pShwPage->idx=%#x!!!\n", 1741 PGM_SHW_TYPE, PGM_GST_TYPE, HCPhys, pShwPage->idx)); 1696 1742 for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRangesX); 1697 1743 pRam; … … 1750 1796 1751 1797 /* write back */ 1752 Log2(("SyncPageWorkerTrackAddRef: u16=%#x->%#x iPTDst=%#x \n", u16, PGM_PAGE_GET_TRACKING(pPage), iPTDst));1798 Log2(("SyncPageWorkerTrackAddRef: u16=%#x->%#x iPTDst=%#x pPage=%p\n", u16, PGM_PAGE_GET_TRACKING(pPage), iPTDst, pPage)); 1753 1799 PGM_PAGE_SET_TRACKING(pVM, pPage, u16); 1754 1800 … … 2574 2620 if (SHW_PTE_IS_P(*pPte)) 2575 2621 { 2576 Log2((" SyncPageWorker: deref! *pPte=%RX64\n", SHW_PTE_LOG64(*pPte)));2622 Log2(("NestedSyncPageWorker: deref! *pPte=%RX64\n", SHW_PTE_LOG64(*pPte))); 2577 2623 PGM_BTH_NAME(SyncPageWorkerTrackDeref)(pVCpu, pShwPage, SHW_PTE_GET_HCPHYS(*pPte), iPte, NIL_RTGCPHYS); 2578 2624 } … … 2650 2696 else if (SHW_PTE_GET_HCPHYS(*pPte) != SHW_PTE_GET_HCPHYS(Pte)) 2651 2697 { 2652 Log2((" SyncPageWorker: deref! *pPte=%RX64 Pte=%RX64\n", SHW_PTE_LOG64(*pPte), SHW_PTE_LOG64(Pte)));2698 Log2(("NestedSyncPageWorker: deref! *pPte=%RX64 Pte=%RX64\n", SHW_PTE_LOG64(*pPte), SHW_PTE_LOG64(Pte))); 2653 2699 PGM_BTH_NAME(SyncPageWorkerTrackDeref)(pVCpu, pShwPage, SHW_PTE_GET_HCPHYS(*pPte), iPte, NIL_RTGCPHYS); 2654 2700 PGM_BTH_NAME(SyncPageWorkerTrackAddref)(pVCpu, pShwPage, PGM_PAGE_GET_TRACKING(pPage), pPage, iPte); … … 2657 2703 else if (SHW_PTE_IS_P(*pPte)) 2658 2704 { 2659 Log2((" SyncPageWorker: deref! *pPte=%RX64\n", SHW_PTE_LOG64(*pPte)));2705 Log2(("NestedSyncPageWorker: deref! *pPte=%RX64\n", SHW_PTE_LOG64(*pPte))); 2660 2706 PGM_BTH_NAME(SyncPageWorkerTrackDeref)(pVCpu, pShwPage, SHW_PTE_GET_HCPHYS(*pPte), iPte, NIL_RTGCPHYS); 2661 2707 } … … 3849 3895 } 3850 3896 } 3897 # if !defined(VBOX_WITH_NEW_LAZY_PAGE_ALLOC) && !defined(PGM_WITH_PAGE_ZEROING_DETECTION) /* This code is too aggresive! */ 3851 3898 else if ( PGMIsUsingLargePages(pVM) 3852 3899 && PGM_A20_IS_ENABLED(pVCpu)) … … 3862 3909 LogFlow(("pgmPhysAllocLargePage failed with %Rrc\n", rc)); 3863 3910 } 3911 # endif 3864 3912 3865 3913 if (HCPhys != NIL_RTHCPHYS) -
trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp
r100577 r100964 3750 3750 * will be needed for this problem of course, but it will have to wait... 3751 3751 */ 3752 # ifndef VBOX_WITH_NEW_LAZY_PAGE_ALLOC /* end up guruing after pgmR0PhysAllocateLargePage otherwise. */ 3752 3753 if ( PGM_PAGE_IS_ZERO(pPhysPage) 3753 3754 || PGM_PAGE_IS_BALLOONED(pPhysPage)) 3755 # else 3756 if (PGM_PAGE_IS_BALLOONED(pPhysPage)) 3757 # endif 3754 3758 rc = VINF_PGM_GCPHYS_ALIASED; 3755 3759 else
Note:
See TracChangeset
for help on using the changeset viewer.