VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3-memalloc-1.c64@ 106683

Last change on this file since 106683 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: bs3-memalloc-1.c64 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * BS3Kit - bs3-timers-1, 64-bit C code.
4 */
5
6/*
7 * Copyright (C) 2021-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.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 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <bs3kit.h>
42#include <iprt/asm-amd64-x86.h>
43#include <VBox/VMMDevTesting.h>
44
45
46/*********************************************************************************************************************************
47* Global Variables *
48*********************************************************************************************************************************/
49/** Copy of interesting E820 entries. */
50static INT15E820ENTRY g_aEntries[16];
51/** Number of interesting entires. */
52static unsigned g_cEntries = 0;
53/** Number of intersting bytes found. */
54static uint64_t g_cbInteresting = 0;
55/** Lowest interesting address. */
56static uint64_t g_uInterestingStart = UINT64_MAX;
57/** End of interesting addresses. */
58static uint64_t g_uInterestingEnd = 0;
59
60
61/**
62 * For subsequence touch iterations that doesn't allocate any RAM.
63 *
64 * This may cause page pool activitiy if we've got more memory than we have room
65 * for in the pool. This depends on amount of guest RAM and how much could be
66 * backed by large pages.
67 */
68static uint64_t CheckTouchedMemory(void)
69{
70 unsigned iEntry;
71 uint64_t iPage = 0;
72 uint64_t cErrors = 0;
73 for (iEntry = 0; iEntry < g_cEntries; iEntry++)
74 {
75 uint64_t volatile *pu64Cur = (uint64_t *)g_aEntries[iEntry].uBaseAddr;
76 uint64_t cbLeft = g_aEntries[iEntry].cbRange;
77 while (cbLeft >= X86_PAGE_SIZE)
78 {
79 /* Check first. */
80 if (RT_LIKELY( pu64Cur[0] == iPage
81 && pu64Cur[1] == iPage))
82 { /* likely */ }
83 else
84 {
85 Bs3TestFailedF("%p: %#llx + %#llx, expected twice %#llx\n", pu64Cur, pu64Cur[0], pu64Cur[1], iPage);
86 cErrors++;
87 }
88
89 /* Then write again. */
90 pu64Cur[0] = iPage;
91 pu64Cur[1] = iPage;
92
93 /* Advance. */
94 iPage++;
95 pu64Cur += X86_PAGE_SIZE / sizeof(*pu64Cur);
96 cbLeft -= X86_PAGE_SIZE;
97 }
98 }
99 return cErrors;
100}
101
102
103/**
104 * First touching of memory, assuming content is ZERO.
105 */
106static uint64_t FirstTouchMemory(void)
107{
108 unsigned iEntry;
109 uint64_t iPage = 0;
110 for (iEntry = 0; iEntry < g_cEntries; iEntry++)
111 {
112 uint64_t volatile *pu64Cur = (uint64_t volatile *)g_aEntries[iEntry].uBaseAddr;
113 uint64_t cbLeft = g_aEntries[iEntry].cbRange;
114 while (cbLeft >= X86_PAGE_SIZE)
115 {
116 /*
117 * Write to the page first so we won't waste time mapping the zero
118 * page and get straight to the actual page allocation.
119 */
120 pu64Cur[0] = iPage;
121
122 /* Then check that the 2nd qword is zero before writing it. */
123 if (RT_LIKELY(pu64Cur[1] == 0))
124 { /* likely */ }
125 else
126 Bs3TestFailedF("%p: %#llx, expected zero\n", pu64Cur, pu64Cur[1]);
127 pu64Cur[1] = iPage;
128
129 /* Advance. */
130 iPage++;
131 pu64Cur += X86_PAGE_SIZE / sizeof(*pu64Cur);
132 cbLeft -= X86_PAGE_SIZE;
133 }
134 }
135 return iPage;
136}
137
138
139/**
140 * Translates a E820 entry type to a string.
141 */
142static const char *getEntryTypeName(uint32_t uType)
143{
144 switch (uType)
145 {
146 case INT15E820_TYPE_USABLE: return "USABLE";
147 case INT15E820_TYPE_RESERVED: return "RESERVED";
148 case INT15E820_TYPE_ACPI_RECLAIMABLE: return "ACPI_RECLAIMABLE";
149 case INT15E820_TYPE_ACPI_NVS: return "ACPI_NVS";
150 case INT15E820_TYPE_BAD: return "BAD";
151 default: return "unknown";
152 }
153}
154
155BS3_DECL(void) Main_lm64()
156{
157 uint32_t uCont;
158 unsigned i;
159
160 Bs3TestInit("bs3-memalloc-1");
161
162 /*
163 * Get the E820 memory descriptors and pick out those describing memory not
164 * already used by the Bs3Kit.
165 */
166 Bs3TestSub("INT15h/E820");
167 for (uCont = i = 0; i < 2048; i++)
168 {
169 uint32_t const uEbxCur = uCont;
170 INT15E820ENTRY Entry = { 0, 0, 0, 0 };
171 uint32_t cbEntry = sizeof(Entry);
172 if (!Bs3BiosInt15hE820_lm64(&Entry, &cbEntry, &uCont))
173 {
174 Bs3TestFailedF("int15h/E820 failed i=%u", i);
175 break;
176 }
177 Bs3TestPrintf("#%u/%#x: %#018llx LB %#018llx %s (%d)\n",
178 i, uEbxCur, Entry.uBaseAddr, Entry.cbRange, getEntryTypeName(Entry.uType), Entry.uType);
179 if (Entry.uType == INT15E820_TYPE_USABLE)
180 {
181 if (Entry.uBaseAddr >= _4G)
182 {
183 if (g_cEntries < RT_ELEMENTS(g_aEntries))
184 {
185 g_cbInteresting += Entry.cbRange;
186 if (g_uInterestingStart > Entry.uBaseAddr)
187 g_uInterestingStart = Entry.uBaseAddr;
188 if (g_uInterestingEnd < Entry.uBaseAddr + Entry.cbRange)
189 g_uInterestingEnd = Entry.uBaseAddr + Entry.cbRange;
190 Bs3MemCpy(&g_aEntries[g_cEntries++], &Entry, sizeof(Entry));
191 }
192 else
193 Bs3TestFailedF("Too many interesting E820 entries! Extend g_aEntries!\n");
194 }
195 }
196
197 /* Done? */
198 if (uCont == 0)
199 break;
200 }
201 if (g_cEntries == 0)
202 Bs3TestFailedF("No interesting E820 entries! Make sure you've assigned more than 4GB to the VM!\n");
203 else
204 {
205 uint64_t uFailurePoint = 0;
206 int rc;
207 Bs3TestPrintf("Found %u interesting entries covering %#llx bytes (%u GB).\n"
208 "From %#llx to %#llx\n",
209 g_cEntries, g_cbInteresting, (unsigned)(g_cbInteresting / _1G), g_uInterestingStart, g_uInterestingEnd);
210
211 if (g_uBs3EndOfRamAbove4G < g_uInterestingEnd)
212 Bs3TestFailedF("g_uBs3EndOfRamAbove4G (%#llx) is lower than g_uInterestingEnd (%#llx)!\n",
213 g_uBs3EndOfRamAbove4G, g_uInterestingEnd);
214
215
216 /*
217 * Map all the memory (Bs3Kit only maps memory below 4G).
218 */
219 Bs3TestSub("Mapping memory above 4GB");
220 if (!(g_uBs3CpuDetected & BS3CPU_F_PSE))
221 Bs3TestFailedF("PSE was not detected!\n");
222 else if (!(ASMGetCR4() & X86_CR4_PSE))
223 Bs3TestFailedF("PSE was not enabled!\n");
224 else if (RT_SUCCESS(rc = Bs3PagingMapRamAbove4GForLM(&uFailurePoint)))
225 {
226#define PAGES_2_MB(a_cPages) ((a_cPages) / (_1M / X86_PAGE_SIZE))
227 uint64_t cTotalPages;
228 unsigned iLoop;
229
230 /*
231 * Time touching all the memory.
232 */
233 Bs3TestSub("Allocation speed");
234 {
235 uint64_t const nsStart = Bs3TestNow();
236 uint64_t const uTscStart = ASMReadTSC();
237 uint64_t const cPages = FirstTouchMemory();
238 uint64_t const cTicksElapsed = ASMReadTSC() - uTscStart;
239 uint64_t const cNsElapsed = Bs3TestNow() - nsStart;
240 uint64_t uThruput;
241 Bs3TestValue("Pages", cPages, VMMDEV_TESTING_UNIT_PAGES);
242 Bs3TestValue("MiBs", PAGES_2_MB(cPages), VMMDEV_TESTING_UNIT_MEGABYTES);
243 Bs3TestValue("Alloc elapsed", cNsElapsed, VMMDEV_TESTING_UNIT_NS);
244 Bs3TestValue("Alloc elapsed in ticks", cTicksElapsed, VMMDEV_TESTING_UNIT_TICKS);
245 Bs3TestValue("Page alloc time", cNsElapsed / cPages, VMMDEV_TESTING_UNIT_NS_PER_PAGE);
246 Bs3TestValue("Page alloc time in ticks", cTicksElapsed / cPages, VMMDEV_TESTING_UNIT_TICKS_PER_PAGE);
247 uThruput = cPages * RT_NS_1SEC / cNsElapsed;
248 Bs3TestValue("Alloc thruput", uThruput, VMMDEV_TESTING_UNIT_PAGES_PER_SEC);
249 Bs3TestValue("Alloc thruput in MiBs", PAGES_2_MB(uThruput), VMMDEV_TESTING_UNIT_MEGABYTES_PER_SEC);
250 cTotalPages = cPages;
251 }
252
253 /*
254 * Time accessing all the memory again. This might give a clue as to page pool performance.
255 */
256 for (iLoop = 0; iLoop < 2; iLoop++)
257 {
258 Bs3TestSub(iLoop == 0 ? "2nd access" : "3rd access");
259 {
260 uint64_t const nsStart = Bs3TestNow();
261 uint64_t const uTscStart = ASMReadTSC();
262 uint64_t const cErrors = CheckTouchedMemory();
263 uint64_t const cTicksElapsed = ASMReadTSC() - uTscStart;
264 uint64_t const cNsElapsed = Bs3TestNow() - nsStart;
265 uint64_t uThruput;
266 Bs3TestValue("Access elapsed", cNsElapsed, VMMDEV_TESTING_UNIT_NS);
267 Bs3TestValue("Access elapsed in ticks", cTicksElapsed, VMMDEV_TESTING_UNIT_TICKS);
268 Bs3TestValue("Page access time", cNsElapsed / cTotalPages, VMMDEV_TESTING_UNIT_NS_PER_PAGE);
269 Bs3TestValue("Page access time in ticks", cTicksElapsed / cTotalPages, VMMDEV_TESTING_UNIT_TICKS_PER_PAGE);
270 uThruput = cTotalPages * RT_NS_1SEC / cNsElapsed;
271 Bs3TestValue("Access thruput", uThruput, VMMDEV_TESTING_UNIT_PAGES_PER_SEC);
272 Bs3TestValue("Access thruput in MiBs", PAGES_2_MB(uThruput), VMMDEV_TESTING_UNIT_MEGABYTES_PER_SEC);
273 }
274 }
275 }
276 else
277 Bs3TestFailedF("Bs3PagingMapRamAbove4GForLM failed at %#llx: %d", uFailurePoint, rc);
278 }
279
280 Bs3TestTerm();
281}
282
Note: See TracBrowser for help on using the repository browser.

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