VirtualBox

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

Last change on this file was 109050, checked in by vboxsync, 11 days ago

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