VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp

最後變更 在這個檔案是 108132,由 vboxsync 提交於 5 週 前

VMM/PGM: Merge and deduplicate code targeting x86 & amd64 in PGM.cpp. Don't bother compiling pool stuff on arm and darwin.amd64. jiraref:VBP-1531

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 7.8 KB
 
1/* $Id: PGMR0SharedPage.cpp 108132 2025-02-10 11:05:23Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, Page Sharing, Ring-0.
4 */
5
6/*
7 * Copyright (C) 2010-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_PGM_SHARED
33#define VBOX_WITHOUT_PAGING_BIT_FIELDS /* 64-bit bitfields are just asking for trouble. See @bugref{9841} and others. */
34#define VBOX_VMM_TARGET_X86
35#include <VBox/vmm/pgm.h>
36#include <VBox/vmm/iem.h>
37#include <VBox/vmm/gmm.h>
38#include "PGMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/gvm.h>
41#include "PGMInline.h"
42#include <VBox/log.h>
43#include <VBox/err.h>
44#include <iprt/assert.h>
45#include <iprt/mem.h>
46
47
48#ifdef VBOX_WITH_PAGE_SHARING
49/**
50 * Check a registered module for shared page changes.
51 *
52 * The PGM lock shall be taken prior to calling this method.
53 *
54 * @returns The following VBox status codes.
55 *
56 * @param pVM The cross context VM structure.
57 * @param pGVM Pointer to the GVM instance data.
58 * @param idCpu The ID of the calling virtual CPU.
59 * @param pModule Global module description.
60 * @param paRegionsGCPtrs Array parallel to pModules->aRegions with the
61 * addresses of the regions in the calling
62 * process.
63 */
64VMMR0DECL(int) PGMR0SharedModuleCheck(PVMCC pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PCRTGCPTR64 paRegionsGCPtrs)
65{
66 PVMCPUCC pVCpu = &pGVM->aCpus[idCpu];
67 int rc = VINF_SUCCESS;
68 bool fFlushTLBs = false;
69 bool fFlushRemTLBs = false;
70 GMMSHAREDPAGEDESC PageDesc;
71
72 Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
73
74 PGM_LOCK_ASSERT_OWNER(pVM); /* This cannot fail as we grab the lock in pgmR3SharedModuleRegRendezvous before calling into ring-0. */
75
76 /*
77 * Check every region of the shared module.
78 */
79 for (uint32_t idxRegion = 0; idxRegion < pModule->cRegions; idxRegion++)
80 {
81 RTGCPTR GCPtrPage = paRegionsGCPtrs[idxRegion] & ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK;
82 uint32_t cbLeft = pModule->aRegions[idxRegion].cb; Assert(!(cbLeft & GUEST_PAGE_OFFSET_MASK));
83 uint32_t idxPage = 0;
84
85 while (cbLeft)
86 {
87 /** @todo inefficient to fetch each guest page like this... */
88 PGMPTWALK Walk;
89 rc = PGMGstGetPage(pVCpu, GCPtrPage, &Walk);
90 if ( rc == VINF_SUCCESS
91 && !(Walk.fEffective & X86_PTE_RW)) /* important as we make assumptions about this below! */
92 {
93 PPGMPAGE pPage = pgmPhysGetPage(pVM, Walk.GCPhys);
94 Assert(!pPage || !PGM_PAGE_IS_BALLOONED(pPage));
95 if ( pPage
96 && PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED
97 && PGM_PAGE_GET_READ_LOCKS(pPage) == 0
98 && PGM_PAGE_GET_WRITE_LOCKS(pPage) == 0 )
99 {
100 PageDesc.idPage = PGM_PAGE_GET_PAGEID(pPage);
101 PageDesc.HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
102 PageDesc.GCPhys = Walk.GCPhys;
103
104 rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc);
105 if (RT_FAILURE(rc))
106 break;
107
108 /*
109 * Any change for this page?
110 */
111 if (PageDesc.idPage != NIL_GMM_PAGEID)
112 {
113 Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
114
115 Log(("PGMR0SharedModuleCheck: shared page gst virt=%RGv phys=%RGp host %RHp->%RHp\n",
116 GCPtrPage, PageDesc.GCPhys, PGM_PAGE_GET_HCPHYS(pPage), PageDesc.HCPhys));
117
118 /* Page was either replaced by an existing shared
119 version of it or converted into a read-only shared
120 page, so, clear all references. */
121 bool fFlush = false;
122 rc = pgmPoolTrackUpdateGCPhys(pVM, PageDesc.GCPhys, pPage, true /* clear the entries */, &fFlush);
123 Assert( rc == VINF_SUCCESS
124 || ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3)
125 && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
126 if (rc == VINF_SUCCESS)
127 fFlushTLBs |= fFlush;
128 fFlushRemTLBs = true;
129
130 if (PageDesc.HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
131 {
132 /* Update the physical address and page id now. */
133 PGM_PAGE_SET_HCPHYS(pVM, pPage, PageDesc.HCPhys);
134 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.idPage);
135
136 /* Invalidate page map TLB entry for this page too. */
137 pgmPhysInvalidatePageMapTLBEntry(pVM, PageDesc.GCPhys);
138 IEMTlbInvalidateAllPhysicalAllCpus(pVM, NIL_VMCPUID, IEMTLBPHYSFLUSHREASON_SHARED);
139 pVM->pgm.s.cReusedSharedPages++;
140 }
141 /* else: nothing changed (== this page is now a shared
142 page), so no need to flush anything. */
143
144 pVM->pgm.s.cSharedPages++;
145 pVM->pgm.s.cPrivatePages--;
146 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_SHARED);
147
148# ifdef VBOX_STRICT /* check sum hack */
149 pPage->s.u2Unused0 = PageDesc.u32StrictChecksum & 3;
150 //pPage->s.u2Unused1 = (PageDesc.u32StrictChecksum >> 8) & 3;
151# endif
152 }
153 }
154 }
155 else
156 {
157 Assert( rc == VINF_SUCCESS
158 || rc == VERR_PAGE_NOT_PRESENT
159 || rc == VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
160 || rc == VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
161 || rc == VERR_PAGE_TABLE_NOT_PRESENT);
162 rc = VINF_SUCCESS; /* ignore error */
163 }
164
165 idxPage++;
166 GCPtrPage += HOST_PAGE_SIZE;
167 cbLeft -= HOST_PAGE_SIZE;
168 }
169 }
170
171 /*
172 * Do TLB flushing if necessary.
173 */
174 if (fFlushTLBs)
175 PGM_INVL_ALL_VCPU_TLBS(pVM);
176
177 if (fFlushRemTLBs)
178 for (VMCPUID idCurCpu = 0; idCurCpu < pGVM->cCpus; idCurCpu++)
179 CPUMSetChangedFlags(&pGVM->aCpus[idCurCpu], CPUM_CHANGED_GLOBAL_TLB_FLUSH);
180
181 return rc;
182}
183#endif /* VBOX_WITH_PAGE_SHARING */
184
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette