VirtualBox

source: vbox/trunk/src/VBox/VMM/tools/VBoxCpuReport.cpp@ 94884

Last change on this file since 94884 was 93515, checked in by vboxsync, 3 years ago

iprt/asm-amd64-x86.h: Split out some non-assembly functions that related more to x86.h than to asm.h, changing the function prefix from ASM to RTX86. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 229.8 KB
Line 
1/* $Id: VBoxCpuReport.cpp 93515 2022-01-31 22:17:19Z vboxsync $ */
2/** @file
3 * VBoxCpuReport - Produces the basis for a CPU DB entry.
4 */
5
6/*
7 * Copyright (C) 2013-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 <iprt/asm.h>
23#include <iprt/asm-amd64-x86.h>
24#include <iprt/buildconfig.h>
25#include <iprt/ctype.h>
26#include <iprt/file.h>
27#include <iprt/getopt.h>
28#include <iprt/initterm.h>
29#include <iprt/message.h>
30#include <iprt/mem.h>
31#include <iprt/path.h>
32#include <iprt/string.h>
33#include <iprt/stream.h>
34#include <iprt/symlink.h>
35#include <iprt/thread.h>
36#include <iprt/time.h>
37
38#include <VBox/err.h>
39#include <VBox/vmm/cpum.h>
40#include <VBox/sup.h>
41
42#include "VBoxCpuReport.h"
43
44
45/*********************************************************************************************************************************
46* Structures and Typedefs *
47*********************************************************************************************************************************/
48/** Write only register. */
49#define VBCPUREPMSR_F_WRITE_ONLY RT_BIT(0)
50
51typedef struct VBCPUREPMSR
52{
53 /** The first MSR register number. */
54 uint32_t uMsr;
55 /** Flags (MSRREPORT_F_XXX). */
56 uint32_t fFlags;
57 /** The value we read, unless write-only. */
58 uint64_t uValue;
59} VBCPUREPMSR;
60
61
62/*********************************************************************************************************************************
63* Global Variables *
64*********************************************************************************************************************************/
65/** The CPU vendor. Used by the MSR code. */
66static CPUMCPUVENDOR g_enmVendor = CPUMCPUVENDOR_INVALID;
67/** The CPU microarchitecture. Used by the MSR code. */
68static CPUMMICROARCH g_enmMicroarch = kCpumMicroarch_Invalid;
69/** Set if g_enmMicroarch indicates an Intel NetBurst CPU. */
70static bool g_fIntelNetBurst = false;
71/** The alternative report stream. */
72static PRTSTREAM g_pReportOut;
73/** The alternative debug stream. */
74static PRTSTREAM g_pDebugOut;
75/** Whether to skip MSR collection. */
76static bool g_fNoMsrs = false;
77
78/** Snooping info storage for vbCpuRepGuessScalableBusFrequencyName. */
79static uint64_t g_uMsrIntelP6FsbFrequency = UINT64_MAX;
80
81/** The MSR accessors interface. */
82static VBCPUREPMSRACCESSORS g_MsrAcc;
83
84
85
86void vbCpuRepDebug(const char *pszMsg, ...)
87{
88 va_list va;
89
90 /* Always print a copy of the report to standard error. */
91 va_start(va, pszMsg);
92 RTStrmPrintfV(g_pStdErr, pszMsg, va);
93 va_end(va);
94 RTStrmFlush(g_pStdErr);
95
96 /* Alternatively, also print to a log file. */
97 if (g_pDebugOut)
98 {
99 va_start(va, pszMsg);
100 RTStrmPrintfV(g_pDebugOut, pszMsg, va);
101 va_end(va);
102 RTStrmFlush(g_pDebugOut);
103 }
104
105 /* Give the output device a chance to write / display it. */
106 RTThreadSleep(1);
107}
108
109
110void vbCpuRepPrintf(const char *pszMsg, ...)
111{
112 va_list va;
113
114 /* Output to report file, if requested. */
115 if (g_pReportOut)
116 {
117 va_start(va, pszMsg);
118 RTStrmPrintfV(g_pReportOut, pszMsg, va);
119 va_end(va);
120 RTStrmFlush(g_pReportOut);
121 }
122
123 /* Always print a copy of the report to standard out. */
124 va_start(va, pszMsg);
125 RTStrmPrintfV(g_pStdOut, pszMsg, va);
126 va_end(va);
127 RTStrmFlush(g_pStdOut);
128}
129
130
131
132static int vbCpuRepMsrsAddOne(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs,
133 uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
134{
135 /*
136 * Grow the array?
137 */
138 uint32_t cMsrs = *pcMsrs;
139 if ((cMsrs % 64) == 0)
140 {
141 void *pvNew = RTMemRealloc(*ppaMsrs, (cMsrs + 64) * sizeof(**ppaMsrs));
142 if (!pvNew)
143 {
144 RTMemFree(*ppaMsrs);
145 *ppaMsrs = NULL;
146 *pcMsrs = 0;
147 return VERR_NO_MEMORY;
148 }
149 *ppaMsrs = (VBCPUREPMSR *)pvNew;
150 }
151
152 /*
153 * Add it.
154 */
155 VBCPUREPMSR *pEntry = *ppaMsrs + cMsrs;
156 pEntry->uMsr = uMsr;
157 pEntry->fFlags = fFlags;
158 pEntry->uValue = uValue;
159 *pcMsrs = cMsrs + 1;
160
161 return VINF_SUCCESS;
162}
163
164
165/**
166 * Returns the max physical address width as a number of bits.
167 *
168 * @returns Bit count.
169 */
170static uint8_t vbCpuRepGetPhysAddrWidth(void)
171{
172 uint8_t cMaxWidth;
173 if (!ASMHasCpuId())
174 cMaxWidth = 32;
175 else
176 {
177 uint32_t cMaxExt = ASMCpuId_EAX(0x80000000);
178 if (RTX86IsValidExtRange(cMaxExt)&& cMaxExt >= 0x80000008)
179 cMaxWidth = ASMCpuId_EAX(0x80000008) & 0xff;
180 else if ( RTX86IsValidStdRange(ASMCpuId_EAX(0))
181 && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PSE36))
182 cMaxWidth = 36;
183 else
184 cMaxWidth = 32;
185 }
186 return cMaxWidth;
187}
188
189
190static bool vbCpuRepSupportsPae(void)
191{
192 return ASMHasCpuId()
193 && RTX86IsValidStdRange(ASMCpuId_EAX(0))
194 && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PAE);
195}
196
197
198static bool vbCpuRepSupportsLongMode(void)
199{
200 return ASMHasCpuId()
201 && RTX86IsValidExtRange(ASMCpuId_EAX(0x80000000))
202 && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
203}
204
205
206static bool vbCpuRepSupportsNX(void)
207{
208 return ASMHasCpuId()
209 && RTX86IsValidExtRange(ASMCpuId_EAX(0x80000000))
210 && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_NX);
211}
212
213
214static bool vbCpuRepSupportsX2Apic(void)
215{
216 return ASMHasCpuId()
217 && RTX86IsValidStdRange(ASMCpuId_EAX(0))
218 && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_X2APIC);
219}
220
221
222
223#if 0 /* unused */
224static bool msrProberWrite(uint32_t uMsr, uint64_t uValue)
225{
226 bool fGp;
227 int rc = g_MsrAcc.pfnMsrWrite(uMsr, NIL_RTCPUID, uValue, &fGp);
228 AssertRC(rc);
229 return RT_SUCCESS(rc) && !fGp;
230}
231#endif
232
233
234static bool msrProberRead(uint32_t uMsr, uint64_t *puValue)
235{
236 *puValue = 0;
237 bool fGp;
238 int rc = g_MsrAcc.pfnMsrProberRead(uMsr, NIL_RTCPUID, puValue, &fGp);
239 AssertRC(rc);
240 return RT_SUCCESS(rc) && !fGp;
241}
242
243
244/** Tries to modify the register by writing the original value to it. */
245static bool msrProberModifyNoChange(uint32_t uMsr)
246{
247 SUPMSRPROBERMODIFYRESULT Result;
248 int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, UINT64_MAX, 0, &Result);
249 return RT_SUCCESS(rc)
250 && !Result.fBeforeGp
251 && !Result.fModifyGp
252 && !Result.fAfterGp
253 && !Result.fRestoreGp;
254}
255
256
257/** Tries to modify the register by writing zero to it. */
258static bool msrProberModifyZero(uint32_t uMsr)
259{
260 SUPMSRPROBERMODIFYRESULT Result;
261 int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, 0, 0, &Result);
262 return RT_SUCCESS(rc)
263 && !Result.fBeforeGp
264 && !Result.fModifyGp
265 && !Result.fAfterGp
266 && !Result.fRestoreGp;
267}
268
269
270/**
271 * Tries to modify each bit in the MSR and see if we can make it change.
272 *
273 * @returns VBox status code.
274 * @param uMsr The MSR.
275 * @param pfIgnMask The ignore mask to update.
276 * @param pfGpMask The GP mask to update.
277 * @param fSkipMask Mask of bits to skip.
278 */
279static int msrProberModifyBitChanges(uint32_t uMsr, uint64_t *pfIgnMask, uint64_t *pfGpMask, uint64_t fSkipMask)
280{
281 for (unsigned iBit = 0; iBit < 64; iBit++)
282 {
283 uint64_t fBitMask = RT_BIT_64(iBit);
284 if (fBitMask & fSkipMask)
285 continue;
286
287 /* Set it. */
288 SUPMSRPROBERMODIFYRESULT ResultSet;
289 int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
290 if (RT_FAILURE(rc))
291 return RTMsgErrorRc(rc, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
292
293 /* Clear it. */
294 SUPMSRPROBERMODIFYRESULT ResultClear;
295 rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
296 if (RT_FAILURE(rc))
297 return RTMsgErrorRc(rc, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
298
299 if (ResultSet.fModifyGp || ResultClear.fModifyGp)
300 *pfGpMask |= fBitMask;
301 else if ( ( ((ResultSet.uBefore ^ ResultSet.uAfter) & fBitMask) == 0
302 && !ResultSet.fBeforeGp
303 && !ResultSet.fAfterGp)
304 && ( ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) == 0
305 && !ResultClear.fBeforeGp
306 && !ResultClear.fAfterGp) )
307 *pfIgnMask |= fBitMask;
308 }
309
310 return VINF_SUCCESS;
311}
312
313
314#if 0 /* currently unused */
315/**
316 * Tries to modify one bit.
317 *
318 * @retval -2 on API error.
319 * @retval -1 on \#GP.
320 * @retval 0 if ignored.
321 * @retval 1 if it changed.
322 *
323 * @param uMsr The MSR.
324 * @param iBit The bit to try modify.
325 */
326static int msrProberModifyBit(uint32_t uMsr, unsigned iBit)
327{
328 uint64_t fBitMask = RT_BIT_64(iBit);
329
330 /* Set it. */
331 SUPMSRPROBERMODIFYRESULT ResultSet;
332 int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
333 if (RT_FAILURE(rc))
334 return RTMsgErrorRc(-2, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
335
336 /* Clear it. */
337 SUPMSRPROBERMODIFYRESULT ResultClear;
338 rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
339 if (RT_FAILURE(rc))
340 return RTMsgErrorRc(-2, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
341
342 if (ResultSet.fModifyGp || ResultClear.fModifyGp)
343 return -1;
344
345 if ( ( ((ResultSet.uBefore ^ ResultSet.uAfter) & fBitMask) != 0
346 && !ResultSet.fBeforeGp
347 && !ResultSet.fAfterGp)
348 || ( ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) != 0
349 && !ResultClear.fBeforeGp
350 && !ResultClear.fAfterGp) )
351 return 1;
352
353 return 0;
354}
355#endif
356
357
358/**
359 * Tries to do a simple AND+OR change and see if we \#GP or not.
360 *
361 * @retval @c true if successfully modified.
362 * @retval @c false if \#GP or other error.
363 *
364 * @param uMsr The MSR.
365 * @param fAndMask The AND mask.
366 * @param fOrMask The OR mask.
367 */
368static bool msrProberModifySimpleGp(uint32_t uMsr, uint64_t fAndMask, uint64_t fOrMask)
369{
370 SUPMSRPROBERMODIFYRESULT Result;
371 int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, fAndMask, fOrMask, &Result);
372 if (RT_FAILURE(rc))
373 {
374 RTMsgError("g_MsrAcc.pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, fAndMask, fOrMask, rc);
375 return false;
376 }
377 return !Result.fBeforeGp
378 && !Result.fModifyGp
379 && !Result.fAfterGp
380 && !Result.fRestoreGp;
381}
382
383
384
385
386/**
387 * Combination of the basic tests.
388 *
389 * @returns VBox status code.
390 * @param uMsr The MSR.
391 * @param fSkipMask Mask of bits to skip.
392 * @param pfReadOnly Where to return read-only status.
393 * @param pfIgnMask Where to return the write ignore mask. Need not
394 * be initialized.
395 * @param pfGpMask Where to return the write GP mask. Need not
396 * be initialized.
397 */
398static int msrProberModifyBasicTests(uint32_t uMsr, uint64_t fSkipMask, bool *pfReadOnly, uint64_t *pfIgnMask, uint64_t *pfGpMask)
399{
400 if (msrProberModifyNoChange(uMsr))
401 {
402 *pfReadOnly = false;
403 *pfIgnMask = 0;
404 *pfGpMask = 0;
405 return msrProberModifyBitChanges(uMsr, pfIgnMask, pfGpMask, fSkipMask);
406 }
407
408 *pfReadOnly = true;
409 *pfIgnMask = 0;
410 *pfGpMask = UINT64_MAX;
411 return VINF_SUCCESS;
412}
413
414
415
416/**
417 * Determines for the MSR AND mask.
418 *
419 * Older CPUs doesn't necessiarly implement all bits of the MSR register number.
420 * So, we have to approximate how many are used so we don't get an overly large
421 * and confusing set of MSRs when probing.
422 *
423 * @returns The mask.
424 */
425static uint32_t determineMsrAndMask(void)
426{
427#define VBCPUREP_MASK_TEST_MSRS 7
428 static uint32_t const s_aMsrs[VBCPUREP_MASK_TEST_MSRS] =
429 {
430 /* Try a bunch of mostly read only registers: */
431 MSR_P5_MC_TYPE, MSR_IA32_PLATFORM_ID, MSR_IA32_MTRR_CAP, MSR_IA32_MCG_CAP, MSR_IA32_CR_PAT,
432 /* Then some which aren't supposed to be present on any CPU: */
433 0x00000015, 0x00000019,
434 };
435
436 /* Get the base values. */
437 uint64_t auBaseValues[VBCPUREP_MASK_TEST_MSRS];
438 for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
439 {
440 if (!msrProberRead(s_aMsrs[i], &auBaseValues[i]))
441 auBaseValues[i] = UINT64_MAX;
442 //vbCpuRepDebug("Base: %#x -> %#llx\n", s_aMsrs[i], auBaseValues[i]);
443 }
444
445 /* Do the probing. */
446 unsigned iBit;
447 for (iBit = 31; iBit > 8; iBit--)
448 {
449 uint64_t fMsrOrMask = RT_BIT_64(iBit);
450 for (unsigned iTest = 0; iTest <= 64 && fMsrOrMask < UINT32_MAX; iTest++)
451 {
452 for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
453 {
454 uint64_t uValue;
455 if (!msrProberRead(s_aMsrs[i] | fMsrOrMask, &uValue))
456 uValue = UINT64_MAX;
457 if (uValue != auBaseValues[i])
458 {
459 uint32_t fMsrMask = iBit >= 31 ? UINT32_MAX : RT_BIT_32(iBit + 1) - 1;
460 vbCpuRepDebug("MSR AND mask: quit on iBit=%u uMsr=%#x (%#x) %llx != %llx => fMsrMask=%#x\n",
461 iBit, s_aMsrs[i] | (uint32_t)fMsrOrMask, s_aMsrs[i], uValue, auBaseValues[i], fMsrMask);
462 return fMsrMask;
463 }
464 }
465
466 /* Advance. */
467 if (iBit <= 6)
468 fMsrOrMask += RT_BIT_64(iBit);
469 else if (iBit <= 11)
470 fMsrOrMask += RT_BIT_64(iBit) * 33;
471 else if (iBit <= 16)
472 fMsrOrMask += RT_BIT_64(iBit) * 1025;
473 else if (iBit <= 22)
474 fMsrOrMask += RT_BIT_64(iBit) * 65537;
475 else
476 fMsrOrMask += RT_BIT_64(iBit) * 262145;
477 }
478 }
479
480 uint32_t fMsrMask = RT_BIT_32(iBit + 1) - 1;
481 vbCpuRepDebug("MSR AND mask: less that %u bits that matters?!? => fMsrMask=%#x\n", iBit + 1, fMsrMask);
482 return fMsrMask;
483}
484
485
486static int findMsrs(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs, uint32_t fMsrMask)
487{
488 /*
489 * Gather them.
490 */
491 static struct { uint32_t uFirst, cMsrs; } const s_aRanges[] =
492 {
493 { 0x00000000, 0x00042000 },
494 { 0x10000000, 0x00001000 },
495 { 0x20000000, 0x00001000 },
496 { 0x40000000, 0x00012000 },
497 { 0x80000000, 0x00012000 },
498 { 0xc0000000, 0x00022000 }, /* Had some trouble here on solaris with the tstVMM setup. */
499 };
500
501 *pcMsrs = 0;
502 *ppaMsrs = NULL;
503
504 for (unsigned i = 0; i < RT_ELEMENTS(s_aRanges); i++)
505 {
506 uint32_t uMsr = s_aRanges[i].uFirst;
507 if ((uMsr & fMsrMask) != uMsr)
508 continue;
509 uint32_t cLeft = s_aRanges[i].cMsrs;
510 while (cLeft-- > 0 && (uMsr & fMsrMask) == uMsr)
511 {
512 if ((uMsr & 0xfff) == 0)
513 {
514 vbCpuRepDebug("testing %#x...\n", uMsr);
515 RTThreadSleep(22);
516 }
517#if 0
518 else if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
519 {
520 vbCpuRepDebug("testing %#x...\n", uMsr);
521 RTThreadSleep(250);
522 }
523#endif
524 /* Skip 0xc0011012..13 as it seems to be bad for our health (Phenom II X6 1100T). */
525 /* Ditto for 0x0000002ff (MSR_IA32_MTRR_DEF_TYPE) on AMD (Ryzen 7 1800X). */
526 /* Ditto for 0x0000002a (EBL_CR_POWERON) and 0x00000277 (MSR_IA32_CR_PAT) on Intel (Atom 330). */
527 /* And more of the same for 0x280 on Intel Pentium III. */
528 if ( ((uMsr >= 0xc0011012 && uMsr <= 0xc0011013) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
529 || ( uMsr == 0x2ff
530 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON)
531 && g_enmMicroarch >= kCpumMicroarch_AMD_Zen_First)
532 || ( (uMsr == 0x2a || uMsr == 0x277)
533 && g_enmVendor == CPUMCPUVENDOR_INTEL
534 && g_enmMicroarch == kCpumMicroarch_Intel_Atom_Bonnell)
535 || ( (uMsr == 0x280)
536 && g_enmMicroarch == kCpumMicroarch_Intel_P6_III))
537 vbCpuRepDebug("Skipping %#x\n", uMsr);
538 else
539 {
540 /* Read probing normally does it. */
541 uint64_t uValue = 0;
542 bool fGp = true;
543 int rc = g_MsrAcc.pfnMsrProberRead(uMsr, NIL_RTCPUID, &uValue, &fGp);
544 if (RT_FAILURE(rc))
545 {
546 RTMemFree(*ppaMsrs);
547 *ppaMsrs = NULL;
548 return RTMsgErrorRc(rc, "pfnMsrProberRead failed on %#x: %Rrc\n", uMsr, rc);
549 }
550
551 uint32_t fFlags;
552 if (!fGp)
553 fFlags = 0;
554 /* VIA/Shanghai HACK - writing to 0x0000317e on a quad core make the core unresponsive. */
555 else if (uMsr == 0x0000317e && (g_enmVendor == CPUMCPUVENDOR_VIA || g_enmVendor == CPUMCPUVENDOR_SHANGHAI))
556 {
557 uValue = 0;
558 fFlags = VBCPUREPMSR_F_WRITE_ONLY;
559 fGp = *pcMsrs == 0
560 || (*ppaMsrs)[*pcMsrs - 1].uMsr != 0x0000317d
561 || (*ppaMsrs)[*pcMsrs - 1].fFlags != VBCPUREPMSR_F_WRITE_ONLY;
562 }
563 else
564 {
565 /* Is it a write only register? */
566#if 0
567 if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
568 {
569 vbCpuRepDebug("test writing %#x...\n", uMsr);
570 RTThreadSleep(250);
571 }
572#endif
573 fGp = true;
574 rc = g_MsrAcc.pfnMsrProberWrite(uMsr, NIL_RTCPUID, 0, &fGp);
575 if (RT_FAILURE(rc))
576 {
577 RTMemFree(*ppaMsrs);
578 *ppaMsrs = NULL;
579 return RTMsgErrorRc(rc, "pfnMsrProberWrite failed on %#x: %Rrc\n", uMsr, rc);
580 }
581 uValue = 0;
582 fFlags = VBCPUREPMSR_F_WRITE_ONLY;
583
584 /*
585 * Tweaks. On Intel CPUs we've got trouble detecting
586 * IA32_BIOS_UPDT_TRIG (0x00000079), so we have to add it manually here.
587 * Ditto on AMD with PATCH_LOADER (0xc0010020).
588 */
589 if ( uMsr == 0x00000079
590 && fGp
591 && g_enmMicroarch >= kCpumMicroarch_Intel_P6_Core_Atom_First
592 && g_enmMicroarch <= kCpumMicroarch_Intel_End)
593 fGp = false;
594 if ( uMsr == 0xc0010020
595 && fGp
596 && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First
597 && g_enmMicroarch <= kCpumMicroarch_AMD_End)
598 fGp = false;
599 }
600
601 if (!fGp)
602 {
603 /* Add it. */
604 rc = vbCpuRepMsrsAddOne(ppaMsrs, pcMsrs, uMsr, uValue, fFlags);
605 if (RT_FAILURE(rc))
606 return RTMsgErrorRc(rc, "Out of memory (uMsr=%#x).\n", uMsr);
607 if ( (g_enmVendor != CPUMCPUVENDOR_VIA && g_enmVendor != CPUMCPUVENDOR_SHANGHAI)
608 || uValue
609 || fFlags)
610 vbCpuRepDebug("%#010x: uValue=%#llx fFlags=%#x\n", uMsr, uValue, fFlags);
611 }
612 }
613
614 uMsr++;
615 }
616 }
617
618 return VINF_SUCCESS;
619}
620
621/**
622 * Get the name of the specified MSR, if we know it and can handle it.
623 *
624 * Do _NOT_ add any new names here without ALSO at the SAME TIME making sure it
625 * is handled correctly by the PROBING CODE and REPORTED correctly!!
626 *
627 * @returns Pointer to name if handled, NULL if not yet explored.
628 * @param uMsr The MSR in question.
629 */
630static const char *getMsrNameHandled(uint32_t uMsr)
631{
632 /** @todo figure out where NCU_EVENT_CORE_MASK might be... */
633 switch (uMsr)
634 {
635 case 0x00000000: return "IA32_P5_MC_ADDR";
636 case 0x00000001: return "IA32_P5_MC_TYPE";
637 case 0x00000006:
638 if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
639 return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
640 return "IA32_MONITOR_FILTER_LINE_SIZE";
641 //case 0x0000000e: return "P?_TR12"; /* K6-III docs */
642 case 0x00000010: return "IA32_TIME_STAMP_COUNTER";
643 case 0x00000017: return "IA32_PLATFORM_ID";
644 case 0x00000018: return "P6_UNK_0000_0018"; /* P6_M_Dothan. */
645 case 0x0000001b: return "IA32_APIC_BASE";
646 case 0x00000021: return "C2_UNK_0000_0021"; /* Core2_Penryn */
647 case 0x0000002a: return g_fIntelNetBurst ? "P4_EBC_HARD_POWERON" : "EBL_CR_POWERON";
648 case 0x0000002b: return g_fIntelNetBurst ? "P4_EBC_SOFT_POWERON" : NULL;
649 case 0x0000002c: return g_fIntelNetBurst ? "P4_EBC_FREQUENCY_ID" : NULL;
650 case 0x0000002e: return "I7_UNK_0000_002e"; /* SandyBridge, IvyBridge. */
651 case 0x0000002f: return "P6_UNK_0000_002f"; /* P6_M_Dothan. */
652 case 0x00000032: return "P6_UNK_0000_0032"; /* P6_M_Dothan. */
653 case 0x00000033: return "TEST_CTL";
654 case 0x00000034: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)
655 || CPUMMICROARCH_IS_INTEL_SILVERMONT_PLUS(g_enmMicroarch)
656 ? "MSR_SMI_COUNT" : "P6_UNK_0000_0034"; /* P6_M_Dothan. */
657 case 0x00000035: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "MSR_CORE_THREAD_COUNT" : "P6_UNK_0000_0035"; /* P6_M_Dothan. */
658 case 0x00000036: return "I7_UNK_0000_0036"; /* SandyBridge, IvyBridge. */
659 case 0x00000039: return "C2_UNK_0000_0039"; /* Core2_Penryn */
660 case 0x0000003a: return "IA32_FEATURE_CONTROL";
661 case 0x0000003b: return "P6_UNK_0000_003b"; /* P6_M_Dothan. */
662 case 0x0000003e: return "I7_UNK_0000_003e"; /* SandyBridge, IvyBridge. */
663 case 0x0000003f: return "P6_UNK_0000_003f"; /* P6_M_Dothan. */
664 case 0x00000040: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_0_FROM_IP" : "MSR_LASTBRANCH_0";
665 case 0x00000041: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_1_FROM_IP" : "MSR_LASTBRANCH_1";
666 case 0x00000042: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_2_FROM_IP" : "MSR_LASTBRANCH_2";
667 case 0x00000043: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_3_FROM_IP" : "MSR_LASTBRANCH_3";
668 case 0x00000044: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_4_FROM_IP" : "MSR_LASTBRANCH_4";
669 case 0x00000045: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_5_FROM_IP" : "MSR_LASTBRANCH_5";
670 case 0x00000046: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_6_FROM_IP" : "MSR_LASTBRANCH_6";
671 case 0x00000047: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_7_FROM_IP" : "MSR_LASTBRANCH_7";
672 case 0x00000048: return "MSR_LASTBRANCH_8"; /*??*/
673 case 0x00000049: return "MSR_LASTBRANCH_9"; /*??*/
674 case 0x0000004a: return "P6_UNK_0000_004a"; /* P6_M_Dothan. */
675 case 0x0000004b: return "P6_UNK_0000_004b"; /* P6_M_Dothan. */
676 case 0x0000004c: return "P6_UNK_0000_004c"; /* P6_M_Dothan. */
677 case 0x0000004d: return "P6_UNK_0000_004d"; /* P6_M_Dothan. */
678 case 0x0000004e: return "P6_UNK_0000_004e"; /* P6_M_Dothan. */
679 case 0x0000004f: return "P6_UNK_0000_004f"; /* P6_M_Dothan. */
680 case 0x00000050: return "P6_UNK_0000_0050"; /* P6_M_Dothan. */
681 case 0x00000051: return "P6_UNK_0000_0051"; /* P6_M_Dothan. */
682 case 0x00000052: return "P6_UNK_0000_0052"; /* P6_M_Dothan. */
683 case 0x00000053: return "P6_UNK_0000_0053"; /* P6_M_Dothan. */
684 case 0x00000054: return "P6_UNK_0000_0054"; /* P6_M_Dothan. */
685 case 0x00000060: return "MSR_LASTBRANCH_0_TO_IP"; /* Core2_Penryn */
686 case 0x00000061: return "MSR_LASTBRANCH_1_TO_IP"; /* Core2_Penryn */
687 case 0x00000062: return "MSR_LASTBRANCH_2_TO_IP"; /* Core2_Penryn */
688 case 0x00000063: return "MSR_LASTBRANCH_3_TO_IP"; /* Core2_Penryn */
689 case 0x00000064: return "MSR_LASTBRANCH_4_TO_IP"; /* Atom? */
690 case 0x00000065: return "MSR_LASTBRANCH_5_TO_IP";
691 case 0x00000066: return "MSR_LASTBRANCH_6_TO_IP";
692 case 0x00000067: return "MSR_LASTBRANCH_7_TO_IP";
693 case 0x0000006c: return "P6_UNK_0000_006c"; /* P6_M_Dothan. */
694 case 0x0000006d: return "P6_UNK_0000_006d"; /* P6_M_Dothan. */
695 case 0x0000006e: return "P6_UNK_0000_006e"; /* P6_M_Dothan. */
696 case 0x0000006f: return "P6_UNK_0000_006f"; /* P6_M_Dothan. */
697 case 0x00000079: return "IA32_BIOS_UPDT_TRIG";
698 case 0x00000080: return "P4_UNK_0000_0080";
699 case 0x00000088: return "BBL_CR_D0";
700 case 0x00000089: return "BBL_CR_D1";
701 case 0x0000008a: return "BBL_CR_D2";
702 case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON ? "AMD_K8_PATCH_LEVEL"
703 : g_fIntelNetBurst ? "IA32_BIOS_SIGN_ID" : "BBL_CR_D3|BIOS_SIGN";
704 case 0x0000008c: return "P6_UNK_0000_008c"; /* P6_M_Dothan. */
705 case 0x0000008d: return "P6_UNK_0000_008d"; /* P6_M_Dothan. */
706 case 0x0000008e: return "P6_UNK_0000_008e"; /* P6_M_Dothan. */
707 case 0x0000008f: return "P6_UNK_0000_008f"; /* P6_M_Dothan. */
708 case 0x00000090: return "P6_UNK_0000_0090"; /* P6_M_Dothan. */
709 case 0x0000009b: return "IA32_SMM_MONITOR_CTL";
710 case 0x000000a8: return "C2_EMTTM_CR_TABLES_0";
711 case 0x000000a9: return "C2_EMTTM_CR_TABLES_1";
712 case 0x000000aa: return "C2_EMTTM_CR_TABLES_2";
713 case 0x000000ab: return "C2_EMTTM_CR_TABLES_3";
714 case 0x000000ac: return "C2_EMTTM_CR_TABLES_4";
715 case 0x000000ad: return "C2_EMTTM_CR_TABLES_5";
716 case 0x000000ae: return "P6_UNK_0000_00ae"; /* P6_M_Dothan. */
717 case 0x000000c1: return "IA32_PMC0";
718 case 0x000000c2: return "IA32_PMC1";
719 case 0x000000c3: return "IA32_PMC2";
720 case 0x000000c4: return "IA32_PMC3";
721 /* PMC4+ first seen on SandyBridge. The earlier cut off is just to be
722 on the safe side as we must avoid P6_M_Dothan and possibly others. */
723 case 0x000000c5: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC4" : NULL;
724 case 0x000000c6: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC5" : NULL;
725 case 0x000000c7: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC6" : "P6_UNK_0000_00c7"; /* P6_M_Dothan. */
726 case 0x000000c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC7" : NULL;
727 case 0x000000cd: return "MSR_FSB_FREQ"; /* P6_M_Dothan. */
728 case 0x000000ce: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PLATFORM_INFO" : "P6_UNK_0000_00ce"; /* P6_M_Dothan. */
729 case 0x000000cf: return "C2_UNK_0000_00cf"; /* Core2_Penryn. */
730 case 0x000000e0: return "C2_UNK_0000_00e0"; /* Core2_Penryn. */
731 case 0x000000e1: return "C2_UNK_0000_00e1"; /* Core2_Penryn. */
732 case 0x000000e2: return "MSR_PKG_CST_CONFIG_CONTROL";
733 case 0x000000e3: return "C2_SMM_CST_MISC_INFO"; /* Core2_Penryn. */
734 case 0x000000e4: return "MSR_PMG_IO_CAPTURE_BASE";
735 case 0x000000e5: return "C2_UNK_0000_00e5"; /* Core2_Penryn. */
736 case 0x000000e7: return "IA32_MPERF";
737 case 0x000000e8: return "IA32_APERF";
738 case 0x000000ee: return "C1_EXT_CONFIG"; /* Core2_Penryn. msrtool lists it for Core1 as well. */
739 case 0x000000fe: return "IA32_MTRRCAP";
740 case 0x00000102: return "I7_IB_UNK_0000_0102"; /* IvyBridge. */
741 case 0x00000103: return "I7_IB_UNK_0000_0103"; /* IvyBridge. */
742 case 0x00000104: return "I7_IB_UNK_0000_0104"; /* IvyBridge. */
743 case 0x00000116: return "BBL_CR_ADDR";
744 case 0x00000118: return "BBL_CR_DECC";
745 case 0x00000119: return "BBL_CR_CTL";
746 case 0x0000011a: return "BBL_CR_TRIG";
747 case 0x0000011b: return "P6_UNK_0000_011b"; /* P6_M_Dothan. */
748 case 0x0000011c: return "C2_UNK_0000_011c"; /* Core2_Penryn. */
749 case 0x0000011e: return "BBL_CR_CTL3";
750 case 0x00000120: return "SILV_UNK_0000_0120"; /* Silvermont */
751 case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
752 || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
753 ? "CPUID1_FEATURE_MASK" : NULL;
754 case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
755 || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
756 ? "CPUID80000001_FEATURE_MASK" : "P6_UNK_0000_0131" /* P6_M_Dothan. */;
757 case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
758 ? "CPUID1_FEATURE_MASK" : NULL;
759 case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
760 ? "CPUIDD_01_FEATURE_MASK" : NULL;
761 case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
762 ? "CPUID80000001_FEATURE_MASK" : NULL;
763 case 0x0000013c: return "I7_SB_AES_NI_CTL"; /* SandyBridge. Bit 0 is lock bit, bit 1 disables AES-NI. */
764 case 0x00000140: return "I7_IB_UNK_0000_0140"; /* IvyBridge. */
765 case 0x00000142: return "I7_IB_UNK_0000_0142"; /* IvyBridge. */
766 case 0x0000014e: return "P6_UNK_0000_014e"; /* P6_M_Dothan. */
767 case 0x0000014f: return "P6_UNK_0000_014f"; /* P6_M_Dothan. */
768 case 0x00000150: return "P6_UNK_0000_0150"; /* P6_M_Dothan. */
769 case 0x00000151: return "P6_UNK_0000_0151"; /* P6_M_Dothan. */
770 case 0x00000154: return "P6_UNK_0000_0154"; /* P6_M_Dothan. */
771 case 0x0000015b: return "P6_UNK_0000_015b"; /* P6_M_Dothan. */
772 case 0x0000015e: return "C2_UNK_0000_015e"; /* Core2_Penryn. */
773 case 0x0000015f: return "C1_DTS_CAL_CTRL"; /* Core2_Penryn. msrtool only docs this for core1! */
774 case 0x00000174: return "IA32_SYSENTER_CS";
775 case 0x00000175: return "IA32_SYSENTER_ESP";
776 case 0x00000176: return "IA32_SYSENTER_EIP";
777 case 0x00000179: return "IA32_MCG_CAP";
778 case 0x0000017a: return "IA32_MCG_STATUS";
779 case 0x0000017b: return "IA32_MCG_CTL";
780 case 0x0000017f: return "I7_SB_ERROR_CONTROL"; /* SandyBridge. */
781 case 0x00000180: return g_fIntelNetBurst ? "MSR_MCG_RAX" : NULL;
782 case 0x00000181: return g_fIntelNetBurst ? "MSR_MCG_RBX" : NULL;
783 case 0x00000182: return g_fIntelNetBurst ? "MSR_MCG_RCX" : NULL;
784 case 0x00000183: return g_fIntelNetBurst ? "MSR_MCG_RDX" : NULL;
785 case 0x00000184: return g_fIntelNetBurst ? "MSR_MCG_RSI" : NULL;
786 case 0x00000185: return g_fIntelNetBurst ? "MSR_MCG_RDI" : NULL;
787 case 0x00000186: return g_fIntelNetBurst ? "MSR_MCG_RBP" : "IA32_PERFEVTSEL0";
788 case 0x00000187: return g_fIntelNetBurst ? "MSR_MCG_RSP" : "IA32_PERFEVTSEL1";
789 case 0x00000188: return g_fIntelNetBurst ? "MSR_MCG_RFLAGS" : "IA32_PERFEVTSEL2";
790 case 0x00000189: return g_fIntelNetBurst ? "MSR_MCG_RIP" : "IA32_PERFEVTSEL3";
791 case 0x0000018a: return g_fIntelNetBurst ? "MSR_MCG_MISC" : "IA32_PERFEVTSEL4";
792 case 0x0000018b: return g_fIntelNetBurst ? "MSR_MCG_RESERVED1" : "IA32_PERFEVTSEL5";
793 case 0x0000018c: return g_fIntelNetBurst ? "MSR_MCG_RESERVED2" : "IA32_PERFEVTSEL6";
794 case 0x0000018d: return g_fIntelNetBurst ? "MSR_MCG_RESERVED3" : "IA32_PERFEVTSEL7";
795 case 0x0000018e: return g_fIntelNetBurst ? "MSR_MCG_RESERVED4" : "IA32_PERFEVTSEL8";
796 case 0x0000018f: return g_fIntelNetBurst ? "MSR_MCG_RESERVED5" : "IA32_PERFEVTSEL9";
797 case 0x00000190: return g_fIntelNetBurst ? "MSR_MCG_R8" : NULL;
798 case 0x00000191: return g_fIntelNetBurst ? "MSR_MCG_R9" : NULL;
799 case 0x00000192: return g_fIntelNetBurst ? "MSR_MCG_R10" : NULL;
800 case 0x00000193: return g_fIntelNetBurst ? "MSR_MCG_R11" : "C2_UNK_0000_0193";
801 case 0x00000194: return g_fIntelNetBurst ? "MSR_MCG_R12" : "CLOCK_FLEX_MAX";
802 case 0x00000195: return g_fIntelNetBurst ? "MSR_MCG_R13" : NULL;
803 case 0x00000196: return g_fIntelNetBurst ? "MSR_MCG_R14" : NULL;
804 case 0x00000197: return g_fIntelNetBurst ? "MSR_MCG_R15" : NULL;
805 case 0x00000198: return "IA32_PERF_STATUS";
806 case 0x00000199: return "IA32_PERF_CTL";
807 case 0x0000019a: return "IA32_CLOCK_MODULATION";
808 case 0x0000019b: return "IA32_THERM_INTERRUPT";
809 case 0x0000019c: return "IA32_THERM_STATUS";
810 case 0x0000019d: return "IA32_THERM2_CTL";
811 case 0x0000019e: return "P6_UNK_0000_019e"; /* P6_M_Dothan. */
812 case 0x0000019f: return "P6_UNK_0000_019f"; /* P6_M_Dothan. */
813 case 0x000001a0: return "IA32_MISC_ENABLE";
814 case 0x000001a1: return g_fIntelNetBurst ? "MSR_PLATFORM_BRV" : "P6_UNK_0000_01a1" /* P6_M_Dothan. */;
815 case 0x000001a2: return g_fIntelNetBurst ? "P4_UNK_0000_01a2" : "I7_MSR_TEMPERATURE_TARGET" /* SandyBridge, IvyBridge. */;
816 case 0x000001a4: return "I7_UNK_0000_01a4"; /* SandyBridge, IvyBridge. */
817 case 0x000001a6: return "I7_MSR_OFFCORE_RSP_0";
818 case 0x000001a7: return "I7_MSR_OFFCORE_RSP_1";
819 case 0x000001a8: return "I7_UNK_0000_01a8"; /* SandyBridge, IvyBridge. */
820 case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "MSR_MISC_PWR_MGMT" : "P6_PIC_SENS_CFG" /* Pentium M. */;
821 case 0x000001ad: return "I7_MSR_TURBO_RATIO_LIMIT"; /* SandyBridge+, Silvermount+ */
822 case 0x000001ae: return "P6_UNK_0000_01ae"; /* P6_M_Dothan. */
823 case 0x000001af: return "P6_UNK_0000_01af"; /* P6_M_Dothan. */
824 case 0x000001b0: return "IA32_ENERGY_PERF_BIAS";
825 case 0x000001b1: return "IA32_PACKAGE_THERM_STATUS";
826 case 0x000001b2: return "IA32_PACKAGE_THERM_INTERRUPT";
827 case 0x000001bf: return "C2_UNK_0000_01bf"; /* Core2_Penryn. */
828 case 0x000001c6: return "I7_UNK_0000_01c6"; /* SandyBridge*/
829 case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "MSR_LBR_SELECT" : NULL;
830 case 0x000001c9: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
831 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
832 ? "MSR_LASTBRANCH_TOS" : NULL /* Pentium M Dothan seems to have something else here. */;
833 case 0x000001d3: return "P6_UNK_0000_01d3"; /* P6_M_Dothan. */
834 case 0x000001d7: return g_fIntelNetBurst ? "MSR_LER_FROM_LIP" : NULL;
835 case 0x000001d8: return g_fIntelNetBurst ? "MSR_LER_TO_LIP" : NULL;
836 case 0x000001d9: return "IA32_DEBUGCTL";
837 case 0x000001da: return g_fIntelNetBurst ? "MSR_LASTBRANCH_TOS" : NULL;
838 case 0x000001db: return g_fIntelNetBurst ? "P6_LASTBRANCH_0" : "P6_LAST_BRANCH_FROM_IP"; /* Not exclusive to P6, also AMD. */
839 case 0x000001dc: return g_fIntelNetBurst ? "P6_LASTBRANCH_1" : "P6_LAST_BRANCH_TO_IP";
840 case 0x000001dd: return g_fIntelNetBurst ? "P6_LASTBRANCH_2" : "P6_LAST_INT_FROM_IP";
841 case 0x000001de: return g_fIntelNetBurst ? "P6_LASTBRANCH_3" : "P6_LAST_INT_TO_IP";
842 case 0x000001e0: return "MSR_ROB_CR_BKUPTMPDR6";
843 case 0x000001e1: return "I7_SB_UNK_0000_01e1";
844 case 0x000001ef: return "I7_SB_UNK_0000_01ef";
845 case 0x000001f0: return "I7_VLW_CAPABILITY"; /* SandyBridge. Bit 1 is A20M and was implemented incorrectly (AAJ49). */
846 case 0x000001f2: return "IA32_SMRR_PHYSBASE";
847 case 0x000001f3: return "IA32_SMRR_PHYSMASK";
848 case 0x000001f8: return "IA32_PLATFORM_DCA_CAP";
849 case 0x000001f9: return "IA32_CPU_DCA_CAP";
850 case 0x000001fa: return "IA32_DCA_0_CAP";
851 case 0x000001fc: return "I7_MSR_POWER_CTL";
852
853 case 0x00000200: return "IA32_MTRR_PHYS_BASE0";
854 case 0x00000202: return "IA32_MTRR_PHYS_BASE1";
855 case 0x00000204: return "IA32_MTRR_PHYS_BASE2";
856 case 0x00000206: return "IA32_MTRR_PHYS_BASE3";
857 case 0x00000208: return "IA32_MTRR_PHYS_BASE4";
858 case 0x0000020a: return "IA32_MTRR_PHYS_BASE5";
859 case 0x0000020c: return "IA32_MTRR_PHYS_BASE6";
860 case 0x0000020e: return "IA32_MTRR_PHYS_BASE7";
861 case 0x00000210: return "IA32_MTRR_PHYS_BASE8";
862 case 0x00000212: return "IA32_MTRR_PHYS_BASE9";
863 case 0x00000214: return "IA32_MTRR_PHYS_BASE10";
864 case 0x00000216: return "IA32_MTRR_PHYS_BASE11";
865 case 0x00000218: return "IA32_MTRR_PHYS_BASE12";
866 case 0x0000021a: return "IA32_MTRR_PHYS_BASE13";
867 case 0x0000021c: return "IA32_MTRR_PHYS_BASE14";
868 case 0x0000021e: return "IA32_MTRR_PHYS_BASE15";
869
870 case 0x00000201: return "IA32_MTRR_PHYS_MASK0";
871 case 0x00000203: return "IA32_MTRR_PHYS_MASK1";
872 case 0x00000205: return "IA32_MTRR_PHYS_MASK2";
873 case 0x00000207: return "IA32_MTRR_PHYS_MASK3";
874 case 0x00000209: return "IA32_MTRR_PHYS_MASK4";
875 case 0x0000020b: return "IA32_MTRR_PHYS_MASK5";
876 case 0x0000020d: return "IA32_MTRR_PHYS_MASK6";
877 case 0x0000020f: return "IA32_MTRR_PHYS_MASK7";
878 case 0x00000211: return "IA32_MTRR_PHYS_MASK8";
879 case 0x00000213: return "IA32_MTRR_PHYS_MASK9";
880 case 0x00000215: return "IA32_MTRR_PHYS_MASK10";
881 case 0x00000217: return "IA32_MTRR_PHYS_MASK11";
882 case 0x00000219: return "IA32_MTRR_PHYS_MASK12";
883 case 0x0000021b: return "IA32_MTRR_PHYS_MASK13";
884 case 0x0000021d: return "IA32_MTRR_PHYS_MASK14";
885 case 0x0000021f: return "IA32_MTRR_PHYS_MASK15";
886
887 case 0x00000250: return "IA32_MTRR_FIX64K_00000";
888 case 0x00000258: return "IA32_MTRR_FIX16K_80000";
889 case 0x00000259: return "IA32_MTRR_FIX16K_A0000";
890 case 0x00000268: return "IA32_MTRR_FIX4K_C0000";
891 case 0x00000269: return "IA32_MTRR_FIX4K_C8000";
892 case 0x0000026a: return "IA32_MTRR_FIX4K_D0000";
893 case 0x0000026b: return "IA32_MTRR_FIX4K_D8000";
894 case 0x0000026c: return "IA32_MTRR_FIX4K_E0000";
895 case 0x0000026d: return "IA32_MTRR_FIX4K_E8000";
896 case 0x0000026e: return "IA32_MTRR_FIX4K_F0000";
897 case 0x0000026f: return "IA32_MTRR_FIX4K_F8000";
898 case 0x00000277: return "IA32_PAT";
899 case 0x00000280: return "IA32_MC0_CTL2";
900 case 0x00000281: return "IA32_MC1_CTL2";
901 case 0x00000282: return "IA32_MC2_CTL2";
902 case 0x00000283: return "IA32_MC3_CTL2";
903 case 0x00000284: return "IA32_MC4_CTL2";
904 case 0x00000285: return "IA32_MC5_CTL2";
905 case 0x00000286: return "IA32_MC6_CTL2";
906 case 0x00000287: return "IA32_MC7_CTL2";
907 case 0x00000288: return "IA32_MC8_CTL2";
908 case 0x00000289: return "IA32_MC9_CTL2";
909 case 0x0000028a: return "IA32_MC10_CTL2";
910 case 0x0000028b: return "IA32_MC11_CTL2";
911 case 0x0000028c: return "IA32_MC12_CTL2";
912 case 0x0000028d: return "IA32_MC13_CTL2";
913 case 0x0000028e: return "IA32_MC14_CTL2";
914 case 0x0000028f: return "IA32_MC15_CTL2";
915 case 0x00000290: return "IA32_MC16_CTL2";
916 case 0x00000291: return "IA32_MC17_CTL2";
917 case 0x00000292: return "IA32_MC18_CTL2";
918 case 0x00000293: return "IA32_MC19_CTL2";
919 case 0x00000294: return "IA32_MC20_CTL2";
920 case 0x00000295: return "IA32_MC21_CTL2";
921 //case 0x00000296: return "IA32_MC22_CTL2";
922 //case 0x00000297: return "IA32_MC23_CTL2";
923 //case 0x00000298: return "IA32_MC24_CTL2";
924 //case 0x00000299: return "IA32_MC25_CTL2";
925 //case 0x0000029a: return "IA32_MC26_CTL2";
926 //case 0x0000029b: return "IA32_MC27_CTL2";
927 //case 0x0000029c: return "IA32_MC28_CTL2";
928 //case 0x0000029d: return "IA32_MC29_CTL2";
929 //case 0x0000029e: return "IA32_MC30_CTL2";
930 //case 0x0000029f: return "IA32_MC31_CTL2";
931 case 0x000002e0: return "I7_SB_NO_EVICT_MODE"; /* (Bits 1 & 0 are said to have something to do with no-evict cache mode used during early boot.) */
932 case 0x000002e6: return "I7_IB_UNK_0000_02e6"; /* IvyBridge */
933 case 0x000002e7: return "I7_IB_UNK_0000_02e7"; /* IvyBridge */
934 case 0x000002ff: return "IA32_MTRR_DEF_TYPE";
935 case 0x00000300: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER0" : "I7_SB_UNK_0000_0300" /* SandyBridge */;
936 case 0x00000301: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER1" : NULL;
937 case 0x00000302: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER2" : NULL;
938 case 0x00000303: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER3" : NULL;
939 case 0x00000304: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER0" : NULL;
940 case 0x00000305: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER1" : "I7_SB_UNK_0000_0305" /* SandyBridge, IvyBridge */;
941 case 0x00000306: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER2" : NULL;
942 case 0x00000307: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER3" : NULL;
943 case 0x00000308: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER0" : NULL;
944 case 0x00000309: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER1" : "IA32_FIXED_CTR0";
945 case 0x0000030a: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER2" : "IA32_FIXED_CTR1";
946 case 0x0000030b: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER3" : "IA32_FIXED_CTR2";
947 case 0x0000030c: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER0" : NULL;
948 case 0x0000030d: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER1" : NULL;
949 case 0x0000030e: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER2" : NULL;
950 case 0x0000030f: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER3" : NULL;
951 case 0x00000310: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER4" : NULL;
952 case 0x00000311: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER5" : NULL;
953 case 0x00000345: return "IA32_PERF_CAPABILITIES";
954 case 0x00000360: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR0" : NULL;
955 case 0x00000361: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR1" : NULL;
956 case 0x00000362: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR2" : NULL;
957 case 0x00000363: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR3" : NULL;
958 case 0x00000364: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR0" : NULL;
959 case 0x00000365: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR1" : NULL;
960 case 0x00000366: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR2" : NULL;
961 case 0x00000367: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR3" : NULL;
962 case 0x00000368: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR0" : NULL;
963 case 0x00000369: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR1" : NULL;
964 case 0x0000036a: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR2" : NULL;
965 case 0x0000036b: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR3" : NULL;
966 case 0x0000036c: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR0" : NULL;
967 case 0x0000036d: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR1" : NULL;
968 case 0x0000036e: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR2" : NULL;
969 case 0x0000036f: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR3" : NULL;
970 case 0x00000370: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR4" : NULL;
971 case 0x00000371: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR5" : NULL;
972 case 0x0000038d: return "IA32_FIXED_CTR_CTRL";
973 case 0x0000038e: return "IA32_PERF_GLOBAL_STATUS";
974 case 0x0000038f: return "IA32_PERF_GLOBAL_CTRL";
975 case 0x00000390: return "IA32_PERF_GLOBAL_OVF_CTRL";
976 case 0x00000391: return "I7_UNC_PERF_GLOBAL_CTRL"; /* S,H,X */
977 case 0x00000392: return "I7_UNC_PERF_GLOBAL_STATUS"; /* S,H,X */
978 case 0x00000393: return "I7_UNC_PERF_GLOBAL_OVF_CTRL"; /* X. ASSUMING this is the same on sandybridge and later. */
979 case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR" /* X */ : "I7_UNC_PERF_FIXED_CTR_CTRL"; /* >= S,H */
980 case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR_CTRL" /* X*/ : "I7_UNC_PERF_FIXED_CTR"; /* >= S,H */
981 case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_ADDR_OPCODE_MATCH" /* X */ : "I7_UNC_CBO_CONFIG"; /* >= S,H */
982 case 0x00000397: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? NULL : "I7_SB_UNK_0000_0397";
983 case 0x0000039c: return "I7_SB_MSR_PEBS_NUM_ALT";
984 case 0x000003a0: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR0" : NULL;
985 case 0x000003a1: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR1" : NULL;
986 case 0x000003a2: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR0" : NULL;
987 case 0x000003a3: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR1" : NULL;
988 case 0x000003a4: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR0" : NULL;
989 case 0x000003a5: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR1" : NULL;
990 case 0x000003a6: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR0" : NULL;
991 case 0x000003a7: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR1" : NULL;
992 case 0x000003a8: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR0" : NULL;
993 case 0x000003a9: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR1" : NULL;
994 case 0x000003aa: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR0" : NULL;
995 case 0x000003ab: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR1" : NULL;
996 case 0x000003ac: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR0" : NULL;
997 case 0x000003ad: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR1" : NULL;
998 case 0x000003ae: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR0" : NULL;
999 case 0x000003af: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR1" : NULL;
1000 case 0x000003b0: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC0" /* X */ : "I7_UNC_ARB_PERF_CTR0"; /* >= S,H */
1001 case 0x000003b1: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC1" /* X */ : "I7_UNC_ARB_PERF_CTR1"; /* >= S,H */
1002 case 0x000003b2: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC2" /* X */ : "I7_UNC_ARB_PERF_EVT_SEL0"; /* >= S,H */
1003 case 0x000003b3: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC3" /* X */ : "I7_UNC_ARB_PERF_EVT_SEL1"; /* >= S,H */
1004 case 0x000003b4: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR0" : "I7_UNC_PMC4";
1005 case 0x000003b5: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR1" : "I7_UNC_PMC5";
1006 case 0x000003b6: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR0" : "I7_UNC_PMC6";
1007 case 0x000003b7: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR1" : "I7_UNC_PMC7";
1008 case 0x000003b8: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR0" : NULL;
1009 case 0x000003b9: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR1" : NULL;
1010 case 0x000003ba: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR0" : NULL;
1011 case 0x000003bb: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR1" : NULL;
1012 case 0x000003bc: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR0" : NULL;
1013 case 0x000003bd: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR1" : NULL;
1014 case 0x000003be: return g_fIntelNetBurst ? "P4_MSR_SSU_ESCR0" : NULL;
1015 case 0x000003c0: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR0" : "I7_UNC_PERF_EVT_SEL0";
1016 case 0x000003c1: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR1" : "I7_UNC_PERF_EVT_SEL1";
1017 case 0x000003c2: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR0" : "I7_UNC_PERF_EVT_SEL2";
1018 case 0x000003c3: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR1" : "I7_UNC_PERF_EVT_SEL3";
1019 case 0x000003c4: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR0" : "I7_UNC_PERF_EVT_SEL4";
1020 case 0x000003c5: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR1" : "I7_UNC_PERF_EVT_SEL5";
1021 case 0x000003c6: return g_fIntelNetBurst ? NULL : "I7_UNC_PERF_EVT_SEL6";
1022 case 0x000003c7: return g_fIntelNetBurst ? NULL : "I7_UNC_PERF_EVT_SEL7";
1023 case 0x000003c8: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0" : NULL;
1024 case 0x000003c9: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0" : NULL;
1025 case 0x000003ca: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR0" : NULL;
1026 case 0x000003cb: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR1" : NULL;
1027 case 0x000003cc: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR2" : NULL;
1028 case 0x000003cd: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR3" : NULL;
1029 case 0x000003e0: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR4" : NULL;
1030 case 0x000003e1: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR5" : NULL;
1031 case 0x000003f0: return g_fIntelNetBurst ? "P4_MSR_TC_PRECISE_EVENT" : NULL;
1032 case 0x000003f1: return "IA32_PEBS_ENABLE";
1033 case 0x000003f2: return g_fIntelNetBurst ? "P4_MSR_PEBS_MATRIX_VERT" : "IA32_PEBS_ENABLE";
1034 case 0x000003f3: return g_fIntelNetBurst ? "P4_UNK_0000_03f3" : NULL;
1035 case 0x000003f4: return g_fIntelNetBurst ? "P4_UNK_0000_03f4" : NULL;
1036 case 0x000003f5: return g_fIntelNetBurst ? "P4_UNK_0000_03f5" : NULL;
1037 case 0x000003f6: return g_fIntelNetBurst ? "P4_UNK_0000_03f6" : "I7_MSR_PEBS_LD_LAT";
1038 case 0x000003f7: return g_fIntelNetBurst ? "P4_UNK_0000_03f7" : "I7_MSR_PEBS_LD_LAT";
1039 case 0x000003f8: return g_fIntelNetBurst ? "P4_UNK_0000_03f8" : "I7_MSR_PKG_C3_RESIDENCY";
1040 case 0x000003f9: return "I7_MSR_PKG_C6_RESIDENCY";
1041 case 0x000003fa: return "I7_MSR_PKG_C7_RESIDENCY";
1042 case 0x000003fc: return "I7_MSR_CORE_C3_RESIDENCY";
1043 case 0x000003fd: return "I7_MSR_CORE_C6_RESIDENCY";
1044 case 0x000003fe: return "I7_MSR_CORE_C7_RESIDENCY";
1045 case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "CPUID1_FEATURE_MASK" : NULL;
1046 case 0x00000480: return "IA32_VMX_BASIC";
1047 case 0x00000481: return "IA32_VMX_PINBASED_CTLS";
1048 case 0x00000482: return "IA32_VMX_PROCBASED_CTLS";
1049 case 0x00000483: return "IA32_VMX_EXIT_CTLS";
1050 case 0x00000484: return "IA32_VMX_ENTRY_CTLS";
1051 case 0x00000485: return "IA32_VMX_MISC";
1052 case 0x00000486: return "IA32_VMX_CR0_FIXED0";
1053 case 0x00000487: return "IA32_VMX_CR0_FIXED1";
1054 case 0x00000488: return "IA32_VMX_CR4_FIXED0";
1055 case 0x00000489: return "IA32_VMX_CR4_FIXED1";
1056 case 0x0000048a: return "IA32_VMX_VMCS_ENUM";
1057 case 0x0000048b: return "IA32_VMX_PROCBASED_CTLS2";
1058 case 0x0000048c: return "IA32_VMX_EPT_VPID_CAP";
1059 case 0x0000048d: return "IA32_VMX_TRUE_PINBASED_CTLS";
1060 case 0x0000048e: return "IA32_VMX_TRUE_PROCBASED_CTLS";
1061 case 0x0000048f: return "IA32_VMX_TRUE_EXIT_CTLS";
1062 case 0x00000490: return "IA32_VMX_TRUE_ENTRY_CTLS";
1063 case 0x00000491: return "IA32_VMX_VMFUNC";
1064 case 0x000004c1: return "IA32_A_PMC0";
1065 case 0x000004c2: return "IA32_A_PMC1";
1066 case 0x000004c3: return "IA32_A_PMC2";
1067 case 0x000004c4: return "IA32_A_PMC3";
1068 case 0x000004c5: return "IA32_A_PMC4";
1069 case 0x000004c6: return "IA32_A_PMC5";
1070 case 0x000004c7: return "IA32_A_PMC6";
1071 case 0x000004c8: return "IA32_A_PMC7";
1072 case 0x000004f8: return "C2_UNK_0000_04f8"; /* Core2_Penryn. */
1073 case 0x000004f9: return "C2_UNK_0000_04f9"; /* Core2_Penryn. */
1074 case 0x000004fa: return "C2_UNK_0000_04fa"; /* Core2_Penryn. */
1075 case 0x000004fb: return "C2_UNK_0000_04fb"; /* Core2_Penryn. */
1076 case 0x000004fc: return "C2_UNK_0000_04fc"; /* Core2_Penryn. */
1077 case 0x000004fd: return "C2_UNK_0000_04fd"; /* Core2_Penryn. */
1078 case 0x000004fe: return "C2_UNK_0000_04fe"; /* Core2_Penryn. */
1079 case 0x000004ff: return "C2_UNK_0000_04ff"; /* Core2_Penryn. */
1080 case 0x00000502: return "I7_SB_UNK_0000_0502";
1081 case 0x00000590: return "C2_UNK_0000_0590"; /* Core2_Penryn. */
1082 case 0x00000591: return "C2_UNK_0000_0591"; /* Core2_Penryn. */
1083 case 0x000005a0: return "C2_PECI_CTL"; /* Core2_Penryn. */
1084 case 0x000005a1: return "C2_UNK_0000_05a1"; /* Core2_Penryn. */
1085 case 0x00000600: return "IA32_DS_AREA";
1086 case 0x00000601: return "I7_SB_MSR_VR_CURRENT_CONFIG"; /* SandyBridge, IvyBridge. */
1087 case 0x00000602: return "I7_IB_UNK_0000_0602";
1088 case 0x00000603: return "I7_SB_MSR_VR_MISC_CONFIG"; /* SandyBridge, IvyBridge. */
1089 case 0x00000604: return "I7_IB_UNK_0000_0602";
1090 case 0x00000606: return "I7_SB_MSR_RAPL_POWER_UNIT"; /* SandyBridge, IvyBridge. */
1091 case 0x00000609: return "I7_SB_UNK_0000_0609"; /* SandyBridge (non EP). */
1092 case 0x0000060a: return "I7_SB_MSR_PKGC3_IRTL"; /* SandyBridge, IvyBridge. */
1093 case 0x0000060b: return "I7_SB_MSR_PKGC6_IRTL"; /* SandyBridge, IvyBridge. */
1094 case 0x0000060c: return "I7_SB_MSR_PKGC7_IRTL"; /* SandyBridge, IvyBridge. */
1095 case 0x0000060d: return "I7_SB_MSR_PKG_C2_RESIDENCY"; /* SandyBridge, IvyBridge. */
1096 case 0x00000610: return "I7_SB_MSR_PKG_POWER_LIMIT";
1097 case 0x00000611: return "I7_SB_MSR_PKG_ENERGY_STATUS";
1098 case 0x00000613: return "I7_SB_MSR_PKG_PERF_STATUS";
1099 case 0x00000614: return "I7_SB_MSR_PKG_POWER_INFO";
1100 case 0x00000618: return "I7_SB_MSR_DRAM_POWER_LIMIT";
1101 case 0x00000619: return "I7_SB_MSR_DRAM_ENERGY_STATUS";
1102 case 0x0000061b: return "I7_SB_MSR_DRAM_PERF_STATUS";
1103 case 0x0000061c: return "I7_SB_MSR_DRAM_POWER_INFO";
1104 case 0x00000638: return "I7_SB_MSR_PP0_POWER_LIMIT";
1105 case 0x00000639: return "I7_SB_MSR_PP0_ENERGY_STATUS";
1106 case 0x0000063a: return "I7_SB_MSR_PP0_POLICY";
1107 case 0x0000063b: return "I7_SB_MSR_PP0_PERF_STATUS";
1108 case 0x00000640: return "I7_HW_MSR_PP0_POWER_LIMIT";
1109 case 0x00000641: return "I7_HW_MSR_PP0_ENERGY_STATUS";
1110 case 0x00000642: return "I7_HW_MSR_PP0_POLICY";
1111 case 0x00000648: return "I7_IB_MSR_CONFIG_TDP_NOMINAL";
1112 case 0x00000649: return "I7_IB_MSR_CONFIG_TDP_LEVEL1";
1113 case 0x0000064a: return "I7_IB_MSR_CONFIG_TDP_LEVEL2";
1114 case 0x0000064b: return "I7_IB_MSR_CONFIG_TDP_CONTROL";
1115 case 0x0000064c: return "I7_IB_MSR_TURBO_ACTIVATION_RATIO";
1116 case 0x00000660: return "SILV_CORE_C1_RESIDENCY";
1117 case 0x00000661: return "SILV_UNK_0000_0661";
1118 case 0x00000662: return "SILV_UNK_0000_0662";
1119 case 0x00000663: return "SILV_UNK_0000_0663";
1120 case 0x00000664: return "SILV_UNK_0000_0664";
1121 case 0x00000665: return "SILV_UNK_0000_0665";
1122 case 0x00000666: return "SILV_UNK_0000_0666";
1123 case 0x00000667: return "SILV_UNK_0000_0667";
1124 case 0x00000668: return "SILV_UNK_0000_0668";
1125 case 0x00000669: return "SILV_UNK_0000_0669";
1126 case 0x0000066a: return "SILV_UNK_0000_066a";
1127 case 0x0000066b: return "SILV_UNK_0000_066b";
1128 case 0x0000066c: return "SILV_UNK_0000_066c";
1129 case 0x0000066d: return "SILV_UNK_0000_066d";
1130 case 0x0000066e: return "SILV_UNK_0000_066e";
1131 case 0x0000066f: return "SILV_UNK_0000_066f";
1132 case 0x00000670: return "SILV_UNK_0000_0670";
1133 case 0x00000671: return "SILV_UNK_0000_0671";
1134 case 0x00000672: return "SILV_UNK_0000_0672";
1135 case 0x00000673: return "SILV_UNK_0000_0673";
1136 case 0x00000674: return "SILV_UNK_0000_0674";
1137 case 0x00000675: return "SILV_UNK_0000_0675";
1138 case 0x00000676: return "SILV_UNK_0000_0676";
1139 case 0x00000677: return "SILV_UNK_0000_0677";
1140
1141 case 0x00000680: return "MSR_LASTBRANCH_0_FROM_IP";
1142 case 0x00000681: return "MSR_LASTBRANCH_1_FROM_IP";
1143 case 0x00000682: return "MSR_LASTBRANCH_2_FROM_IP";
1144 case 0x00000683: return "MSR_LASTBRANCH_3_FROM_IP";
1145 case 0x00000684: return "MSR_LASTBRANCH_4_FROM_IP";
1146 case 0x00000685: return "MSR_LASTBRANCH_5_FROM_IP";
1147 case 0x00000686: return "MSR_LASTBRANCH_6_FROM_IP";
1148 case 0x00000687: return "MSR_LASTBRANCH_7_FROM_IP";
1149 case 0x00000688: return "MSR_LASTBRANCH_8_FROM_IP";
1150 case 0x00000689: return "MSR_LASTBRANCH_9_FROM_IP";
1151 case 0x0000068a: return "MSR_LASTBRANCH_10_FROM_IP";
1152 case 0x0000068b: return "MSR_LASTBRANCH_11_FROM_IP";
1153 case 0x0000068c: return "MSR_LASTBRANCH_12_FROM_IP";
1154 case 0x0000068d: return "MSR_LASTBRANCH_13_FROM_IP";
1155 case 0x0000068e: return "MSR_LASTBRANCH_14_FROM_IP";
1156 case 0x0000068f: return "MSR_LASTBRANCH_15_FROM_IP";
1157 case 0x000006c0: return "MSR_LASTBRANCH_0_TO_IP";
1158 case 0x000006c1: return "MSR_LASTBRANCH_1_TO_IP";
1159 case 0x000006c2: return "MSR_LASTBRANCH_2_TO_IP";
1160 case 0x000006c3: return "MSR_LASTBRANCH_3_TO_IP";
1161 case 0x000006c4: return "MSR_LASTBRANCH_4_TO_IP";
1162 case 0x000006c5: return "MSR_LASTBRANCH_5_TO_IP";
1163 case 0x000006c6: return "MSR_LASTBRANCH_6_TO_IP";
1164 case 0x000006c7: return "MSR_LASTBRANCH_7_TO_IP";
1165 case 0x000006c8: return "MSR_LASTBRANCH_8_TO_IP";
1166 case 0x000006c9: return "MSR_LASTBRANCH_9_TO_IP";
1167 case 0x000006ca: return "MSR_LASTBRANCH_10_TO_IP";
1168 case 0x000006cb: return "MSR_LASTBRANCH_11_TO_IP";
1169 case 0x000006cc: return "MSR_LASTBRANCH_12_TO_IP";
1170 case 0x000006cd: return "MSR_LASTBRANCH_13_TO_IP";
1171 case 0x000006ce: return "MSR_LASTBRANCH_14_TO_IP";
1172 case 0x000006cf: return "MSR_LASTBRANCH_15_TO_IP";
1173 case 0x000006e0: return "IA32_TSC_DEADLINE";
1174
1175 case 0x00000768: return "SILV_UNK_0000_0768";
1176 case 0x00000769: return "SILV_UNK_0000_0769";
1177 case 0x0000076a: return "SILV_UNK_0000_076a";
1178 case 0x0000076b: return "SILV_UNK_0000_076b";
1179 case 0x0000076c: return "SILV_UNK_0000_076c";
1180 case 0x0000076d: return "SILV_UNK_0000_076d";
1181 case 0x0000076e: return "SILV_UNK_0000_076e";
1182
1183 case 0x00000c80: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "IA32_DEBUG_INTERFACE" : NULL; /* Mentioned in an intel dataskit called 4th-gen-core-family-desktop-vol-1-datasheet.pdf. */
1184 case 0x00000c81: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c81" : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
1185 case 0x00000c82: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c82" : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
1186 case 0x00000c83: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c83" : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
1187
1188 /* 0x1000..0x1004 seems to have been used by IBM 386 and 486 clones too. */
1189 case 0x00001000: return "P6_DEBUG_REGISTER_0";
1190 case 0x00001001: return "P6_DEBUG_REGISTER_1";
1191 case 0x00001002: return "P6_DEBUG_REGISTER_2";
1192 case 0x00001003: return "P6_DEBUG_REGISTER_3";
1193 case 0x00001004: return "P6_DEBUG_REGISTER_4";
1194 case 0x00001005: return "P6_DEBUG_REGISTER_5";
1195 case 0x00001006: return "P6_DEBUG_REGISTER_6";
1196 case 0x00001007: return "P6_DEBUG_REGISTER_7";
1197 case 0x0000103f: return "P6_UNK_0000_103f"; /* P6_M_Dothan. */
1198 case 0x000010cd: return "P6_UNK_0000_10cd"; /* P6_M_Dothan. */
1199
1200 case 0x00001107: return "VIA_UNK_0000_1107";
1201 case 0x0000110f: return "VIA_UNK_0000_110f";
1202 case 0x00001153: return "VIA_UNK_0000_1153";
1203 case 0x00001200: return "VIA_UNK_0000_1200";
1204 case 0x00001201: return "VIA_UNK_0000_1201";
1205 case 0x00001202: return "VIA_UNK_0000_1202";
1206 case 0x00001203: return "VIA_UNK_0000_1203";
1207 case 0x00001204: return "VIA_UNK_0000_1204";
1208 case 0x00001205: return "VIA_UNK_0000_1205";
1209 case 0x00001206: return "VIA_ALT_VENDOR_EBX";
1210 case 0x00001207: return "VIA_ALT_VENDOR_ECDX";
1211 case 0x00001208: return "VIA_UNK_0000_1208";
1212 case 0x00001209: return "VIA_UNK_0000_1209";
1213 case 0x0000120a: return "VIA_UNK_0000_120a";
1214 case 0x0000120b: return "VIA_UNK_0000_120b";
1215 case 0x0000120c: return "VIA_UNK_0000_120c";
1216 case 0x0000120d: return "VIA_UNK_0000_120d";
1217 case 0x0000120e: return "VIA_UNK_0000_120e";
1218 case 0x0000120f: return "VIA_UNK_0000_120f";
1219 case 0x00001210: return "VIA_UNK_0000_1210";
1220 case 0x00001211: return "VIA_UNK_0000_1211";
1221 case 0x00001212: return "VIA_UNK_0000_1212";
1222 case 0x00001213: return "VIA_UNK_0000_1213";
1223 case 0x00001214: return "VIA_UNK_0000_1214";
1224 case 0x00001220: return "VIA_UNK_0000_1220";
1225 case 0x00001221: return "VIA_UNK_0000_1221";
1226 case 0x00001230: return "VIA_UNK_0000_1230";
1227 case 0x00001231: return "VIA_UNK_0000_1231";
1228 case 0x00001232: return "VIA_UNK_0000_1232";
1229 case 0x00001233: return "VIA_UNK_0000_1233";
1230 case 0x00001234: return "VIA_UNK_0000_1234";
1231 case 0x00001235: return "VIA_UNK_0000_1235";
1232 case 0x00001236: return "VIA_UNK_0000_1236";
1233 case 0x00001237: return "VIA_UNK_0000_1237";
1234 case 0x00001238: return "VIA_UNK_0000_1238";
1235 case 0x00001239: return "VIA_UNK_0000_1239";
1236 case 0x00001240: return "VIA_UNK_0000_1240";
1237 case 0x00001241: return "VIA_UNK_0000_1241";
1238 case 0x00001243: return "VIA_UNK_0000_1243";
1239 case 0x00001245: return "VIA_UNK_0000_1245";
1240 case 0x00001246: return "VIA_UNK_0000_1246";
1241 case 0x00001247: return "VIA_UNK_0000_1247";
1242 case 0x00001248: return "VIA_UNK_0000_1248";
1243 case 0x00001249: return "VIA_UNK_0000_1249";
1244 case 0x0000124a: return "VIA_UNK_0000_124a";
1245
1246 case 0x00001301: return "VIA_UNK_0000_1301";
1247 case 0x00001302: return "VIA_UNK_0000_1302";
1248 case 0x00001303: return "VIA_UNK_0000_1303";
1249 case 0x00001304: return "VIA_UNK_0000_1304";
1250 case 0x00001305: return "VIA_UNK_0000_1305";
1251 case 0x00001306: return "VIA_UNK_0000_1306";
1252 case 0x00001307: return "VIA_UNK_0000_1307";
1253 case 0x00001308: return "VIA_UNK_0000_1308";
1254 case 0x00001309: return "VIA_UNK_0000_1309";
1255 case 0x0000130d: return "VIA_UNK_0000_130d";
1256 case 0x0000130e: return "VIA_UNK_0000_130e";
1257 case 0x00001312: return "VIA_UNK_0000_1312";
1258 case 0x00001315: return "VIA_UNK_0000_1315";
1259 case 0x00001317: return "VIA_UNK_0000_1317";
1260 case 0x00001318: return "VIA_UNK_0000_1318";
1261 case 0x0000131a: return "VIA_UNK_0000_131a";
1262 case 0x0000131b: return "VIA_UNK_0000_131b";
1263 case 0x00001402: return "VIA_UNK_0000_1402";
1264 case 0x00001403: return "VIA_UNK_0000_1403";
1265 case 0x00001404: return "VIA_UNK_0000_1404";
1266 case 0x00001405: return "VIA_UNK_0000_1405";
1267 case 0x00001406: return "VIA_UNK_0000_1406";
1268 case 0x00001407: return "VIA_UNK_0000_1407";
1269 case 0x00001410: return "VIA_UNK_0000_1410";
1270 case 0x00001411: return "VIA_UNK_0000_1411";
1271 case 0x00001412: return "VIA_UNK_0000_1412";
1272 case 0x00001413: return "VIA_UNK_0000_1413";
1273 case 0x00001414: return "VIA_UNK_0000_1414";
1274 case 0x00001415: return "VIA_UNK_0000_1415";
1275 case 0x00001416: return "VIA_UNK_0000_1416";
1276 case 0x00001417: return "VIA_UNK_0000_1417";
1277 case 0x00001418: return "VIA_UNK_0000_1418";
1278 case 0x00001419: return "VIA_UNK_0000_1419";
1279 case 0x0000141a: return "VIA_UNK_0000_141a";
1280 case 0x0000141b: return "VIA_UNK_0000_141b";
1281 case 0x0000141c: return "VIA_UNK_0000_141c";
1282 case 0x0000141d: return "VIA_UNK_0000_141d";
1283 case 0x0000141e: return "VIA_UNK_0000_141e";
1284 case 0x0000141f: return "VIA_UNK_0000_141f";
1285 case 0x00001420: return "VIA_UNK_0000_1420";
1286 case 0x00001421: return "VIA_UNK_0000_1421";
1287 case 0x00001422: return "VIA_UNK_0000_1422";
1288 case 0x00001423: return "VIA_UNK_0000_1423";
1289 case 0x00001424: return "VIA_UNK_0000_1424";
1290 case 0x00001425: return "VIA_UNK_0000_1425";
1291 case 0x00001426: return "VIA_UNK_0000_1426";
1292 case 0x00001427: return "VIA_UNK_0000_1427";
1293 case 0x00001428: return "VIA_UNK_0000_1428";
1294 case 0x00001429: return "VIA_UNK_0000_1429";
1295 case 0x0000142a: return "VIA_UNK_0000_142a";
1296 case 0x0000142b: return "VIA_UNK_0000_142b";
1297 case 0x0000142c: return "VIA_UNK_0000_142c";
1298 case 0x0000142d: return "VIA_UNK_0000_142d";
1299 case 0x0000142e: return "VIA_UNK_0000_142e";
1300 case 0x0000142f: return "VIA_UNK_0000_142f";
1301 case 0x00001434: return "VIA_UNK_0000_1434";
1302 case 0x00001435: return "VIA_UNK_0000_1435";
1303 case 0x00001436: return "VIA_UNK_0000_1436";
1304 case 0x00001437: return "VIA_UNK_0000_1437";
1305 case 0x00001438: return "VIA_UNK_0000_1438";
1306 case 0x0000143a: return "VIA_UNK_0000_143a";
1307 case 0x0000143c: return "VIA_UNK_0000_143c";
1308 case 0x0000143d: return "VIA_UNK_0000_143d";
1309 case 0x00001440: return "VIA_UNK_0000_1440";
1310 case 0x00001441: return "VIA_UNK_0000_1441";
1311 case 0x00001442: return "VIA_UNK_0000_1442";
1312 case 0x00001449: return "VIA_UNK_0000_1449";
1313 case 0x00001450: return "VIA_UNK_0000_1450";
1314 case 0x00001451: return "VIA_UNK_0000_1451";
1315 case 0x00001452: return "VIA_UNK_0000_1452";
1316 case 0x00001453: return "VIA_UNK_0000_1453";
1317 case 0x00001460: return "VIA_UNK_0000_1460";
1318 case 0x00001461: return "VIA_UNK_0000_1461";
1319 case 0x00001462: return "VIA_UNK_0000_1462";
1320 case 0x00001463: return "VIA_UNK_0000_1463";
1321 case 0x00001465: return "VIA_UNK_0000_1465";
1322 case 0x00001466: return "VIA_UNK_0000_1466";
1323 case 0x00001470: return "VIA_UNK_0000_1470";
1324 case 0x00001471: return "VIA_UNK_0000_1471";
1325 case 0x00001480: return "VIA_UNK_0000_1480";
1326 case 0x00001481: return "VIA_UNK_0000_1481";
1327 case 0x00001482: return "VIA_UNK_0000_1482";
1328 case 0x00001483: return "VIA_UNK_0000_1483";
1329 case 0x00001484: return "VIA_UNK_0000_1484";
1330 case 0x00001485: return "VIA_UNK_0000_1485";
1331 case 0x00001486: return "VIA_UNK_0000_1486";
1332 case 0x00001490: return "VIA_UNK_0000_1490";
1333 case 0x00001491: return "VIA_UNK_0000_1491";
1334 case 0x00001492: return "VIA_UNK_0000_1492";
1335 case 0x00001493: return "VIA_UNK_0000_1493";
1336 case 0x00001494: return "VIA_UNK_0000_1494";
1337 case 0x00001495: return "VIA_UNK_0000_1495";
1338 case 0x00001496: return "VIA_UNK_0000_1496";
1339 case 0x00001497: return "VIA_UNK_0000_1497";
1340 case 0x00001498: return "VIA_UNK_0000_1498";
1341 case 0x00001499: return "VIA_UNK_0000_1499";
1342 case 0x0000149a: return "VIA_UNK_0000_149a";
1343 case 0x0000149b: return "VIA_UNK_0000_149b";
1344 case 0x0000149c: return "VIA_UNK_0000_149c";
1345 case 0x0000149f: return "VIA_UNK_0000_149f";
1346 case 0x00001523: return "VIA_UNK_0000_1523";
1347
1348 case 0x00002000: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR0" : NULL;
1349 case 0x00002002: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR2" : NULL;
1350 case 0x00002003: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR3" : NULL;
1351 case 0x00002004: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR4" : NULL;
1352 case 0x0000203f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_203f" /* P6_M_Dothan. */ : NULL;
1353 case 0x000020cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_20cd" /* P6_M_Dothan. */ : NULL;
1354 case 0x0000303f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_303f" /* P6_M_Dothan. */ : NULL;
1355 case 0x000030cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_30cd" /* P6_M_Dothan. */ : NULL;
1356
1357 case 0x0000317a: return "VIA_UNK_0000_317a";
1358 case 0x0000317b: return "VIA_UNK_0000_317b";
1359 case 0x0000317d: return "VIA_UNK_0000_317d";
1360 case 0x0000317e: return "VIA_UNK_0000_317e";
1361 case 0x0000317f: return "VIA_UNK_0000_317f";
1362 case 0x80000198: return "VIA_UNK_8000_0198";
1363
1364 case 0xc0000080: return "AMD64_EFER";
1365 case 0xc0000081: return "AMD64_STAR";
1366 case 0xc0000082: return "AMD64_STAR64";
1367 case 0xc0000083: return "AMD64_STARCOMPAT";
1368 case 0xc0000084: return "AMD64_SYSCALL_FLAG_MASK";
1369 case 0xc0000100: return "AMD64_FS_BASE";
1370 case 0xc0000101: return "AMD64_GS_BASE";
1371 case 0xc0000102: return "AMD64_KERNEL_GS_BASE";
1372 case 0xc0000103: return "AMD64_TSC_AUX";
1373 case 0xc0000104: return "AMD_15H_TSC_RATE";
1374 case 0xc0000105: return "AMD_15H_LWP_CFG"; /* Only Family 15h? */
1375 case 0xc0000106: return "AMD_15H_LWP_CBADDR"; /* Only Family 15h? */
1376 case 0xc0000408: return "AMD_10H_MC4_MISC1";
1377 case 0xc0000409: return "AMD_10H_MC4_MISC2";
1378 case 0xc000040a: return "AMD_10H_MC4_MISC3";
1379 case 0xc000040b: return "AMD_10H_MC4_MISC4";
1380 case 0xc000040c: return "AMD_10H_MC4_MISC5";
1381 case 0xc000040d: return "AMD_10H_MC4_MISC6";
1382 case 0xc000040e: return "AMD_10H_MC4_MISC7";
1383 case 0xc000040f: return "AMD_10H_MC4_MISC8";
1384 case 0xc0010000: return "AMD_K8_PERF_CTL_0";
1385 case 0xc0010001: return "AMD_K8_PERF_CTL_1";
1386 case 0xc0010002: return "AMD_K8_PERF_CTL_2";
1387 case 0xc0010003: return "AMD_K8_PERF_CTL_3";
1388 case 0xc0010004: return "AMD_K8_PERF_CTR_0";
1389 case 0xc0010005: return "AMD_K8_PERF_CTR_1";
1390 case 0xc0010006: return "AMD_K8_PERF_CTR_2";
1391 case 0xc0010007: return "AMD_K8_PERF_CTR_3";
1392 case 0xc0010010: return "AMD_K8_SYS_CFG";
1393 case 0xc0010015: return "AMD_K8_HW_CFG";
1394 case 0xc0010016: return "AMD_K8_IORR_BASE_0";
1395 case 0xc0010017: return "AMD_K8_IORR_MASK_0";
1396 case 0xc0010018: return "AMD_K8_IORR_BASE_1";
1397 case 0xc0010019: return "AMD_K8_IORR_MASK_1";
1398 case 0xc001001a: return "AMD_K8_TOP_MEM";
1399 case 0xc001001d: return "AMD_K8_TOP_MEM2";
1400 case 0xc001001e: return "AMD_K8_MANID";
1401 case 0xc001001f: return "AMD_K8_NB_CFG1";
1402 case 0xc0010020: return "AMD_K8_PATCH_LOADER";
1403 case 0xc0010021: return "AMD_K8_UNK_c001_0021";
1404 case 0xc0010022: return "AMD_K8_MC_XCPT_REDIR";
1405 case 0xc0010028: return "AMD_K8_UNK_c001_0028";
1406 case 0xc0010029: return "AMD_K8_UNK_c001_0029";
1407 case 0xc001002a: return "AMD_K8_UNK_c001_002a";
1408 case 0xc001002b: return "AMD_K8_UNK_c001_002b";
1409 case 0xc001002c: return "AMD_K8_UNK_c001_002c";
1410 case 0xc001002d: return "AMD_K8_UNK_c001_002d";
1411 case 0xc0010030: return "AMD_K8_CPU_NAME_0";
1412 case 0xc0010031: return "AMD_K8_CPU_NAME_1";
1413 case 0xc0010032: return "AMD_K8_CPU_NAME_2";
1414 case 0xc0010033: return "AMD_K8_CPU_NAME_3";
1415 case 0xc0010034: return "AMD_K8_CPU_NAME_4";
1416 case 0xc0010035: return "AMD_K8_CPU_NAME_5";
1417 case 0xc001003e: return "AMD_K8_HTC";
1418 case 0xc001003f: return "AMD_K8_STC";
1419 case 0xc0010041: return "AMD_K8_FIDVID_CTL";
1420 case 0xc0010042: return "AMD_K8_FIDVID_STATUS";
1421 case 0xc0010043: return "AMD_K8_THERMTRIP_STATUS"; /* BDKG says it was removed in K8 revision C.*/
1422 case 0xc0010044: return "AMD_K8_MC_CTL_MASK_0";
1423 case 0xc0010045: return "AMD_K8_MC_CTL_MASK_1";
1424 case 0xc0010046: return "AMD_K8_MC_CTL_MASK_2";
1425 case 0xc0010047: return "AMD_K8_MC_CTL_MASK_3";
1426 case 0xc0010048: return "AMD_K8_MC_CTL_MASK_4";
1427 case 0xc0010049: return "AMD_K8_MC_CTL_MASK_5";
1428 case 0xc001004a: return "AMD_K8_MC_CTL_MASK_6";
1429 //case 0xc001004b: return "AMD_K8_MC_CTL_MASK_7";
1430 case 0xc0010050: return "AMD_K8_SMI_ON_IO_TRAP_0";
1431 case 0xc0010051: return "AMD_K8_SMI_ON_IO_TRAP_1";
1432 case 0xc0010052: return "AMD_K8_SMI_ON_IO_TRAP_2";
1433 case 0xc0010053: return "AMD_K8_SMI_ON_IO_TRAP_3";
1434 case 0xc0010054: return "AMD_K8_SMI_ON_IO_TRAP_CTL_STS";
1435 case 0xc0010055: return "AMD_K8_INT_PENDING_MSG";
1436 case 0xc0010056: return "AMD_K8_SMI_TRIGGER_IO_CYCLE";
1437 case 0xc0010057: return "AMD_10H_UNK_c001_0057";
1438 case 0xc0010058: return "AMD_10H_MMIO_CFG_BASE_ADDR";
1439 case 0xc0010059: return "AMD_10H_TRAP_CTL?"; /* Undocumented, only one google hit. */
1440 case 0xc001005a: return "AMD_10H_UNK_c001_005a";
1441 case 0xc001005b: return "AMD_10H_UNK_c001_005b";
1442 case 0xc001005c: return "AMD_10H_UNK_c001_005c";
1443 case 0xc001005d: return "AMD_10H_UNK_c001_005d";
1444 case 0xc0010060: return "AMD_K8_BIST_RESULT"; /* BDKG says it as introduced with revision F. */
1445 case 0xc0010061: return "AMD_10H_P_ST_CUR_LIM";
1446 case 0xc0010062: return "AMD_10H_P_ST_CTL";
1447 case 0xc0010063: return "AMD_10H_P_ST_STS";
1448 case 0xc0010064: return "AMD_10H_P_ST_0";
1449 case 0xc0010065: return "AMD_10H_P_ST_1";
1450 case 0xc0010066: return "AMD_10H_P_ST_2";
1451 case 0xc0010067: return "AMD_10H_P_ST_3";
1452 case 0xc0010068: return "AMD_10H_P_ST_4";
1453 case 0xc0010069: return "AMD_10H_P_ST_5";
1454 case 0xc001006a: return "AMD_10H_P_ST_6";
1455 case 0xc001006b: return "AMD_10H_P_ST_7";
1456 case 0xc0010070: return "AMD_10H_COFVID_CTL";
1457 case 0xc0010071: return "AMD_10H_COFVID_STS";
1458 case 0xc0010073: return "AMD_10H_C_ST_IO_BASE_ADDR";
1459 case 0xc0010074: return "AMD_10H_CPU_WD_TMR_CFG";
1460 // case 0xc0010075: return "AMD_15H_APML_TDP_LIM";
1461 // case 0xc0010077: return "AMD_15H_CPU_PWR_IN_TDP";
1462 // case 0xc0010078: return "AMD_15H_PWR_AVG_PERIOD";
1463 // case 0xc0010079: return "AMD_15H_DRAM_CTR_CMD_THR";
1464 // case 0xc0010080: return "AMD_16H_FSFM_ACT_CNT_0";
1465 // case 0xc0010081: return "AMD_16H_FSFM_REF_CNT_0";
1466 case 0xc0010111: return "AMD_K8_SMM_BASE";
1467 case 0xc0010112: return "AMD_K8_SMM_ADDR";
1468 case 0xc0010113: return "AMD_K8_SMM_MASK";
1469 case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_CR" : "AMD_K8_UNK_c001_0114";
1470 case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AMD_K8_IGNNE" : "AMD_K8_UNK_c001_0115";
1471 case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AMD_K8_SMM_CTL" : "AMD_K8_UNK_c001_0116";
1472 case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_HSAVE_PA" : "AMD_K8_UNK_c001_0117";
1473 case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_10H_VM_LOCK_KEY" : "AMD_K8_UNK_c001_0118";
1474 case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AMD_10H_SSM_LOCK_KEY" : "AMD_K8_UNK_c001_0119";
1475 case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AMD_10H_LOCAL_SMI_STS" : "AMD_K8_UNK_c001_011a";
1476 case 0xc001011b: return "AMD_K8_UNK_c001_011b";
1477 case 0xc001011c: return "AMD_K8_UNK_c001_011c";
1478 case 0xc0010140: return "AMD_10H_OSVW_ID_LEN";
1479 case 0xc0010141: return "AMD_10H_OSVW_STS";
1480 case 0xc0010200: return "AMD_K8_PERF_CTL_0";
1481 case 0xc0010202: return "AMD_K8_PERF_CTL_1";
1482 case 0xc0010204: return "AMD_K8_PERF_CTL_2";
1483 case 0xc0010206: return "AMD_K8_PERF_CTL_3";
1484 case 0xc0010208: return "AMD_K8_PERF_CTL_4";
1485 case 0xc001020a: return "AMD_K8_PERF_CTL_5";
1486 //case 0xc001020c: return "AMD_K8_PERF_CTL_6";
1487 //case 0xc001020e: return "AMD_K8_PERF_CTL_7";
1488 case 0xc0010201: return "AMD_K8_PERF_CTR_0";
1489 case 0xc0010203: return "AMD_K8_PERF_CTR_1";
1490 case 0xc0010205: return "AMD_K8_PERF_CTR_2";
1491 case 0xc0010207: return "AMD_K8_PERF_CTR_3";
1492 case 0xc0010209: return "AMD_K8_PERF_CTR_4";
1493 case 0xc001020b: return "AMD_K8_PERF_CTR_5";
1494 //case 0xc001020d: return "AMD_K8_PERF_CTR_6";
1495 //case 0xc001020f: return "AMD_K8_PERF_CTR_7";
1496 case 0xc0010230: return "AMD_16H_L2I_PERF_CTL_0";
1497 case 0xc0010232: return "AMD_16H_L2I_PERF_CTL_1";
1498 case 0xc0010234: return "AMD_16H_L2I_PERF_CTL_2";
1499 case 0xc0010236: return "AMD_16H_L2I_PERF_CTL_3";
1500 //case 0xc0010238: return "AMD_16H_L2I_PERF_CTL_4";
1501 //case 0xc001023a: return "AMD_16H_L2I_PERF_CTL_5";
1502 //case 0xc001030c: return "AMD_16H_L2I_PERF_CTL_6";
1503 //case 0xc001023e: return "AMD_16H_L2I_PERF_CTL_7";
1504 case 0xc0010231: return "AMD_16H_L2I_PERF_CTR_0";
1505 case 0xc0010233: return "AMD_16H_L2I_PERF_CTR_1";
1506 case 0xc0010235: return "AMD_16H_L2I_PERF_CTR_2";
1507 case 0xc0010237: return "AMD_16H_L2I_PERF_CTR_3";
1508 //case 0xc0010239: return "AMD_16H_L2I_PERF_CTR_4";
1509 //case 0xc001023b: return "AMD_16H_L2I_PERF_CTR_5";
1510 //case 0xc001023d: return "AMD_16H_L2I_PERF_CTR_6";
1511 //case 0xc001023f: return "AMD_16H_L2I_PERF_CTR_7";
1512 case 0xc0010240: return "AMD_15H_NB_PERF_CTL_0";
1513 case 0xc0010242: return "AMD_15H_NB_PERF_CTL_1";
1514 case 0xc0010244: return "AMD_15H_NB_PERF_CTL_2";
1515 case 0xc0010246: return "AMD_15H_NB_PERF_CTL_3";
1516 //case 0xc0010248: return "AMD_15H_NB_PERF_CTL_4";
1517 //case 0xc001024a: return "AMD_15H_NB_PERF_CTL_5";
1518 //case 0xc001024c: return "AMD_15H_NB_PERF_CTL_6";
1519 //case 0xc001024e: return "AMD_15H_NB_PERF_CTL_7";
1520 case 0xc0010241: return "AMD_15H_NB_PERF_CTR_0";
1521 case 0xc0010243: return "AMD_15H_NB_PERF_CTR_1";
1522 case 0xc0010245: return "AMD_15H_NB_PERF_CTR_2";
1523 case 0xc0010247: return "AMD_15H_NB_PERF_CTR_3";
1524 //case 0xc0010249: return "AMD_15H_NB_PERF_CTR_4";
1525 //case 0xc001024b: return "AMD_15H_NB_PERF_CTR_5";
1526 //case 0xc001024d: return "AMD_15H_NB_PERF_CTR_6";
1527 //case 0xc001024f: return "AMD_15H_NB_PERF_CTR_7";
1528 case 0xc0011000: return "AMD_K7_MCODE_CTL";
1529 case 0xc0011001: return "AMD_K7_APIC_CLUSTER_ID"; /* Mentioned in BKDG (r3.00) for fam16h when describing EBL_CR_POWERON. */
1530 case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD07" : NULL;
1531 case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD06" : NULL;
1532 case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD01" : NULL;
1533 case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_EXT01" : NULL;
1534 case 0xc0011006: return "AMD_K7_DEBUG_STS?";
1535 case 0xc0011007: return "AMD_K7_BH_TRACE_BASE?";
1536 case 0xc0011008: return "AMD_K7_BH_TRACE_PTR?";
1537 case 0xc0011009: return "AMD_K7_BH_TRACE_LIM?";
1538 case 0xc001100a: return "AMD_K7_HDT_CFG?";
1539 case 0xc001100b: return "AMD_K7_FAST_FLUSH_COUNT?";
1540 case 0xc001100c: return "AMD_K7_NODE_ID";
1541 case 0xc001100d: return "AMD_K8_LOGICAL_CPUS_NUM?";
1542 case 0xc001100e: return "AMD_K8_WRMSR_BP?";
1543 case 0xc001100f: return "AMD_K8_WRMSR_BP_MASK?";
1544 case 0xc0011010: return "AMD_K8_BH_TRACE_CTL?";
1545 case 0xc0011011: return "AMD_K8_BH_TRACE_USRD?";
1546 case 0xc0011012: return "AMD_K7_UNK_c001_1012";
1547 case 0xc0011013: return "AMD_K7_UNK_c001_1013";
1548 case 0xc0011014: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP?" : "AMD_K7_MOBIL_DEBUG?";
1549 case 0xc0011015: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP_MASK?" : NULL;
1550 case 0xc0011016: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL?" : NULL;
1551 case 0xc0011017: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL_MASK?" : NULL;
1552 case 0xc0011018: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_CTL?" : NULL;
1553 case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR1_ADDR_MASK" : NULL;
1554 case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR2_ADDR_MASK" : NULL;
1555 case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR3_ADDR_MASK" : NULL;
1556 case 0xc001101d: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_BIST?" : NULL;
1557 case 0xc001101e: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_THERMTRIP_2?" : NULL;
1558 case 0xc001101f: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_CFG?" : NULL;
1559 case 0xc0011020: return "AMD_K7_LS_CFG";
1560 case 0xc0011021: return "AMD_K7_IC_CFG";
1561 case 0xc0011022: return "AMD_K7_DC_CFG";
1562 case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_CU_CFG" : "AMD_K7_BU_CFG";
1563 case 0xc0011024: return "AMD_K7_DEBUG_CTL_2?";
1564 case 0xc0011025: return "AMD_K7_DR0_DATA_MATCH?";
1565 case 0xc0011026: return "AMD_K7_DR0_DATA_MATCH?";
1566 case 0xc0011027: return "AMD_K7_DR0_ADDR_MASK";
1567 case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_FP_CFG"
1568 : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) ? "AMD_10H_UNK_c001_1028"
1569 : NULL;
1570 case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_DC_CFG"
1571 : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) ? "AMD_10H_UNK_c001_1029"
1572 : NULL;
1573 case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_CU_CFG2"
1574 : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
1575 ? "AMD_10H_BU_CFG2" /* 10h & 16h */ : NULL;
1576 case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_CU_CFG3" : NULL;
1577 case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_EX_CFG" : NULL;
1578 case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_LS_CFG2" : NULL;
1579 case 0xc0011030: return "AMD_10H_IBS_FETCH_CTL";
1580 case 0xc0011031: return "AMD_10H_IBS_FETCH_LIN_ADDR";
1581 case 0xc0011032: return "AMD_10H_IBS_FETCH_PHYS_ADDR";
1582 case 0xc0011033: return "AMD_10H_IBS_OP_EXEC_CTL";
1583 case 0xc0011034: return "AMD_10H_IBS_OP_RIP";
1584 case 0xc0011035: return "AMD_10H_IBS_OP_DATA";
1585 case 0xc0011036: return "AMD_10H_IBS_OP_DATA2";
1586 case 0xc0011037: return "AMD_10H_IBS_OP_DATA3";
1587 case 0xc0011038: return "AMD_10H_IBS_DC_LIN_ADDR";
1588 case 0xc0011039: return "AMD_10H_IBS_DC_PHYS_ADDR";
1589 case 0xc001103a: return "AMD_10H_IBS_CTL";
1590 case 0xc001103b: return "AMD_14H_IBS_BR_TARGET";
1591
1592 case 0xc0011040: return "AMD_15H_UNK_c001_1040";
1593 case 0xc0011041: return "AMD_15H_UNK_c001_1041";
1594 case 0xc0011042: return "AMD_15H_UNK_c001_1042";
1595 case 0xc0011043: return "AMD_15H_UNK_c001_1043";
1596 case 0xc0011044: return "AMD_15H_UNK_c001_1044";
1597 case 0xc0011045: return "AMD_15H_UNK_c001_1045";
1598 case 0xc0011046: return "AMD_15H_UNK_c001_1046";
1599 case 0xc0011047: return "AMD_15H_UNK_c001_1047";
1600 case 0xc0011048: return "AMD_15H_UNK_c001_1048";
1601 case 0xc0011049: return "AMD_15H_UNK_c001_1049";
1602 case 0xc001104a: return "AMD_15H_UNK_c001_104a";
1603 case 0xc001104b: return "AMD_15H_UNK_c001_104b";
1604 case 0xc001104c: return "AMD_15H_UNK_c001_104c";
1605 case 0xc001104d: return "AMD_15H_UNK_c001_104d";
1606 case 0xc001104e: return "AMD_15H_UNK_c001_104e";
1607 case 0xc001104f: return "AMD_15H_UNK_c001_104f";
1608 case 0xc0011050: return "AMD_15H_UNK_c001_1050";
1609 case 0xc0011051: return "AMD_15H_UNK_c001_1051";
1610 case 0xc0011052: return "AMD_15H_UNK_c001_1052";
1611 case 0xc0011053: return "AMD_15H_UNK_c001_1053";
1612 case 0xc0011054: return "AMD_15H_UNK_c001_1054";
1613 case 0xc0011055: return "AMD_15H_UNK_c001_1055";
1614 case 0xc0011056: return "AMD_15H_UNK_c001_1056";
1615 case 0xc0011057: return "AMD_15H_UNK_c001_1057";
1616 case 0xc0011058: return "AMD_15H_UNK_c001_1058";
1617 case 0xc0011059: return "AMD_15H_UNK_c001_1059";
1618 case 0xc001105a: return "AMD_15H_UNK_c001_105a";
1619 case 0xc001105b: return "AMD_15H_UNK_c001_105b";
1620 case 0xc001105c: return "AMD_15H_UNK_c001_105c";
1621 case 0xc001105d: return "AMD_15H_UNK_c001_105d";
1622 case 0xc001105e: return "AMD_15H_UNK_c001_105e";
1623 case 0xc001105f: return "AMD_15H_UNK_c001_105f";
1624 case 0xc0011060: return "AMD_15H_UNK_c001_1060";
1625 case 0xc0011061: return "AMD_15H_UNK_c001_1061";
1626 case 0xc0011062: return "AMD_15H_UNK_c001_1062";
1627 case 0xc0011063: return "AMD_15H_UNK_c001_1063";
1628 case 0xc0011064: return "AMD_15H_UNK_c001_1064";
1629 case 0xc0011065: return "AMD_15H_UNK_c001_1065";
1630 case 0xc0011066: return "AMD_15H_UNK_c001_1066";
1631 case 0xc0011067: return "AMD_15H_UNK_c001_1067";
1632 case 0xc0011068: return "AMD_15H_UNK_c001_1068";
1633 case 0xc0011069: return "AMD_15H_UNK_c001_1069";
1634 case 0xc001106a: return "AMD_15H_UNK_c001_106a";
1635 case 0xc001106b: return "AMD_15H_UNK_c001_106b";
1636 case 0xc001106c: return "AMD_15H_UNK_c001_106c";
1637 case 0xc001106d: return "AMD_15H_UNK_c001_106d";
1638 case 0xc001106e: return "AMD_15H_UNK_c001_106e";
1639 case 0xc001106f: return "AMD_15H_UNK_c001_106f";
1640 case 0xc0011070: return "AMD_15H_UNK_c001_1070"; /* coreboot defines this, but with a numerical name. */
1641 case 0xc0011071: return "AMD_15H_UNK_c001_1071";
1642 case 0xc0011072: return "AMD_15H_UNK_c001_1072";
1643 case 0xc0011073: return "AMD_15H_UNK_c001_1073";
1644 case 0xc0011080: return "AMD_15H_UNK_c001_1080";
1645 }
1646
1647 /*
1648 * Uncore stuff on Sandy. Putting it here to avoid ugly microarch checks for each register.
1649 * Note! These are found on model 42 (2a) but not 45 (2d), the latter is the EP variant.
1650 */
1651 if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_SandyBridge)
1652 switch (uMsr)
1653 {
1654 case 0x00000700: return "MSR_UNC_CBO_0_PERFEVTSEL0";
1655 case 0x00000701: return "MSR_UNC_CBO_0_PERFEVTSEL1";
1656 case 0x00000702: return "MSR_UNC_CBO_0_PERFEVTSEL2?";
1657 case 0x00000703: return "MSR_UNC_CBO_0_PERFEVTSEL3?";
1658 case 0x00000704: return "MSR_UNC_CBO_0_UNK_4";
1659 case 0x00000705: return "MSR_UNC_CBO_0_UNK_5";
1660 case 0x00000706: return "MSR_UNC_CBO_0_PER_CTR0";
1661 case 0x00000707: return "MSR_UNC_CBO_0_PER_CTR1";
1662 case 0x00000708: return "MSR_UNC_CBO_0_PER_CTR2?";
1663 case 0x00000709: return "MSR_UNC_CBO_0_PER_CTR3?";
1664 case 0x00000710: return "MSR_UNC_CBO_1_PERFEVTSEL0";
1665 case 0x00000711: return "MSR_UNC_CBO_1_PERFEVTSEL1";
1666 case 0x00000712: return "MSR_UNC_CBO_1_PERFEVTSEL2?";
1667 case 0x00000713: return "MSR_UNC_CBO_1_PERFEVTSEL3?";
1668 case 0x00000714: return "MSR_UNC_CBO_1_UNK_4";
1669 case 0x00000715: return "MSR_UNC_CBO_1_UNK_5";
1670 case 0x00000716: return "MSR_UNC_CBO_1_PER_CTR0";
1671 case 0x00000717: return "MSR_UNC_CBO_1_PER_CTR1";
1672 case 0x00000718: return "MSR_UNC_CBO_1_PER_CTR2?";
1673 case 0x00000719: return "MSR_UNC_CBO_1_PER_CTR3?";
1674 case 0x00000720: return "MSR_UNC_CBO_2_PERFEVTSEL0";
1675 case 0x00000721: return "MSR_UNC_CBO_2_PERFEVTSEL1";
1676 case 0x00000722: return "MSR_UNC_CBO_2_PERFEVTSEL2?";
1677 case 0x00000723: return "MSR_UNC_CBO_2_PERFEVTSEL3?";
1678 case 0x00000724: return "MSR_UNC_CBO_2_UNK_4";
1679 case 0x00000725: return "MSR_UNC_CBO_2_UNK_5";
1680 case 0x00000726: return "MSR_UNC_CBO_2_PER_CTR0";
1681 case 0x00000727: return "MSR_UNC_CBO_2_PER_CTR1";
1682 case 0x00000728: return "MSR_UNC_CBO_2_PER_CTR2?";
1683 case 0x00000729: return "MSR_UNC_CBO_2_PER_CTR3?";
1684 case 0x00000730: return "MSR_UNC_CBO_3_PERFEVTSEL0";
1685 case 0x00000731: return "MSR_UNC_CBO_3_PERFEVTSEL1";
1686 case 0x00000732: return "MSR_UNC_CBO_3_PERFEVTSEL2?";
1687 case 0x00000733: return "MSR_UNC_CBO_3_PERFEVTSEL3?";
1688 case 0x00000734: return "MSR_UNC_CBO_3_UNK_4";
1689 case 0x00000735: return "MSR_UNC_CBO_3_UNK_5";
1690 case 0x00000736: return "MSR_UNC_CBO_3_PER_CTR0";
1691 case 0x00000737: return "MSR_UNC_CBO_3_PER_CTR1";
1692 case 0x00000738: return "MSR_UNC_CBO_3_PER_CTR2?";
1693 case 0x00000739: return "MSR_UNC_CBO_3_PER_CTR3?";
1694 case 0x00000740: return "MSR_UNC_CBO_4_PERFEVTSEL0?";
1695 case 0x00000741: return "MSR_UNC_CBO_4_PERFEVTSEL1?";
1696 case 0x00000742: return "MSR_UNC_CBO_4_PERFEVTSEL2?";
1697 case 0x00000743: return "MSR_UNC_CBO_4_PERFEVTSEL3?";
1698 case 0x00000744: return "MSR_UNC_CBO_4_UNK_4";
1699 case 0x00000745: return "MSR_UNC_CBO_4_UNK_5";
1700 case 0x00000746: return "MSR_UNC_CBO_4_PER_CTR0?";
1701 case 0x00000747: return "MSR_UNC_CBO_4_PER_CTR1?";
1702 case 0x00000748: return "MSR_UNC_CBO_4_PER_CTR2?";
1703 case 0x00000749: return "MSR_UNC_CBO_4_PER_CTR3?";
1704
1705 }
1706
1707 /*
1708 * Bunch of unknown sandy bridge registers. They might seem like the
1709 * nehalem based xeon stuff, but the layout doesn't match. I bet it's the
1710 * same kind of registes though (i.e. uncore (UNC)).
1711 *
1712 * Kudos to Intel for keeping these a secret! Many thanks guys!!
1713 */
1714 if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_SandyBridge)
1715 switch (uMsr)
1716 {
1717 case 0x00000a00: return "I7_SB_UNK_0000_0a00"; case 0x00000a01: return "I7_SB_UNK_0000_0a01";
1718 case 0x00000a02: return "I7_SB_UNK_0000_0a02";
1719 case 0x00000c00: return "I7_SB_UNK_0000_0c00"; case 0x00000c01: return "I7_SB_UNK_0000_0c01";
1720 case 0x00000c06: return "I7_SB_UNK_0000_0c06"; case 0x00000c08: return "I7_SB_UNK_0000_0c08";
1721 case 0x00000c09: return "I7_SB_UNK_0000_0c09"; case 0x00000c10: return "I7_SB_UNK_0000_0c10";
1722 case 0x00000c11: return "I7_SB_UNK_0000_0c11"; case 0x00000c14: return "I7_SB_UNK_0000_0c14";
1723 case 0x00000c15: return "I7_SB_UNK_0000_0c15"; case 0x00000c16: return "I7_SB_UNK_0000_0c16";
1724 case 0x00000c17: return "I7_SB_UNK_0000_0c17"; case 0x00000c24: return "I7_SB_UNK_0000_0c24";
1725 case 0x00000c30: return "I7_SB_UNK_0000_0c30"; case 0x00000c31: return "I7_SB_UNK_0000_0c31";
1726 case 0x00000c32: return "I7_SB_UNK_0000_0c32"; case 0x00000c33: return "I7_SB_UNK_0000_0c33";
1727 case 0x00000c34: return "I7_SB_UNK_0000_0c34"; case 0x00000c35: return "I7_SB_UNK_0000_0c35";
1728 case 0x00000c36: return "I7_SB_UNK_0000_0c36"; case 0x00000c37: return "I7_SB_UNK_0000_0c37";
1729 case 0x00000c38: return "I7_SB_UNK_0000_0c38"; case 0x00000c39: return "I7_SB_UNK_0000_0c39";
1730 case 0x00000d04: return "I7_SB_UNK_0000_0d04";
1731 case 0x00000d10: return "I7_SB_UNK_0000_0d10"; case 0x00000d11: return "I7_SB_UNK_0000_0d11";
1732 case 0x00000d12: return "I7_SB_UNK_0000_0d12"; case 0x00000d13: return "I7_SB_UNK_0000_0d13";
1733 case 0x00000d14: return "I7_SB_UNK_0000_0d14"; case 0x00000d15: return "I7_SB_UNK_0000_0d15";
1734 case 0x00000d16: return "I7_SB_UNK_0000_0d16"; case 0x00000d17: return "I7_SB_UNK_0000_0d17";
1735 case 0x00000d18: return "I7_SB_UNK_0000_0d18"; case 0x00000d19: return "I7_SB_UNK_0000_0d19";
1736 case 0x00000d24: return "I7_SB_UNK_0000_0d24";
1737 case 0x00000d30: return "I7_SB_UNK_0000_0d30"; case 0x00000d31: return "I7_SB_UNK_0000_0d31";
1738 case 0x00000d32: return "I7_SB_UNK_0000_0d32"; case 0x00000d33: return "I7_SB_UNK_0000_0d33";
1739 case 0x00000d34: return "I7_SB_UNK_0000_0d34"; case 0x00000d35: return "I7_SB_UNK_0000_0d35";
1740 case 0x00000d36: return "I7_SB_UNK_0000_0d36"; case 0x00000d37: return "I7_SB_UNK_0000_0d37";
1741 case 0x00000d38: return "I7_SB_UNK_0000_0d38"; case 0x00000d39: return "I7_SB_UNK_0000_0d39";
1742 case 0x00000d44: return "I7_SB_UNK_0000_0d44";
1743 case 0x00000d50: return "I7_SB_UNK_0000_0d50"; case 0x00000d51: return "I7_SB_UNK_0000_0d51";
1744 case 0x00000d52: return "I7_SB_UNK_0000_0d52"; case 0x00000d53: return "I7_SB_UNK_0000_0d53";
1745 case 0x00000d54: return "I7_SB_UNK_0000_0d54"; case 0x00000d55: return "I7_SB_UNK_0000_0d55";
1746 case 0x00000d56: return "I7_SB_UNK_0000_0d56"; case 0x00000d57: return "I7_SB_UNK_0000_0d57";
1747 case 0x00000d58: return "I7_SB_UNK_0000_0d58"; case 0x00000d59: return "I7_SB_UNK_0000_0d59";
1748 case 0x00000d64: return "I7_SB_UNK_0000_0d64";
1749 case 0x00000d70: return "I7_SB_UNK_0000_0d70"; case 0x00000d71: return "I7_SB_UNK_0000_0d71";
1750 case 0x00000d72: return "I7_SB_UNK_0000_0d72"; case 0x00000d73: return "I7_SB_UNK_0000_0d73";
1751 case 0x00000d74: return "I7_SB_UNK_0000_0d74"; case 0x00000d75: return "I7_SB_UNK_0000_0d75";
1752 case 0x00000d76: return "I7_SB_UNK_0000_0d76"; case 0x00000d77: return "I7_SB_UNK_0000_0d77";
1753 case 0x00000d78: return "I7_SB_UNK_0000_0d78"; case 0x00000d79: return "I7_SB_UNK_0000_0d79";
1754 case 0x00000d84: return "I7_SB_UNK_0000_0d84";
1755 case 0x00000d90: return "I7_SB_UNK_0000_0d90"; case 0x00000d91: return "I7_SB_UNK_0000_0d91";
1756 case 0x00000d92: return "I7_SB_UNK_0000_0d92"; case 0x00000d93: return "I7_SB_UNK_0000_0d93";
1757 case 0x00000d94: return "I7_SB_UNK_0000_0d94"; case 0x00000d95: return "I7_SB_UNK_0000_0d95";
1758 case 0x00000d96: return "I7_SB_UNK_0000_0d96"; case 0x00000d97: return "I7_SB_UNK_0000_0d97";
1759 case 0x00000d98: return "I7_SB_UNK_0000_0d98"; case 0x00000d99: return "I7_SB_UNK_0000_0d99";
1760 case 0x00000da4: return "I7_SB_UNK_0000_0da4";
1761 case 0x00000db0: return "I7_SB_UNK_0000_0db0"; case 0x00000db1: return "I7_SB_UNK_0000_0db1";
1762 case 0x00000db2: return "I7_SB_UNK_0000_0db2"; case 0x00000db3: return "I7_SB_UNK_0000_0db3";
1763 case 0x00000db4: return "I7_SB_UNK_0000_0db4"; case 0x00000db5: return "I7_SB_UNK_0000_0db5";
1764 case 0x00000db6: return "I7_SB_UNK_0000_0db6"; case 0x00000db7: return "I7_SB_UNK_0000_0db7";
1765 case 0x00000db8: return "I7_SB_UNK_0000_0db8"; case 0x00000db9: return "I7_SB_UNK_0000_0db9";
1766 }
1767
1768 /*
1769 * Ditto for ivy bridge (observed on the i5-3570). There are some haswell
1770 * and sandybridge related docs on registers in this ares, but either
1771 * things are different for ivy or they're very incomplete. Again, kudos
1772 * to intel!
1773 */
1774 if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_IvyBridge)
1775 switch (uMsr)
1776 {
1777 case 0x00000700: return "I7_IB_UNK_0000_0700"; case 0x00000701: return "I7_IB_UNK_0000_0701";
1778 case 0x00000702: return "I7_IB_UNK_0000_0702"; case 0x00000703: return "I7_IB_UNK_0000_0703";
1779 case 0x00000704: return "I7_IB_UNK_0000_0704"; case 0x00000705: return "I7_IB_UNK_0000_0705";
1780 case 0x00000706: return "I7_IB_UNK_0000_0706"; case 0x00000707: return "I7_IB_UNK_0000_0707";
1781 case 0x00000708: return "I7_IB_UNK_0000_0708"; case 0x00000709: return "I7_IB_UNK_0000_0709";
1782 case 0x00000710: return "I7_IB_UNK_0000_0710"; case 0x00000711: return "I7_IB_UNK_0000_0711";
1783 case 0x00000712: return "I7_IB_UNK_0000_0712"; case 0x00000713: return "I7_IB_UNK_0000_0713";
1784 case 0x00000714: return "I7_IB_UNK_0000_0714"; case 0x00000715: return "I7_IB_UNK_0000_0715";
1785 case 0x00000716: return "I7_IB_UNK_0000_0716"; case 0x00000717: return "I7_IB_UNK_0000_0717";
1786 case 0x00000718: return "I7_IB_UNK_0000_0718"; case 0x00000719: return "I7_IB_UNK_0000_0719";
1787 case 0x00000720: return "I7_IB_UNK_0000_0720"; case 0x00000721: return "I7_IB_UNK_0000_0721";
1788 case 0x00000722: return "I7_IB_UNK_0000_0722"; case 0x00000723: return "I7_IB_UNK_0000_0723";
1789 case 0x00000724: return "I7_IB_UNK_0000_0724"; case 0x00000725: return "I7_IB_UNK_0000_0725";
1790 case 0x00000726: return "I7_IB_UNK_0000_0726"; case 0x00000727: return "I7_IB_UNK_0000_0727";
1791 case 0x00000728: return "I7_IB_UNK_0000_0728"; case 0x00000729: return "I7_IB_UNK_0000_0729";
1792 case 0x00000730: return "I7_IB_UNK_0000_0730"; case 0x00000731: return "I7_IB_UNK_0000_0731";
1793 case 0x00000732: return "I7_IB_UNK_0000_0732"; case 0x00000733: return "I7_IB_UNK_0000_0733";
1794 case 0x00000734: return "I7_IB_UNK_0000_0734"; case 0x00000735: return "I7_IB_UNK_0000_0735";
1795 case 0x00000736: return "I7_IB_UNK_0000_0736"; case 0x00000737: return "I7_IB_UNK_0000_0737";
1796 case 0x00000738: return "I7_IB_UNK_0000_0738"; case 0x00000739: return "I7_IB_UNK_0000_0739";
1797 case 0x00000740: return "I7_IB_UNK_0000_0740"; case 0x00000741: return "I7_IB_UNK_0000_0741";
1798 case 0x00000742: return "I7_IB_UNK_0000_0742"; case 0x00000743: return "I7_IB_UNK_0000_0743";
1799 case 0x00000744: return "I7_IB_UNK_0000_0744"; case 0x00000745: return "I7_IB_UNK_0000_0745";
1800 case 0x00000746: return "I7_IB_UNK_0000_0746"; case 0x00000747: return "I7_IB_UNK_0000_0747";
1801 case 0x00000748: return "I7_IB_UNK_0000_0748"; case 0x00000749: return "I7_IB_UNK_0000_0749";
1802
1803 }
1804 return NULL;
1805}
1806
1807
1808/**
1809 * Gets the name of an MSR.
1810 *
1811 * This may return a static buffer, so the content should only be considered
1812 * valid until the next time this function is called!.
1813 *
1814 * @returns MSR name.
1815 * @param uMsr The MSR in question.
1816 */
1817static const char *getMsrName(uint32_t uMsr)
1818{
1819 const char *pszReadOnly = getMsrNameHandled(uMsr);
1820 if (pszReadOnly)
1821 return pszReadOnly;
1822
1823 /*
1824 * This MSR needs looking into, return a TODO_XXXX_XXXX name.
1825 */
1826 static char s_szBuf[32];
1827 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
1828 return s_szBuf;
1829}
1830
1831
1832
1833/**
1834 * Gets the name of an MSR range.
1835 *
1836 * This may return a static buffer, so the content should only be considered
1837 * valid until the next time this function is called!.
1838 *
1839 * @returns MSR name.
1840 * @param uMsr The first MSR in the range.
1841 */
1842static const char *getMsrRangeName(uint32_t uMsr)
1843{
1844 switch (uMsr)
1845 {
1846 case 0x00000040:
1847 return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_n_FROM_IP" : "MSR_LASTBRANCH_n";
1848 case 0x00000060:
1849 if (g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
1850 return "MSR_LASTBRANCH_n_TO_IP";
1851 break;
1852
1853 case 0x000003f8:
1854 case 0x000003f9:
1855 case 0x000003fa:
1856 return "I7_MSR_PKG_Cn_RESIDENCY";
1857 case 0x000003fc:
1858 case 0x000003fd:
1859 case 0x000003fe:
1860 return "I7_MSR_CORE_Cn_RESIDENCY";
1861
1862 case 0x00000400:
1863 return "IA32_MCi_CTL_STATUS_ADDR_MISC";
1864
1865 case 0x00000680:
1866 return "MSR_LASTBRANCH_n_FROM_IP";
1867 case 0x000006c0:
1868 return "MSR_LASTBRANCH_n_TO_IP";
1869
1870 case 0x00000800: case 0x00000801: case 0x00000802: case 0x00000803:
1871 case 0x00000804: case 0x00000805: case 0x00000806: case 0x00000807:
1872 case 0x00000808: case 0x00000809: case 0x0000080a: case 0x0000080b:
1873 case 0x0000080c: case 0x0000080d: case 0x0000080e: case 0x0000080f:
1874 return "IA32_X2APIC_n";
1875 }
1876
1877 static char s_szBuf[96];
1878 const char *pszReadOnly = getMsrNameHandled(uMsr);
1879 if (pszReadOnly)
1880 {
1881 /*
1882 * Replace the last char with 'n'.
1883 */
1884 RTStrCopy(s_szBuf, sizeof(s_szBuf), pszReadOnly);
1885 size_t off = strlen(s_szBuf);
1886 if (off > 0)
1887 off--;
1888 if (off + 1 < sizeof(s_szBuf))
1889 {
1890 s_szBuf[off] = 'n';
1891 s_szBuf[off + 1] = '\0';
1892 }
1893 }
1894 else
1895 {
1896 /*
1897 * This MSR needs looking into, return a TODO_XXXX_XXXX_n name.
1898 */
1899 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x_n", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
1900 }
1901 return s_szBuf;
1902}
1903
1904
1905/**
1906 * Returns the function name for MSRs that have one or two.
1907 *
1908 * @returns Function name if applicable, NULL if not.
1909 * @param uMsr The MSR in question.
1910 * @param pfTakesValue Whether this MSR function takes a value or not.
1911 * Optional.
1912 */
1913static const char *getMsrFnName(uint32_t uMsr, bool *pfTakesValue)
1914{
1915 bool fTmp;
1916 if (!pfTakesValue)
1917 pfTakesValue = &fTmp;
1918
1919 *pfTakesValue = false;
1920
1921 switch (uMsr)
1922 {
1923 case 0x00000000: return "Ia32P5McAddr";
1924 case 0x00000001: return "Ia32P5McType";
1925 case 0x00000006:
1926 if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
1927 return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
1928 return "Ia32MonitorFilterLineSize";
1929 case 0x00000010: return "Ia32TimestampCounter";
1930 case 0x00000017: *pfTakesValue = true; return "Ia32PlatformId";
1931 case 0x0000001b: return "Ia32ApicBase";
1932 case 0x0000002a: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcHardPowerOn" : "IntelEblCrPowerOn";
1933 case 0x0000002b: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcSoftPowerOn" : NULL;
1934 case 0x0000002c: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcFrequencyId" : NULL;
1935 //case 0x00000033: return "IntelTestCtl";
1936 case 0x00000034: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)
1937 || CPUMMICROARCH_IS_INTEL_SILVERMONT_PLUS(g_enmMicroarch)
1938 ? "IntelI7SmiCount" : NULL;
1939 case 0x00000035: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelI7CoreThreadCount" : NULL;
1940 case 0x0000003a: return "Ia32FeatureControl";
1941
1942 case 0x00000040:
1943 case 0x00000041:
1944 case 0x00000042:
1945 case 0x00000043:
1946 case 0x00000044:
1947 case 0x00000045:
1948 case 0x00000046:
1949 case 0x00000047:
1950 return "IntelLastBranchFromToN";
1951
1952 case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON
1953 ? "AmdK8PatchLevel" : "Ia32BiosSignId";
1954 case 0x0000009b: return "Ia32SmmMonitorCtl";
1955
1956 case 0x000000a8:
1957 case 0x000000a9:
1958 case 0x000000aa:
1959 case 0x000000ab:
1960 case 0x000000ac:
1961 case 0x000000ad:
1962 *pfTakesValue = true;
1963 return "IntelCore2EmttmCrTablesN";
1964
1965 case 0x000000c1:
1966 case 0x000000c2:
1967 case 0x000000c3:
1968 case 0x000000c4:
1969 return "Ia32PmcN";
1970 case 0x000000c5:
1971 case 0x000000c6:
1972 case 0x000000c7:
1973 case 0x000000c8:
1974 if (g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First)
1975 return "Ia32PmcN";
1976 return NULL;
1977
1978 case 0x000000cd: *pfTakesValue = true; return "IntelP6FsbFrequency";
1979 case 0x000000ce: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelPlatformInfo" : NULL;
1980 case 0x000000e2: return "IntelPkgCStConfigControl";
1981 case 0x000000e3: return "IntelCore2SmmCStMiscInfo";
1982 case 0x000000e4: return "IntelPmgIoCaptureBase";
1983 case 0x000000e7: return "Ia32MPerf";
1984 case 0x000000e8: return "Ia32APerf";
1985 case 0x000000ee: return "IntelCore1ExtConfig";
1986 case 0x000000fe: *pfTakesValue = true; return "Ia32MtrrCap";
1987 case 0x00000119: *pfTakesValue = true; return "IntelBblCrCtl";
1988 case 0x0000011e: *pfTakesValue = true; return "IntelBblCrCtl3";
1989
1990 case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
1991 || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
1992 ? "IntelCpuId1FeatureMaskEcdx" : NULL;
1993 case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
1994 || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
1995 ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
1996 case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
1997 ? "IntelCpuId1FeatureMaskEax" : NULL;
1998 case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
1999 ? "IntelCpuId1FeatureMaskEcdx" : NULL;
2000 case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
2001 ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
2002 case 0x0000013c: return "IntelI7SandyAesNiCtl";
2003 case 0x0000015f: return "IntelCore1DtsCalControl";
2004 case 0x00000174: return "Ia32SysEnterCs";
2005 case 0x00000175: return "Ia32SysEnterEsp";
2006 case 0x00000176: return "Ia32SysEnterEip";
2007 case 0x00000179: *pfTakesValue = true; return "Ia32McgCap";
2008 case 0x0000017a: return "Ia32McgStatus";
2009 case 0x0000017b: return "Ia32McgCtl";
2010 case 0x0000017f: return "IntelI7SandyErrorControl"; /* SandyBridge. */
2011 case 0x00000186: return "Ia32PerfEvtSelN";
2012 case 0x00000187: return "Ia32PerfEvtSelN";
2013 case 0x00000193: return /*g_fIntelNetBurst ? NULL :*/ NULL /* Core2_Penryn. */;
2014 case 0x00000194: if (g_fIntelNetBurst) break; *pfTakesValue = true; return "IntelFlexRatio";
2015 case 0x00000198: *pfTakesValue = true; return "Ia32PerfStatus";
2016 case 0x00000199: *pfTakesValue = true; return "Ia32PerfCtl";
2017 case 0x0000019a: *pfTakesValue = true; return "Ia32ClockModulation";
2018 case 0x0000019b: *pfTakesValue = true; return "Ia32ThermInterrupt";
2019 case 0x0000019c: *pfTakesValue = true; return "Ia32ThermStatus";
2020 case 0x0000019d: *pfTakesValue = true; return "Ia32Therm2Ctl";
2021 case 0x000001a0: *pfTakesValue = true; return "Ia32MiscEnable";
2022 case 0x000001a2: *pfTakesValue = true; return "IntelI7TemperatureTarget";
2023 case 0x000001a6: return "IntelI7MsrOffCoreResponseN";
2024 case 0x000001a7: return "IntelI7MsrOffCoreResponseN";
2025 case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelI7MiscPwrMgmt" : NULL /*"P6PicSensCfg"*/;
2026 case 0x000001ad: *pfTakesValue = true; return "IntelI7TurboRatioLimit"; /* SandyBridge+, Silvermount+ */
2027 case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "IntelI7LbrSelect" : NULL;
2028 case 0x000001c9: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
2029 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
2030 ? "IntelLastBranchTos" : NULL /* Pentium M Dothan seems to have something else here. */;
2031 case 0x000001d7: return g_fIntelNetBurst ? "P6LastIntFromIp" : NULL;
2032 case 0x000001d8: return g_fIntelNetBurst ? "P6LastIntToIp" : NULL;
2033 case 0x000001d9: return "Ia32DebugCtl";
2034 case 0x000001da: return g_fIntelNetBurst ? "IntelLastBranchTos" : NULL;
2035 case 0x000001db: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchFromIp";
2036 case 0x000001dc: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchToIp";
2037 case 0x000001dd: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntFromIp";
2038 case 0x000001de: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntToIp";
2039 case 0x000001f0: return "IntelI7VirtualLegacyWireCap"; /* SandyBridge. */
2040 case 0x000001f2: return "Ia32SmrrPhysBase";
2041 case 0x000001f3: return "Ia32SmrrPhysMask";
2042 case 0x000001f8: return "Ia32PlatformDcaCap";
2043 case 0x000001f9: return "Ia32CpuDcaCap";
2044 case 0x000001fa: return "Ia32Dca0Cap";
2045 case 0x000001fc: return "IntelI7PowerCtl";
2046
2047 case 0x00000200: case 0x00000202: case 0x00000204: case 0x00000206:
2048 case 0x00000208: case 0x0000020a: case 0x0000020c: case 0x0000020e:
2049 case 0x00000210: case 0x00000212: case 0x00000214: case 0x00000216:
2050 case 0x00000218: case 0x0000021a: case 0x0000021c: case 0x0000021e:
2051 return "Ia32MtrrPhysBaseN";
2052 case 0x00000201: case 0x00000203: case 0x00000205: case 0x00000207:
2053 case 0x00000209: case 0x0000020b: case 0x0000020d: case 0x0000020f:
2054 case 0x00000211: case 0x00000213: case 0x00000215: case 0x00000217:
2055 case 0x00000219: case 0x0000021b: case 0x0000021d: case 0x0000021f:
2056 return "Ia32MtrrPhysMaskN";
2057 case 0x00000250:
2058 case 0x00000258: case 0x00000259:
2059 case 0x00000268: case 0x00000269: case 0x0000026a: case 0x0000026b:
2060 case 0x0000026c: case 0x0000026d: case 0x0000026e: case 0x0000026f:
2061 return "Ia32MtrrFixed";
2062 case 0x00000277: *pfTakesValue = true; return "Ia32Pat";
2063
2064 case 0x00000280: case 0x00000281: case 0x00000282: case 0x00000283:
2065 case 0x00000284: case 0x00000285: case 0x00000286: case 0x00000287:
2066 case 0x00000288: case 0x00000289: case 0x0000028a: case 0x0000028b:
2067 case 0x0000028c: case 0x0000028d: case 0x0000028e: case 0x0000028f:
2068 case 0x00000290: case 0x00000291: case 0x00000292: case 0x00000293:
2069 case 0x00000294: case 0x00000295: //case 0x00000296: case 0x00000297:
2070 //case 0x00000298: case 0x00000299: case 0x0000029a: case 0x0000029b:
2071 //case 0x0000029c: case 0x0000029d: case 0x0000029e: case 0x0000029f:
2072 return "Ia32McNCtl2";
2073
2074 case 0x000002ff: return "Ia32MtrrDefType";
2075 //case 0x00000305: return g_fIntelNetBurst ? TODO : NULL;
2076 case 0x00000309: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
2077 case 0x0000030a: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
2078 case 0x0000030b: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
2079 case 0x00000345: *pfTakesValue = true; return "Ia32PerfCapabilities";
2080 /* Note! Lots of P4 MSR 0x00000360..0x00000371. */
2081 case 0x0000038d: return "Ia32FixedCtrCtrl";
2082 case 0x0000038e: *pfTakesValue = true; return "Ia32PerfGlobalStatus";
2083 case 0x0000038f: return "Ia32PerfGlobalCtrl";
2084 case 0x00000390: return "Ia32PerfGlobalOvfCtrl";
2085 case 0x00000391: return "IntelI7UncPerfGlobalCtrl"; /* S,H,X */
2086 case 0x00000392: return "IntelI7UncPerfGlobalStatus"; /* S,H,X */
2087 case 0x00000393: return "IntelI7UncPerfGlobalOvfCtrl"; /* X. ASSUMING this is the same on sandybridge and later. */
2088 case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtr" /* X */ : "IntelI7UncPerfFixedCtrCtrl"; /* >= S,H */
2089 case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtrCtrl" /* X*/ : "IntelI7UncPerfFixedCtr"; /* >= S,H */
2090 case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncAddrOpcodeMatch" /* X */ : "IntelI7UncCBoxConfig"; /* >= S,H */
2091 case 0x0000039c: return "IntelI7SandyPebsNumAlt";
2092 /* Note! Lots of P4 MSR 0x000003a0..0x000003e1. */
2093 case 0x000003b0: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */ : "IntelI7UncArbPerfCtrN"; /* >= S,H */
2094 case 0x000003b1: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */ : "IntelI7UncArbPerfCtrN"; /* >= S,H */
2095 case 0x000003b2: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */ : "IntelI7UncArbPerfEvtSelN"; /* >= S,H */
2096 case 0x000003b3: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */ : "IntelI7UncArbPerfEvtSelN"; /* >= S,H */
2097 case 0x000003b4: case 0x000003b5: case 0x000003b6: case 0x000003b7:
2098 return g_fIntelNetBurst ? NULL : "IntelI7UncPmcN";
2099 case 0x000003c0: case 0x000003c1: case 0x000003c2: case 0x000003c3:
2100 case 0x000003c4: case 0x000003c5: case 0x000003c6: case 0x000003c7:
2101 return g_fIntelNetBurst ? NULL : "IntelI7UncPerfEvtSelN";
2102 case 0x000003f1: return "Ia32PebsEnable";
2103 case 0x000003f6: return g_fIntelNetBurst ? NULL /*??*/ : "IntelI7PebsLdLat";
2104 case 0x000003f8: return g_fIntelNetBurst ? NULL : "IntelI7PkgCnResidencyN";
2105 case 0x000003f9: return "IntelI7PkgCnResidencyN";
2106 case 0x000003fa: return "IntelI7PkgCnResidencyN";
2107 case 0x000003fc: return "IntelI7CoreCnResidencyN";
2108 case 0x000003fd: return "IntelI7CoreCnResidencyN";
2109 case 0x000003fe: return "IntelI7CoreCnResidencyN";
2110
2111 case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "IntelCpuId1FeatureMaskEcdx" : NULL;
2112 case 0x00000480: *pfTakesValue = true; return "Ia32VmxBasic";
2113 case 0x00000481: *pfTakesValue = true; return "Ia32VmxPinbasedCtls";
2114 case 0x00000482: *pfTakesValue = true; return "Ia32VmxProcbasedCtls";
2115 case 0x00000483: *pfTakesValue = true; return "Ia32VmxExitCtls";
2116 case 0x00000484: *pfTakesValue = true; return "Ia32VmxEntryCtls";
2117 case 0x00000485: *pfTakesValue = true; return "Ia32VmxMisc";
2118 case 0x00000486: *pfTakesValue = true; return "Ia32VmxCr0Fixed0";
2119 case 0x00000487: *pfTakesValue = true; return "Ia32VmxCr0Fixed1";
2120 case 0x00000488: *pfTakesValue = true; return "Ia32VmxCr4Fixed0";
2121 case 0x00000489: *pfTakesValue = true; return "Ia32VmxCr4Fixed1";
2122 case 0x0000048a: *pfTakesValue = true; return "Ia32VmxVmcsEnum";
2123 case 0x0000048b: *pfTakesValue = true; return "Ia32VmxProcBasedCtls2";
2124 case 0x0000048c: *pfTakesValue = true; return "Ia32VmxEptVpidCap";
2125 case 0x0000048d: *pfTakesValue = true; return "Ia32VmxTruePinbasedCtls";
2126 case 0x0000048e: *pfTakesValue = true; return "Ia32VmxTrueProcbasedCtls";
2127 case 0x0000048f: *pfTakesValue = true; return "Ia32VmxTrueExitCtls";
2128 case 0x00000490: *pfTakesValue = true; return "Ia32VmxTrueEntryCtls";
2129 case 0x00000491: *pfTakesValue = true; return "Ia32VmxVmFunc";
2130
2131 case 0x000004c1:
2132 case 0x000004c2:
2133 case 0x000004c3:
2134 case 0x000004c4:
2135 case 0x000004c5:
2136 case 0x000004c6:
2137 case 0x000004c7:
2138 case 0x000004c8:
2139 return "Ia32PmcN";
2140
2141 case 0x000005a0: return "IntelCore2PeciControl"; /* Core2_Penryn. */
2142
2143 case 0x00000600: return "Ia32DsArea";
2144 case 0x00000601: *pfTakesValue = true; return "IntelI7SandyVrCurrentConfig";
2145 case 0x00000603: *pfTakesValue = true; return "IntelI7SandyVrMiscConfig";
2146 case 0x00000606: *pfTakesValue = true; return "IntelI7SandyRaplPowerUnit";
2147 case 0x0000060a: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
2148 case 0x0000060b: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
2149 case 0x0000060c: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
2150 case 0x0000060d: *pfTakesValue = true; return "IntelI7SandyPkgC2Residency";
2151
2152 case 0x00000610: *pfTakesValue = true; return "IntelI7RaplPkgPowerLimit";
2153 case 0x00000611: *pfTakesValue = true; return "IntelI7RaplPkgEnergyStatus";
2154 case 0x00000613: *pfTakesValue = true; return "IntelI7RaplPkgPerfStatus";
2155 case 0x00000614: *pfTakesValue = true; return "IntelI7RaplPkgPowerInfo";
2156 case 0x00000618: *pfTakesValue = true; return "IntelI7RaplDramPowerLimit";
2157 case 0x00000619: *pfTakesValue = true; return "IntelI7RaplDramEnergyStatus";
2158 case 0x0000061b: *pfTakesValue = true; return "IntelI7RaplDramPerfStatus";
2159 case 0x0000061c: *pfTakesValue = true; return "IntelI7RaplDramPowerInfo";
2160 case 0x00000638: *pfTakesValue = true; return "IntelI7RaplPp0PowerLimit";
2161 case 0x00000639: *pfTakesValue = true; return "IntelI7RaplPp0EnergyStatus";
2162 case 0x0000063a: *pfTakesValue = true; return "IntelI7RaplPp0Policy";
2163 case 0x0000063b: *pfTakesValue = true; return "IntelI7RaplPp0PerfStatus";
2164 case 0x00000640: *pfTakesValue = true; return "IntelI7RaplPp1PowerLimit";
2165 case 0x00000641: *pfTakesValue = true; return "IntelI7RaplPp1EnergyStatus";
2166 case 0x00000642: *pfTakesValue = true; return "IntelI7RaplPp1Policy";
2167 case 0x00000648: *pfTakesValue = true; return "IntelI7IvyConfigTdpNominal";
2168 case 0x00000649: *pfTakesValue = true; return "IntelI7IvyConfigTdpLevel1";
2169 case 0x0000064a: *pfTakesValue = true; return "IntelI7IvyConfigTdpLevel2";
2170 case 0x0000064b: return "IntelI7IvyConfigTdpControl";
2171 case 0x0000064c: return "IntelI7IvyTurboActivationRatio";
2172
2173 case 0x00000660: return "IntelAtSilvCoreC1Recidency";
2174
2175 case 0x00000680: case 0x00000681: case 0x00000682: case 0x00000683:
2176 case 0x00000684: case 0x00000685: case 0x00000686: case 0x00000687:
2177 case 0x00000688: case 0x00000689: case 0x0000068a: case 0x0000068b:
2178 case 0x0000068c: case 0x0000068d: case 0x0000068e: case 0x0000068f:
2179 //case 0x00000690: case 0x00000691: case 0x00000692: case 0x00000693:
2180 //case 0x00000694: case 0x00000695: case 0x00000696: case 0x00000697:
2181 //case 0x00000698: case 0x00000699: case 0x0000069a: case 0x0000069b:
2182 //case 0x0000069c: case 0x0000069d: case 0x0000069e: case 0x0000069f:
2183 return "IntelLastBranchFromN";
2184 case 0x000006c0: case 0x000006c1: case 0x000006c2: case 0x000006c3:
2185 case 0x000006c4: case 0x000006c5: case 0x000006c6: case 0x000006c7:
2186 case 0x000006c8: case 0x000006c9: case 0x000006ca: case 0x000006cb:
2187 case 0x000006cc: case 0x000006cd: case 0x000006ce: case 0x000006cf:
2188 //case 0x000006d0: case 0x000006d1: case 0x000006d2: case 0x000006d3:
2189 //case 0x000006d4: case 0x000006d5: case 0x000006d6: case 0x000006d7:
2190 //case 0x000006d8: case 0x000006d9: case 0x000006da: case 0x000006db:
2191 //case 0x000006dc: case 0x000006dd: case 0x000006de: case 0x000006df:
2192 return "IntelLastBranchToN";
2193 case 0x000006e0: return "Ia32TscDeadline"; /** @todo detect this correctly! */
2194
2195 case 0x00000c80: return g_enmMicroarch > kCpumMicroarch_Intel_Core7_Nehalem ? "Ia32DebugInterface" : NULL;
2196
2197 case 0xc0000080: return "Amd64Efer";
2198 case 0xc0000081: return "Amd64SyscallTarget";
2199 case 0xc0000082: return "Amd64LongSyscallTarget";
2200 case 0xc0000083: return "Amd64CompSyscallTarget";
2201 case 0xc0000084: return "Amd64SyscallFlagMask";
2202 case 0xc0000100: return "Amd64FsBase";
2203 case 0xc0000101: return "Amd64GsBase";
2204 case 0xc0000102: return "Amd64KernelGsBase";
2205 case 0xc0000103: return "Amd64TscAux";
2206 case 0xc0000104: return "AmdFam15hTscRate";
2207 case 0xc0000105: return "AmdFam15hLwpCfg";
2208 case 0xc0000106: return "AmdFam15hLwpCbAddr";
2209 case 0xc0000408: return "AmdFam10hMc4MiscN";
2210 case 0xc0000409: return "AmdFam10hMc4MiscN";
2211 case 0xc000040a: return "AmdFam10hMc4MiscN";
2212 case 0xc000040b: return "AmdFam10hMc4MiscN";
2213 case 0xc000040c: return "AmdFam10hMc4MiscN";
2214 case 0xc000040d: return "AmdFam10hMc4MiscN";
2215 case 0xc000040e: return "AmdFam10hMc4MiscN";
2216 case 0xc000040f: return "AmdFam10hMc4MiscN";
2217 case 0xc0010000: return "AmdK8PerfCtlN";
2218 case 0xc0010001: return "AmdK8PerfCtlN";
2219 case 0xc0010002: return "AmdK8PerfCtlN";
2220 case 0xc0010003: return "AmdK8PerfCtlN";
2221 case 0xc0010004: return "AmdK8PerfCtrN";
2222 case 0xc0010005: return "AmdK8PerfCtrN";
2223 case 0xc0010006: return "AmdK8PerfCtrN";
2224 case 0xc0010007: return "AmdK8PerfCtrN";
2225 case 0xc0010010: *pfTakesValue = true; return "AmdK8SysCfg";
2226 case 0xc0010015: return "AmdK8HwCr";
2227 case 0xc0010016: case 0xc0010018: return "AmdK8IorrBaseN";
2228 case 0xc0010017: case 0xc0010019: return "AmdK8IorrMaskN";
2229 case 0xc001001a: case 0xc001001d: return "AmdK8TopOfMemN";
2230 case 0xc001001f: return "AmdK8NbCfg1";
2231 case 0xc0010020: return "AmdK8PatchLoader";
2232 case 0xc0010022: return "AmdK8McXcptRedir";
2233 case 0xc0010030: case 0xc0010031: case 0xc0010032:
2234 case 0xc0010033: case 0xc0010034: case 0xc0010035:
2235 return "AmdK8CpuNameN";
2236 case 0xc001003e: *pfTakesValue = true; return "AmdK8HwThermalCtrl";
2237 case 0xc001003f: return "AmdK8SwThermalCtrl";
2238 case 0xc0010041: *pfTakesValue = true; return "AmdK8FidVidControl";
2239 case 0xc0010042: *pfTakesValue = true; return "AmdK8FidVidStatus";
2240 case 0xc0010044: case 0xc0010045: case 0xc0010046: case 0xc0010047:
2241 case 0xc0010048: case 0xc0010049: case 0xc001004a: //case 0xc001004b:
2242 return "AmdK8McCtlMaskN";
2243 case 0xc0010050: case 0xc0010051: case 0xc0010052: case 0xc0010053:
2244 return "AmdK8SmiOnIoTrapN";
2245 case 0xc0010054: return "AmdK8SmiOnIoTrapCtlSts";
2246 case 0xc0010055: return "AmdK8IntPendingMessage";
2247 case 0xc0010056: return "AmdK8SmiTriggerIoCycle";
2248 case 0xc0010058: return "AmdFam10hMmioCfgBaseAddr";
2249 case 0xc0010059: return "AmdFam10hTrapCtlMaybe";
2250 case 0xc0010061: *pfTakesValue = true; return "AmdFam10hPStateCurLimit";
2251 case 0xc0010062: *pfTakesValue = true; return "AmdFam10hPStateControl";
2252 case 0xc0010063: *pfTakesValue = true; return "AmdFam10hPStateStatus";
2253 case 0xc0010064: case 0xc0010065: case 0xc0010066: case 0xc0010067:
2254 case 0xc0010068: case 0xc0010069: case 0xc001006a: case 0xc001006b:
2255 *pfTakesValue = true; return "AmdFam10hPStateN";
2256 case 0xc0010070: *pfTakesValue = true; return "AmdFam10hCofVidControl";
2257 case 0xc0010071: *pfTakesValue = true; return "AmdFam10hCofVidStatus";
2258 case 0xc0010073: return "AmdFam10hCStateIoBaseAddr";
2259 case 0xc0010074: return "AmdFam10hCpuWatchdogTimer";
2260 // case 0xc0010075: return "AmdFam15hApmlTdpLimit";
2261 // case 0xc0010077: return "AmdFam15hCpuPowerInTdp";
2262 // case 0xc0010078: return "AmdFam15hPowerAveragingPeriod";
2263 // case 0xc0010079: return "AmdFam15hDramCtrlCmdThrottle";
2264 // case 0xc0010080: return "AmdFam16hFreqSensFeedbackMonActCnt0";
2265 // case 0xc0010081: return "AmdFam16hFreqSensFeedbackMonRefCnt0";
2266 case 0xc0010111: return "AmdK8SmmBase"; /** @todo probably misdetected ign/gp due to locking */
2267 case 0xc0010112: return "AmdK8SmmAddr"; /** @todo probably misdetected ign/gp due to locking */
2268 case 0xc0010113: return "AmdK8SmmMask"; /** @todo probably misdetected ign/gp due to locking */
2269 case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmCr" : NULL; /** @todo probably misdetected due to locking */
2270 case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AmdK8IgnNe" : NULL;
2271 case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AmdK8SmmCtl" : NULL;
2272 case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmHSavePa" : NULL; /** @todo probably misdetected due to locking */
2273 case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdFam10hVmLockKey" : NULL;
2274 case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AmdFam10hSmmLockKey" : NULL; /* Not documented by BKDG, found in netbsd patch. */
2275 case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm ? "AmdFam10hLocalSmiStatus" : NULL;
2276 case 0xc0010140: *pfTakesValue = true; return "AmdFam10hOsVisWrkIdLength";
2277 case 0xc0010141: *pfTakesValue = true; return "AmdFam10hOsVisWrkStatus";
2278 case 0xc0010200: case 0xc0010202: case 0xc0010204: case 0xc0010206:
2279 case 0xc0010208: case 0xc001020a: //case 0xc001020c: case 0xc001020e:
2280 return "AmdK8PerfCtlN";
2281 case 0xc0010201: case 0xc0010203: case 0xc0010205: case 0xc0010207:
2282 case 0xc0010209: case 0xc001020b: //case 0xc001020d: case 0xc001020f:
2283 return "AmdK8PerfCtrN";
2284 case 0xc0010230: case 0xc0010232: case 0xc0010234: case 0xc0010236:
2285 //case 0xc0010238: case 0xc001023a: case 0xc001030c: case 0xc001023e:
2286 return "AmdFam16hL2IPerfCtlN";
2287 case 0xc0010231: case 0xc0010233: case 0xc0010235: case 0xc0010237:
2288 //case 0xc0010239: case 0xc001023b: case 0xc001023d: case 0xc001023f:
2289 return "AmdFam16hL2IPerfCtrN";
2290 case 0xc0010240: case 0xc0010242: case 0xc0010244: case 0xc0010246:
2291 //case 0xc0010248: case 0xc001024a: case 0xc001024c: case 0xc001024e:
2292 return "AmdFam15hNorthbridgePerfCtlN";
2293 case 0xc0010241: case 0xc0010243: case 0xc0010245: case 0xc0010247:
2294 //case 0xc0010249: case 0xc001024b: case 0xc001024d: case 0xc001024f:
2295 return "AmdFam15hNorthbridgePerfCtrN";
2296 case 0xc0011000: *pfTakesValue = true; return "AmdK7MicrocodeCtl";
2297 case 0xc0011001: *pfTakesValue = true; return "AmdK7ClusterIdMaybe";
2298 case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd07hEbax" : NULL;
2299 case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd06hEcx" : NULL;
2300 case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd01hEdcx" : NULL;
2301 case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlExt01hEdcx" : NULL;
2302 case 0xc0011006: return "AmdK7DebugStatusMaybe";
2303 case 0xc0011007: return "AmdK7BHTraceBaseMaybe";
2304 case 0xc0011008: return "AmdK7BHTracePtrMaybe";
2305 case 0xc0011009: return "AmdK7BHTraceLimitMaybe";
2306 case 0xc001100a: return "AmdK7HardwareDebugToolCfgMaybe";
2307 case 0xc001100b: return "AmdK7FastFlushCountMaybe";
2308 case 0xc001100c: return "AmdK7NodeId"; /** @todo dunno if this was there is K7 already. Kinda doubt it. */
2309 case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
2310 case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
2311 case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
2312 case 0xc0011020: return "AmdK7LoadStoreCfg";
2313 case 0xc0011021: return "AmdK7InstrCacheCfg";
2314 case 0xc0011022: return "AmdK7DataCacheCfg";
2315 case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hCombUnitCfg" : "AmdK7BusUnitCfg";
2316 case 0xc0011024: return "AmdK7DebugCtl2Maybe";
2317 case 0xc0011025: return "AmdK7Dr0DataMatchMaybe";
2318 case 0xc0011026: return "AmdK7Dr0DataMaskMaybe";
2319 case 0xc0011027: return "AmdK7DrXAddrMaskN";
2320 case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hFpuCfg" : NULL;
2321 case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hDecoderCfg" : NULL;
2322 case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hCombUnitCfg2"
2323 : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
2324 ? "AmdFam10hBusUnitCfg2" /* 10h & 16h */ : NULL;
2325 case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hCombUnitCfg3" : NULL;
2326 case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hExecUnitCfg" : NULL;
2327 case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hLoadStoreCfg2" : NULL;
2328 case 0xc0011030: return "AmdFam10hIbsFetchCtl";
2329 case 0xc0011031: return "AmdFam10hIbsFetchLinAddr";
2330 case 0xc0011032: return "AmdFam10hIbsFetchPhysAddr";
2331 case 0xc0011033: return "AmdFam10hIbsOpExecCtl";
2332 case 0xc0011034: return "AmdFam10hIbsOpRip";
2333 case 0xc0011035: return "AmdFam10hIbsOpData";
2334 case 0xc0011036: return "AmdFam10hIbsOpData2";
2335 case 0xc0011037: return "AmdFam10hIbsOpData3";
2336 case 0xc0011038: return "AmdFam10hIbsDcLinAddr";
2337 case 0xc0011039: return "AmdFam10hIbsDcPhysAddr";
2338 case 0xc001103a: return "AmdFam10hIbsCtl";
2339 case 0xc001103b: return "AmdFam14hIbsBrTarget";
2340 }
2341 return NULL;
2342}
2343
2344
2345/**
2346 * Names CPUMCPU variables that MSRs corresponds to.
2347 *
2348 * @returns The variable name @a uMsr corresponds to, NULL if no variable.
2349 * @param uMsr The MSR in question.
2350 */
2351static const char *getMsrCpumCpuVarName(uint32_t uMsr)
2352{
2353 switch (uMsr)
2354 {
2355 case 0x00000250: return "GuestMsrs.msr.MtrrFix64K_00000";
2356 case 0x00000258: return "GuestMsrs.msr.MtrrFix16K_80000";
2357 case 0x00000259: return "GuestMsrs.msr.MtrrFix16K_A0000";
2358 case 0x00000268: return "GuestMsrs.msr.MtrrFix4K_C0000";
2359 case 0x00000269: return "GuestMsrs.msr.MtrrFix4K_C8000";
2360 case 0x0000026a: return "GuestMsrs.msr.MtrrFix4K_D0000";
2361 case 0x0000026b: return "GuestMsrs.msr.MtrrFix4K_D8000";
2362 case 0x0000026c: return "GuestMsrs.msr.MtrrFix4K_E0000";
2363 case 0x0000026d: return "GuestMsrs.msr.MtrrFix4K_E8000";
2364 case 0x0000026e: return "GuestMsrs.msr.MtrrFix4K_F0000";
2365 case 0x0000026f: return "GuestMsrs.msr.MtrrFix4K_F8000";
2366 case 0x00000277: return "Guest.msrPAT";
2367 case 0x000002ff: return "GuestMsrs.msr.MtrrDefType";
2368 }
2369 return NULL;
2370}
2371
2372
2373/**
2374 * Checks whether the MSR should read as zero for some reason.
2375 *
2376 * @returns true if the register should read as zero, false if not.
2377 * @param uMsr The MSR.
2378 */
2379static bool doesMsrReadAsZero(uint32_t uMsr)
2380{
2381 switch (uMsr)
2382 {
2383 case 0x00000088: return true; // "BBL_CR_D0" - RAZ until understood/needed.
2384 case 0x00000089: return true; // "BBL_CR_D1" - RAZ until understood/needed.
2385 case 0x0000008a: return true; // "BBL_CR_D2" - RAZ until understood/needed.
2386
2387 /* Non-zero, but unknown register. */
2388 case 0x0000004a:
2389 case 0x0000004b:
2390 case 0x0000004c:
2391 case 0x0000004d:
2392 case 0x0000004e:
2393 case 0x0000004f:
2394 case 0x00000050:
2395 case 0x00000051:
2396 case 0x00000052:
2397 case 0x00000053:
2398 case 0x00000054:
2399 case 0x0000008c:
2400 case 0x0000008d:
2401 case 0x0000008e:
2402 case 0x0000008f:
2403 case 0x00000090:
2404 case 0xc0011011:
2405 return true;
2406 }
2407
2408 return false;
2409}
2410
2411
2412/**
2413 * Gets the skip mask for the given MSR.
2414 *
2415 * @returns Skip mask (0 means skipping nothing).
2416 * @param uMsr The MSR.
2417 */
2418static uint64_t getGenericSkipMask(uint32_t uMsr)
2419{
2420 switch (uMsr)
2421 {
2422 case 0x0000013c: return 3; /* AES-NI lock bit ++. */
2423
2424 case 0x000001f2: return UINT64_C(0xfffff00f); /* Ia32SmrrPhysBase - Only writable in SMM. */
2425 case 0x000001f3: return UINT64_C(0xfffff800); /* Ia32SmrrPhysMask - Only writable in SMM. */
2426
2427 /* these two have lock bits. */
2428 case 0x0000064b: return UINT64_C(0x80000003);
2429 case 0x0000064c: return UINT64_C(0x800000ff);
2430
2431 case 0xc0010015: return 1; /* SmmLock bit */
2432
2433 /* SmmLock effect: */
2434 case 0xc0010111: return UINT32_MAX;
2435 case 0xc0010112: return UINT64_C(0xfffe0000) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
2436 case 0xc0010113: return UINT64_C(0xfffe773f) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
2437 case 0xc0010116: return 0x1f;
2438
2439 case 0xc0010114: return RT_BIT_64(3) /* SVM lock */ | RT_BIT_64(4) /* SvmeDisable */;
2440
2441 /* Canonical */
2442 case 0xc0011034:
2443 case 0xc0011038:
2444 case 0xc001103b:
2445 return UINT64_C(0xffff800000000000);
2446
2447 case 0x00000060: case 0x00000061: case 0x00000062: case 0x00000063:
2448 case 0x00000064: case 0x00000065: case 0x00000066: case 0x00000067:
2449 case 0x00000040: case 0x00000041: case 0x00000042: case 0x00000043:
2450 case 0x00000044: case 0x00000045: case 0x00000046: case 0x00000047:
2451 case 0x00000600:
2452 if (g_enmMicroarch >= kCpumMicroarch_Intel_Core2_First)
2453 return UINT64_C(0xffff800000000000);
2454 break;
2455
2456
2457 /* Write only bits. */
2458 case 0xc0010041: return RT_BIT_64(16); /* FIDVID_CTL.InitFidVid */
2459
2460 /* Time counters - fudge them to avoid incorrect ignore masks. */
2461 case 0x00000010:
2462 case 0x000000e7:
2463 case 0x000000e8:
2464 return RT_BIT_32(29) - 1;
2465 }
2466 return 0;
2467}
2468
2469
2470
2471
2472/** queryMsrWriteBadness return values. */
2473typedef enum
2474{
2475 /** . */
2476 VBCPUREPBADNESS_MOSTLY_HARMLESS = 0,
2477 /** Not a problem if accessed with care. */
2478 VBCPUREPBADNESS_MIGHT_BITE,
2479 /** Worse than a bad james bond villain. */
2480 VBCPUREPBADNESS_BOND_VILLAIN
2481} VBCPUREPBADNESS;
2482
2483
2484/**
2485 * Backlisting and graylisting of MSRs which may cause tripple faults.
2486 *
2487 * @returns Badness factor.
2488 * @param uMsr The MSR in question.
2489 */
2490static VBCPUREPBADNESS queryMsrWriteBadness(uint32_t uMsr)
2491{
2492 /** @todo Having trouble in the 0xc0010247,0xc0011006,?? region on Bulldozer. */
2493 /** @todo Having trouble in the 0xc001100f,0xc001100d,?? region on Opteron
2494 * 2384. */
2495
2496 switch (uMsr)
2497 {
2498 case 0x00000050:
2499 case 0x00000051:
2500 case 0x00000052:
2501 case 0x00000053:
2502 case 0x00000054:
2503
2504 case 0x00001006:
2505 case 0x00001007:
2506 return VBCPUREPBADNESS_BOND_VILLAIN;
2507
2508 case 0x0000120e:
2509 case 0x00001233:
2510 case 0x00001239:
2511 case 0x00001249:
2512 case 0x0000124a:
2513 case 0x00001404:
2514 case 0x00001405:
2515 case 0x00001413:
2516 case 0x0000142c: /* Caused rip to be set to 297 or some such weirdness... */
2517 case 0x0000142e:
2518 case 0x00001435:
2519 case 0x00001436:
2520 case 0x00001438:
2521 case 0x0000317f:
2522 if (g_enmVendor == CPUMCPUVENDOR_VIA || g_enmVendor == CPUMCPUVENDOR_SHANGHAI)
2523 return VBCPUREPBADNESS_BOND_VILLAIN;
2524 break;
2525
2526 case 0xc0010010:
2527 case 0xc0010016:
2528 case 0xc0010017:
2529 case 0xc0010018:
2530 case 0xc0010019:
2531 case 0xc001001a:
2532 case 0xc001001d:
2533
2534 case 0xc0010058: /* MMIO Configuration Base Address on AMD Zen CPUs. */
2535 if (CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
2536 return VBCPUREPBADNESS_BOND_VILLAIN;
2537 break;
2538
2539 case 0xc0010064: /* P-state fequency, voltage, ++. */
2540 case 0xc0010065: /* P-state fequency, voltage, ++. */
2541 case 0xc0010066: /* P-state fequency, voltage, ++. */
2542 case 0xc0010067: /* P-state fequency, voltage, ++. */
2543 case 0xc0010068: /* P-state fequency, voltage, ++. */
2544 case 0xc0010069: /* P-state fequency, voltage, ++. */
2545 case 0xc001006a: /* P-state fequency, voltage, ++. */
2546 case 0xc001006b: /* P-state fequency, voltage, ++. */
2547 case 0xc0010070: /* COFVID Control. */
2548 case 0xc001101e:
2549 case 0xc0011021: /* IC_CFG (instruction cache configuration) */
2550 case 0xc0011023: /* CU_CFG (combined unit configuration) */
2551 case 0xc001102c: /* EX_CFG (execution unit configuration) */
2552 return VBCPUREPBADNESS_BOND_VILLAIN;
2553
2554 case 0xc0011012:
2555 if (CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch))
2556 return VBCPUREPBADNESS_MIGHT_BITE;
2557 break;
2558
2559 /* KVM MSRs that are unsafe to touch. */
2560 case 0x00000011: /* KVM */
2561 case 0x00000012: /* KVM */
2562 return VBCPUREPBADNESS_BOND_VILLAIN;
2563
2564 /*
2565 * The TSC is tricky -- writing it isn't a problem, but if we put back the original
2566 * value, we'll throw it out of whack. If we're on an SMP OS that uses the TSC for timing,
2567 * we'll likely kill it, especially if we can't do the modification very quickly.
2568 */
2569 case 0x00000010: /* IA32_TIME_STAMP_COUNTER */
2570 if (!g_MsrAcc.fAtomic)
2571 return VBCPUREPBADNESS_BOND_VILLAIN;
2572 break;
2573
2574 /*
2575 * The following MSRs are not safe to modify in a typical OS if we can't do it atomically,
2576 * i.e. read/modify/restore without allowing any other code to execute. Everything related
2577 * to syscalls will blow up in our face if we go back to userland with modified MSRs.
2578 */
2579// case 0x0000001b: /* IA32_APIC_BASE */
2580 case 0xc0000081: /* MSR_K6_STAR */
2581 case 0xc0000082: /* AMD64_STAR64 */
2582 case 0xc0000083: /* AMD64_STARCOMPAT */
2583 case 0xc0000084: /* AMD64_SYSCALL_FLAG_MASK */
2584 case 0xc0000100: /* AMD64_FS_BASE */
2585 case 0xc0000101: /* AMD64_GS_BASE */
2586 case 0xc0000102: /* AMD64_KERNEL_GS_BASE */
2587 if (!g_MsrAcc.fAtomic)
2588 return VBCPUREPBADNESS_MIGHT_BITE;
2589 break;
2590
2591 case 0x000001a0: /* IA32_MISC_ENABLE */
2592 case 0x00000199: /* IA32_PERF_CTL */
2593 return VBCPUREPBADNESS_MIGHT_BITE;
2594
2595 case 0x000005a0: /* C2_PECI_CTL */
2596 case 0x000005a1: /* C2_UNK_0000_05a1 */
2597 if (g_enmVendor == CPUMCPUVENDOR_INTEL)
2598 return VBCPUREPBADNESS_MIGHT_BITE;
2599 break;
2600
2601 case 0x00002000: /* P6_CR0. */
2602 case 0x00002003: /* P6_CR3. */
2603 case 0x00002004: /* P6_CR4. */
2604 if (g_enmVendor == CPUMCPUVENDOR_INTEL)
2605 return VBCPUREPBADNESS_MIGHT_BITE;
2606 break;
2607 case 0xc0000080: /* MSR_K6_EFER */
2608 return VBCPUREPBADNESS_MIGHT_BITE;
2609 }
2610 return VBCPUREPBADNESS_MOSTLY_HARMLESS;
2611}
2612
2613
2614/**
2615 * Checks if this might be a VIA/Shanghai dummy register.
2616 *
2617 * @returns true if it's a dummy, false if it isn't.
2618 * @param uMsr The MSR.
2619 * @param uValue The value.
2620 * @param fFlags The flags.
2621 */
2622static bool isMsrViaShanghaiDummy(uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
2623{
2624 if (g_enmVendor != CPUMCPUVENDOR_VIA && g_enmVendor != CPUMCPUVENDOR_SHANGHAI)
2625 return false;
2626
2627 if (uValue)
2628 return false;
2629
2630 if (fFlags)
2631 return false;
2632
2633 switch (uMsr)
2634 {
2635 case 0x00000010:
2636 case 0x0000001b:
2637 case 0x000000c1:
2638 case 0x000000c2:
2639 case 0x0000011e:
2640 case 0x00000186:
2641 case 0x00000187:
2642 //case 0x00000200 ... (mtrrs will be detected)
2643 return false;
2644
2645 case 0xc0000080:
2646 case 0xc0000081:
2647 case 0xc0000082:
2648 case 0xc0000083:
2649 if (vbCpuRepSupportsLongMode())
2650 return false;
2651 break;
2652 }
2653
2654 if (uMsr >= 0x00001200 && uMsr <= 0x00003fff && queryMsrWriteBadness(uMsr) != VBCPUREPBADNESS_MOSTLY_HARMLESS)
2655 return false;
2656
2657 if ( !msrProberModifyNoChange(uMsr)
2658 && !msrProberModifyZero(uMsr))
2659 return false;
2660
2661 uint64_t fIgnMask = 0;
2662 uint64_t fGpMask = 0;
2663 int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0);
2664 if (RT_FAILURE(rc))
2665 return false;
2666
2667 if (fIgnMask != UINT64_MAX)
2668 return false;
2669 if (fGpMask != 0)
2670 return false;
2671
2672 return true;
2673}
2674
2675
2676/**
2677 * Adjusts the ignore and GP masks for MSRs which contains canonical addresses.
2678 *
2679 * @param uMsr The MSR.
2680 * @param pfIgn Pointer to the ignore mask.
2681 * @param pfGp Pointer to the GP mask.
2682 */
2683static void adjustCanonicalIgnAndGpMasks(uint32_t uMsr, uint64_t *pfIgn, uint64_t *pfGp)
2684{
2685 RT_NOREF1(pfIgn);
2686 if (!vbCpuRepSupportsLongMode())
2687 return;
2688 switch (uMsr)
2689 {
2690 case 0x00000175:
2691 case 0x00000176:
2692 case 0x000001da:
2693 case 0x000001db:
2694 case 0x000001dc:
2695 case 0x000001de:
2696 case 0x00000600:
2697 if (*pfGp == UINT64_C(0xffff800000000000))
2698 *pfGp = 0;
2699 break;
2700 case 0x000001dd:
2701 if (*pfGp == UINT64_C(0x7fff800000000000) || *pfGp == UINT64_C(0xffff800000000000)) /* why is the top bit writable? */
2702 *pfGp = 0;
2703 break;
2704
2705 case 0xc0000082:
2706 case 0xc0000083:
2707 case 0xc0000100:
2708 case 0xc0000101:
2709 case 0xc0000102:
2710 *pfGp = 0;
2711 break;
2712 }
2713}
2714
2715
2716
2717/**
2718 * Prints a 64-bit value in the best way.
2719 *
2720 * @param uValue The value.
2721 */
2722static void printMsrValueU64(uint64_t uValue)
2723{
2724 if (uValue == 0)
2725 vbCpuRepPrintf(", 0");
2726 else if (uValue == UINT16_MAX)
2727 vbCpuRepPrintf(", UINT16_MAX");
2728 else if (uValue == UINT32_MAX)
2729 vbCpuRepPrintf(", UINT32_MAX");
2730 else if (uValue == UINT64_MAX)
2731 vbCpuRepPrintf(", UINT64_MAX");
2732 else if (uValue == UINT64_C(0xffffffff00000000))
2733 vbCpuRepPrintf(", ~(uint64_t)UINT32_MAX");
2734 else if (uValue <= (UINT32_MAX >> 1))
2735 vbCpuRepPrintf(", %#llx", uValue);
2736 else if (uValue <= UINT32_MAX)
2737 vbCpuRepPrintf(", UINT32_C(%#llx)", uValue);
2738 else
2739 vbCpuRepPrintf(", UINT64_C(%#llx)", uValue);
2740}
2741
2742
2743/**
2744 * Prints the newline after an MSR line has been printed.
2745 *
2746 * This is used as a hook to slow down the output and make sure the remote
2747 * terminal or/and output file has received the last update before we go and
2748 * crash probing the next MSR.
2749 */
2750static void printMsrNewLine(void)
2751{
2752 vbCpuRepPrintf("\n");
2753#if 1
2754 RTThreadSleep(8);
2755#endif
2756}
2757
2758static int printMsrWriteOnly(uint32_t uMsr, const char *pszWrFnName, const char *pszAnnotation)
2759{
2760 if (!pszWrFnName)
2761 pszWrFnName = "IgnoreWrite";
2762 vbCpuRepPrintf(pszAnnotation
2763 ? " MFN(%#010x, \"%s\", WriteOnly, %s), /* %s */"
2764 : " MFN(%#010x, \"%s\", WriteOnly, %s),",
2765 uMsr, getMsrName(uMsr), pszWrFnName, pszAnnotation);
2766 printMsrNewLine();
2767 return VINF_SUCCESS;
2768}
2769
2770
2771static int printMsrValueReadOnly(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
2772{
2773 vbCpuRepPrintf(" MVO(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
2774 printMsrValueU64(uValue);
2775 vbCpuRepPrintf("),");
2776 if (pszAnnotation)
2777 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2778 printMsrNewLine();
2779 return VINF_SUCCESS;
2780}
2781
2782
2783
2784static int printMsrValueIgnoreWritesNamed(uint32_t uMsr, uint64_t uValue, const char *pszName, const char *pszAnnotation)
2785{
2786 vbCpuRepPrintf(" MVI(%#010x, \"%s\"", uMsr, pszName);
2787 printMsrValueU64(uValue);
2788 vbCpuRepPrintf("),");
2789 if (pszAnnotation)
2790 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2791 printMsrNewLine();
2792 return VINF_SUCCESS;
2793}
2794
2795
2796static int printMsrValueIgnoreWrites(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
2797{
2798 return printMsrValueIgnoreWritesNamed(uMsr, uValue, getMsrName(uMsr), pszAnnotation);
2799}
2800
2801
2802static int printMsrValueExtended(uint32_t uMsr, uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask,
2803 const char *pszAnnotation)
2804{
2805 vbCpuRepPrintf(" MVX(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
2806 printMsrValueU64(uValue);
2807 printMsrValueU64(fIgnMask);
2808 printMsrValueU64(fGpMask);
2809 vbCpuRepPrintf("),");
2810 if (pszAnnotation)
2811 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2812 printMsrNewLine();
2813 return VINF_SUCCESS;
2814}
2815
2816
2817static int printMsrRangeValueReadOnly(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
2818{
2819 vbCpuRepPrintf(" RVO(%#010x, %#010x, \"%s\"", uMsr, uLast, getMsrRangeName(uMsr));
2820 printMsrValueU64(uValue);
2821 vbCpuRepPrintf("),");
2822 if (pszAnnotation)
2823 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2824 printMsrNewLine();
2825 return VINF_SUCCESS;
2826}
2827
2828
2829static int printMsrRangeValueIgnoreWritesNamed(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszName, const char *pszAnnotation)
2830{
2831 vbCpuRepPrintf(" RVI(%#010x, %#010x, \"%s\"", uMsr, uLast, pszName);
2832 printMsrValueU64(uValue);
2833 vbCpuRepPrintf("),");
2834 if (pszAnnotation)
2835 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2836 printMsrNewLine();
2837 return VINF_SUCCESS;
2838}
2839
2840
2841static int printMsrRangeValueIgnoreWrites(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
2842{
2843 return printMsrRangeValueIgnoreWritesNamed(uMsr, uLast, uValue, getMsrRangeName(uMsr), pszAnnotation);
2844}
2845
2846
2847static int printMsrFunction(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, const char *pszAnnotation)
2848{
2849 if (!pszRdFnName)
2850 pszRdFnName = getMsrFnName(uMsr, NULL);
2851 if (!pszWrFnName)
2852 pszWrFnName = pszRdFnName;
2853 vbCpuRepPrintf(" MFN(%#010x, \"%s\", %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
2854 if (pszAnnotation)
2855 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2856 printMsrNewLine();
2857 return VINF_SUCCESS;
2858}
2859
2860
2861static int printMsrFunctionReadOnly(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
2862{
2863 if (!pszRdFnName)
2864 pszRdFnName = getMsrFnName(uMsr, NULL);
2865 vbCpuRepPrintf(" MFO(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
2866 if (pszAnnotation)
2867 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2868 printMsrNewLine();
2869 return VINF_SUCCESS;
2870}
2871
2872
2873static int printMsrFunctionIgnoreWrites(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
2874{
2875 if (!pszRdFnName)
2876 pszRdFnName = getMsrFnName(uMsr, NULL);
2877 vbCpuRepPrintf(" MFI(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
2878 if (pszAnnotation)
2879 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2880 printMsrNewLine();
2881 return VINF_SUCCESS;
2882}
2883
2884
2885static int printMsrFunctionIgnoreMask(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
2886 uint64_t fIgnMask, const char *pszAnnotation)
2887{
2888 if (!pszRdFnName)
2889 pszRdFnName = getMsrFnName(uMsr, NULL);
2890 if (!pszWrFnName)
2891 pszWrFnName = pszRdFnName;
2892 vbCpuRepPrintf(" MFW(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
2893 printMsrValueU64(fIgnMask);
2894 vbCpuRepPrintf("),");
2895 if (pszAnnotation)
2896 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2897 printMsrNewLine();
2898 return VINF_SUCCESS;
2899}
2900
2901
2902static int printMsrFunctionExtended(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
2903 uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
2904{
2905 if (!pszRdFnName)
2906 pszRdFnName = getMsrFnName(uMsr, NULL);
2907 if (!pszWrFnName)
2908 pszWrFnName = pszRdFnName;
2909 vbCpuRepPrintf(" MFX(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
2910 printMsrValueU64(uValue);
2911 printMsrValueU64(fIgnMask);
2912 printMsrValueU64(fGpMask);
2913 vbCpuRepPrintf("),");
2914 if (pszAnnotation)
2915 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2916 printMsrNewLine();
2917 return VINF_SUCCESS;
2918}
2919
2920
2921static int printMsrFunctionExtendedIdxVal(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
2922 uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
2923{
2924 if (!pszRdFnName)
2925 pszRdFnName = getMsrFnName(uMsr, NULL);
2926 if (!pszWrFnName)
2927 pszWrFnName = pszRdFnName;
2928 vbCpuRepPrintf(" MFX(%#010x, \"%s\", %s, %s, %#x", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, uValue);
2929 printMsrValueU64(fIgnMask);
2930 printMsrValueU64(fGpMask);
2931 vbCpuRepPrintf("),");
2932 if (pszAnnotation)
2933 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2934 printMsrNewLine();
2935 return VINF_SUCCESS;
2936}
2937
2938
2939static int printMsrFunctionCpumCpu(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
2940 const char *pszCpumCpuStorage, const char *pszAnnotation)
2941{
2942 if (!pszRdFnName)
2943 pszRdFnName = getMsrFnName(uMsr, NULL);
2944 if (!pszWrFnName)
2945 pszWrFnName = pszRdFnName;
2946 if (!pszCpumCpuStorage)
2947 pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
2948 if (!pszCpumCpuStorage)
2949 return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
2950 vbCpuRepPrintf(" MFS(%#010x, \"%s\", %s, %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
2951 if (pszAnnotation)
2952 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2953 printMsrNewLine();
2954 return VINF_SUCCESS;
2955}
2956
2957
2958static int printMsrFunctionCpumCpuEx(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
2959 const char *pszCpumCpuStorage, uint64_t fIgnMask, uint64_t fGpMask,
2960 const char *pszAnnotation)
2961{
2962 if (!pszRdFnName)
2963 pszRdFnName = getMsrFnName(uMsr, NULL);
2964 if (!pszWrFnName)
2965 pszWrFnName = pszRdFnName;
2966 if (!pszCpumCpuStorage)
2967 pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
2968 if (!pszCpumCpuStorage)
2969 return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
2970 vbCpuRepPrintf(" MFZ(%#010x, \"%s\", %s, %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
2971 printMsrValueU64(fIgnMask);
2972 printMsrValueU64(fGpMask);
2973 vbCpuRepPrintf("),");
2974 if (pszAnnotation)
2975 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2976 printMsrNewLine();
2977 return VINF_SUCCESS;
2978}
2979
2980
2981static int printMsrRangeFunction(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
2982 const char *pszAnnotation)
2983{
2984 if (!pszRdFnName)
2985 pszRdFnName = getMsrFnName(uMsr, NULL);
2986 if (!pszWrFnName)
2987 pszWrFnName = pszRdFnName;
2988 vbCpuRepPrintf(" RFN(%#010x, %#010x, \"%s\", %s, %s),", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
2989 if (pszAnnotation)
2990 vbCpuRepPrintf(" /* %s */", pszAnnotation);
2991 printMsrNewLine();
2992 return VINF_SUCCESS;
2993}
2994
2995
2996static int printMsrRangeFunctionEx(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
2997 uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
2998{
2999 if (!pszRdFnName)
3000 pszRdFnName = getMsrFnName(uMsr, NULL);
3001 if (!pszWrFnName)
3002 pszWrFnName = pszRdFnName;
3003 vbCpuRepPrintf(" RSN(%#010x, %#010x, \"%s\", %s, %s", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
3004 printMsrValueU64(uValue);
3005 printMsrValueU64(fIgnMask);
3006 printMsrValueU64(fGpMask);
3007 vbCpuRepPrintf("),");
3008 if (pszAnnotation)
3009 vbCpuRepPrintf(" /* %s */", pszAnnotation);
3010 printMsrNewLine();
3011 return VINF_SUCCESS;
3012}
3013
3014
3015static int printMsrRangeFunctionExIdxVal(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
3016 uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
3017{
3018 if (!pszRdFnName)
3019 pszRdFnName = getMsrFnName(uMsr, NULL);
3020 if (!pszWrFnName)
3021 pszWrFnName = pszRdFnName;
3022 vbCpuRepPrintf(" RSN(%#010x, %#010x, \"%s\", %s, %s, %#x",
3023 uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName, uValue);
3024 printMsrValueU64(fIgnMask);
3025 printMsrValueU64(fGpMask);
3026 vbCpuRepPrintf("),");
3027 if (pszAnnotation)
3028 vbCpuRepPrintf(" /* %s */", pszAnnotation);
3029 printMsrNewLine();
3030 return VINF_SUCCESS;
3031}
3032
3033
3034static int printMsrAlias(uint32_t uMsr, uint32_t uTarget, const char *pszAnnotation)
3035{
3036 vbCpuRepPrintf(" MAL(%#010x, \"%s\", %#010x),", uMsr, getMsrName(uMsr), uTarget);
3037 if (pszAnnotation)
3038 vbCpuRepPrintf(" /* %s */", pszAnnotation);
3039 printMsrNewLine();
3040 return VINF_SUCCESS;
3041}
3042
3043
3044
3045static const char *annotateValue(uint64_t uValue)
3046{
3047 static char s_szBuf[40];
3048 if (uValue <= UINT32_MAX)
3049 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#llx", uValue);
3050 else
3051 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#x`%08x", RT_HI_U32(uValue), RT_LO_U32(uValue));
3052 return s_szBuf;
3053}
3054
3055
3056static const char *annotateValueExtra(const char *pszExtra, uint64_t uValue)
3057{
3058 static char s_szBuf[40];
3059 if (uValue <= UINT32_MAX)
3060 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#llx", pszExtra, uValue);
3061 else
3062 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#x`%08x", pszExtra, RT_HI_U32(uValue), RT_LO_U32(uValue));
3063 return s_szBuf;
3064}
3065
3066
3067static const char *annotateIfMissingBits(uint64_t uValue, uint64_t fBits)
3068{
3069 static char s_szBuf[80];
3070 if ((uValue & fBits) == fBits)
3071 return annotateValue(uValue);
3072 RTStrPrintf(s_szBuf, sizeof(s_szBuf), "XXX: Unexpected value %#llx - wanted bits %#llx to be set.", uValue, fBits);
3073 return s_szBuf;
3074}
3075
3076
3077static int reportMsr_Generic(uint32_t uMsr, uint32_t fFlags, uint64_t uValue)
3078{
3079 int rc;
3080 bool fTakesValue = false;
3081 const char *pszFnName = getMsrFnName(uMsr, &fTakesValue);
3082
3083 if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
3084 rc = printMsrWriteOnly(uMsr, pszFnName, NULL);
3085 else
3086 {
3087 bool fReadAsZero = doesMsrReadAsZero(uMsr);
3088 fTakesValue = fTakesValue && !fReadAsZero;
3089
3090
3091 switch (queryMsrWriteBadness(uMsr))
3092 {
3093 /* This is what we're here for... */
3094 case VBCPUREPBADNESS_MOSTLY_HARMLESS:
3095 {
3096 if ( msrProberModifyNoChange(uMsr)
3097 || msrProberModifyZero(uMsr))
3098 {
3099 uint64_t fSkipMask = getGenericSkipMask(uMsr);
3100 uint64_t fIgnMask = 0;
3101 uint64_t fGpMask = 0;
3102 rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
3103 if (RT_FAILURE(rc))
3104 return rc;
3105 adjustCanonicalIgnAndGpMasks(uMsr, &fIgnMask, &fGpMask);
3106
3107 if (pszFnName)
3108 {
3109 if (fGpMask == 0 && fIgnMask == UINT64_MAX && !fTakesValue)
3110 rc = printMsrFunctionIgnoreWrites(uMsr, pszFnName, annotateValue(uValue));
3111 else if (fGpMask == 0 && fIgnMask == 0 && (!fTakesValue || uValue == 0))
3112 rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValue(uValue));
3113 else
3114 rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, fTakesValue ? uValue : 0,
3115 fIgnMask, fGpMask, annotateValue(uValue));
3116 }
3117 else if (fGpMask == 0 && fIgnMask == UINT64_MAX)
3118 rc = printMsrValueIgnoreWrites(uMsr, fReadAsZero ? 0 : uValue, fReadAsZero ? annotateValue(uValue) : NULL);
3119 else
3120 rc = printMsrValueExtended(uMsr, fReadAsZero ? 0 : uValue, fIgnMask, fGpMask,
3121 fReadAsZero ? annotateValue(uValue) : NULL);
3122 }
3123 /* Most likely read-only. */
3124 else if (pszFnName && !fTakesValue)
3125 rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValue(uValue));
3126 else if (pszFnName)
3127 rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, 0, annotateValue(uValue));
3128 else if (fReadAsZero)
3129 rc = printMsrValueReadOnly(uMsr, 0, annotateValue(uValue));
3130 else
3131 rc = printMsrValueReadOnly(uMsr, uValue, NULL);
3132 break;
3133 }
3134
3135 /* These should have special handling, so just do a simple
3136 write back same value check to see if it's writable. */
3137 case VBCPUREPBADNESS_MIGHT_BITE:
3138 if (msrProberModifyNoChange(uMsr))
3139 {
3140 if (pszFnName && !fTakesValue)
3141 rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Might bite.", uValue));
3142 else if (pszFnName)
3143 rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
3144 annotateValueExtra("Might bite.", uValue));
3145 else if (fReadAsZero)
3146 rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Might bite.", uValue));
3147 else
3148 rc = printMsrValueIgnoreWrites(uMsr, uValue, "Might bite.");
3149 }
3150 else if (pszFnName && !fTakesValue)
3151 rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValueExtra("Might bite.", uValue));
3152 else if (pszFnName)
3153 rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, UINT64_MAX,
3154 annotateValueExtra("Might bite.", uValue));
3155 else if (fReadAsZero)
3156 rc = printMsrValueReadOnly(uMsr, 0, annotateValueExtra("Might bite.", uValue));
3157 else
3158 rc = printMsrValueReadOnly(uMsr, uValue, "Might bite.");
3159 break;
3160
3161
3162 /* Don't try anything with these guys. */
3163 case VBCPUREPBADNESS_BOND_VILLAIN:
3164 default:
3165 if (pszFnName && !fTakesValue)
3166 rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Villain?", uValue));
3167 else if (pszFnName)
3168 rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
3169 annotateValueExtra("Villain?", uValue));
3170 else if (fReadAsZero)
3171 rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Villain?", uValue));
3172 else
3173 rc = printMsrValueIgnoreWrites(uMsr, uValue, "Villain?");
3174 break;
3175 }
3176 }
3177
3178 return rc;
3179}
3180
3181
3182static int reportMsr_GenRangeFunctionEx(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
3183 uint32_t uMsrBase, bool fEarlyEndOk, bool fNoIgnMask, uint64_t fSkipMask, uint32_t *pidxLoop)
3184{
3185 uint32_t uMsr = paMsrs[0].uMsr;
3186 uint32_t iRange = uMsr - uMsrBase;
3187 Assert(cMax > iRange);
3188 cMax -= iRange;
3189
3190 /* Resolve default function name. */
3191 if (!pszRdWrFnName)
3192 {
3193 pszRdWrFnName = getMsrFnName(uMsr, NULL);
3194 if (!pszRdWrFnName)
3195 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
3196 }
3197
3198 /* Figure the possible register count. */
3199 if (cMax > cMsrs)
3200 cMax = cMsrs;
3201 uint32_t cRegs = 1;
3202 while ( cRegs < cMax
3203 && paMsrs[cRegs].uMsr == uMsr + cRegs)
3204 cRegs++;
3205
3206 /* Probe the first register and check that the others exhibit
3207 the same characteristics. */
3208 bool fReadOnly0;
3209 uint64_t fIgnMask0, fGpMask0;
3210 int rc = msrProberModifyBasicTests(uMsr, fSkipMask, &fReadOnly0, &fIgnMask0, &fGpMask0);
3211 if (RT_FAILURE(rc))
3212 return rc;
3213
3214 const char *pszAnnotation = NULL;
3215 for (uint32_t i = 1; i < cRegs; i++)
3216 {
3217 bool fReadOnlyN;
3218 uint64_t fIgnMaskN, fGpMaskN;
3219 rc = msrProberModifyBasicTests(paMsrs[i].uMsr, fSkipMask, &fReadOnlyN, &fIgnMaskN, &fGpMaskN);
3220 if (RT_FAILURE(rc))
3221 return rc;
3222 if ( fReadOnlyN != fReadOnly0
3223 || (fIgnMaskN != fIgnMask0 && !fNoIgnMask)
3224 || fGpMaskN != fGpMask0)
3225 {
3226 if (!fEarlyEndOk && !isMsrViaShanghaiDummy(uMsr, paMsrs[i].uValue, paMsrs[i].fFlags))
3227 {
3228 vbCpuRepDebug("MSR %s (%#x) range ended unexpectedly early on %#x: ro=%d ign=%#llx/%#llx gp=%#llx/%#llx [N/0]\n",
3229 getMsrNameHandled(uMsr), uMsr, paMsrs[i].uMsr,
3230 fReadOnlyN, fReadOnly0, fIgnMaskN, fIgnMask0, fGpMaskN, fGpMask0);
3231 pszAnnotation = "XXX: The range ended earlier than expected!";
3232 }
3233 cRegs = i;
3234 break;
3235 }
3236 }
3237
3238 /*
3239 * Report the range (or single MSR as it might be).
3240 */
3241 *pidxLoop += cRegs - 1;
3242
3243 if (fNoIgnMask)
3244 fIgnMask0 = 0;
3245 bool fSimple = fIgnMask0 == 0
3246 && (fGpMask0 == 0 || (fGpMask0 == UINT64_MAX && fReadOnly0))
3247 && iRange == 0;
3248 if (cRegs == 1)
3249 return printMsrFunctionExtendedIdxVal(uMsr, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
3250 iRange, fIgnMask0, fGpMask0,
3251 pszAnnotation ? pszAnnotation : annotateValue(paMsrs[0].uValue));
3252 if (fSimple)
3253 return printMsrRangeFunction(uMsr, uMsr + cRegs - 1,
3254 pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName, pszAnnotation);
3255
3256 return printMsrRangeFunctionExIdxVal(uMsr, uMsr + cRegs - 1, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
3257 iRange /*uValue*/, fIgnMask0, fGpMask0, pszAnnotation);
3258}
3259
3260
3261static int reportMsr_GenRangeFunction(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
3262 uint32_t *pidxLoop)
3263{
3264 return reportMsr_GenRangeFunctionEx(paMsrs, cMsrs, cMax, pszRdWrFnName, paMsrs[0].uMsr, false /*fEarlyEndOk*/, false /*fNoIgnMask*/,
3265 getGenericSkipMask(paMsrs[0].uMsr), pidxLoop);
3266}
3267
3268
3269/**
3270 * Generic report for an MSR implemented by functions, extended version.
3271 *
3272 * @returns VBox status code.
3273 * @param uMsr The MSR.
3274 * @param pszRdWrFnName The read/write function name, optional.
3275 * @param uValue The MSR range value.
3276 * @param fSkipMask Mask of bits to skip.
3277 * @param fNoGpMask Mask of bits to remove from the GP mask after
3278 * probing
3279 * @param pszAnnotate Annotation.
3280 */
3281static int reportMsr_GenFunctionEx(uint32_t uMsr, const char *pszRdWrFnName, uint32_t uValue,
3282 uint64_t fSkipMask, uint64_t fNoGpMask, const char *pszAnnotate)
3283{
3284 /* Resolve default function name. */
3285 if (!pszRdWrFnName)
3286 {
3287 pszRdWrFnName = getMsrFnName(uMsr, NULL);
3288 if (!pszRdWrFnName)
3289 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
3290 }
3291
3292 /* Probe the register and report. */
3293 uint64_t fIgnMask = 0;
3294 uint64_t fGpMask = 0;
3295 int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
3296 if (RT_SUCCESS(rc))
3297 {
3298 fGpMask &= ~fNoGpMask;
3299
3300 if (fGpMask == UINT64_MAX && uValue == 0 && !msrProberModifyZero(uMsr))
3301 rc = printMsrFunctionReadOnly(uMsr, pszRdWrFnName, pszAnnotate);
3302 else if (fIgnMask == UINT64_MAX && fGpMask == 0 && uValue == 0)
3303 rc = printMsrFunctionIgnoreWrites(uMsr, pszRdWrFnName, pszAnnotate);
3304 else if (fIgnMask != 0 && fGpMask == 0 && uValue == 0)
3305 rc = printMsrFunctionIgnoreMask(uMsr, pszRdWrFnName, NULL, fIgnMask, pszAnnotate);
3306 else if (fIgnMask == 0 && fGpMask == 0 && uValue == 0)
3307 rc = printMsrFunction(uMsr, pszRdWrFnName, NULL, pszAnnotate);
3308 else
3309 rc = printMsrFunctionExtended(uMsr, pszRdWrFnName, NULL, uValue, fIgnMask, fGpMask, pszAnnotate);
3310 }
3311 return rc;
3312}
3313
3314
3315/**
3316 * Reports a VIA/Shanghai dummy range.
3317 *
3318 * @returns VBox status code.
3319 * @param paMsrs Pointer to the first MSR.
3320 * @param cMsrs The number of MSRs in the array @a paMsr.
3321 * @param pidxLoop Index variable that should be advanced to the
3322 * last MSR entry in the range.
3323 */
3324static int reportMsr_ViaShanghaiDummyRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3325{
3326 /* Figure how many. */
3327 uint32_t uMsr = paMsrs[0].uMsr;
3328 uint32_t cRegs = 1;
3329 while ( cRegs < cMsrs
3330 && paMsrs[cRegs].uMsr == uMsr + cRegs
3331 && isMsrViaShanghaiDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags))
3332 {
3333 cRegs++;
3334 if (!(cRegs % 0x80))
3335 vbCpuRepDebug("VIA dummy detection %#llx..%#llx (%#x regs)...\n", uMsr, uMsr + cRegs - 1, cRegs);
3336 }
3337
3338 /* Advance. */
3339 *pidxLoop += cRegs - 1;
3340
3341 /* Report it/them. */
3342 char szName[80];
3343 if (cRegs == 1)
3344 {
3345 RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
3346 return printMsrValueIgnoreWritesNamed(uMsr, 0, szName, NULL);
3347 }
3348
3349 uint32_t uMsrLast = uMsr + cRegs - 1;
3350 RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x_THRU_%04x_%04x",
3351 RT_HI_U16(uMsr), RT_LO_U16(uMsr), RT_HI_U16(uMsrLast), RT_LO_U16(uMsrLast));
3352 return printMsrRangeValueIgnoreWritesNamed(uMsr, uMsrLast, 0, szName, NULL);
3353}
3354
3355
3356/**
3357 * Special function for reporting the IA32_APIC_BASE register, as it seems to be
3358 * causing trouble on newer systems.
3359 *
3360 * @returns
3361 * @param uMsr The MSR number.
3362 * @param uValue The value.
3363 */
3364static int reportMsr_Ia32ApicBase(uint32_t uMsr, uint64_t uValue)
3365{
3366 /* Trouble with the generic treatment of both the "APIC Global Enable" and
3367 "Enable x2APIC mode" bits on an i7-3820QM running OS X 10.8.5. */
3368 uint64_t fSkipMask = RT_BIT_64(11);
3369 if (vbCpuRepSupportsX2Apic())
3370 fSkipMask |= RT_BIT_64(10);
3371 /* For some reason, twiddling this bit kills a Tualatin PIII-S. */
3372 if (g_enmMicroarch == kCpumMicroarch_Intel_P6_III)
3373 fSkipMask |= RT_BIT(9);
3374
3375 /* If the OS uses the APIC, we have to be super careful. */
3376 if (!g_MsrAcc.fAtomic)
3377 fSkipMask |= UINT64_C(0x0000000ffffff000);
3378
3379 /** @todo This makes the host unstable on a AMD Ryzen 1800X CPU, skip everything for now.
3380 * Figure out exactly what causes the issue.
3381 */
3382 if ( g_enmMicroarch >= kCpumMicroarch_AMD_Zen_First
3383 && g_enmMicroarch >= kCpumMicroarch_AMD_Zen_End)
3384 fSkipMask |= UINT64_C(0xffffffffffffffff);
3385
3386 return reportMsr_GenFunctionEx(uMsr, "Ia32ApicBase", uValue, fSkipMask, 0, NULL);
3387}
3388
3389
3390/**
3391 * Special function for reporting the IA32_MISC_ENABLE register, as it seems to
3392 * be causing trouble on newer systems.
3393 *
3394 * @returns
3395 * @param uMsr The MSR number.
3396 * @param uValue The value.
3397 */
3398static int reportMsr_Ia32MiscEnable(uint32_t uMsr, uint64_t uValue)
3399{
3400 uint64_t fSkipMask = 0;
3401
3402 if ( ( g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Broadwell
3403 && g_enmMicroarch <= kCpumMicroarch_Intel_Core7_End)
3404 || ( g_enmMicroarch >= kCpumMicroarch_Intel_Atom_Airmount
3405 && g_enmMicroarch <= kCpumMicroarch_Intel_Atom_End)
3406 )
3407 {
3408 vbCpuRepPrintf("WARNING: IA32_MISC_ENABLE probing needs hacking on this CPU!\n");
3409 RTThreadSleep(128);
3410 }
3411
3412 /* If the OS is using MONITOR/MWAIT we'd better not disable it! */
3413 if (!g_MsrAcc.fAtomic)
3414 fSkipMask |= RT_BIT(18);
3415
3416 /* The no execute related flag is deadly if clear. */
3417 if ( !(uValue & MSR_IA32_MISC_ENABLE_XD_DISABLE)
3418 && ( g_enmMicroarch < kCpumMicroarch_Intel_First
3419 || g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
3420 || vbCpuRepSupportsNX() ) )
3421 fSkipMask |= MSR_IA32_MISC_ENABLE_XD_DISABLE;
3422
3423 uint64_t fIgnMask = 0;
3424 uint64_t fGpMask = 0;
3425 int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
3426 if (RT_SUCCESS(rc))
3427 rc = printMsrFunctionExtended(uMsr, "Ia32MiscEnable", "Ia32MiscEnable", uValue,
3428 fIgnMask, fGpMask, annotateValue(uValue));
3429 return rc;
3430}
3431
3432
3433/**
3434 * Verifies that MTRR type field works correctly in the given MSR.
3435 *
3436 * @returns VBox status code (failure if bad MSR behavior).
3437 * @param uMsr The MSR.
3438 * @param iBit The first bit of the type field (8-bit wide).
3439 * @param cExpected The number of types expected - PAT=8, MTRR=7.
3440 */
3441static int msrVerifyMtrrTypeGPs(uint32_t uMsr, uint32_t iBit, uint32_t cExpected)
3442{
3443 uint32_t uEndTypes = 0;
3444 while (uEndTypes < 255)
3445 {
3446 bool fGp = !msrProberModifySimpleGp(uMsr, ~(UINT64_C(0xff) << iBit), (uint64_t)uEndTypes << iBit);
3447 if (!fGp && (uEndTypes == 2 || uEndTypes == 3))
3448 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types %u does not cause a GP as it should. (msr %#x)\n",
3449 uEndTypes, uMsr);
3450 if (fGp && uEndTypes != 2 && uEndTypes != 3)
3451 break;
3452 uEndTypes++;
3453 }
3454 if (uEndTypes != cExpected)
3455 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types detected to be %#x (msr %#x). Expected %#x.\n",
3456 uEndTypes, uMsr, cExpected);
3457 return VINF_SUCCESS;
3458}
3459
3460
3461/**
3462 * Deals with the variable MTRR MSRs.
3463 *
3464 * @returns VBox status code.
3465 * @param paMsrs Pointer to the first variable MTRR MSR (200h).
3466 * @param cMsrs The number of MSRs in the array @a paMsr.
3467 * @param pidxLoop Index variable that should be advanced to the
3468 * last MTRR MSR entry.
3469 */
3470static int reportMsr_Ia32MtrrPhysBaseMaskN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3471{
3472 uint32_t uMsr = paMsrs[0].uMsr;
3473
3474 /* Count them. */
3475 uint32_t cRegs = 1;
3476 while ( cRegs < cMsrs
3477 && paMsrs[cRegs].uMsr == uMsr + cRegs
3478 && !isMsrViaShanghaiDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags) )
3479 cRegs++;
3480 if (cRegs & 1)
3481 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is odd: cRegs=%#x\n", cRegs);
3482 if (cRegs > 0x20)
3483 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is too large: cRegs=%#x\n", cRegs);
3484
3485 /* Find a disabled register that we can play around with. */
3486 uint32_t iGuineaPig;
3487 for (iGuineaPig = 0; iGuineaPig < cRegs; iGuineaPig += 2)
3488 if (!(paMsrs[iGuineaPig + 1].uValue & RT_BIT_32(11)))
3489 break;
3490 if (iGuineaPig >= cRegs)
3491 iGuineaPig = cRegs - 2;
3492 vbCpuRepDebug("iGuineaPig=%#x -> %#x\n", iGuineaPig, uMsr + iGuineaPig);
3493
3494 /* Probe the base. */
3495 uint64_t fIgnBase = 0;
3496 uint64_t fGpBase = 0;
3497 int rc = msrProberModifyBitChanges(uMsr + iGuineaPig, &fIgnBase, &fGpBase, 0);
3498 if (RT_FAILURE(rc))
3499 return rc;
3500 rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
3501 if (RT_FAILURE(rc))
3502 return rc;
3503 vbCpuRepDebug("fIgnBase=%#llx fGpBase=%#llx\n", fIgnBase, fGpBase);
3504
3505 /* Probing the mask is relatively straight forward. */
3506 uint64_t fIgnMask = 0;
3507 uint64_t fGpMask = 0;
3508 rc = msrProberModifyBitChanges(uMsr + iGuineaPig + 1, &fIgnMask, &fGpMask, 0x800); /* enabling it may cause trouble */
3509 if (RT_FAILURE(rc))
3510 return rc;
3511 vbCpuRepDebug("fIgnMask=%#llx fGpMask=%#llx\n", fIgnMask, fGpMask);
3512
3513 /* Validate that the whole range subscribes to the apprimately same GP rules. */
3514 for (uint32_t i = 0; i < cRegs; i += 2)
3515 {
3516 uint64_t fSkipBase = ~fGpBase;
3517 uint64_t fSkipMask = ~fGpMask;
3518 if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
3519 fSkipBase = fSkipMask = 0;
3520 fSkipBase |= 0x7; /* Always skip the type. */
3521 fSkipMask |= RT_BIT_32(11); /* Always skip the enable bit. */
3522
3523 vbCpuRepDebug("i=%#x fSkipBase=%#llx fSkipMask=%#llx\n", i, fSkipBase, fSkipMask);
3524
3525 if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
3526 {
3527 rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
3528 if (RT_FAILURE(rc))
3529 return rc;
3530 }
3531
3532 uint64_t fIgnBaseN = 0;
3533 uint64_t fGpBaseN = 0;
3534 rc = msrProberModifyBitChanges(uMsr + i, &fIgnBaseN, &fGpBaseN, fSkipBase);
3535 if (RT_FAILURE(rc))
3536 return rc;
3537
3538 if ( fIgnBaseN != (fIgnBase & ~fSkipBase)
3539 || fGpBaseN != (fGpBase & ~fSkipBase) )
3540 return RTMsgErrorRc(VERR_INVALID_PARAMETER,
3541 "MTRR PHYS BASE register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipBase=%#llx)\n",
3542 uMsr + i, uMsr + iGuineaPig,
3543 fIgnBaseN, fIgnBase & ~fSkipBase, fGpBaseN, fGpBase & ~fSkipBase, fSkipBase);
3544
3545 uint64_t fIgnMaskN = 0;
3546 uint64_t fGpMaskN = 0;
3547 rc = msrProberModifyBitChanges(uMsr + i + 1, &fIgnMaskN, &fGpMaskN, fSkipMask);
3548 if (RT_FAILURE(rc))
3549 return rc;
3550 if ( fIgnMaskN != (fIgnMask & ~fSkipMask)
3551 || fGpMaskN != (fGpMask & ~fSkipMask) )
3552 return RTMsgErrorRc(VERR_INVALID_PARAMETER,
3553 "MTRR PHYS MASK register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipMask=%#llx)\n",
3554 uMsr + i + 1, uMsr + iGuineaPig + 1,
3555 fIgnMaskN, fIgnMask & ~fSkipMask, fGpMaskN, fGpMask & ~fSkipMask, fSkipMask);
3556 }
3557
3558 /* Print the whole range. */
3559 fGpBase &= ~(uint64_t)0x7; /* Valid type bits, see msrVerifyMtrrTypeGPs(). */
3560 for (uint32_t i = 0; i < cRegs; i += 2)
3561 {
3562 printMsrFunctionExtendedIdxVal(uMsr + i, "Ia32MtrrPhysBaseN", NULL, i / 2, fIgnBase, fGpBase,
3563 annotateValue(paMsrs[i].uValue));
3564 printMsrFunctionExtendedIdxVal(uMsr + i + 1, "Ia32MtrrPhysMaskN", NULL, i / 2, fIgnMask, fGpMask,
3565 annotateValue(paMsrs[i + 1].uValue));
3566 }
3567
3568 *pidxLoop += cRegs - 1;
3569 return VINF_SUCCESS;
3570}
3571
3572
3573/**
3574 * Deals with fixed MTRR and PAT MSRs, checking the 8 memory type fields.
3575 *
3576 * @returns VBox status code.
3577 * @param uMsr The MSR.
3578 */
3579static int reportMsr_Ia32MtrrFixedOrPat(uint32_t uMsr)
3580{
3581 /* Had a spot of trouble on an old macbook pro with core2 duo T9900 (penryn)
3582 running 64-bit win81pe. Not giving PAT such a scrutiny fixes it. */
3583 /* This hangs the host on a AMD Ryzen 1800X CPU */
3584 if ( uMsr != 0x00000277
3585 || ( g_enmVendor == CPUMCPUVENDOR_INTEL
3586 ? g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First
3587 : g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON
3588 ? ( g_enmMicroarch != kCpumMicroarch_AMD_K8_90nm_AMDV
3589 && !CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
3590 : true) )
3591 {
3592 /* Every 8 bytes is a type, check the type ranges one by one. */
3593 for (uint32_t iBit = 0; iBit < 64; iBit += 8)
3594 {
3595 int rc = msrVerifyMtrrTypeGPs(uMsr, iBit, 7 + (uMsr == 0x00000277));
3596 if (RT_FAILURE(rc))
3597 return rc;
3598 }
3599 }
3600
3601 return printMsrFunctionCpumCpu(uMsr, NULL, NULL, NULL, NULL);
3602}
3603
3604
3605/**
3606 * Deals with IA32_MTRR_DEF_TYPE.
3607 *
3608 * @returns VBox status code.
3609 * @param uMsr The MSR.
3610 */
3611static int reportMsr_Ia32MtrrDefType(uint32_t uMsr)
3612{
3613 uint64_t fGpMask = 0;
3614 uint64_t fIgnMask = 0;
3615 if (g_enmMicroarch == kCpumMicroarch_AMD_K8_90nm_AMDV)
3616 {
3617 /* Problematic CPU! Fake it for now. */
3618 fGpMask = ~(uint64_t)0xc07;
3619 fIgnMask = 0;
3620 }
3621 else
3622 {
3623 int rc = msrVerifyMtrrTypeGPs(uMsr, 0, 7);
3624 if (RT_FAILURE(rc))
3625 return rc;
3626
3627 rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0x7);
3628 if (RT_FAILURE(rc))
3629 return rc;
3630 Assert(!(fGpMask & 7)); Assert(!(fIgnMask & 7));
3631 }
3632
3633 return printMsrFunctionCpumCpuEx(uMsr, NULL, NULL, NULL, fIgnMask, fGpMask, NULL);
3634}
3635
3636
3637/**
3638 * Deals with the Machine Check (MC) MSRs in the 400h+ area.
3639 *
3640 * @returns VBox status code.
3641 * @param paMsrs Pointer to the first MC MSR (400h).
3642 * @param cMsrs The number of MSRs in the array @a paMsr.
3643 * @param pidxLoop Index variable that should be advanced to the
3644 * last MC MSR entry.
3645 */
3646static int reportMsr_Ia32McCtlStatusAddrMiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3647{
3648 uint32_t uMsr = paMsrs[0].uMsr;
3649
3650 /* Count them. */
3651 uint32_t cRegs = 1;
3652 uint32_t cDetectedRegs = 1;
3653 while ( cDetectedRegs < cMsrs
3654 && ( paMsrs[cDetectedRegs].uMsr == uMsr + cRegs
3655 || (cRegs & 3) == 2 /* ADDR may or may not be there, depends on STATUS and CPU. */
3656 || (cRegs & 3) == 3 /* MISC may or may not be there, depends on STATUS and CPU. */
3657 || cRegs == 0x13 /* MC4_MISC may not be there, depends on CPU. */
3658 || cRegs == 0x14 /* MC5_CTL may not be there, depends on CPU. */)
3659 && cRegs < 0x7f )
3660 {
3661 if (paMsrs[cDetectedRegs].uMsr == uMsr + cRegs)
3662 cDetectedRegs++;
3663 cRegs++;
3664 }
3665
3666 /** aeichner: An AMD Ryzen 7 1800X CPU triggers this and I'm too lazy to check the correctness in detail. */
3667 if ( (cRegs & 3)
3668 && !CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
3669 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MC MSR range is odd: cRegs=%#x\n", cRegs);
3670
3671 /* Just report them. We don't bother probing here as the CTL format
3672 and such seems to be a lot of work to test correctly and changes between
3673 cpu generations. */
3674 *pidxLoop += cDetectedRegs - 1;
3675 return printMsrRangeFunction(uMsr, uMsr + cRegs - 1, "Ia32McCtlStatusAddrMiscN", NULL, NULL);
3676}
3677
3678
3679
3680/**
3681 * Deals with the X2APIC msrs.
3682 *
3683 * @returns VBox status code.
3684 * @param paMsrs Pointer to the first X2APIC MSR.
3685 * @param cMsrs The number of MSRs in the array @a paMsr.
3686 * @param pidxLoop Index variable that should be advanced to the
3687 * last X2APIC MSR entry.
3688 */
3689static int reportMsr_GenX2Apic(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3690{
3691 /* Advance. */
3692 uint32_t cRegs = 1;
3693 while ( cRegs < cMsrs
3694 && paMsrs[cRegs].uMsr <= 0x8ff)
3695 cRegs++;
3696 *pidxLoop += cRegs - 1;
3697
3698 /* Just emit an X2APIC range. */
3699 return printMsrRangeFunction(0x800, 0x8ff, "Ia32X2ApicN", NULL, NULL);
3700}
3701
3702
3703/**
3704 * Deals carefully with the EFER register.
3705 *
3706 * @returns VBox status code.
3707 * @param uMsr The MSR number.
3708 * @param uValue The current value.
3709 */
3710static int reportMsr_Amd64Efer(uint32_t uMsr, uint64_t uValue)
3711{
3712 uint64_t fSkipMask = 0;
3713 if (vbCpuRepSupportsLongMode())
3714 {
3715 fSkipMask |= MSR_K6_EFER_LME;
3716 if (!g_MsrAcc.fAtomic && (uValue & MSR_K6_EFER_SCE))
3717 fSkipMask |= MSR_K6_EFER_SCE;
3718 }
3719 if ( (uValue & MSR_K6_EFER_NXE)
3720 || vbCpuRepSupportsNX())
3721 fSkipMask |= MSR_K6_EFER_NXE;
3722
3723 /* NetBurst prescott 2MB (model 4) hung or triple faulted here. The extra
3724 sleep or something seemed to help for some screwed up reason. */
3725 if (g_fIntelNetBurst)
3726 {
3727 // This doesn't matter:
3728 //fSkipMask |= MSR_K6_EFER_SCE;
3729 //if (vbCpuRepSupportsLongMode())
3730 // fSkipMask |= MSR_K6_EFER_LMA;
3731 //vbCpuRepDebug("EFER - netburst workaround - ignore SCE & LMA (fSkipMask=%#llx)\n", fSkipMask);
3732
3733 vbCpuRepDebug("EFER - netburst sleep fudge - fSkipMask=%#llx\n", fSkipMask);
3734 RTThreadSleep(1000);
3735 }
3736
3737 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, MSR_K6_EFER_LMA, NULL);
3738}
3739
3740
3741/**
3742 * Deals with the MC4_MISCn (n >= 1) range and the following reserved MSRs.
3743 *
3744 * @returns VBox status code.
3745 * @param paMsrs Pointer to the first MSR.
3746 * @param cMsrs The number of MSRs in the array @a paMsr.
3747 * @param pidxLoop Index variable that should be advanced to the
3748 * last MSR entry in the range.
3749 */
3750static int reportMsr_AmdFam10hMc4MiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3751{
3752 /* Count registers. */
3753 uint32_t cRegs = 1;
3754 while ( cRegs < cMsrs
3755 && cRegs < 8
3756 && paMsrs[cRegs].uMsr == paMsrs[0].uMsr + cRegs)
3757 cRegs++;
3758
3759 /* Probe & report used MSRs. */
3760 uint64_t fIgnMask = 0;
3761 uint64_t fGpMask = 0;
3762 uint32_t cUsed = 0;
3763 while (cUsed < cRegs)
3764 {
3765 uint64_t fIgnMaskN = 0;
3766 uint64_t fGpMaskN = 0;
3767 int rc = msrProberModifyBitChanges(paMsrs[cUsed].uMsr, &fIgnMaskN, &fGpMaskN, 0);
3768 if (RT_FAILURE(rc))
3769 return rc;
3770 if (fIgnMaskN == UINT64_MAX || fGpMaskN == UINT64_MAX)
3771 break;
3772 if (cUsed == 0)
3773 {
3774 fIgnMask = fIgnMaskN;
3775 fGpMask = fGpMaskN;
3776 }
3777 else if ( fIgnMaskN != fIgnMask
3778 || fGpMaskN != fGpMask)
3779 return RTMsgErrorRc(VERR_NOT_EQUAL, "AmdFam16hMc4MiscN mismatch: fIgn=%#llx/%#llx fGp=%#llx/%#llx uMsr=%#x\n",
3780 fIgnMaskN, fIgnMask, fGpMaskN, fGpMask, paMsrs[cUsed].uMsr);
3781 cUsed++;
3782 }
3783 if (cUsed > 0)
3784 printMsrRangeFunctionEx(paMsrs[0].uMsr, paMsrs[cUsed - 1].uMsr, "AmdFam10hMc4MiscN", NULL, 0, fIgnMask, fGpMask, NULL);
3785
3786 /* Probe & report reserved MSRs. */
3787 uint32_t cReserved = 0;
3788 while (cUsed + cReserved < cRegs)
3789 {
3790 fIgnMask = fGpMask = 0;
3791 int rc = msrProberModifyBitChanges(paMsrs[cUsed + cReserved].uMsr, &fIgnMask, &fGpMask, 0);
3792 if (RT_FAILURE(rc))
3793 return rc;
3794 if ((fIgnMask != UINT64_MAX && fGpMask != UINT64_MAX) || paMsrs[cUsed + cReserved].uValue)
3795 return RTMsgErrorRc(VERR_NOT_EQUAL,
3796 "Unexpected reserved AmdFam16hMc4MiscN: fIgn=%#llx fGp=%#llx uMsr=%#x uValue=%#llx\n",
3797 fIgnMask, fGpMask, paMsrs[cUsed + cReserved].uMsr, paMsrs[cUsed + cReserved].uValue);
3798 cReserved++;
3799 }
3800 if (cReserved > 0 && fIgnMask == UINT64_MAX)
3801 printMsrRangeValueIgnoreWrites(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
3802 else if (cReserved > 0 && fGpMask == UINT64_MAX)
3803 printMsrRangeValueReadOnly(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
3804
3805 *pidxLoop += cRegs - 1;
3806 return VINF_SUCCESS;
3807}
3808
3809
3810/**
3811 * Deals with the AMD PERF_CTL range.
3812 *
3813 * @returns VBox status code.
3814 * @param paMsrs Pointer to the first MSR.
3815 * @param cMsrs The number of MSRs in the array @a paMsr.
3816 * @param pidxLoop Index variable that should be advanced to the
3817 * last MSR entry in the range.
3818 */
3819static int reportMsr_AmdK8PerfCtlN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3820{
3821 uint32_t uMsr = paMsrs[0].uMsr;
3822 Assert(uMsr == 0xc0010000);
3823
3824 /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
3825 if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
3826 {
3827 for (uint32_t i = 0; i < 4; i++)
3828 printMsrAlias(uMsr + i, 0xc0010200 + i * 2, NULL);
3829 *pidxLoop += 3;
3830 }
3831 else
3832 return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtlN", pidxLoop);
3833 return VINF_SUCCESS;
3834}
3835
3836
3837/**
3838 * Deals with the AMD PERF_CTR range.
3839 *
3840 * @returns VBox status code.
3841 * @param paMsrs Pointer to the first MSR.
3842 * @param cMsrs The number of MSRs in the array @a paMsr.
3843 * @param pidxLoop Index variable that should be advanced to the
3844 * last MSR entry in the range.
3845 */
3846static int reportMsr_AmdK8PerfCtrN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
3847{
3848 uint32_t uMsr = paMsrs[0].uMsr;
3849 Assert(uMsr == 0xc0010004);
3850
3851 /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
3852 if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
3853 {
3854 for (uint32_t i = 0; i < 4; i++)
3855 printMsrAlias(uMsr + i, 0xc0010201 + i * 2, NULL);
3856 *pidxLoop += 3;
3857 }
3858 else
3859 return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtrN", pidxLoop);
3860 return VINF_SUCCESS;
3861}
3862
3863
3864/**
3865 * Deals carefully with the SYS_CFG register.
3866 *
3867 * @returns VBox status code.
3868 * @param uMsr The MSR number.
3869 * @param uValue The current value.
3870 */
3871static int reportMsr_AmdK8SysCfg(uint32_t uMsr, uint64_t uValue)
3872{
3873 uint64_t fSkipMask = 0;
3874
3875 /* Bit 21 (MtrrTom2En) is marked reserved in family 0fh, while in family
3876 10h BKDG this changes (as does the document style). Testing this bit
3877 causes bulldozer running win64 to restart, thus this special treatment. */
3878 if (g_enmMicroarch >= kCpumMicroarch_AMD_K10)
3879 fSkipMask |= RT_BIT(21);
3880
3881 /* Turns out there are more killer bits here, at least on Opteron 2384.
3882 Skipping all known bits. */
3883 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV /* Not sure when introduced - harmless? */)
3884 fSkipMask |= RT_BIT(22); /* Tom2ForceMemTypeWB */
3885 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3886 fSkipMask |= RT_BIT(21); /* MtrrTom2En */
3887 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3888 fSkipMask |= RT_BIT(20); /* MtrrVarDramEn*/
3889 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3890 fSkipMask |= RT_BIT(19); /* MtrrFixDramModEn */
3891 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3892 fSkipMask |= RT_BIT(18); /* MtrrFixDramEn */
3893 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3894 fSkipMask |= RT_BIT(17); /* SysUcLockEn */
3895 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
3896 fSkipMask |= RT_BIT(16); /* ChgToDirtyDis */
3897 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
3898 fSkipMask |= RT_BIT(10); /* SetDirtyEnO */
3899 if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
3900 fSkipMask |= RT_BIT(9); /* SetDirtyEnS */
3901 if ( CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
3902 || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
3903 fSkipMask |= RT_BIT(8); /* SetDirtyEnE */
3904 if ( CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
3905 || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
3906 fSkipMask |= RT_BIT(7) /* SysVicLimit */
3907 | RT_BIT(6) /* SysVicLimit */
3908 | RT_BIT(5) /* SysVicLimit */
3909 | RT_BIT(4) /* SysAckLimit */
3910 | RT_BIT(3) /* SysAckLimit */
3911 | RT_BIT(2) /* SysAckLimit */
3912 | RT_BIT(1) /* SysAckLimit */
3913 | RT_BIT(0) /* SysAckLimit */;
3914
3915 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
3916}
3917
3918
3919/**
3920 * Deals carefully with the HWCR register.
3921 *
3922 * @returns VBox status code.
3923 * @param uMsr The MSR number.
3924 * @param uValue The current value.
3925 */
3926static int reportMsr_AmdK8HwCr(uint32_t uMsr, uint64_t uValue)
3927{
3928 uint64_t fSkipMask = 0;
3929
3930 /* Trouble on Opteron 2384, skip some of the known bits. */
3931 if (g_enmMicroarch >= kCpumMicroarch_AMD_K10 && !CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch))
3932 fSkipMask |= /*RT_BIT(10)*/ 0 /* MonMwaitUserEn */
3933 | RT_BIT(9); /* MonMwaitDis */
3934 fSkipMask |= RT_BIT(8); /* #IGNNE port emulation */
3935 if ( CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
3936 || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
3937 fSkipMask |= RT_BIT(7) /* DisLock */
3938 | RT_BIT(6); /* FFDis (TLB flush filter) */
3939 fSkipMask |= RT_BIT(4); /* INVD to WBINVD */
3940 fSkipMask |= RT_BIT(3); /* TLBCACHEDIS */
3941 if ( CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
3942 || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
3943 || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
3944 fSkipMask |= RT_BIT(1); /* SLOWFENCE */
3945 fSkipMask |= RT_BIT(0); /* SMMLOCK */
3946
3947 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
3948}
3949
3950
3951/**
3952 * Deals carefully with a IORRBasei register.
3953 *
3954 * @returns VBox status code.
3955 * @param uMsr The MSR number.
3956 * @param uValue The current value.
3957 */
3958static int reportMsr_AmdK8IorrBaseN(uint32_t uMsr, uint64_t uValue)
3959{
3960 /* Skip know bits here, as harm seems to come from messing with them. */
3961 uint64_t fSkipMask = RT_BIT(4) | RT_BIT(3);
3962 fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
3963 return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010016) / 2, fSkipMask, 0, annotateValue(uValue));
3964}
3965
3966
3967/**
3968 * Deals carefully with a IORRMaski register.
3969 *
3970 * @returns VBox status code.
3971 * @param uMsr The MSR number.
3972 * @param uValue The current value.
3973 */
3974static int reportMsr_AmdK8IorrMaskN(uint32_t uMsr, uint64_t uValue)
3975{
3976 /* Skip know bits here, as harm seems to come from messing with them. */
3977 uint64_t fSkipMask = RT_BIT(11);
3978 fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
3979 return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010017) / 2, fSkipMask, 0, annotateValue(uValue));
3980}
3981
3982
3983/**
3984 * Deals carefully with a IORRMaski register.
3985 *
3986 * @returns VBox status code.
3987 * @param uMsr The MSR number.
3988 * @param uValue The current value.
3989 */
3990static int reportMsr_AmdK8TopMemN(uint32_t uMsr, uint64_t uValue)
3991{
3992 /* Skip know bits here, as harm seems to come from messing with them. */
3993 uint64_t fSkipMask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(RT_BIT_64(23) - 1);
3994 return reportMsr_GenFunctionEx(uMsr, NULL, uMsr == 0xc001001d, fSkipMask, 0, annotateValue(uValue));
3995}
3996
3997
3998/**
3999 * Deals with the AMD P-state config range.
4000 *
4001 * @returns VBox status code.
4002 * @param paMsrs Pointer to the first MSR.
4003 * @param cMsrs The number of MSRs in the array @a paMsr.
4004 * @param pidxLoop Index variable that should be advanced to the
4005 * last MSR entry in the range.
4006 */
4007static int reportMsr_AmdFam10hPStateN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
4008{
4009 uint32_t uMsr = paMsrs[0].uMsr;
4010 AssertRelease(uMsr == 0xc0010064);
4011
4012 /* Count them. */
4013 uint32_t cRegs = 1;
4014 while ( cRegs < 8
4015 && cRegs < cMsrs
4016 && paMsrs[cRegs].uMsr == uMsr + cRegs)
4017 cRegs++;
4018
4019 /* Figure out which bits we should skip when probing. This is based on
4020 specs and may need adjusting for real life when handy. */
4021 uint64_t fSkipMask = RT_BIT_64(63); /* PstateEn */
4022 fSkipMask |= RT_BIT_64(41) | RT_BIT_64(40); /* IddDiv */
4023 fSkipMask |= UINT64_C(0x000000ff00000000); /* IddValue */
4024 if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
4025 fSkipMask |= UINT32_C(0xfe000000); /* NbVid - Northbridge VID */
4026 if ( CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
4027 || CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
4028 fSkipMask |= RT_BIT_32(22); /* NbDid or NbPstate. */
4029 if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
4030 fSkipMask |= RT_BIT_32(16); /* CpuVid[7] */
4031 fSkipMask |= UINT32_C(0x0000fe00); /* CpuVid[6:0] */
4032 fSkipMask |= UINT32_C(0x000001c0); /* CpuDid */
4033 fSkipMask |= UINT32_C(0x0000003f); /* CpuFid */
4034
4035 /* Probe and report them one by one since we're passing values instead of
4036 register indexes to the functions. */
4037 for (uint32_t i = 0; i < cRegs; i++)
4038 {
4039 uint64_t fIgnMask = 0;
4040 uint64_t fGpMask = 0;
4041 int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, fSkipMask);
4042 if (RT_FAILURE(rc))
4043 return rc;
4044 printMsrFunctionExtended(uMsr + i, "AmdFam10hPStateN", NULL, paMsrs[i].uValue, fIgnMask, fGpMask,
4045 annotateValue(paMsrs[i].uValue));
4046 }
4047
4048 /* Advance. */
4049 *pidxLoop += cRegs - 1;
4050 return VINF_SUCCESS;
4051}
4052
4053
4054/**
4055 * Deals carefully with a COFVID control register.
4056 *
4057 * @returns VBox status code.
4058 * @param uMsr The MSR number.
4059 * @param uValue The current value.
4060 */
4061static int reportMsr_AmdFam10hCofVidControl(uint32_t uMsr, uint64_t uValue)
4062{
4063 /* Skip know bits here, as harm seems to come from messing with them. */
4064 uint64_t fSkipMask = 0;
4065 if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
4066 fSkipMask |= UINT32_C(0xfe000000); /* NbVid - Northbridge VID */
4067 else if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
4068 fSkipMask |= UINT32_C(0xff000000); /* NbVid - Northbridge VID - includes bit 24 for Fam15h and Fam16h. Odd... */
4069 if ( CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
4070 || g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
4071 fSkipMask |= RT_BIT_32(22); /* NbDid or NbPstate. */
4072 if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
4073 fSkipMask |= RT_BIT_32(20); /* CpuVid[7] */
4074 fSkipMask |= UINT32_C(0x00070000); /* PstatId */
4075 fSkipMask |= UINT32_C(0x0000fe00); /* CpuVid[6:0] */
4076 fSkipMask |= UINT32_C(0x000001c0); /* CpuDid */
4077 fSkipMask |= UINT32_C(0x0000003f); /* CpuFid */
4078
4079 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
4080}
4081
4082
4083/**
4084 * Deals with the AMD [|L2I_|NB_]PERF_CT[LR] mixed ranges.
4085 *
4086 * Mixed here refers to the control and counter being in mixed in pairs as
4087 * opposed to them being two separate parallel arrays like in the 0xc0010000
4088 * area.
4089 *
4090 * @returns VBox status code.
4091 * @param paMsrs Pointer to the first MSR.
4092 * @param cMsrs The number of MSRs in the array @a paMsr.
4093 * @param cMax The max number of MSRs (not counters).
4094 * @param pidxLoop Index variable that should be advanced to the
4095 * last MSR entry in the range.
4096 */
4097static int reportMsr_AmdGenPerfMixedRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, uint32_t *pidxLoop)
4098{
4099 uint32_t uMsr = paMsrs[0].uMsr;
4100
4101 /* Count them. */
4102 uint32_t cRegs = 1;
4103 while ( cRegs < cMax
4104 && cRegs < cMsrs
4105 && paMsrs[cRegs].uMsr == uMsr + cRegs)
4106 cRegs++;
4107 if (cRegs & 1)
4108 return RTMsgErrorRc(VERR_INVALID_PARAMETER, "PERF range at %#x is odd: cRegs=%#x\n", uMsr, cRegs);
4109
4110 /* Report them as individual entries, using default names and such. */
4111 for (uint32_t i = 0; i < cRegs; i++)
4112 {
4113 uint64_t fIgnMask = 0;
4114 uint64_t fGpMask = 0;
4115 int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, 0);
4116 if (RT_FAILURE(rc))
4117 return rc;
4118 printMsrFunctionExtendedIdxVal(uMsr + i, NULL, NULL, i / 2, fIgnMask, fGpMask, annotateValue(paMsrs[i].uValue));
4119 }
4120
4121 /* Advance. */
4122 *pidxLoop += cRegs - 1;
4123 return VINF_SUCCESS;
4124}
4125
4126
4127/**
4128 * Deals carefully with a LS_CFG register.
4129 *
4130 * @returns VBox status code.
4131 * @param uMsr The MSR number.
4132 * @param uValue The current value.
4133 */
4134static int reportMsr_AmdK7InstrCacheCfg(uint32_t uMsr, uint64_t uValue)
4135{
4136 /* Skip know bits here, as harm seems to come from messing with them. */
4137 uint64_t fSkipMask = RT_BIT_64(9) /* DIS_SPEC_TLB_RLD */;
4138 if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
4139 fSkipMask |= RT_BIT_64(14); /* DIS_IND */
4140 if (CPUMMICROARCH_IS_AMD_FAM_16H(g_enmMicroarch))
4141 fSkipMask |= RT_BIT_64(26); /* DIS_WIDEREAD_PWR_SAVE */
4142 if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
4143 {
4144 fSkipMask |= 0x1e; /* DisIcWayFilter */
4145 fSkipMask |= RT_BIT_64(39); /* DisLoopPredictor */
4146 fSkipMask |= RT_BIT_64(27); /* Unknown killer bit, possibly applicable to other microarchs. */
4147 fSkipMask |= RT_BIT_64(28); /* Unknown killer bit, possibly applicable to other microarchs. */
4148 }
4149 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
4150}
4151
4152
4153/**
4154 * Deals carefully with a CU_CFG register.
4155 *
4156 * @returns VBox status code.
4157 * @param uMsr The MSR number.
4158 * @param uValue The current value.
4159 */
4160static int reportMsr_AmdFam15hCombUnitCfg(uint32_t uMsr, uint64_t uValue)
4161{
4162 /* Skip know bits here, as harm seems to come from messing with them. */
4163 uint64_t fSkipMask = RT_BIT_64(23) /* L2WayLock */
4164 | RT_BIT_64(22) /* L2FirstLockWay */
4165 | RT_BIT_64(21) /* L2FirstLockWay */
4166 | RT_BIT_64(20) /* L2FirstLockWay */
4167 | RT_BIT_64(19) /* L2FirstLockWay */
4168 | RT_BIT_64(10) /* DcacheAggressivePriority */;
4169 fSkipMask |= RT_BIT_64(46) | RT_BIT_64(45); /* Killer field. Seen bit 46 set, 45 clear. Messing with either means reboot/BSOD. */
4170 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
4171}
4172
4173
4174/**
4175 * Deals carefully with a EX_CFG register.
4176 *
4177 * @returns VBox status code.
4178 * @param uMsr The MSR number.
4179 * @param uValue The current value.
4180 */
4181static int reportMsr_AmdFam15hExecUnitCfg(uint32_t uMsr, uint64_t uValue)
4182{
4183 /* Skip know bits here, as harm seems to come from messing with them. */
4184 uint64_t fSkipMask = RT_BIT_64(54) /* LateSbzResync */;
4185 fSkipMask |= RT_BIT_64(35); /* Undocumented killer bit. */
4186 return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
4187}
4188
4189
4190
4191static int produceMsrReport(VBCPUREPMSR *paMsrs, uint32_t cMsrs)
4192{
4193 vbCpuRepDebug("produceMsrReport\n");
4194 RTThreadSleep(500);
4195
4196 for (uint32_t i = 0; i < cMsrs; i++)
4197 {
4198 uint32_t uMsr = paMsrs[i].uMsr;
4199 uint32_t fFlags = paMsrs[i].fFlags;
4200 uint64_t uValue = paMsrs[i].uValue;
4201 int rc;
4202#if 0
4203 //if (uMsr < 0x00000000)
4204 // continue;
4205 if (uMsr >= 0x00000277)
4206 {
4207 vbCpuRepDebug("produceMsrReport: uMsr=%#x (%s)...\n", uMsr, getMsrNameHandled(uMsr));
4208 RTThreadSleep(1000);
4209 }
4210#endif
4211 /*
4212 * Deal with write only regs first to avoid having to avoid them all the time.
4213 */
4214 if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
4215 {
4216 if (uMsr == 0x00000079)
4217 rc = printMsrWriteOnly(uMsr, NULL, NULL);
4218 else
4219 rc = reportMsr_Generic(uMsr, fFlags, uValue);
4220 }
4221 /*
4222 * VIA implement MSRs in a interesting way, so we have to select what we
4223 * want to handle there to avoid making the code below unreadable.
4224 */
4225 /** @todo r=klaus check if Shanghai CPUs really are behaving the same */
4226 else if (isMsrViaShanghaiDummy(uMsr, uValue, fFlags))
4227 rc = reportMsr_ViaShanghaiDummyRange(&paMsrs[i], cMsrs - i, &i);
4228 /*
4229 * This shall be sorted by uMsr as much as possible.
4230 */
4231 else if (uMsr == 0x00000000 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON) && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
4232 rc = printMsrAlias(uMsr, 0x00000402, NULL);
4233 else if (uMsr == 0x00000001 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON) && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
4234 rc = printMsrAlias(uMsr, 0x00000401, NULL); /** @todo not 101% correct on Fam15h and later, 0xc0010015[McstatusWrEn] effect differs. */
4235 else if (uMsr == 0x0000001b)
4236 rc = reportMsr_Ia32ApicBase(uMsr, uValue);
4237 else if (uMsr == 0x00000040 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_M_Dothan)
4238 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromToN", &i);
4239 else if (uMsr == 0x00000040)
4240 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchToN", uMsr, false,
4241 true, getGenericSkipMask(uMsr), &i);
4242 else if (uMsr == 0x00000060 && g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
4243 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromN", uMsr, false,
4244 true, getGenericSkipMask(uMsr), &i);
4245 else if (uMsr == 0x000000c1)
4246 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i,
4247 g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? 8 : 4 /*cMax*/,
4248 NULL, &i);
4249 else if (uMsr == 0x00000186 && !g_fIntelNetBurst)
4250 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "Ia32PerfEvtSelN", &i);
4251 else if (uMsr == 0x000001a0)
4252 rc = reportMsr_Ia32MiscEnable(uMsr, uValue);
4253 else if (uMsr >= 0x000001a6 && uMsr <= 0x000001a7)
4254 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 2 /*cMax*/, "IntelI7MsrOffCoreResponseN", &i);
4255 else if (uMsr == 0x000001db && g_fIntelNetBurst)
4256 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4 /*cMax*/, "IntelLastBranchFromToN", &i);
4257 else if (uMsr == 0x00000200)
4258 rc = reportMsr_Ia32MtrrPhysBaseMaskN(&paMsrs[i], cMsrs - i, &i);
4259 else if (uMsr >= 0x00000250 && uMsr <= 0x00000279)
4260 rc = reportMsr_Ia32MtrrFixedOrPat(uMsr);
4261 else if (uMsr >= 0x00000280 && uMsr <= 0x00000295)
4262 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 22 /*cMax*/, NULL, 0x00000280, true /*fEarlyEndOk*/, false, 0, &i);
4263 else if (uMsr == 0x000002ff)
4264 rc = reportMsr_Ia32MtrrDefType(uMsr);
4265 else if (uMsr >= 0x00000309 && uMsr <= 0x0000030b && !g_fIntelNetBurst)
4266 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3 /*cMax*/, NULL, 0x00000309, true /*fEarlyEndOk*/, false, 0, &i);
4267 else if ((uMsr == 0x000003f8 || uMsr == 0x000003fc || uMsr == 0x0000060a) && !g_fIntelNetBurst)
4268 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 4, NULL, uMsr - 3, true, false, 0, &i);
4269 else if ((uMsr == 0x000003f9 || uMsr == 0x000003fd || uMsr == 0x0000060b) && !g_fIntelNetBurst)
4270 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 6, true, false, 0, &i);
4271 else if ((uMsr == 0x000003fa || uMsr == 0x000003fe || uMsr == 0x0000060c) && !g_fIntelNetBurst)
4272 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 7, true, false, 0, &i);
4273 else if (uMsr >= 0x00000400 && uMsr <= 0x00000477)
4274 rc = reportMsr_Ia32McCtlStatusAddrMiscN(&paMsrs[i], cMsrs - i, &i);
4275 else if (uMsr == 0x000004c1)
4276 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8, NULL, &i);
4277 else if (uMsr == 0x00000680 || uMsr == 0x000006c0)
4278 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 16, NULL, uMsr, false, false,
4279 g_fIntelNetBurst
4280 ? UINT64_C(0xffffffffffffff00) /* kludge */
4281 : UINT64_C(0xffff800000000000), &i);
4282 else if (uMsr >= 0x00000800 && uMsr <= 0x000008ff)
4283 rc = reportMsr_GenX2Apic(&paMsrs[i], cMsrs - i, &i);
4284 else if (uMsr == 0x00002000 && g_enmVendor == CPUMCPUVENDOR_INTEL)
4285 rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 0, X86_CR0_PE | X86_CR0_PG, 0,
4286 annotateIfMissingBits(uValue, X86_CR0_PE | X86_CR0_PE | X86_CR0_ET));
4287 else if (uMsr == 0x00002002 && g_enmVendor == CPUMCPUVENDOR_INTEL)
4288 rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 2, 0, 0, annotateValue(uValue));
4289 else if (uMsr == 0x00002003 && g_enmVendor == CPUMCPUVENDOR_INTEL)
4290 {
4291 uint64_t fCr3Mask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & (X86_CR3_PAE_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK);
4292 if (!vbCpuRepSupportsPae())
4293 fCr3Mask &= X86_CR3_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK;
4294 rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 3, fCr3Mask, 0, annotateValue(uValue));
4295 }
4296 else if (uMsr == 0x00002004 && g_enmVendor == CPUMCPUVENDOR_INTEL)
4297 rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 4,
4298 X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE | X86_CR4_SMXE, 0,
4299 annotateValue(uValue));
4300 else if (uMsr == 0xc0000080)
4301 rc = reportMsr_Amd64Efer(uMsr, uValue);
4302 else if (uMsr >= 0xc0000408 && uMsr <= 0xc000040f)
4303 rc = reportMsr_AmdFam10hMc4MiscN(&paMsrs[i], cMsrs - i, &i);
4304 else if (uMsr == 0xc0010000 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4305 rc = reportMsr_AmdK8PerfCtlN(&paMsrs[i], cMsrs - i, &i);
4306 else if (uMsr == 0xc0010004 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4307 rc = reportMsr_AmdK8PerfCtrN(&paMsrs[i], cMsrs - i, &i);
4308 else if (uMsr == 0xc0010010 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4309 rc = reportMsr_AmdK8SysCfg(uMsr, uValue);
4310 else if (uMsr == 0xc0010015 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4311 rc = reportMsr_AmdK8HwCr(uMsr, uValue);
4312 else if ((uMsr == 0xc0010016 || uMsr == 0xc0010018) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4313 rc = reportMsr_AmdK8IorrBaseN(uMsr, uValue);
4314 else if ((uMsr == 0xc0010017 || uMsr == 0xc0010019) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4315 rc = reportMsr_AmdK8IorrMaskN(uMsr, uValue);
4316 else if ((uMsr == 0xc001001a || uMsr == 0xc001001d) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4317 rc = reportMsr_AmdK8TopMemN(uMsr, uValue);
4318 else if (uMsr == 0xc0010030 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4319 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 6, "AmdK8CpuNameN", &i);
4320 else if (uMsr >= 0xc0010044 && uMsr <= 0xc001004a && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4321 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 7, "AmdK8McCtlMaskN", 0xc0010044, true /*fEarlyEndOk*/, false, 0, &i);
4322 else if (uMsr == 0xc0010050 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4323 rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4, "AmdK8SmiOnIoTrapN", &i);
4324 else if (uMsr == 0xc0010064 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4325 rc = reportMsr_AmdFam10hPStateN(&paMsrs[i], cMsrs - i, &i);
4326 else if (uMsr == 0xc0010070 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4327 rc = reportMsr_AmdFam10hCofVidControl(uMsr, uValue);
4328 else if ((uMsr == 0xc0010118 || uMsr == 0xc0010119) && getMsrFnName(uMsr, NULL) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4329 rc = printMsrFunction(uMsr, NULL, NULL, annotateValue(uValue)); /* RAZ, write key. */
4330 else if (uMsr == 0xc0010200 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4331 rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 12, &i);
4332 else if (uMsr == 0xc0010230 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4333 rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
4334 else if (uMsr == 0xc0010240 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4335 rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
4336 else if (uMsr == 0xc0011019 && g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4337 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3, "AmdK7DrXAddrMaskN", 0xc0011019 - 1,
4338 false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
4339 else if (uMsr == 0xc0011021 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4340 rc = reportMsr_AmdK7InstrCacheCfg(uMsr, uValue);
4341 else if (uMsr == 0xc0011023 && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
4342 rc = reportMsr_AmdFam15hCombUnitCfg(uMsr, uValue);
4343 else if (uMsr == 0xc0011027 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
4344 rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 1, "AmdK7DrXAddrMaskN", 0xc0011027,
4345 false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
4346 else if (uMsr == 0xc001102c && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
4347 rc = reportMsr_AmdFam15hExecUnitCfg(uMsr, uValue);
4348 /* generic handling. */
4349 else
4350 rc = reportMsr_Generic(uMsr, fFlags, uValue);
4351
4352 if (RT_FAILURE(rc))
4353 return rc;
4354
4355 /*
4356 * A little ugly snooping.
4357 */
4358 if (uMsr == 0x000000cd && !(fFlags & VBCPUREPMSR_F_WRITE_ONLY))
4359 g_uMsrIntelP6FsbFrequency = uValue;
4360 }
4361
4362 return VINF_SUCCESS;
4363}
4364
4365
4366/**
4367 * Custom MSR hacking & probing.
4368 *
4369 * Called when the '-d' option is given.
4370 *
4371 * @returns VBox status code.
4372 */
4373static int hackingMsrs(void)
4374{
4375#if 0
4376 vbCpuRepDebug("\nhackingMsrs:\n"); RTStrmFlush(g_pDebugOut); RTThreadSleep(2000);
4377
4378 uint32_t uMsr = 0xc0000081;
4379 vbCpuRepDebug("%#x: msrProberModifyNoChange -> %RTbool\n", uMsr, msrProberModifyNoChange(uMsr));
4380 RTThreadSleep(3000);
4381
4382 vbCpuRepDebug("%#x: msrProberModifyBit 30 -> %d\n", uMsr, msrProberModifyBit(uMsr, 30));
4383 RTThreadSleep(3000);
4384
4385 vbCpuRepDebug("%#x: msrProberModifyZero -> %RTbool\n", uMsr, msrProberModifyZero(uMsr));
4386 RTThreadSleep(3000);
4387
4388 for (uint32_t i = 0; i < 63; i++)
4389 {
4390 vbCpuRepDebug("%#x: bit=%02u -> %d\n", msrProberModifyBit(uMsr, i));
4391 RTThreadSleep(500);
4392 }
4393#else
4394
4395 uint32_t uMsr = 0xc0010010;
4396 uint64_t uValue = 0;
4397 msrProberRead(uMsr, &uValue);
4398 reportMsr_AmdK8SysCfg(uMsr, uValue);
4399#endif
4400 return VINF_SUCCESS;
4401}
4402
4403
4404static int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc,
4405 char *pszMsrMask, size_t cbMsrMask)
4406{
4407 /* Initialize the mask. */
4408 if (pszMsrMask && cbMsrMask)
4409 RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX /** @todo */");
4410
4411 /*
4412 * Are MSRs supported by the CPU?
4413 */
4414 if ( !RTX86IsValidStdRange(ASMCpuId_EAX(0))
4415 || !(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_MSR) )
4416 {
4417 vbCpuRepDebug("Skipping MSR probing, CPUID indicates there isn't any MSR support.\n");
4418 return VINF_SUCCESS;
4419 }
4420 if (g_fNoMsrs)
4421 {
4422 vbCpuRepDebug("Skipping MSR probing (--no-msr).\n");
4423 return VINF_SUCCESS;
4424 }
4425
4426 /*
4427 * First try the the support library (also checks if we can really read MSRs).
4428 */
4429 int rc = VbCpuRepMsrProberInitSupDrv(&g_MsrAcc);
4430 if (RT_FAILURE(rc))
4431 {
4432#ifdef VBCR_HAVE_PLATFORM_MSR_PROBER
4433 /* Next try a platform-specific interface. */
4434 rc = VbCpuRepMsrProberInitPlatform(&g_MsrAcc);
4435#endif
4436 if (RT_FAILURE(rc))
4437 {
4438 vbCpuRepDebug("warning: Unable to initialize any MSR access interface (%Rrc), skipping MSR detection.\n", rc);
4439 return VINF_SUCCESS;
4440 }
4441 }
4442
4443 uint64_t uValue;
4444 bool fGp;
4445 rc = g_MsrAcc.pfnMsrProberRead(MSR_IA32_TSC, NIL_RTCPUID, &uValue, &fGp);
4446 if (RT_FAILURE(rc))
4447 {
4448 vbCpuRepDebug("warning: MSR probing not supported by the support driver (%Rrc), skipping MSR detection.\n", rc);
4449 return VINF_SUCCESS;
4450 }
4451 vbCpuRepDebug("MSR_IA32_TSC: %#llx fGp=%RTbool\n", uValue, fGp);
4452 rc = g_MsrAcc.pfnMsrProberRead(0xdeadface, NIL_RTCPUID, &uValue, &fGp);
4453 vbCpuRepDebug("0xdeadface: %#llx fGp=%RTbool rc=%Rrc\n", uValue, fGp, rc);
4454
4455 /*
4456 * Initialize globals we use.
4457 */
4458 uint32_t uEax, uEbx, uEcx, uEdx;
4459 ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4460 if (!RTX86IsValidStdRange(uEax))
4461 return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
4462 g_enmVendor = CPUMR3CpuIdDetectVendorEx(uEax, uEbx, uEcx, uEdx);
4463
4464 ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4465 g_enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(g_enmVendor,
4466 RTX86GetCpuFamily(uEax),
4467 RTX86GetCpuModel(uEax, g_enmVendor == CPUMCPUVENDOR_INTEL),
4468 RTX86GetCpuStepping(uEax));
4469 g_fIntelNetBurst = CPUMMICROARCH_IS_INTEL_NETBURST(g_enmMicroarch);
4470
4471 /*
4472 * Do the probing.
4473 */
4474 if (fHacking)
4475 rc = hackingMsrs();
4476 else
4477 {
4478 /* Determine the MSR mask. */
4479 uint32_t fMsrMask = determineMsrAndMask();
4480 if (fMsrMask == UINT32_MAX)
4481 RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX");
4482 else
4483 RTStrPrintf(pszMsrMask, cbMsrMask, "UINT32_C(%#x)", fMsrMask);
4484
4485 /* Detect MSR. */
4486 VBCPUREPMSR *paMsrs;
4487 uint32_t cMsrs;
4488 rc = findMsrs(&paMsrs, &cMsrs, fMsrMask);
4489 if (RT_FAILURE(rc))
4490 return rc;
4491
4492 /* Probe the MSRs and spit out the database table. */
4493 vbCpuRepPrintf("\n"
4494 "#ifndef CPUM_DB_STANDALONE\n"
4495 "/**\n"
4496 " * MSR ranges for %s.\n"
4497 " */\n"
4498 "static CPUMMSRRANGE const g_aMsrRanges_%s[] =\n{\n",
4499 pszCpuDesc,
4500 pszNameC);
4501 rc = produceMsrReport(paMsrs, cMsrs);
4502 vbCpuRepPrintf("};\n"
4503 "#endif /* !CPUM_DB_STANDALONE */\n"
4504 "\n"
4505 );
4506
4507 RTMemFree(paMsrs);
4508 paMsrs = NULL;
4509 }
4510 if (g_MsrAcc.pfnTerm)
4511 g_MsrAcc.pfnTerm();
4512 RT_ZERO(g_MsrAcc);
4513 return rc;
4514}
4515
4516
4517static int produceCpuIdArray(const char *pszNameC, const char *pszCpuDesc)
4518{
4519 /*
4520 * Collect the data.
4521 */
4522 PCPUMCPUIDLEAF paLeaves;
4523 uint32_t cLeaves;
4524 int rc = CPUMR3CpuIdCollectLeaves(&paLeaves, &cLeaves);
4525 if (RT_FAILURE(rc))
4526 return RTMsgErrorRc(rc, "CPUMR3CollectCpuIdInfo failed: %Rrc\n", rc);
4527
4528 /*
4529 * Dump the array.
4530 */
4531 vbCpuRepPrintf("\n"
4532 "#ifndef CPUM_DB_STANDALONE\n"
4533 "/**\n"
4534 " * CPUID leaves for %s.\n"
4535 " */\n"
4536 "static CPUMCPUIDLEAF const g_aCpuIdLeaves_%s[] =\n{\n",
4537 pszCpuDesc,
4538 pszNameC);
4539 for (uint32_t i = 0; i < cLeaves; i++)
4540 {
4541 vbCpuRepPrintf(" { %#010x, %#010x, ", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf);
4542 if (paLeaves[i].fSubLeafMask == UINT32_MAX)
4543 vbCpuRepPrintf("UINT32_MAX, ");
4544 else
4545 vbCpuRepPrintf("%#010x, ", paLeaves[i].fSubLeafMask);
4546 vbCpuRepPrintf("%#010x, %#010x, %#010x, %#010x, ",
4547 paLeaves[i].uEax, paLeaves[i].uEbx, paLeaves[i].uEcx, paLeaves[i].uEdx);
4548 if (paLeaves[i].fFlags == 0)
4549 vbCpuRepPrintf("0 },\n");
4550 else
4551 {
4552 vbCpuRepPrintf("0");
4553 uint32_t fFlags = paLeaves[i].fFlags;
4554 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES)
4555 {
4556 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES");
4557 fFlags &= ~CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES;
4558 }
4559 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID)
4560 {
4561 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID");
4562 fFlags &= ~CPUMCPUIDLEAF_F_CONTAINS_APIC_ID;
4563 }
4564 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC)
4565 {
4566 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_CONTAINS_APIC");
4567 fFlags &= ~CPUMCPUIDLEAF_F_CONTAINS_APIC;
4568 }
4569 if (fFlags)
4570 {
4571 RTMemFree(paLeaves);
4572 return RTMsgErrorRc(rc, "Unknown CPUID flags %#x\n", fFlags);
4573 }
4574 vbCpuRepPrintf(" },\n");
4575 }
4576 }
4577 vbCpuRepPrintf("};\n"
4578 "#endif /* !CPUM_DB_STANDALONE */\n"
4579 "\n");
4580 RTMemFree(paLeaves);
4581 return VINF_SUCCESS;
4582}
4583
4584
4585static const char *cpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
4586{
4587 switch (enmCpuVendor)
4588 {
4589 case CPUMCPUVENDOR_INTEL: return "Intel";
4590 case CPUMCPUVENDOR_AMD: return "AMD";
4591 case CPUMCPUVENDOR_VIA: return "VIA";
4592 case CPUMCPUVENDOR_CYRIX: return "Cyrix";
4593 case CPUMCPUVENDOR_SHANGHAI: return "Shanghai";
4594 case CPUMCPUVENDOR_HYGON: return "Hygon";
4595 case CPUMCPUVENDOR_INVALID:
4596 case CPUMCPUVENDOR_UNKNOWN:
4597 case CPUMCPUVENDOR_32BIT_HACK:
4598 break;
4599 }
4600 return "invalid-cpu-vendor";
4601}
4602
4603
4604/**
4605 * Takes a shot a the bus frequency name (last part).
4606 *
4607 * @returns Name suffix.
4608 */
4609static const char *vbCpuRepGuessScalableBusFrequencyName(void)
4610{
4611 if (CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch))
4612 return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge ? "100MHZ" : "133MHZ";
4613
4614 if (g_uMsrIntelP6FsbFrequency != UINT64_MAX)
4615 switch (g_uMsrIntelP6FsbFrequency & 0x7)
4616 {
4617 case 5: return "100MHZ";
4618 case 1: return "133MHZ";
4619 case 3: return "167MHZ";
4620 case 2: return "200MHZ";
4621 case 0: return "267MHZ";
4622 case 4: return "333MHZ";
4623 case 6: return "400MHZ";
4624 }
4625
4626 return "UNKNOWN";
4627}
4628
4629
4630static int produceCpuReport(void)
4631{
4632 /*
4633 * Figure the cpu vendor.
4634 */
4635 if (!ASMHasCpuId())
4636 return RTMsgErrorRc(VERR_NOT_SUPPORTED, "No CPUID support.\n");
4637 uint32_t uEax, uEbx, uEcx, uEdx;
4638 ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4639 if (!RTX86IsValidStdRange(uEax))
4640 return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
4641
4642 CPUMCPUVENDOR enmVendor = CPUMR3CpuIdDetectVendorEx(uEax, uEbx, uEcx, uEdx);
4643 if (enmVendor == CPUMCPUVENDOR_UNKNOWN)
4644 return RTMsgErrorRc(VERR_NOT_IMPLEMENTED, "Unknown CPU vendor: %.4s%.4s%.4s\n", &uEbx, &uEdx, &uEcx);
4645 vbCpuRepDebug("CPU Vendor: %s - %.4s%.4s%.4s\n", CPUMR3CpuVendorName(enmVendor), &uEbx, &uEdx, &uEcx);
4646
4647 /*
4648 * Determine the micro arch.
4649 */
4650 ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4651 CPUMMICROARCH enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(enmVendor,
4652 RTX86GetCpuFamily(uEax),
4653 RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
4654 RTX86GetCpuStepping(uEax));
4655
4656 /*
4657 * Generate a name.
4658 */
4659 char szName[16*3+1];
4660 char szNameC[16*3+1];
4661 char szNameRaw[16*3+1];
4662 char *pszName = szName;
4663 char *pszCpuDesc = (char *)"";
4664
4665 ASMCpuIdExSlow(0x80000000, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4666 if (RTX86IsValidExtRange(uEax) && uEax >= UINT32_C(0x80000004))
4667 {
4668 /* Get the raw name and strip leading spaces. */
4669 ASMCpuIdExSlow(0x80000002, 0, 0, 0, &szNameRaw[0 + 0], &szNameRaw[4 + 0], &szNameRaw[8 + 0], &szNameRaw[12 + 0]);
4670 ASMCpuIdExSlow(0x80000003, 0, 0, 0, &szNameRaw[0 + 16], &szNameRaw[4 + 16], &szNameRaw[8 + 16], &szNameRaw[12 + 16]);
4671 ASMCpuIdExSlow(0x80000004, 0, 0, 0, &szNameRaw[0 + 32], &szNameRaw[4 + 32], &szNameRaw[8 + 32], &szNameRaw[12 + 32]);
4672 szNameRaw[48] = '\0';
4673 pszCpuDesc = RTStrStrip(szNameRaw);
4674 vbCpuRepDebug("Name2: %s\n", pszCpuDesc);
4675
4676 /* Reduce the name. */
4677 pszName = strcpy(szName, pszCpuDesc);
4678
4679 static const char * const s_apszSuffixes[] =
4680 {
4681 "CPU @",
4682 };
4683 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszSuffixes); i++)
4684 {
4685 char *pszHit = strstr(pszName, s_apszSuffixes[i]);
4686 if (pszHit)
4687 RT_BZERO(pszHit, strlen(pszHit));
4688 }
4689
4690 static const char * const s_apszWords[] =
4691 {
4692 "(TM)", "(tm)", "(R)", "(r)", "Processor", "CPU", "@",
4693 };
4694 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszWords); i++)
4695 {
4696 const char *pszWord = s_apszWords[i];
4697 size_t cchWord = strlen(pszWord);
4698 char *pszHit;
4699 while ((pszHit = strstr(pszName, pszWord)) != NULL)
4700 memset(pszHit, ' ', cchWord);
4701 }
4702
4703 RTStrStripR(pszName);
4704 for (char *psz = pszName; *psz; psz++)
4705 if (RT_C_IS_BLANK(*psz))
4706 {
4707 size_t cchBlanks = 1;
4708 while (RT_C_IS_BLANK(psz[cchBlanks]))
4709 cchBlanks++;
4710 *psz = ' ';
4711 if (cchBlanks > 1)
4712 memmove(psz + 1, psz + cchBlanks, strlen(psz + cchBlanks) + 1);
4713 }
4714 pszName = RTStrStripL(pszName);
4715 vbCpuRepDebug("Name: %s\n", pszName);
4716
4717 /* Make it C/C++ acceptable. */
4718 strcpy(szNameC, pszName);
4719 unsigned offDst = 0;
4720 for (unsigned offSrc = 0; ; offSrc++)
4721 {
4722 char ch = szNameC[offSrc];
4723 if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != '\0')
4724 ch = '_';
4725 if (ch == '_' && offDst > 0 && szNameC[offDst - 1] == '_')
4726 offDst--;
4727 szNameC[offDst++] = ch;
4728 if (!ch)
4729 break;
4730 }
4731 while (offDst > 1 && szNameC[offDst - 1] == '_')
4732 szNameC[--offDst] = '\0';
4733
4734 vbCpuRepDebug("NameC: %s\n", szNameC);
4735 }
4736 else
4737 {
4738 ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4739 RTStrPrintf(szNameC, sizeof(szNameC), "%s_%u_%u_%u", cpuVendorToString(enmVendor), RTX86GetCpuFamily(uEax),
4740 RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), RTX86GetCpuStepping(uEax));
4741 pszCpuDesc = pszName = szNameC;
4742 vbCpuRepDebug("Name/NameC: %s\n", szNameC);
4743 }
4744
4745 /*
4746 * Print a file header, if we're not outputting to stdout (assumption being
4747 * that stdout is used while hacking the reporter and too much output is
4748 * unwanted).
4749 */
4750 if (g_pReportOut)
4751 {
4752 RTTIMESPEC Now;
4753 char szNow[64];
4754 RTTimeSpecToString(RTTimeNow(&Now), szNow, sizeof(szNow));
4755 char *pchDot = strchr(szNow, '.');
4756 if (pchDot)
4757 strcpy(pchDot, "Z");
4758
4759 vbCpuRepPrintf("/* $" "Id" "$ */\n"
4760 "/** @file\n"
4761 " * CPU database entry \"%s\".\n"
4762 " * Generated at %s by VBoxCpuReport v%sr%s on %s.%s.\n"
4763 " */\n"
4764 "\n"
4765 "/*\n"
4766 " * Copyright (C) 2013-2020 Oracle Corporation\n"
4767 " *\n"
4768 " * This file is part of VirtualBox Open Source Edition (OSE), as\n"
4769 " * available from http://www.virtualbox.org. This file is free software;\n"
4770 " * you can redistribute it and/or modify it under the terms of the GNU\n"
4771 " * General Public License (GPL) as published by the Free Software\n"
4772 " * Foundation, in version 2 as it comes in the \"COPYING\" file of the\n"
4773 " * VirtualBox OSE distribution. VirtualBox OSE is distributed in the\n"
4774 " * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.\n"
4775 " */\n"
4776 "\n"
4777 "#ifndef VBOX_CPUDB_%s_h\n"
4778 "#define VBOX_CPUDB_%s_h\n"
4779 "#ifndef RT_WITHOUT_PRAGMA_ONCE\n"
4780 "# pragma once\n"
4781 "#endif\n"
4782 "\n",
4783 pszName,
4784 szNow, RTBldCfgVersion(), RTBldCfgRevisionStr(), RTBldCfgTarget(), RTBldCfgTargetArch(),
4785 szNameC, szNameC);
4786 }
4787
4788 /*
4789 * Extract CPUID based data.
4790 */
4791 int rc = produceCpuIdArray(szNameC, pszCpuDesc);
4792 if (RT_FAILURE(rc))
4793 return rc;
4794
4795 CPUMUNKNOWNCPUID enmUnknownMethod;
4796 CPUMCPUID DefUnknown;
4797 rc = CPUMR3CpuIdDetectUnknownLeafMethod(&enmUnknownMethod, &DefUnknown);
4798 if (RT_FAILURE(rc))
4799 return RTMsgErrorRc(rc, "CPUMR3DetectCpuIdUnknownMethod failed: %Rrc\n", rc);
4800 vbCpuRepDebug("enmUnknownMethod=%s\n", CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod));
4801
4802 /*
4803 * Do the MSRs, if we can.
4804 */
4805 char szMsrMask[64];
4806 probeMsrs(false /*fHacking*/, szNameC, pszCpuDesc, szMsrMask, sizeof(szMsrMask));
4807
4808 /*
4809 * Emit the CPUMDBENTRY record.
4810 */
4811 ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
4812 vbCpuRepPrintf("\n"
4813 "/**\n"
4814 " * Database entry for %s.\n"
4815 " */\n"
4816 "static CPUMDBENTRY const g_Entry_%s = \n"
4817 "{\n"
4818 " /*.pszName = */ \"%s\",\n"
4819 " /*.pszFullName = */ \"%s\",\n"
4820 " /*.enmVendor = */ CPUMCPUVENDOR_%s,\n"
4821 " /*.uFamily = */ %u,\n"
4822 " /*.uModel = */ %u,\n"
4823 " /*.uStepping = */ %u,\n"
4824 " /*.enmMicroarch = */ kCpumMicroarch_%s,\n"
4825 " /*.uScalableBusFreq = */ CPUM_SBUSFREQ_%s,\n"
4826 " /*.fFlags = */ 0,\n"
4827 " /*.cMaxPhysAddrWidth= */ %u,\n"
4828 " /*.fMxCsrMask = */ %#010x,\n"
4829 " /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_%s),\n"
4830 " /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_%s)),\n"
4831 " /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_%s,\n"
4832 " /*.DefUnknownCpuId = */ { %#010x, %#010x, %#010x, %#010x },\n"
4833 " /*.fMsrMask = */ %s,\n"
4834 " /*.cMsrRanges = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_%s)),\n"
4835 " /*.paMsrRanges = */ NULL_ALONE(g_aMsrRanges_%s),\n"
4836 "};\n"
4837 "\n"
4838 "#endif /* !VBOX_CPUDB_%s_h */\n"
4839 "\n",
4840 pszCpuDesc,
4841 szNameC,
4842 pszName,
4843 pszCpuDesc,
4844 CPUMR3CpuVendorName(enmVendor),
4845 RTX86GetCpuFamily(uEax),
4846 RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
4847 RTX86GetCpuStepping(uEax),
4848 CPUMR3MicroarchName(enmMicroarch),
4849 vbCpuRepGuessScalableBusFrequencyName(),
4850 vbCpuRepGetPhysAddrWidth(),
4851 CPUMR3DeterminHostMxCsrMask(),
4852 szNameC,
4853 szNameC,
4854 CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod),
4855 DefUnknown.uEax,
4856 DefUnknown.uEbx,
4857 DefUnknown.uEcx,
4858 DefUnknown.uEdx,
4859 szMsrMask,
4860 szNameC,
4861 szNameC,
4862 szNameC
4863 );
4864
4865 return VINF_SUCCESS;
4866}
4867
4868
4869int main(int argc, char **argv)
4870{
4871 int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
4872 if (RT_FAILURE(rc))
4873 return RTMsgInitFailure(rc);
4874
4875 /*
4876 * Argument parsing?
4877 */
4878 static const RTGETOPTDEF s_aOptions[] =
4879 {
4880 { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING },
4881 { "--msrs-dev", 'd', RTGETOPT_REQ_NOTHING },
4882 { "--no-msrs", 'n', RTGETOPT_REQ_NOTHING },
4883 { "--output", 'o', RTGETOPT_REQ_STRING },
4884 { "--log", 'l', RTGETOPT_REQ_STRING },
4885 };
4886 RTGETOPTSTATE State;
4887 RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
4888
4889 enum
4890 {
4891 kCpuReportOp_Normal,
4892 kCpuReportOp_MsrsOnly,
4893 kCpuReportOp_MsrsHacking
4894 } enmOp = kCpuReportOp_Normal;
4895 g_pReportOut = NULL;
4896 g_pDebugOut = NULL;
4897 const char *pszOutput = NULL;
4898 const char *pszDebugOut = NULL;
4899
4900 int iOpt;
4901 RTGETOPTUNION ValueUnion;
4902 while ((iOpt = RTGetOpt(&State, &ValueUnion)) != 0)
4903 {
4904 switch (iOpt)
4905 {
4906 case 'm':
4907 enmOp = kCpuReportOp_MsrsOnly;
4908 break;
4909
4910 case 'd':
4911 enmOp = kCpuReportOp_MsrsHacking;
4912 break;
4913
4914 case 'n':
4915 g_fNoMsrs = true;
4916 break;
4917
4918 case 'o':
4919 pszOutput = ValueUnion.psz;
4920 break;
4921
4922 case 'l':
4923 pszDebugOut = ValueUnion.psz;
4924 break;
4925
4926 case 'h':
4927 RTPrintf("Usage: VBoxCpuReport [-m|--msrs-only] [-d|--msrs-dev] [-n|--no-msrs] [-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n");
4928 RTPrintf("Internal tool for gathering information to the VMM CPU database.\n");
4929 return RTEXITCODE_SUCCESS;
4930 case 'V':
4931 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
4932 return RTEXITCODE_SUCCESS;
4933 default:
4934 return RTGetOptPrintError(iOpt, &ValueUnion);
4935 }
4936 }
4937
4938 /*
4939 * Open the alternative debug log stream.
4940 */
4941 if (pszDebugOut)
4942 {
4943 if (RTFileExists(pszDebugOut) && !RTSymlinkExists(pszDebugOut))
4944 {
4945 char szOld[RTPATH_MAX];
4946 rc = RTStrCopy(szOld, sizeof(szOld), pszDebugOut);
4947 if (RT_SUCCESS(rc))
4948 rc = RTStrCat(szOld, sizeof(szOld), ".old");
4949 if (RT_SUCCESS(rc))
4950 RTFileRename(pszDebugOut, szOld, RTFILEMOVE_FLAGS_REPLACE);
4951 }
4952 rc = RTStrmOpen(pszDebugOut, "w", &g_pDebugOut);
4953 if (RT_FAILURE(rc))
4954 {
4955 RTMsgError("Error opening '%s': %Rrc", pszDebugOut, rc);
4956 g_pDebugOut = NULL;
4957 }
4958 }
4959
4960 /*
4961 * Do the requested job.
4962 */
4963 rc = VERR_INTERNAL_ERROR;
4964 switch (enmOp)
4965 {
4966 case kCpuReportOp_Normal:
4967 /* switch output file. */
4968 if (pszOutput)
4969 {
4970 if (RTFileExists(pszOutput) && !RTSymlinkExists(pszOutput))
4971 {
4972 char szOld[RTPATH_MAX];
4973 rc = RTStrCopy(szOld, sizeof(szOld), pszOutput);
4974 if (RT_SUCCESS(rc))
4975 rc = RTStrCat(szOld, sizeof(szOld), ".old");
4976 if (RT_SUCCESS(rc))
4977 RTFileRename(pszOutput, szOld, RTFILEMOVE_FLAGS_REPLACE);
4978 }
4979 rc = RTStrmOpen(pszOutput, "w", &g_pReportOut);
4980 if (RT_FAILURE(rc))
4981 {
4982 RTMsgError("Error opening '%s': %Rrc", pszOutput, rc);
4983 break;
4984 }
4985 }
4986 rc = produceCpuReport();
4987 break;
4988 case kCpuReportOp_MsrsOnly:
4989 case kCpuReportOp_MsrsHacking:
4990 rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0);
4991 break;
4992 }
4993
4994 /*
4995 * Close the output files.
4996 */
4997 if (g_pReportOut)
4998 {
4999 RTStrmClose(g_pReportOut);
5000 g_pReportOut = NULL;
5001 }
5002
5003 if (g_pDebugOut)
5004 {
5005 RTStrmClose(g_pDebugOut);
5006 g_pDebugOut = NULL;
5007 }
5008
5009 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
5010}
5011
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