VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp

Last change on this file was 109151, checked in by vboxsync, 2 days ago

VMM/cpus: Added M3 Max details. jiraref:VBP-1653

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.2 KB
Line 
1/* $Id: CPUMR3Db.cpp 109151 2025-05-05 11:58:18Z vboxsync $ */
2/** @file
3 * CPUM - CPU database part.
4 */
5
6/*
7 * Copyright (C) 2013-2025 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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_CPUM
33#include <VBox/vmm/cpum.h>
34#include "CPUMInternal.h"
35#include <VBox/vmm/vm.h>
36#include <VBox/vmm/mm.h>
37
38#include <VBox/err.h>
39#if defined(VBOX_VMM_TARGET_ARMV8) || defined(RT_ARCH_ARM64)
40# include <iprt/armv8.h>
41#endif
42#if !defined(RT_ARCH_ARM64)
43# include <iprt/asm-amd64-x86.h>
44#endif
45#include <iprt/mem.h>
46#include <iprt/string.h>
47
48
49/*********************************************************************************************************************************
50* Internal Functions *
51*********************************************************************************************************************************/
52static int cpumDbPopulateInfoFromEntry(PCPUMINFO pInfo, PCCPUMDBENTRY pEntryCore, bool fHost);
53
54
55/*********************************************************************************************************************************
56* Defined Constants And Macros *
57*********************************************************************************************************************************/
58/** @def NULL_ALONE
59 * For eliminating an unnecessary data dependency in standalone builds (for
60 * VBoxSVC). */
61/** @def ZERO_ALONE
62 * For eliminating an unnecessary data size dependency in standalone builds (for
63 * VBoxSVC). */
64#ifndef CPUM_DB_STANDALONE
65# define NULL_ALONE(a_aTable) a_aTable
66# define ZERO_ALONE(a_cTable) a_cTable
67#else
68# define NULL_ALONE(a_aTable) NULL
69# define ZERO_ALONE(a_cTable) 0
70#endif
71
72
73/*********************************************************************************************************************************
74* Global Variables *
75*********************************************************************************************************************************/
76/*
77 * Include the X86 profiles.
78 */
79#if defined(VBOX_VMM_TARGET_X86)
80
81# include "CPUMR3Msr-x86.h" /* MSR macros needed by the profiles. */
82
83# include "cpus/Intel_Core_i7_6700K.h"
84# include "cpus/Intel_Core_i7_5600U.h"
85# include "cpus/Intel_Core_i7_3960X.h"
86# include "cpus/Intel_Core_i5_3570.h"
87# include "cpus/Intel_Core_i7_2635QM.h"
88# include "cpus/Intel_Xeon_X5482_3_20GHz.h"
89# include "cpus/Intel_Core2_X6800_2_93GHz.h"
90# include "cpus/Intel_Core2_T7600_2_33GHz.h"
91# include "cpus/Intel_Core_Duo_T2600_2_16GHz.h"
92# include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
93# include "cpus/Intel_Pentium_4_3_00GHz.h"
94# include "cpus/Intel_Pentium_N3530_2_16GHz.h"
95# include "cpus/Intel_Atom_330_1_60GHz.h"
96# include "cpus/Intel_80486.h"
97# include "cpus/Intel_80386.h"
98# include "cpus/Intel_80286.h"
99# include "cpus/Intel_80186.h"
100# include "cpus/Intel_8086.h"
101
102# include "cpus/AMD_Ryzen_7_1800X_Eight_Core.h"
103# include "cpus/AMD_FX_8150_Eight_Core.h"
104# include "cpus/AMD_Phenom_II_X6_1100T.h"
105# include "cpus/Quad_Core_AMD_Opteron_2384.h"
106# include "cpus/AMD_Athlon_64_X2_Dual_Core_4200.h"
107# include "cpus/AMD_Athlon_64_3200.h"
108
109# include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
110
111# include "cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h"
112
113# include "cpus/Hygon_C86_7185_32_core.h"
114
115#endif /* VBOX_VMM_TARGET_X86 */
116
117
118/*
119 * Include the ARM profiles.
120 *
121 * Note! We include these when on ARM64 hosts regardless of the VMM target, so
122 * we can get more info about the host CPU.
123 */
124#if defined(VBOX_VMM_TARGET_ARMV8) || defined(RT_ARCH_ARM64)
125
126# include "cpus/ARM_Apple_M1.h"
127# include "cpus/ARM_Apple_M2_Max.h"
128# include "cpus/ARM_Apple_M3_Max.h"
129# include "cpus/ARM_Qualcomm_Snapdragon_X.h"
130
131#endif
132
133
134/**
135 * The database entries.
136 *
137 * 1. The first entry is special. It is the fallback for unknown
138 * processors. Thus, it better be pretty representative.
139 *
140 * 2. The first entry for a CPU vendor is likewise important as it is
141 * the default entry for that vendor.
142 *
143 * Generally we put the most recent CPUs first, since these tend to have the
144 * most complicated and backwards compatible list of MSRs.
145 */
146static CPUMDBENTRY const * const g_apCpumDbEntries[] =
147{
148#if defined(VBOX_VMM_TARGET_X86)
149 /*
150 * X86 profiles:
151 */
152# ifdef VBOX_CPUDB_Intel_Core_i7_6700K_h
153 &g_Entry_Intel_Core_i7_6700K.Core,
154# endif
155# ifdef VBOX_CPUDB_Intel_Core_i7_5600U_h
156 &g_Entry_Intel_Core_i7_5600U.Core,
157# endif
158# ifdef VBOX_CPUDB_Intel_Core_i5_3570_h
159 &g_Entry_Intel_Core_i5_3570.Core,
160# endif
161# ifdef VBOX_CPUDB_Intel_Core_i7_3960X_h
162 &g_Entry_Intel_Core_i7_3960X.Core,
163# endif
164# ifdef VBOX_CPUDB_Intel_Core_i7_2635QM_h
165 &g_Entry_Intel_Core_i7_2635QM.Core,
166# endif
167# ifdef VBOX_CPUDB_Intel_Pentium_N3530_2_16GHz_h
168 &g_Entry_Intel_Pentium_N3530_2_16GHz.Core,
169# endif
170# ifdef VBOX_CPUDB_Intel_Atom_330_1_60GHz_h
171 &g_Entry_Intel_Atom_330_1_60GHz.Core,
172# endif
173# ifdef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz_h
174 &g_Entry_Intel_Pentium_M_processor_2_00GHz.Core,
175# endif
176# ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz_h
177 &g_Entry_Intel_Xeon_X5482_3_20GHz.Core,
178# endif
179# ifdef VBOX_CPUDB_Intel_Core2_X6800_2_93GHz_h
180 &g_Entry_Intel_Core2_X6800_2_93GHz.Core,
181# endif
182# ifdef VBOX_CPUDB_Intel_Core2_T7600_2_33GHz_h
183 &g_Entry_Intel_Core2_T7600_2_33GHz.Core,
184# endif
185# ifdef VBOX_CPUDB_Intel_Core_Duo_T2600_2_16GHz_h
186 &g_Entry_Intel_Core_Duo_T2600_2_16GHz.Core,
187# endif
188# ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz_h
189 &g_Entry_Intel_Pentium_4_3_00GHz.Core,
190# endif
191/** @todo pentium, pentium mmx, pentium pro, pentium II, pentium III */
192# ifdef VBOX_CPUDB_Intel_80486_h
193 &g_Entry_Intel_80486.Core,
194# endif
195# ifdef VBOX_CPUDB_Intel_80386_h
196 &g_Entry_Intel_80386.Core,
197# endif
198# ifdef VBOX_CPUDB_Intel_80286_h
199 &g_Entry_Intel_80286.Core,
200# endif
201# ifdef VBOX_CPUDB_Intel_80186_h
202 &g_Entry_Intel_80186.Core,
203# endif
204# ifdef VBOX_CPUDB_Intel_8086_h
205 &g_Entry_Intel_8086.Core,
206# endif
207
208# ifdef VBOX_CPUDB_AMD_Ryzen_7_1800X_Eight_Core_h
209 &g_Entry_AMD_Ryzen_7_1800X_Eight_Core.Core,
210# endif
211# ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core_h
212 &g_Entry_AMD_FX_8150_Eight_Core.Core,
213# endif
214# ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T_h
215 &g_Entry_AMD_Phenom_II_X6_1100T.Core,
216# endif
217# ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384_h
218 &g_Entry_Quad_Core_AMD_Opteron_2384.Core,
219# endif
220# ifdef VBOX_CPUDB_AMD_Athlon_64_X2_Dual_Core_4200_h
221 &g_Entry_AMD_Athlon_64_X2_Dual_Core_4200.Core,
222# endif
223# ifdef VBOX_CPUDB_AMD_Athlon_64_3200_h
224 &g_Entry_AMD_Athlon_64_3200.Core,
225# endif
226
227# ifdef VBOX_CPUDB_ZHAOXIN_KaiXian_KX_U5581_1_8GHz_h
228 &g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz.Core,
229# endif
230
231# ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz_h
232 &g_Entry_VIA_QuadCore_L4700_1_2_GHz.Core,
233# endif
234
235# ifdef VBOX_CPUDB_NEC_V20_h
236 &g_Entry_NEC_V20.Core,
237# endif
238
239# ifdef VBOX_CPUDB_Hygon_C86_7185_32_core_h
240 &g_Entry_Hygon_C86_7185_32_core.Core,
241# endif
242#endif /* VBOX_VMM_TARGET_X86 */
243
244#if defined(VBOX_VMM_TARGET_ARMV8) || defined(RT_ARCH_ARM64)
245 /*
246 * ARM profiles:
247 */
248 &g_Entry_ARM_Apple_M1.Core,
249 &g_Entry_ARM_Apple_M2_Max.Core,
250 &g_Entry_ARM_Apple_M3_Max.Core,
251 &g_Entry_ARM_Qualcomm_Snapdragon_X.Core,
252#endif /* VBOX_VMM_TARGET_ARMV8 || RT_ARCH_ARM64 */
253};
254
255
256/**
257 * Returns the number of entries in the CPU database.
258 *
259 * @returns Number of entries.
260 * @sa PFNCPUMDBGETENTRIES
261 */
262VMMR3DECL(uint32_t) CPUMR3DbGetEntries(void)
263{
264 return RT_ELEMENTS(g_apCpumDbEntries);
265}
266
267
268/**
269 * Returns CPU database entry for the given index.
270 *
271 * @returns Pointer the CPU database entry, NULL if index is out of bounds.
272 * @param idxCpuDb The index (0..CPUMR3DbGetEntries).
273 * @sa PFNCPUMDBGETENTRYBYINDEX
274 */
275VMMR3DECL(PCCPUMDBENTRY) CPUMR3DbGetEntryByIndex(uint32_t idxCpuDb)
276{
277 AssertReturn(idxCpuDb < RT_ELEMENTS(g_apCpumDbEntries), NULL);
278 return g_apCpumDbEntries[idxCpuDb];
279}
280
281
282/**
283 * Returns CPU database entry with the given name.
284 *
285 * @returns Pointer the CPU database entry, NULL if not found.
286 * @param pszName The name of the profile to return.
287 * @sa PFNCPUMDBGETENTRYBYNAME
288 */
289VMMR3DECL(PCCPUMDBENTRY) CPUMR3DbGetEntryByName(const char *pszName)
290{
291 AssertPtrReturn(pszName, NULL);
292 AssertReturn(*pszName, NULL);
293 for (size_t i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
294 if (strcmp(g_apCpumDbEntries[i]->pszName, pszName) == 0)
295 return g_apCpumDbEntries[i];
296 return NULL;
297}
298
299#if defined(VBOX_VMM_TARGET_X86) && (defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64))
300
301/**
302 * Do we consider @a enmConsider a better match for @a enmTarget than
303 * @a enmFound?
304 *
305 * Only called when @a enmConsider isn't exactly what we're looking for.
306 *
307 * @returns true/false.
308 * @param enmConsider The new microarch to consider.
309 * @param enmTarget The target microarch.
310 * @param enmFound The best microarch match we've found thus far.
311 */
312DECLINLINE(bool) cpumR3DbIsBetterMarchMatch(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
313{
314 Assert(enmConsider != enmTarget);
315
316 /*
317 * If we've got an march match, don't bother with enmConsider.
318 */
319 if (enmFound == enmTarget)
320 return false;
321
322 /*
323 * Found is below: Pick 'consider' if it's closer to the target or above it.
324 */
325 if (enmFound < enmTarget)
326 return enmConsider > enmFound;
327
328 /*
329 * Found is above: Pick 'consider' if it's also above (paranoia: or equal)
330 * and but closer to the target.
331 */
332 return enmConsider >= enmTarget && enmConsider < enmFound;
333}
334
335
336/**
337 * Do we consider @a enmConsider a better match for @a enmTarget than
338 * @a enmFound?
339 *
340 * Only called for intel family 06h CPUs.
341 *
342 * @returns true/false.
343 * @param enmConsider The new microarch to consider.
344 * @param enmTarget The target microarch.
345 * @param enmFound The best microarch match we've found thus far.
346 */
347static bool cpumR3DbIsBetterIntelFam06Match(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
348{
349 /* Check intel family 06h claims. */
350 AssertReturn(enmConsider >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmConsider <= kCpumMicroarch_Intel_P6_Core_Atom_End,
351 false);
352 AssertReturn( (enmTarget >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmTarget <= kCpumMicroarch_Intel_P6_Core_Atom_End)
353 || enmTarget == kCpumMicroarch_Intel_Unknown,
354 false);
355
356 /* Put matches out of the way. */
357 if (enmConsider == enmTarget)
358 return true;
359 if (enmFound == enmTarget)
360 return false;
361
362 /* If found isn't a family 06h march, whatever we're considering must be a better choice. */
363 if ( enmFound < kCpumMicroarch_Intel_P6_Core_Atom_First
364 || enmFound > kCpumMicroarch_Intel_P6_Core_Atom_End)
365 return true;
366
367 /*
368 * The family 06h stuff is split into three categories:
369 * - Common P6 heritage
370 * - Core
371 * - Atom
372 *
373 * Determin which of the three arguments are Atom marchs, because that's
374 * all we need to make the right choice.
375 */
376 bool const fConsiderAtom = enmConsider >= kCpumMicroarch_Intel_Atom_First;
377 bool const fTargetAtom = enmTarget >= kCpumMicroarch_Intel_Atom_First;
378 bool const fFoundAtom = enmFound >= kCpumMicroarch_Intel_Atom_First;
379
380 /*
381 * Want atom:
382 */
383 if (fTargetAtom)
384 {
385 /* Pick the atom if we've got one of each.*/
386 if (fConsiderAtom != fFoundAtom)
387 return fConsiderAtom;
388 /* If we haven't got any atoms under consideration, pick a P6 or the earlier core.
389 Note! Not entirely sure Dothan is the best choice, but it'll do for now. */
390 if (!fConsiderAtom)
391 {
392 if (enmConsider > enmFound)
393 return enmConsider <= kCpumMicroarch_Intel_P6_M_Dothan;
394 return enmFound > kCpumMicroarch_Intel_P6_M_Dothan;
395 }
396 /* else: same category, default comparison rules. */
397 Assert(fConsiderAtom && fFoundAtom);
398 }
399 /*
400 * Want non-atom:
401 */
402 /* Pick the non-atom if we've got one of each. */
403 else if (fConsiderAtom != fFoundAtom)
404 return fFoundAtom;
405 /* If we've only got atoms under consideration, pick the older one just to pick something. */
406 else if (fConsiderAtom)
407 return enmConsider < enmFound;
408 else
409 Assert(!fConsiderAtom && !fFoundAtom);
410
411 /*
412 * Same basic category. Do same compare as caller.
413 */
414 return cpumR3DbIsBetterMarchMatch(enmConsider, enmTarget, enmFound);
415}
416
417
418/**
419 * X86 version of helper that picks a DB entry for the host and merges it with
420 * available info in the @a pInfo structure.
421 */
422static int cpumR3DbCreateHostEntry(PCPUMINFO pInfo)
423{
424 /*
425 * Create a CPU database entry for the host CPU. This means getting
426 * the CPUID bits from the real CPU and grabbing the closest matching
427 * database entry for MSRs.
428 */
429 int rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
430 if (RT_FAILURE(rc))
431 return rc;
432 rc = CPUMCpuIdCollectLeavesFromX86Host(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
433 if (RT_FAILURE(rc))
434 return rc;
435 pInfo->fMxCsrMask = CPUMR3DeterminHostMxCsrMask();
436
437 /* Lookup database entry for MSRs. */
438 CPUMCPUVENDOR const enmVendor = CPUMCpuIdDetectX86VendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
439 pInfo->paCpuIdLeavesR3[0].uEbx,
440 pInfo->paCpuIdLeavesR3[0].uEcx,
441 pInfo->paCpuIdLeavesR3[0].uEdx);
442 uint32_t const uStd1Eax = pInfo->paCpuIdLeavesR3[1].uEax;
443 uint8_t const uFamily = RTX86GetCpuFamily(uStd1Eax);
444 uint8_t const uModel = RTX86GetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
445 uint8_t const uStepping = RTX86GetCpuStepping(uStd1Eax);
446 CPUMMICROARCH const enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor, uFamily, uModel, uStepping);
447
448 PCCPUMDBENTRYX86 pEntry = NULL;
449 for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
450 {
451 CPUMDBENTRY const * const pCurCore = g_apCpumDbEntries[i];
452 if ( (CPUMCPUVENDOR)pCurCore->enmVendor == enmVendor
453 && pCurCore->enmEntryType == CPUMDBENTRYTYPE_X86)
454 {
455 CPUMDBENTRYX86 const * const pCur = (CPUMDBENTRYX86 const *)pCurCore;
456
457 /* Match against Family, Microarch, model and stepping. Except
458 for family, always match the closer with preference given to
459 the later/older ones. */
460 if (pCur->uFamily == uFamily)
461 {
462 if (pCur->Core.enmMicroarch == enmMicroarch)
463 {
464 if (pCur->uModel == uModel)
465 {
466 if (pCur->uStepping == uStepping)
467 {
468 /* Perfect match. */
469 pEntry = pCur;
470 break;
471 }
472
473 if ( !pEntry
474 || pEntry->uModel != uModel
475 || pEntry->Core.enmMicroarch != enmMicroarch
476 || pEntry->uFamily != uFamily)
477 pEntry = pCur;
478 else if ( pCur->uStepping >= uStepping
479 ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
480 : pCur->uStepping > pEntry->uStepping)
481 pEntry = pCur;
482 }
483 else if ( !pEntry
484 || pEntry->Core.enmMicroarch != enmMicroarch
485 || pEntry->uFamily != uFamily)
486 pEntry = pCur;
487 else if ( pCur->uModel >= uModel
488 ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
489 : pCur->uModel > pEntry->uModel)
490 pEntry = pCur;
491 }
492 else if ( !pEntry
493 || pEntry->uFamily != uFamily)
494 pEntry = pCur;
495 /* Special march matching rules applies to intel family 06h. */
496 else if ( enmVendor == CPUMCPUVENDOR_INTEL
497 && uFamily == 6
498 ? cpumR3DbIsBetterIntelFam06Match(pCur->Core.enmMicroarch, enmMicroarch, pEntry->Core.enmMicroarch)
499 : cpumR3DbIsBetterMarchMatch(pCur->Core.enmMicroarch, enmMicroarch, pEntry->Core.enmMicroarch))
500 pEntry = pCur;
501 }
502 /* We don't do closeness matching on family, we use the first
503 entry for the CPU vendor instead. (P4 workaround.) */
504 else if (!pEntry)
505 pEntry = pCur;
506 }
507 }
508
509 if (pEntry)
510 LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
511 CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
512 pEntry->Core.pszName, CPUMCpuVendorName(pEntry->Core.enmVendor), pEntry->uFamily, pEntry->uModel,
513 pEntry->uStepping, CPUMMicroarchName(pEntry->Core.enmMicroarch) ));
514 else
515 {
516 pEntry = (CPUMDBENTRYX86 const *)g_apCpumDbEntries[0];
517 LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
518 CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
519 pEntry->Core.pszName));
520 }
521
522 return cpumDbPopulateInfoFromEntry(pInfo, &pEntry->Core, true /*fHost*/);
523}
524
525#endif /* VBOX_VMM_TARGET_X86 && (RT_ARCH_AMD64 || RT_ARCH_X86) */
526
527
528/**
529 * Helper that populates the CPUMINFO structure from DB entry.
530 */
531static int cpumDbPopulateInfoFromEntry(PCPUMINFO pInfo, PCCPUMDBENTRY pEntryCore, bool fHost)
532{
533#ifdef VBOX_VMM_TARGET_X86
534 /*
535 * X86.
536 */
537 AssertReturn(pEntryCore->enmEntryType == CPUMDBENTRYTYPE_X86, VERR_INTERNAL_ERROR_3);
538 PCCPUMDBENTRYX86 const pEntry = (PCCPUMDBENTRYX86)pEntryCore;
539
540 if (!fHost)
541 {
542 /*
543 * The CPUID tables needs to be copied onto the heap so the caller can
544 * modify them and so they can be freed like in the host case.
545 */
546 pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
547 if (pEntry->cCpuIdLeaves)
548 {
549 /* Must allocate a multiple of 16 here, matching cpumR3CpuIdEnsureSpace. */
550 size_t cbExtra = sizeof(pEntry->paCpuIdLeaves[0]) * (RT_ALIGN(pEntry->cCpuIdLeaves, 16) - pEntry->cCpuIdLeaves);
551 pInfo->paCpuIdLeavesR3 = (PCPUMCPUIDLEAF)RTMemDupEx(pEntry->paCpuIdLeaves,
552 sizeof(pEntry->paCpuIdLeaves[0]) * pEntry->cCpuIdLeaves,
553 cbExtra);
554 if (!pInfo->paCpuIdLeavesR3)
555 return VERR_NO_MEMORY;
556 }
557 else
558 pInfo->paCpuIdLeavesR3 = NULL;
559
560 pInfo->enmUnknownCpuIdMethod = pEntry->enmUnknownCpuId;
561 pInfo->DefCpuId = pEntry->DefUnknownCpuId;
562 pInfo->fMxCsrMask = pEntry->fMxCsrMask;
563
564 LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
565 pEntry->Core.pszName, CPUMCpuVendorName(pEntry->Core.enmVendor),
566 pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMMicroarchName(pEntry->Core.enmMicroarch) ));
567 }
568
569 pInfo->fMsrMask = pEntry->fMsrMask;
570 pInfo->iFirstExtCpuIdLeaf = 0; /* Set by caller. */
571 pInfo->uScalableBusFreq = pEntry->uScalableBusFreq;
572
573 /*
574 * Copy the MSR range.
575 */
576 uint32_t cMsrs = 0;
577 PCPUMMSRRANGE paMsrs = NULL;
578
579 PCCPUMMSRRANGE pCurMsr = pEntry->paMsrRanges;
580 uint32_t cLeft = pEntry->cMsrRanges;
581 while (cLeft-- > 0)
582 {
583 int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
584 if (RT_FAILURE(rc))
585 {
586 Assert(!paMsrs); /* The above function frees this. */
587 RTMemFree(pInfo->paCpuIdLeavesR3);
588 pInfo->paCpuIdLeavesR3 = NULL;
589 return rc;
590 }
591 pCurMsr++;
592 }
593
594 pInfo->paMsrRangesR3 = paMsrs;
595 pInfo->cMsrRanges = cMsrs;
596
597#elif defined(VBOX_VMM_TARGET_ARMV8)
598 /*
599 * ARM.
600 */
601 AssertReturn(pEntryCore->enmEntryType == CPUMDBENTRYTYPE_ARM, VERR_INTERNAL_ERROR_3);
602 PCCPUMDBENTRYARM const pEntry = (PCCPUMDBENTRYARM)pEntryCore;
603 RT_NOREF(pInfo, pEntry, fHost);
604
605#else
606# error "port me"
607#endif
608 return VINF_SUCCESS;
609}
610
611
612int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
613{
614#ifdef VBOX_VMM_TARGET_X86
615 CPUMDBENTRYTYPE const enmEntryType = CPUMDBENTRYTYPE_X86;
616#elif defined(VBOX_VMM_TARGET_ARMV8)
617 CPUMDBENTRYTYPE const enmEntryType = CPUMDBENTRYTYPE_ARM;
618#else
619# error "port me"
620#endif
621
622 /*
623 * Deal with the dynamic 'host' entry first.
624 *
625 * If we're not on a matchin host, we just pick the first entry in the
626 * table and proceed as if this was specified by the caller (configured).
627 */
628 if (!strcmp(pszName, "host"))
629 {
630#if (defined(VBOX_VMM_TARGET_X86) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))) \
631 || (defined(VBOX_VMM_TARGET_ARMV8) && defined(RT_ARCH_ARM64) && 0)
632 return cpumR3DbCreateHostEntry(pInfo);
633#else
634 Assert(g_apCpumDbEntries[0]->enmEntryType == enmEntryType);
635 pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */
636#endif
637 }
638
639 /*
640 * We're supposed to be emulating a specific CPU from the database.
641 */
642 for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
643 if ( g_apCpumDbEntries[i]->enmEntryType == enmEntryType
644 && !strcmp(pszName, g_apCpumDbEntries[i]->pszName))
645 return cpumDbPopulateInfoFromEntry(pInfo, g_apCpumDbEntries[i], false /*fHost*/);
646 LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
647 return VERR_CPUM_DB_CPU_NOT_FOUND;
648}
649
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