VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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