VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PGMR0Pool.cpp@ 108379

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

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 設為 Author Date Id Revision
檔案大小: 8.6 KB
 
1/* $Id: PGMR0Pool.cpp 108132 2025-02-10 11:05:23Z vboxsync $ */
2/** @file
3 * PGM Shadow Page Pool, ring-0 specific bits.
4 */
5
6/*
7 * Copyright (C) 2006-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_POOL
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/hm.h>
37#include "PGMInternal.h"
38#include <VBox/vmm/vmcc.h>
39#include "PGMInline.h"
40
41#include <VBox/log.h>
42#include <VBox/err.h>
43#include <iprt/mem.h>
44#include <iprt/memobj.h>
45
46
47/**
48 * Called by PGMR0InitVM to complete the page pool setup for ring-0.
49 *
50 * @returns VBox status code.
51 * @param pGVM Pointer to the global VM structure.
52 */
53int pgmR0PoolInitVM(PGVM pGVM)
54{
55 PPGMPOOL pPool = pGVM->pgm.s.pPoolR0;
56 AssertPtrReturn(pPool, VERR_PGM_POOL_IPE);
57
58 int rc = PGMR0HandlerPhysicalTypeSetUpContext(pGVM, PGMPHYSHANDLERKIND_WRITE, PGMPHYSHANDLER_F_KEEP_PGM_LOCK,
59 pgmPoolAccessHandler, pgmRZPoolAccessPfHandler,
60 "Guest Paging Access Handler", pPool->hAccessHandlerType);
61 AssertLogRelRCReturn(rc, rc);
62
63 return VINF_SUCCESS;
64}
65
66
67/**
68 * Worker for PGMR0PoolGrow.
69 */
70static int pgmR0PoolGrowInner(PGVM pGVM, PPGMPOOL pPool)
71{
72 int rc;
73
74 /* With 32-bit guests and no EPT, the CR3 limits the root pages to low
75 (below 4 GB) memory. */
76 /** @todo change the pool to handle ROOT page allocations specially when
77 * required. */
78 bool const fCanUseHighMemory = HMIsNestedPagingActive(pGVM);
79
80 /*
81 * Figure out how many pages should allocate.
82 */
83 uint32_t const cMaxPages = RT_MIN(pPool->cMaxPages, PGMPOOL_IDX_LAST);
84 uint32_t const cCurPages = RT_MIN(pPool->cCurPages, cMaxPages);
85 if (cCurPages < cMaxPages)
86 {
87 uint32_t cNewPages = cMaxPages - cCurPages;
88 if (cNewPages > PGMPOOL_CFG_MAX_GROW)
89 cNewPages = PGMPOOL_CFG_MAX_GROW;
90 LogFlow(("PGMR0PoolGrow: Growing the pool by %u (%#x) pages to %u (%#x) pages. fCanUseHighMemory=%RTbool\n",
91 cNewPages, cNewPages, cCurPages + cNewPages, cCurPages + cNewPages, fCanUseHighMemory));
92
93 /* Check that the handles in the arrays entry are both NIL. */
94 uintptr_t const idxMemHandle = cCurPages / (PGMPOOL_CFG_MAX_GROW);
95 AssertCompile( (PGMPOOL_IDX_LAST + (PGMPOOL_CFG_MAX_GROW - 1)) / PGMPOOL_CFG_MAX_GROW
96 <= RT_ELEMENTS(pGVM->pgmr0.s.ahPoolMemObjs));
97 AssertCompile(RT_ELEMENTS(pGVM->pgmr0.s.ahPoolMemObjs) == RT_ELEMENTS(pGVM->pgmr0.s.ahPoolMapObjs));
98 AssertLogRelMsgReturn( pGVM->pgmr0.s.ahPoolMemObjs[idxMemHandle] == NIL_RTR0MEMOBJ
99 && pGVM->pgmr0.s.ahPoolMapObjs[idxMemHandle] == NIL_RTR0MEMOBJ, ("idxMemHandle=%#x\n", idxMemHandle),
100 VERR_PGM_POOL_IPE);
101
102 /*
103 * Allocate the new pages and map them into ring-3.
104 */
105 RTR0MEMOBJ hMemObj = NIL_RTR0MEMOBJ;
106 if (fCanUseHighMemory)
107 rc = RTR0MemObjAllocPage(&hMemObj, cNewPages * HOST_PAGE_SIZE, false /*fExecutable*/);
108 else
109 rc = RTR0MemObjAllocLow(&hMemObj, cNewPages * HOST_PAGE_SIZE, false /*fExecutable*/);
110 if (RT_SUCCESS(rc))
111 {
112 RTR0MEMOBJ hMapObj = NIL_RTR0MEMOBJ;
113 rc = RTR0MemObjMapUser(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, NIL_RTR0PROCESS);
114 if (RT_SUCCESS(rc))
115 {
116 pGVM->pgmr0.s.ahPoolMemObjs[idxMemHandle] = hMemObj;
117 pGVM->pgmr0.s.ahPoolMapObjs[idxMemHandle] = hMapObj;
118
119 uint8_t *pbRing0 = (uint8_t *)RTR0MemObjAddress(hMemObj);
120 RTR3PTR pbRing3 = RTR0MemObjAddressR3(hMapObj);
121 AssertPtr(pbRing0);
122 Assert(((uintptr_t)pbRing0 & HOST_PAGE_OFFSET_MASK) == 0);
123 Assert(pbRing3 != NIL_RTR3PTR);
124 Assert((pbRing3 & HOST_PAGE_OFFSET_MASK) == 0);
125
126 /*
127 * Initialize the new pages.
128 */
129 for (unsigned iNewPage = 0; iNewPage < cNewPages; iNewPage++)
130 {
131 PPGMPOOLPAGE pPage = &pPool->aPages[cCurPages + iNewPage];
132 pPage->pvPageR0 = &pbRing0[iNewPage * HOST_PAGE_SIZE];
133 pPage->pvPageR3 = pbRing3 + iNewPage * HOST_PAGE_SIZE;
134 pPage->Core.Key = RTR0MemObjGetPagePhysAddr(hMemObj, iNewPage);
135 AssertFatal(pPage->Core.Key < _4G || fCanUseHighMemory);
136 pPage->GCPhys = NIL_RTGCPHYS;
137 pPage->enmKind = PGMPOOLKIND_FREE;
138 pPage->idx = pPage - &pPool->aPages[0];
139 LogFlow(("PGMR0PoolGrow: insert page #%#x - %RHp\n", pPage->idx, pPage->Core.Key));
140 pPage->iNext = pPool->iFreeHead;
141 pPage->iUserHead = NIL_PGMPOOL_USER_INDEX;
142 pPage->iModifiedNext = NIL_PGMPOOL_IDX;
143 pPage->iModifiedPrev = NIL_PGMPOOL_IDX;
144 pPage->iMonitoredNext = NIL_PGMPOOL_IDX;
145 pPage->iMonitoredPrev = NIL_PGMPOOL_IDX;
146 pPage->iAgeNext = NIL_PGMPOOL_IDX;
147 pPage->iAgePrev = NIL_PGMPOOL_IDX;
148 /* commit it */
149 bool fRc = RTAvloHCPhysInsert(&pPool->HCPhysTree, &pPage->Core); Assert(fRc); NOREF(fRc);
150 pPool->iFreeHead = cCurPages + iNewPage;
151 pPool->cCurPages = cCurPages + iNewPage + 1;
152 }
153
154 return VINF_SUCCESS;
155 }
156
157 RTR0MemObjFree(hMemObj, true /*fFreeMappings*/);
158 }
159 if (cCurPages > 64)
160 LogRelMax(5, ("PGMR0PoolGrow: rc=%Rrc cNewPages=%#x cCurPages=%#x cMaxPages=%#x fCanUseHighMemory=%d\n",
161 rc, cNewPages, cCurPages, cMaxPages, fCanUseHighMemory));
162 else
163 LogRel(("PGMR0PoolGrow: rc=%Rrc cNewPages=%#x cCurPages=%#x cMaxPages=%#x fCanUseHighMemory=%d\n",
164 rc, cNewPages, cCurPages, cMaxPages, fCanUseHighMemory));
165 }
166 else
167 rc = VINF_SUCCESS;
168 return rc;
169}
170
171
172/**
173 * Grows the shadow page pool.
174 *
175 * I.e. adds more pages to it, assuming that hasn't reached cMaxPages yet.
176 *
177 * @returns VBox status code.
178 * @param pGVM The ring-0 VM structure.
179 * @param idCpu The ID of the calling EMT.
180 * @thread EMT(idCpu)
181 */
182VMMR0_INT_DECL(int) PGMR0PoolGrow(PGVM pGVM, VMCPUID idCpu)
183{
184 /*
185 * Validate input.
186 */
187 PPGMPOOL pPool = pGVM->pgm.s.pPoolR0;
188 AssertReturn(pPool->cCurPages < pPool->cMaxPages, VERR_PGM_POOL_MAXED_OUT_ALREADY);
189 AssertReturn(pPool->pVMR3 == pGVM->pVMR3, VERR_PGM_POOL_IPE);
190 AssertReturn(pPool->pVMR0 == pGVM, VERR_PGM_POOL_IPE);
191
192 AssertReturn(idCpu < pGVM->cCpus, VERR_VM_THREAD_NOT_EMT);
193 PGVMCPU const pGVCpu = &pGVM->aCpus[idCpu];
194
195 /*
196 * Enter the grow critical section and call worker.
197 */
198 STAM_REL_PROFILE_START(&pPool->StatGrow, a);
199
200 VMMR0EMTBLOCKCTX Ctx;
201 int rc = VMMR0EmtPrepareToBlock(pGVCpu, VINF_SUCCESS, __FUNCTION__, &pGVM->pgmr0.s.PoolGrowCritSect, &Ctx);
202 AssertRCReturn(rc, rc);
203
204 rc = RTCritSectEnter(&pGVM->pgmr0.s.PoolGrowCritSect);
205 AssertRCReturn(rc, rc);
206
207 rc = pgmR0PoolGrowInner(pGVM, pPool);
208
209 STAM_REL_PROFILE_STOP(&pPool->StatGrow, a);
210 RTCritSectLeave(&pGVM->pgmr0.s.PoolGrowCritSect);
211
212 VMMR0EmtResumeAfterBlocking(pGVCpu, &Ctx);
213 return rc;
214}
215
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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