VirtualBox

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

Last change on this file since 49988 was 49988, checked in by vboxsync, 11 years ago

CPU: Hacking VIA

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