VirtualBox

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

Last change on this file since 109036 was 109036, checked in by vboxsync, 4 weeks ago

VMM/cpus: First sampling of Snapdragon X Elite. jiraref:VBP-1598

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