VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstMMHyperHeap.cpp@ 93555

Last change on this file since 93555 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 9.4 KB
Line 
1/* $Id: tstMMHyperHeap.cpp 93554 2022-02-02 22:57:02Z vboxsync $ */
2/** @file
3 * MM Hypervisor Heap testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#include <VBox/vmm/mm.h>
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/ssm.h>
25#include <VBox/vmm/stam.h>
26#include <VBox/vmm/vm.h>
27#include <VBox/vmm/uvm.h>
28#include <VBox/vmm/gvm.h>
29#include <VBox/sup.h>
30#include <VBox/param.h>
31#include <iprt/errcore.h>
32
33#include <VBox/log.h>
34#include <iprt/initterm.h>
35#include <iprt/mem.h>
36#include <iprt/assert.h>
37#include <iprt/stream.h>
38#include <iprt/string.h>
39
40#define NUM_CPUS 16
41
42#define OUTPUT(a) do { Log(a); RTPrintf a; } while (0)
43
44/**
45 * Entry point.
46 */
47extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
48{
49 RT_NOREF1(envp);
50
51 /*
52 * Init runtime.
53 */
54 int rc = RTR3InitExe(argc, &argv, 0);
55 AssertRCReturn(rc, RTEXITCODE_INIT);
56
57 /*
58 * Create empty VM structure and call MMR3Init().
59 */
60 void *pvVM = NULL;
61 RTR0PTR pvR0 = NIL_RTR0PTR;
62 SUPPAGE aPages[(sizeof(GVM) + NUM_CPUS * sizeof(GVMCPU)) >> HOST_PAGE_SHIFT];
63 rc = SUPR3Init(NULL);
64 if (RT_FAILURE(rc))
65 {
66 RTPrintf("Fatal error: SUP failure! rc=%Rrc\n", rc);
67 return RTEXITCODE_FAILURE;
68 }
69 rc = SUPR3PageAllocEx(RT_ELEMENTS(aPages), 0, &pvVM, &pvR0, &aPages[0]);
70 if (RT_FAILURE(rc))
71 {
72 RTPrintf("Fatal error: Allocation failure! rc=%Rrc\n", rc);
73 return RTEXITCODE_FAILURE;
74 }
75 RT_BZERO(pvVM, RT_ELEMENTS(aPages) * HOST_PAGE_SIZE); /* SUPR3PageAllocEx doesn't necessarily zero the memory. */
76 PVM pVM = (PVM)pvVM;
77 pVM->paVMPagesR3 = aPages;
78 pVM->pVMR0ForCall = pvR0;
79
80 PUVM pUVM = (PUVM)RTMemPageAllocZ(RT_ALIGN_Z(sizeof(*pUVM), HOST_PAGE_SIZE));
81 if (!pUVM)
82 {
83 RTPrintf("Fatal error: RTMEmPageAllocZ failed\n");
84 return RTEXITCODE_FAILURE;
85 }
86 pUVM->u32Magic = UVM_MAGIC;
87 pUVM->pVM = pVM;
88 pVM->pUVM = pUVM;
89
90 pVM->cCpus = NUM_CPUS;
91 pVM->cbSelf = sizeof(VM);
92 pVM->cbVCpu = sizeof(VMCPU);
93 PVMCPU pVCpu = (PVMCPU)((uintptr_t)pVM + sizeof(GVM));
94 for (VMCPUID idCpu = 0; idCpu < NUM_CPUS; idCpu++)
95 {
96 pVM->apCpusR3[idCpu] = pVCpu;
97 pVCpu = (PVMCPU)((uintptr_t)pVCpu + sizeof(GVMCPU));
98 }
99
100 rc = STAMR3InitUVM(pUVM);
101 if (RT_FAILURE(rc))
102 {
103 RTPrintf("FAILURE: STAMR3Init failed. rc=%Rrc\n", rc);
104 return 1;
105 }
106
107 rc = MMR3InitUVM(pUVM);
108 if (RT_FAILURE(rc))
109 {
110 RTPrintf("FAILURE: STAMR3Init failed. rc=%Rrc\n", rc);
111 return 1;
112 }
113
114 rc = CFGMR3Init(pVM, NULL, NULL);
115 if (RT_FAILURE(rc))
116 {
117 RTPrintf("FAILURE: CFGMR3Init failed. rc=%Rrc\n", rc);
118 return 1;
119 }
120
121 rc = MMR3Init(pVM);
122 if (RT_FAILURE(rc))
123 {
124 RTPrintf("Fatal error: MMR3Init failed! rc=%Rrc\n", rc);
125 return 1;
126 }
127
128 /*
129 * Try allocate.
130 */
131 static struct
132 {
133 size_t cb;
134 unsigned uAlignment;
135 void *pvAlloc;
136 unsigned iFreeOrder;
137 } aOps[] =
138 {
139 { 16, 0, NULL, 0 },
140 { 16, 4, NULL, 1 },
141 { 16, 8, NULL, 2 },
142 { 16, 16, NULL, 5 },
143 { 16, 32, NULL, 4 },
144 { 32, 0, NULL, 3 },
145 { 31, 0, NULL, 6 },
146 { 1024, 0, NULL, 8 },
147 { 1024, 32, NULL, 10 },
148 { 1024, 32, NULL, 12 },
149 { GUEST_PAGE_SIZE, GUEST_PAGE_SIZE, NULL, 13 },
150 { 1024, 32, NULL, 9 },
151 { GUEST_PAGE_SIZE, 32, NULL, 11 },
152 { GUEST_PAGE_SIZE, GUEST_PAGE_SIZE, NULL, 14 },
153 { 16, 0, NULL, 15 },
154 { 9, 0, NULL, 7 },
155 { 16, 0, NULL, 7 },
156 { 36, 0, NULL, 7 },
157 { 16, 0, NULL, 7 },
158 { 12344, 0, NULL, 7 },
159 { 50, 0, NULL, 7 },
160 { 16, 0, NULL, 7 },
161 };
162 unsigned i;
163#ifdef DEBUG
164 MMHyperHeapDump(pVM);
165#endif
166 size_t cbBefore = MMHyperHeapGetFreeSize(pVM);
167 static char szFill[] = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
168
169 /* allocate */
170 for (i = 0; i < RT_ELEMENTS(aOps); i++)
171 {
172 rc = MMHyperAlloc(pVM, aOps[i].cb, aOps[i].uAlignment, MM_TAG_VM, &aOps[i].pvAlloc);
173 if (RT_FAILURE(rc))
174 {
175 RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %d i=%d\n", aOps[i].cb, aOps[i].uAlignment, rc, i);
176 return 1;
177 }
178 memset(aOps[i].pvAlloc, szFill[i], aOps[i].cb);
179 if (RT_ALIGN_P(aOps[i].pvAlloc, (aOps[i].uAlignment ? aOps[i].uAlignment : 8)) != aOps[i].pvAlloc)
180 {
181 RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %p, invalid alignment!\n", aOps[i].cb, aOps[i].uAlignment, aOps[i].pvAlloc);
182 return 1;
183 }
184 }
185
186 /* free and allocate the same node again. */
187#ifdef DEBUG
188 MMHyperHeapDump(pVM);
189#endif
190 for (i = 0; i < RT_ELEMENTS(aOps); i++)
191 {
192 if ( !aOps[i].pvAlloc
193 || aOps[i].uAlignment == GUEST_PAGE_SIZE)
194 continue;
195 size_t cbBeforeSub = MMHyperHeapGetFreeSize(pVM);
196 rc = MMHyperFree(pVM, aOps[i].pvAlloc);
197 if (RT_FAILURE(rc))
198 {
199 RTPrintf("Failure: MMHyperFree(, %p,) -> %d i=%d\n", aOps[i].pvAlloc, rc, i);
200 return 1;
201 }
202 size_t const cbFreed = MMHyperHeapGetFreeSize(pVM);
203 void *pv;
204 rc = MMHyperAlloc(pVM, aOps[i].cb, aOps[i].uAlignment, MM_TAG_VM_REQ, &pv);
205 if (RT_FAILURE(rc))
206 {
207 RTPrintf("Failure: MMHyperAlloc(, %#x, %#x,) -> %d i=%d\n", aOps[i].cb, aOps[i].uAlignment, rc, i);
208 return 1;
209 }
210 if (pv != aOps[i].pvAlloc)
211 {
212 RTPrintf("Failure: Free+Alloc returned different address. new=%p old=%p i=%d (doesn't work with delayed free)\n", pv, aOps[i].pvAlloc, i);
213 //return 1;
214 }
215 aOps[i].pvAlloc = pv;
216 OUTPUT(("debug: i=%02d cbBeforeSub=%d cbFreed=%d now=%d\n", i, cbBeforeSub, cbFreed, MMHyperHeapGetFreeSize(pVM)));
217#if 0 /* won't work :/ */
218 size_t cbAfterSub = MMHyperHeapGetFreeSize(pVM);
219 if (cbBeforeSub != cbAfterSub)
220 {
221 RTPrintf("Failure: cbBeforeSub=%d cbAfterSub=%d. i=%d\n", cbBeforeSub, cbAfterSub, i);
222 return 1;
223 }
224#endif
225 }
226
227 /* free it in a specific order. */
228 int cFreed = 0;
229 for (i = 0; i < RT_ELEMENTS(aOps); i++)
230 {
231 unsigned j;
232 for (j = 0; j < RT_ELEMENTS(aOps); j++)
233 {
234 if ( aOps[j].iFreeOrder != i
235 || !aOps[j].pvAlloc)
236 continue;
237 OUTPUT(("j=%02d i=%02d free=%d cb=%5u pv=%p\n", j, i, MMHyperHeapGetFreeSize(pVM), aOps[j].cb, aOps[j].pvAlloc));
238 if (aOps[j].uAlignment == GUEST_PAGE_SIZE)
239 cbBefore -= aOps[j].cb;
240 else
241 {
242 rc = MMHyperFree(pVM, aOps[j].pvAlloc);
243 if (RT_FAILURE(rc))
244 {
245 RTPrintf("Failure: MMHyperFree(, %p,) -> %d j=%d i=%d\n", aOps[j].pvAlloc, rc, i, j);
246 return 1;
247 }
248 }
249 aOps[j].pvAlloc = NULL;
250 cFreed++;
251 }
252 }
253 Assert(cFreed == RT_ELEMENTS(aOps));
254 OUTPUT(("i=done free=%d\n", MMHyperHeapGetFreeSize(pVM)));
255
256 /* check that we're back at the right amount of free memory. */
257 size_t cbAfter = MMHyperHeapGetFreeSize(pVM);
258 if (cbBefore != cbAfter)
259 {
260 OUTPUT(("Warning: Either we've split out an alignment chunk at the start, or we've got\n"
261 " an alloc/free accounting bug: cbBefore=%d cbAfter=%d\n", cbBefore, cbAfter));
262#ifdef DEBUG
263 MMHyperHeapDump(pVM);
264#endif
265 }
266
267 RTPrintf("tstMMHyperHeap: Success\n");
268#ifdef LOG_ENABLED
269 RTLogFlush(NULL);
270#endif
271 SSMR3Term(pVM);
272 STAMR3TermUVM(pUVM);
273 DBGFR3TermUVM(pUVM);
274 MMR3TermUVM(pUVM);
275 SUPR3PageFreeEx(pVM, RT_ELEMENTS(aPages));
276 RTMemPageFree(pUVM, RT_ALIGN_Z(sizeof(*pUVM), GUEST_PAGE_SIZE));
277 return 0;
278}
279
280
281#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
282/**
283 * Main entry point.
284 */
285int main(int argc, char **argv, char **envp)
286{
287 return TrustedMain(argc, argv, envp);
288}
289#endif
290
Note: See TracBrowser for help on using the repository browser.

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