VirtualBox

source: vbox/trunk/src/VBox/VMM/tools/VBoxCpuReport-x86.cpp

Last change on this file was 109008, checked in by vboxsync, 5 days ago

VMM,Main: Working on ARM CPU profile support, which is neede/useful for getting info about the host CPU as well. The CPUDBENTRY typedef is used externally by Main, so we can't have two definitions of it, so left the bits that are common to both x86 and ARM in CPUDBENTRY and created sub-structures for each of the two targets/platforms. Also started reworking the VBoxCpuReport tool so we can use it on arm as well (much left to do there, though). jiraref:VBP-1598

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette