VirtualBox

source: vbox/trunk/src/VBox/VMM/GMM.cpp@ 28800

Last change on this file since 28800 was 28800, checked in by vboxsync, 14 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.9 KB
Line 
1/* $Id: GMM.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * GMM - Global Memory Manager, ring-3 request wrappers.
4 */
5
6/*
7 * Copyright (C) 2008 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_GMM
23#include <VBox/gmm.h>
24#include <VBox/vmm.h>
25#include <VBox/vm.h>
26#include <VBox/sup.h>
27#include <VBox/err.h>
28#include <VBox/param.h>
29
30#include <iprt/assert.h>
31#include <VBox/log.h>
32#include <iprt/mem.h>
33#include <iprt/string.h>
34
35
36/**
37 * @see GMMR0InitialReservation
38 */
39GMMR3DECL(int) GMMR3InitialReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
40 GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority)
41{
42 GMMINITIALRESERVATIONREQ Req;
43 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
44 Req.Hdr.cbReq = sizeof(Req);
45 Req.cBasePages = cBasePages;
46 Req.cShadowPages = cShadowPages;
47 Req.cFixedPages = cFixedPages;
48 Req.enmPolicy = enmPolicy;
49 Req.enmPriority = enmPriority;
50 return VMMR3CallR0(pVM, VMMR0_DO_GMM_INITIAL_RESERVATION, 0, &Req.Hdr);
51}
52
53
54/**
55 * @see GMMR0UpdateReservation
56 */
57GMMR3DECL(int) GMMR3UpdateReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages)
58{
59 GMMUPDATERESERVATIONREQ Req;
60 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
61 Req.Hdr.cbReq = sizeof(Req);
62 Req.cBasePages = cBasePages;
63 Req.cShadowPages = cShadowPages;
64 Req.cFixedPages = cFixedPages;
65 return VMMR3CallR0(pVM, VMMR0_DO_GMM_UPDATE_RESERVATION, 0, &Req.Hdr);
66}
67
68
69/**
70 * Prepares a GMMR0AllocatePages request.
71 *
72 * @returns VINF_SUCCESS or VERR_NO_TMP_MEMORY.
73 * @param pVM Pointer to the shared VM structure.
74 * @param[out] ppReq Where to store the pointer to the request packet.
75 * @param cPages The number of pages that's to be allocated.
76 * @param enmAccount The account to charge.
77 */
78GMMR3DECL(int) GMMR3AllocatePagesPrepare(PVM pVM, PGMMALLOCATEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount)
79{
80 uint32_t cb = RT_OFFSETOF(GMMALLOCATEPAGESREQ, aPages[cPages]);
81 PGMMALLOCATEPAGESREQ pReq = (PGMMALLOCATEPAGESREQ)RTMemTmpAllocZ(cb);
82 if (!pReq)
83 return VERR_NO_TMP_MEMORY;
84
85 pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
86 pReq->Hdr.cbReq = cb;
87 pReq->enmAccount = enmAccount;
88 pReq->cPages = cPages;
89 NOREF(pVM);
90 *ppReq = pReq;
91 return VINF_SUCCESS;
92}
93
94
95/**
96 * Performs a GMMR0AllocatePages request.
97 * This will call VMSetError on failure.
98 *
99 * @returns VBox status code.
100 * @param pVM Pointer to the shared VM structure.
101 * @param pReq Pointer to the request (returned by GMMR3AllocatePagesPrepare).
102 */
103GMMR3DECL(int) GMMR3AllocatePagesPerform(PVM pVM, PGMMALLOCATEPAGESREQ pReq)
104{
105 for (unsigned i = 0; ; i++)
106 {
107 int rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_ALLOCATE_PAGES, 0, &pReq->Hdr);
108 if (RT_SUCCESS(rc))
109 {
110#ifdef LOG_ENABLED
111 for (uint32_t iPage = 0; iPage < pReq->cPages; iPage++)
112 Log3(("GMMR3AllocatePagesPerform: idPage=%#x HCPhys=%RHp\n",
113 pReq->aPages[iPage].idPage, pReq->aPages[iPage].HCPhysGCPhys));
114#endif
115 return rc;
116 }
117 if (rc != VERR_GMM_SEED_ME)
118 return VMSetError(pVM, rc, RT_SRC_POS,
119 N_("GMMR0AllocatePages failed to allocate %u pages"),
120 pReq->cPages);
121 Assert(i < pReq->cPages);
122
123 /*
124 * Seed another chunk.
125 */
126 void *pvChunk;
127 rc = SUPR3PageAlloc(GMM_CHUNK_SIZE >> PAGE_SHIFT, &pvChunk);
128 if (RT_FAILURE(rc))
129 return VMSetError(pVM, rc, RT_SRC_POS,
130 N_("Out of memory (SUPR3PageAlloc) seeding a %u pages allocation request"),
131 pReq->cPages);
132
133 rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_SEED_CHUNK, (uintptr_t)pvChunk, NULL);
134 if (RT_FAILURE(rc))
135 return VMSetError(pVM, rc, RT_SRC_POS, N_("GMM seeding failed"));
136 }
137}
138
139
140/**
141 * Cleans up a GMMR0AllocatePages request.
142 * @param pReq Pointer to the request (returned by GMMR3AllocatePagesPrepare).
143 */
144GMMR3DECL(void) GMMR3AllocatePagesCleanup(PGMMALLOCATEPAGESREQ pReq)
145{
146 RTMemTmpFree(pReq);
147}
148
149
150/**
151 * Prepares a GMMR0FreePages request.
152 *
153 * @returns VINF_SUCCESS or VERR_NO_TMP_MEMORY.
154 * @param pVM Pointer to the shared VM structure.
155 * @param[out] ppReq Where to store the pointer to the request packet.
156 * @param cPages The number of pages that's to be freed.
157 * @param enmAccount The account to charge.
158 */
159GMMR3DECL(int) GMMR3FreePagesPrepare(PVM pVM, PGMMFREEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount)
160{
161 uint32_t cb = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[cPages]);
162 PGMMFREEPAGESREQ pReq = (PGMMFREEPAGESREQ)RTMemTmpAllocZ(cb);
163 if (!pReq)
164 return VERR_NO_TMP_MEMORY;
165
166 pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
167 pReq->Hdr.cbReq = cb;
168 pReq->enmAccount = enmAccount;
169 pReq->cPages = cPages;
170 NOREF(pVM);
171 *ppReq = pReq;
172 return VINF_SUCCESS;
173}
174
175
176/**
177 * Re-prepares a GMMR0FreePages request.
178 *
179 * @returns VINF_SUCCESS or VERR_NO_TMP_MEMORY.
180 * @param pVM Pointer to the shared VM structure.
181 * @param pReq A request buffer previously returned by
182 * GMMR3FreePagesPrepare().
183 * @param cPages The number of pages originally passed to
184 * GMMR3FreePagesPrepare().
185 * @param enmAccount The account to charge.
186 */
187GMMR3DECL(void) GMMR3FreePagesRePrep(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cPages, GMMACCOUNT enmAccount)
188{
189 Assert(pReq->Hdr.u32Magic == SUPVMMR0REQHDR_MAGIC);
190 pReq->Hdr.cbReq = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[cPages]);
191 pReq->enmAccount = enmAccount;
192 pReq->cPages = cPages;
193 NOREF(pVM);
194}
195
196
197/**
198 * Performs a GMMR0FreePages request.
199 * This will call VMSetError on failure.
200 *
201 * @returns VBox status code.
202 * @param pVM Pointer to the shared VM structure.
203 * @param pReq Pointer to the request (returned by GMMR3FreePagesPrepare).
204 * @param cActualPages The number of pages actually freed.
205 */
206GMMR3DECL(int) GMMR3FreePagesPerform(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cActualPages)
207{
208 /*
209 * Adjust the request if we ended up with fewer pages than anticipated.
210 */
211 if (cActualPages != pReq->cPages)
212 {
213 AssertReturn(cActualPages < pReq->cPages, VERR_INTERNAL_ERROR);
214 if (!cActualPages)
215 return VINF_SUCCESS;
216 pReq->cPages = cActualPages;
217 pReq->Hdr.cbReq = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[cActualPages]);
218 }
219
220 /*
221 * Do the job.
222 */
223 int rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_FREE_PAGES, 0, &pReq->Hdr);
224 if (RT_SUCCESS(rc))
225 return rc;
226 AssertRC(rc);
227 return VMSetError(pVM, rc, RT_SRC_POS,
228 N_("GMMR0FreePages failed to free %u pages"),
229 pReq->cPages);
230}
231
232
233/**
234 * Cleans up a GMMR0FreePages request.
235 * @param pReq Pointer to the request (returned by GMMR3FreePagesPrepare).
236 */
237GMMR3DECL(void) GMMR3FreePagesCleanup(PGMMFREEPAGESREQ pReq)
238{
239 RTMemTmpFree(pReq);
240}
241
242
243/**
244 * Frees allocated pages, for bailing out on failure.
245 *
246 * This will not call VMSetError on failure but will use AssertLogRel instead.
247 *
248 * @param pVM Pointer to the shared VM structure.
249 * @param pAllocReq The allocation request to undo.
250 */
251GMMR3DECL(void) GMMR3FreeAllocatedPages(PVM pVM, GMMALLOCATEPAGESREQ const *pAllocReq)
252{
253 uint32_t cb = RT_OFFSETOF(GMMFREEPAGESREQ, aPages[pAllocReq->cPages]);
254 PGMMFREEPAGESREQ pReq = (PGMMFREEPAGESREQ)RTMemTmpAllocZ(cb);
255 AssertLogRelReturnVoid(pReq);
256
257 pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
258 pReq->Hdr.cbReq = cb;
259 pReq->enmAccount = pAllocReq->enmAccount;
260 pReq->cPages = pAllocReq->cPages;
261 uint32_t iPage = pAllocReq->cPages;
262 while (iPage-- > 0)
263 {
264 Assert(pAllocReq->aPages[iPage].idPage != NIL_GMM_PAGEID);
265 pReq->aPages[iPage].idPage = pAllocReq->aPages[iPage].idPage;
266 }
267
268 int rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_FREE_PAGES, 0, &pReq->Hdr);
269 AssertLogRelRC(rc);
270
271 RTMemTmpFree(pReq);
272}
273
274
275/**
276 * @see GMMR0BalloonedPages
277 */
278GMMR3DECL(int) GMMR3BalloonedPages(PVM pVM, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages)
279{
280 GMMBALLOONEDPAGESREQ Req;
281 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
282 Req.Hdr.cbReq = sizeof(Req);
283 Req.enmAction = enmAction;
284 Req.cBalloonedPages = cBalloonedPages;
285
286 return VMMR3CallR0(pVM, VMMR0_DO_GMM_BALLOONED_PAGES, 0, &Req.Hdr);
287}
288
289/**
290 * @see GMMR0QueryVMMMemoryStatsReq
291 */
292GMMR3DECL(int) GMMR3QueryVMMMemoryStats(PVM pVM, uint64_t *pcTotalAllocPages, uint64_t *pcTotalFreePages, uint64_t *pcTotalBalloonPages)
293{
294 GMMMEMSTATSREQ Req;
295 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
296 Req.Hdr.cbReq = sizeof(Req);
297 Req.cAllocPages = 0;
298 Req.cFreePages = 0;
299 Req.cBalloonedPages = 0;
300
301 *pcTotalAllocPages = 0;
302 *pcTotalFreePages = 0;
303 *pcTotalBalloonPages = 0;
304
305 /* Must be callable from any thread, so can't use VMMR3CallR0. */
306 int rc = SUPR3CallVMMR0Ex(pVM->pVMR0, 0, VMMR0_DO_GMM_QUERY_VMM_MEM_STATS, 0, &Req.Hdr);
307 if (rc == VINF_SUCCESS)
308 {
309 *pcTotalAllocPages = Req.cAllocPages;
310 *pcTotalFreePages = Req.cFreePages;
311 *pcTotalBalloonPages = Req.cBalloonedPages;
312 }
313 return rc;
314}
315
316/**
317 * @see GMMR0MapUnmapChunk
318 */
319GMMR3DECL(int) GMMR3MapUnmapChunk(PVM pVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3)
320{
321 GMMMAPUNMAPCHUNKREQ Req;
322 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
323 Req.Hdr.cbReq = sizeof(Req);
324 Req.idChunkMap = idChunkMap;
325 Req.idChunkUnmap = idChunkUnmap;
326 Req.pvR3 = NULL;
327 int rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_MAP_UNMAP_CHUNK, 0, &Req.Hdr);
328 if (RT_SUCCESS(rc) && ppvR3)
329 *ppvR3 = Req.pvR3;
330 return rc;
331}
332
333/**
334 * @see GMMR0FreeLargePage
335 */
336GMMR3DECL(int) GMMR3FreeLargePage(PVM pVM, uint32_t idPage)
337{
338 GMMFREELARGEPAGEREQ Req;
339 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
340 Req.Hdr.cbReq = sizeof(Req);
341 Req.idPage = idPage;
342 return VMMR3CallR0(pVM, VMMR0_DO_GMM_FREE_LARGE_PAGE, 0, &Req.Hdr);
343}
344
345/**
346 * @see GMMR0SeedChunk
347 */
348GMMR3DECL(int) GMMR3SeedChunk(PVM pVM, RTR3PTR pvR3)
349{
350 return VMMR3CallR0(pVM, VMMR0_DO_GMM_SEED_CHUNK, (uintptr_t)pvR3, NULL);
351}
352
353
354/**
355 * @see GMMR0RegisterSharedModule
356 */
357GMMR3DECL(int) GMMR3RegisterSharedModule(PVM pVM, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule,
358 unsigned cRegions, VMMDEVSHAREDREGIONDESC *pRegions)
359{
360 PGMMREGISTERSHAREDMODULEREQ pReq;
361 int rc;
362
363 /* Sanity check. */
364 AssertReturn(cRegions < VMMDEVSHAREDREGIONDESC_MAX, VERR_INVALID_PARAMETER);
365
366 pReq = (PGMMREGISTERSHAREDMODULEREQ)RTMemAllocZ(RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[cRegions]));
367 AssertReturn(pReq, VERR_NO_MEMORY);
368
369 pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
370 pReq->Hdr.cbReq = sizeof(*pReq);
371 pReq->GCBaseAddr = GCBaseAddr;
372 pReq->cbModule = cbModule;
373 pReq->cRegions = cRegions;
374 for (unsigned i = 0; i < cRegions; i++)
375 pReq->aRegions[i] = pRegions[i];
376
377 if ( RTStrCopy(pReq->szName, sizeof(pReq->szName), pszModuleName) != VINF_SUCCESS
378 || RTStrCopy(pReq->szVersion, sizeof(pReq->szVersion), pszVersion) != VINF_SUCCESS)
379 {
380 rc = VERR_BUFFER_OVERFLOW;
381 goto end;
382 }
383
384 rc = VMMR3CallR0(pVM, VMMR0_DO_GMM_REGISTER_SHARED_MODULE, 0, &pReq->Hdr);
385end:
386 RTMemFree(pReq);
387 return rc;
388}
389
390/**
391 * @see GMMR0RegisterSharedModule
392 */
393GMMR3DECL(int) GMMR3UnregisterSharedModule(PVM pVM, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule)
394{
395 GMMUNREGISTERSHAREDMODULEREQ Req;
396 Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
397 Req.Hdr.cbReq = sizeof(Req);
398
399 Req.GCBaseAddr = GCBaseAddr;
400 Req.cbModule = cbModule;
401
402 if ( RTStrCopy(Req.szName, sizeof(Req.szName), pszModuleName) != VINF_SUCCESS
403 || RTStrCopy(Req.szVersion, sizeof(Req.szVersion), pszVersion) != VINF_SUCCESS)
404 {
405 return VERR_BUFFER_OVERFLOW;
406 }
407
408 return VMMR3CallR0(pVM, VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE, 0, &Req.Hdr);
409}
410
411/**
412 * @see GMMR0CheckSharedModules
413 */
414GMMR3DECL(int) GMMR3CheckSharedModules(PVM pVM)
415{
416 return VMMR3CallR0(pVM, VMMR0_DO_GMM_CHECK_SHARED_MODULES, 0, NULL);
417}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use