summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorMichael Kinney <michael.d.kinney@intel.com>2016-02-18 23:16:02 -0800
committerMichael Kinney <michael.d.kinney@intel.com>2016-02-24 20:36:51 -0800
commit2570575276ab8f1f29e00c536e3d80983d5fccb1 (patch)
treec9b35a3ef77656e8e068c6f8ae2fc8f101743a1f /UefiCpuPkg
parent57d16ba1e7593e4fabc2b483ed5ac53cbfd5d9c7 (diff)
downloadedk2-2570575276ab8f1f29e00c536e3d80983d5fccb1.tar.gz
edk2-2570575276ab8f1f29e00c536e3d80983d5fccb1.tar.bz2
edk2-2570575276ab8f1f29e00c536e3d80983d5fccb1.zip
UefiCpuPkg/Cpuid: Add UEFI CPUID application
Add UEFI application to UefiCpuPkg to display all supported CPUID leafs and sub-leafs described by UefiCpuPkg/Include/Register/Cpuid.h that is based on information from Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 2A, December 2015, CPUID instruction. Cc: Jeff Fan <jeff.fan@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Application/Cpuid/Cpuid.c1353
-rw-r--r--UefiCpuPkg/Application/Cpuid/Cpuid.inf48
-rw-r--r--UefiCpuPkg/Application/Cpuid/Cpuid.uni22
-rw-r--r--UefiCpuPkg/Application/Cpuid/CpuidExtra.uni22
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dsc5
5 files changed, 1450 insertions, 0 deletions
diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.c b/UefiCpuPkg/Application/Cpuid/Cpuid.c
new file mode 100644
index 0000000000..f82e43f563
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.c
@@ -0,0 +1,1353 @@
+/** @file
+ UEFI Application to display CPUID leaf information.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Register/Cpuid.h>
+
+///
+/// Macro used to display the value of a bit field in a register returned by CPUID.
+///
+#define PRINT_BIT_FIELD(Variable, FieldName) \
+ Print (L"%5a%42a: %x\n", #Variable, #FieldName, ##Variable.Bits.##FieldName);
+
+///
+/// Macro used to display the value of a register returned by CPUID.
+///
+#define PRINT_VALUE(Variable, Description) \
+ Print (L"%5a%42a: %x\n", #Variable, #Description, Variable);
+
+///
+/// Structure for cache description lookup table
+///
+typedef struct {
+ UINT8 CacheDescriptor;
+ CHAR8 *Type;
+ CHAR8 *Description;
+} CPUID_CACHE_INFO_DESCRIPTION;
+
+///
+/// Cache description lookup table
+///
+CPUID_CACHE_INFO_DESCRIPTION mCpuidCacheInfoDescription[] = {
+ { 0x00 , "General" , "Null descriptor, this byte contains no information" },
+ { 0x01 , "TLB" , "Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries" },
+ { 0x02 , "TLB" , "Instruction TLB: 4 MByte pages, fully associative, 2 entries" },
+ { 0x03 , "TLB" , "Data TLB: 4 KByte pages, 4-way set associative, 64 entries" },
+ { 0x04 , "TLB" , "Data TLB: 4 MByte pages, 4-way set associative, 8 entries" },
+ { 0x05 , "TLB" , "Data TLB1: 4 MByte pages, 4-way set associative, 32 entries" },
+ { 0x06 , "Cache" , "1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x08 , "Cache" , "1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x09 , "Cache" , "1st-level instruction cache: 32KBytes, 4-way set associative, 64 byte line size" },
+ { 0x0A , "Cache" , "1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size" },
+ { 0x0B , "TLB" , "Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries" },
+ { 0x0C , "Cache" , "1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x0D , "Cache" , "1st-level data cache: 16 KBytes, 4-way set associative, 64 byte line size" },
+ { 0x0E , "Cache" , "1st-level data cache: 24 KBytes, 6-way set associative, 64 byte line size" },
+ { 0x1D , "Cache" , "2nd-level cache: 128 KBytes, 2-way set associative, 64 byte line size" },
+ { 0x21 , "Cache" , "2nd-level cache: 256 KBytes, 8-way set associative, 64 byte line size" },
+ { 0x22 , "Cache" , "3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x23 , "Cache" , "3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x24 , "Cache" , "2nd-level cache: 1 MBytes, 16-way set associative, 64 byte line size" },
+ { 0x25 , "Cache" , "3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x29 , "Cache" , "3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x2C , "Cache" , "1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size" },
+ { 0x30 , "Cache" , "1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size" },
+ { 0x40 , "Cache" , "No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache" },
+ { 0x41 , "Cache" , "2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x42 , "Cache" , "2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x43 , "Cache" , "2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size" },
+ { 0x44 , "Cache" , "2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size" },
+ { 0x45 , "Cache" , "2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size" },
+ { 0x46 , "Cache" , "3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size" },
+ { 0x47 , "Cache" , "3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size" },
+ { 0x48 , "Cache" , "2nd-level cache: 3MByte, 12-way set associative, 64 byte line size" },
+ { 0x49 , "Cache" , "3rd-level cache: 4MB, 16-way set associative, 64-byte line size (Intel Xeon processor MP, Family 0FH, Model 06H). 2nd-level cache: 4 MByte, 16-way set associative, 64 byte line size" },
+ { 0x4A , "Cache" , "3rd-level cache: 6MByte, 12-way set associative, 64 byte line size" },
+ { 0x4B , "Cache" , "3rd-level cache: 8MByte, 16-way set associative, 64 byte line size" },
+ { 0x4C , "Cache" , "3rd-level cache: 12MByte, 12-way set associative, 64 byte line size" },
+ { 0x4D , "Cache" , "3rd-level cache: 16MByte, 16-way set associative, 64 byte line size" },
+ { 0x4E , "Cache" , "2nd-level cache: 6MByte, 24-way set associative, 64 byte line size" },
+ { 0x4F , "TLB" , "Instruction TLB: 4 KByte pages, 32 entries" },
+ { 0x50 , "TLB" , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries" },
+ { 0x51 , "TLB" , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries" },
+ { 0x52 , "TLB" , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries" },
+ { 0x55 , "TLB" , "Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries" },
+ { 0x56 , "TLB" , "Data TLB0: 4 MByte pages, 4-way set associative, 16 entries" },
+ { 0x57 , "TLB" , "Data TLB0: 4 KByte pages, 4-way associative, 16 entries" },
+ { 0x59 , "TLB" , "Data TLB0: 4 KByte pages, fully associative, 16 entries" },
+ { 0x5A , "TLB" , "Data TLB0: 2-MByte or 4 MByte pages, 4-way set associative, 32 entries" },
+ { 0x5B , "TLB" , "Data TLB: 4 KByte and 4 MByte pages, 64 entries" },
+ { 0x5C , "TLB" , "Data TLB: 4 KByte and 4 MByte pages,128 entries" },
+ { 0x5D , "TLB" , "Data TLB: 4 KByte and 4 MByte pages,256 entries" },
+ { 0x60 , "Cache" , "1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size" },
+ { 0x61 , "TLB" , "Instruction TLB: 4 KByte pages, fully associative, 48 entries" },
+ { 0x63 , "TLB" , "Data TLB: 1 GByte pages, 4-way set associative, 4 entries" },
+ { 0x66 , "Cache" , "1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size" },
+ { 0x67 , "Cache" , "1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size" },
+ { 0x68 , "Cache" , "1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size" },
+ { 0x6A , "Cache" , "uTLB: 4 KByte pages, 8-way set associative, 64 entries" },
+ { 0x6B , "Cache" , "DTLB: 4 KByte pages, 8-way set associative, 256 entries" },
+ { 0x6C , "Cache" , "DTLB: 2M/4M pages, 8-way set associative, 128 entries" },
+ { 0x6D , "Cache" , "DTLB: 1 GByte pages, fully associative, 16 entries" },
+ { 0x70 , "Cache" , "Trace cache: 12 K-uop, 8-way set associative" },
+ { 0x71 , "Cache" , "Trace cache: 16 K-uop, 8-way set associative" },
+ { 0x72 , "Cache" , "Trace cache: 32 K-uop, 8-way set associative" },
+ { 0x76 , "TLB" , "Instruction TLB: 2M/4M pages, fully associative, 8 entries" },
+ { 0x78 , "Cache" , "2nd-level cache: 1 MByte, 4-way set associative, 64byte line size" },
+ { 0x79 , "Cache" , "2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x7A , "Cache" , "2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x7B , "Cache" , "2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x7C , "Cache" , "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
+ { 0x7D , "Cache" , "2nd-level cache: 2 MByte, 8-way set associative, 64byte line size" },
+ { 0x7F , "Cache" , "2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size" },
+ { 0x80 , "Cache" , "2nd-level cache: 512 KByte, 8-way set associative, 64-byte line size" },
+ { 0x82 , "Cache" , "2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size" },
+ { 0x83 , "Cache" , "2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size" },
+ { 0x84 , "Cache" , "2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size" },
+ { 0x85 , "Cache" , "2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size" },
+ { 0x86 , "Cache" , "2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size" },
+ { 0x87 , "Cache" , "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size" },
+ { 0xA0 , "DTLB" , "DTLB: 4k pages, fully associative, 32 entries" },
+ { 0xB0 , "TLB" , "Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries" },
+ { 0xB1 , "TLB" , "Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries" },
+ { 0xB2 , "TLB" , "Instruction TLB: 4KByte pages, 4-way set associative, 64 entries" },
+ { 0xB3 , "TLB" , "Data TLB: 4 KByte pages, 4-way set associative, 128 entries" },
+ { 0xB4 , "TLB" , "Data TLB1: 4 KByte pages, 4-way associative, 256 entries" },
+ { 0xB5 , "TLB" , "Instruction TLB: 4KByte pages, 8-way set associative, 64 entries" },
+ { 0xB6 , "TLB" , "Instruction TLB: 4KByte pages, 8-way set associative, 128 entries" },
+ { 0xBA , "TLB" , "Data TLB1: 4 KByte pages, 4-way associative, 64 entries" },
+ { 0xC0 , "TLB" , "Data TLB: 4 KByte and 4 MByte pages, 4-way associative, 8 entries" },
+ { 0xC1 , "STLB" , "Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries" },
+ { 0xC2 , "DTLB" , "DTLB: 4 KByte/2 MByte pages, 4-way associative, 16 entries" },
+ { 0xC3 , "STLB" , "Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries." },
+ { 0xCA , "STLB" , "Shared 2nd-Level TLB: 4 KByte pages, 4-way associative, 512 entries" },
+ { 0xD0 , "Cache" , "3rd-level cache: 512 KByte, 4-way set associative, 64 byte line size" },
+ { 0xD1 , "Cache" , "3rd-level cache: 1 MByte, 4-way set associative, 64 byte line size" },
+ { 0xD2 , "Cache" , "3rd-level cache: 2 MByte, 4-way set associative, 64 byte line size" },
+ { 0xD6 , "Cache" , "3rd-level cache: 1 MByte, 8-way set associative, 64 byte line size" },
+ { 0xD7 , "Cache" , "3rd-level cache: 2 MByte, 8-way set associative, 64 byte line size" },
+ { 0xD8 , "Cache" , "3rd-level cache: 4 MByte, 8-way set associative, 64 byte line size" },
+ { 0xDC , "Cache" , "3rd-level cache: 1.5 MByte, 12-way set associative, 64 byte line size" },
+ { 0xDD , "Cache" , "3rd-level cache: 3 MByte, 12-way set associative, 64 byte line size" },
+ { 0xDE , "Cache" , "3rd-level cache: 6 MByte, 12-way set associative, 64 byte line size" },
+ { 0xE2 , "Cache" , "3rd-level cache: 2 MByte, 16-way set associative, 64 byte line size" },
+ { 0xE3 , "Cache" , "3rd-level cache: 4 MByte, 16-way set associative, 64 byte line size" },
+ { 0xE4 , "Cache" , "3rd-level cache: 8 MByte, 16-way set associative, 64 byte line size" },
+ { 0xEA , "Cache" , "3rd-level cache: 12MByte, 24-way set associative, 64 byte line size" },
+ { 0xEB , "Cache" , "3rd-level cache: 18MByte, 24-way set associative, 64 byte line size" },
+ { 0xEC , "Cache" , "3rd-level cache: 24MByte, 24-way set associative, 64 byte line size" },
+ { 0xF0 , "Prefetch" , "64-Byte prefetching" },
+ { 0xF1 , "Prefetch" , "128-Byte prefetching" },
+ { 0xFF , "General" , "CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters" }
+};
+
+///
+/// The maximum supported CPUID leaf index starting from leaf 0x00000000.
+///
+UINT32 gMaximumBasicFunction = CPUID_SIGNATURE;
+
+///
+/// The maximum supported CPUID leaf index starting from leaf 0x80000000.
+///
+UINT32 gMaximumExtendedFunction = CPUID_EXTENDED_FUNCTION;
+
+/**
+ Display CPUID_SIGNATURE leaf.
+
+**/
+VOID
+CpuidSignature (
+ VOID
+ )
+{
+ UINT32 Eax;
+ UINT32 Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+ CHAR8 Signature[13];
+
+ if (CPUID_SIGNATURE > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_SIGNATURE, &Eax, &Ebx, &Ecx, &Edx);
+
+ Print (L"CPUID_SIGNATURE (Leaf %08x)\n", CPUID_SIGNATURE);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, Ecx, Edx);
+ PRINT_VALUE (Eax, MaximumLeaf);
+ *(UINT32 *)(Signature + 0) = Ebx;
+ *(UINT32 *)(Signature + 4) = Edx;
+ *(UINT32 *)(Signature + 8) = Ecx;
+ Signature [12] = 0;
+ Print (L" Signature = %a\n", Signature);
+
+ gMaximumBasicFunction = Eax;
+}
+
+/**
+ Display CPUID_VERSION_INFO leaf.
+
+**/
+VOID
+CpuidVersionInfo (
+ VOID
+ )
+{
+ CPUID_VERSION_INFO_EAX Eax;
+ CPUID_VERSION_INFO_EBX Ebx;
+ CPUID_VERSION_INFO_ECX Ecx;
+ CPUID_VERSION_INFO_EDX Edx;
+ UINTN DisplayFamily;
+ UINTN DisplayModel;
+
+ if (CPUID_VERSION_INFO > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+
+ Print (L"CPUID_VERSION_INFO (Leaf %08x)\n", CPUID_VERSION_INFO);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+
+ DisplayFamily = Eax.Bits.FamilyId;
+ if (Eax.Bits.FamilyId == 0x0F) {
+ DisplayFamily |= (Eax.Bits.ExtendedFamilyId << 4);
+ }
+
+ DisplayModel = Eax.Bits.Model;
+ if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
+ DisplayModel |= (Eax.Bits.ExtendedModelId << 4);
+ }
+
+ Print (L" Family = %x Model = %x Stepping = %x\n", DisplayFamily, DisplayModel, Eax.Bits.SteppingId);
+
+ PRINT_BIT_FIELD (Eax, SteppingId);
+ PRINT_BIT_FIELD (Eax, Model);
+ PRINT_BIT_FIELD (Eax, FamilyId);
+ PRINT_BIT_FIELD (Eax, ProcessorType);
+ PRINT_BIT_FIELD (Eax, ExtendedModelId);
+ PRINT_BIT_FIELD (Eax, ExtendedFamilyId);
+ PRINT_BIT_FIELD (Ebx, BrandIndex);
+ PRINT_BIT_FIELD (Ebx, CacheLineSize);
+ PRINT_BIT_FIELD (Ebx, MaximumAddressableIdsForLogicalProcessors);
+ PRINT_BIT_FIELD (Ebx, InitialLocalApicId);
+ PRINT_BIT_FIELD (Ecx, SSE3);
+ PRINT_BIT_FIELD (Ecx, PCLMULQDQ);
+ PRINT_BIT_FIELD (Ecx, DTES64);
+ PRINT_BIT_FIELD (Ecx, MONITOR);
+ PRINT_BIT_FIELD (Ecx, DS_CPL);
+ PRINT_BIT_FIELD (Ecx, VMX);
+ PRINT_BIT_FIELD (Ecx, SMX);
+ PRINT_BIT_FIELD (Ecx, TM2);
+ PRINT_BIT_FIELD (Ecx, SSSE3);
+ PRINT_BIT_FIELD (Ecx, CNXT_ID);
+ PRINT_BIT_FIELD (Ecx, SDBG);
+ PRINT_BIT_FIELD (Ecx, FMA);
+ PRINT_BIT_FIELD (Ecx, CMPXCHG16B);
+ PRINT_BIT_FIELD (Ecx, xTPR_Update_Control);
+ PRINT_BIT_FIELD (Ecx, PDCM);
+ PRINT_BIT_FIELD (Ecx, PCID);
+ PRINT_BIT_FIELD (Ecx, DCA);
+ PRINT_BIT_FIELD (Ecx, SSE4_1);
+ PRINT_BIT_FIELD (Ecx, SSE4_2);
+ PRINT_BIT_FIELD (Ecx, x2APIC);
+ PRINT_BIT_FIELD (Ecx, MOVBE);
+ PRINT_BIT_FIELD (Ecx, POPCNT);
+ PRINT_BIT_FIELD (Ecx, TSC_Deadline);
+ PRINT_BIT_FIELD (Ecx, AESNI);
+ PRINT_BIT_FIELD (Ecx, XSAVE);
+ PRINT_BIT_FIELD (Ecx, OSXSAVE);
+ PRINT_BIT_FIELD (Ecx, AVX);
+ PRINT_BIT_FIELD (Ecx, F16C);
+ PRINT_BIT_FIELD (Ecx, RDRAND);
+ PRINT_BIT_FIELD (Edx, FPU);
+ PRINT_BIT_FIELD (Edx, VME);
+ PRINT_BIT_FIELD (Edx, DE);
+ PRINT_BIT_FIELD (Edx, PSE);
+ PRINT_BIT_FIELD (Edx, TSC);
+ PRINT_BIT_FIELD (Edx, MSR);
+ PRINT_BIT_FIELD (Edx, PAE);
+ PRINT_BIT_FIELD (Edx, MCE);
+ PRINT_BIT_FIELD (Edx, CX8);
+ PRINT_BIT_FIELD (Edx, APIC);
+ PRINT_BIT_FIELD (Edx, SEP);
+ PRINT_BIT_FIELD (Edx, MTRR);
+ PRINT_BIT_FIELD (Edx, PGE);
+ PRINT_BIT_FIELD (Edx, MCA);
+ PRINT_BIT_FIELD (Edx, CMOV);
+ PRINT_BIT_FIELD (Edx, PAT);
+ PRINT_BIT_FIELD (Edx, PSE_36);
+ PRINT_BIT_FIELD (Edx, PSN);
+ PRINT_BIT_FIELD (Edx, CLFSH);
+ PRINT_BIT_FIELD (Edx, DS);
+ PRINT_BIT_FIELD (Edx, ACPI);
+ PRINT_BIT_FIELD (Edx, MMX);
+ PRINT_BIT_FIELD (Edx, FXSR);
+ PRINT_BIT_FIELD (Edx, SSE);
+ PRINT_BIT_FIELD (Edx, SSE2);
+ PRINT_BIT_FIELD (Edx, SS);
+ PRINT_BIT_FIELD (Edx, HTT);
+ PRINT_BIT_FIELD (Edx, TM);
+ PRINT_BIT_FIELD (Edx, PBE);
+}
+
+/**
+ Lookup a cache description string from the mCpuidCacheInfoDescription table.
+
+ @param[in] CacheDescriptor Cache descriptor value from CPUID_CACHE_INFO.
+
+**/
+CPUID_CACHE_INFO_DESCRIPTION *
+LookupCacheDescription (
+ UINT8 CacheDescriptor
+ )
+{
+ UINTN NumDescriptors;
+ UINTN Descriptor;
+
+ if (CacheDescriptor == 0x00) {
+ return NULL;
+ }
+ NumDescriptors = sizeof (mCpuidCacheInfoDescription)/sizeof (mCpuidCacheInfoDescription[0]);
+ for (Descriptor = 0; Descriptor < NumDescriptors; Descriptor++) {
+ if (CacheDescriptor == mCpuidCacheInfoDescription[Descriptor].CacheDescriptor) {
+ return &mCpuidCacheInfoDescription[Descriptor];
+ }
+ }
+ return NULL;
+}
+
+/**
+ Display CPUID_CACHE_INFO leaf for each supported cache descriptor.
+
+**/
+VOID
+CpuidCacheInfo (
+ VOID
+ )
+{
+ CPUID_CACHE_INFO_CACHE_TLB Eax;
+ CPUID_CACHE_INFO_CACHE_TLB Ebx;
+ CPUID_CACHE_INFO_CACHE_TLB Ecx;
+ CPUID_CACHE_INFO_CACHE_TLB Edx;
+ UINTN Index;
+ CPUID_CACHE_INFO_DESCRIPTION *CacheDescription;
+
+ if (CPUID_CACHE_INFO > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_CACHE_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+
+ Print (L"CPUID_CACHE_INFO (Leaf %08x)\n", CPUID_CACHE_INFO);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ if (Eax.Bits.NotValid == 0) {
+ //
+ // Process Eax.CacheDescriptor[1..3]. Ignore Eax.CacheDescriptor[0]
+ //
+ for (Index = 1; Index < 4; Index++) {
+ CacheDescription = LookupCacheDescription (Eax.CacheDescriptor[Index]);
+ if (CacheDescription != NULL) {
+ Print (L" %-8a %a\n",
+ CacheDescription->Type,
+ CacheDescription->Description
+ );
+ }
+ }
+ }
+ if (Ebx.Bits.NotValid == 0) {
+ //
+ // Process Ebx.CacheDescriptor[0..3]
+ //
+ for (Index = 0; Index < 4; Index++) {
+ CacheDescription = LookupCacheDescription (Ebx.CacheDescriptor[Index]);
+ if (CacheDescription != NULL) {
+ Print (L" %-8a %a\n",
+ CacheDescription->Type,
+ CacheDescription->Description
+ );
+ }
+ }
+ }
+ if (Ecx.Bits.NotValid == 0) {
+ //
+ // Process Ecx.CacheDescriptor[0..3]
+ //
+ for (Index = 0; Index < 4; Index++) {
+ CacheDescription = LookupCacheDescription (Ecx.CacheDescriptor[Index]);
+ if (CacheDescription != NULL) {
+ Print (L" %-8a %a\n",
+ CacheDescription->Type,
+ CacheDescription->Description
+ );
+ }
+ }
+ }
+ if (Edx.Bits.NotValid == 0) {
+ //
+ // Process Edx.CacheDescriptor[0..3]
+ //
+ for (Index = 0; Index < 4; Index++) {
+ CacheDescription = LookupCacheDescription (Edx.CacheDescriptor[Index]);
+ if (CacheDescription != NULL) {
+ Print (L" %-8a %a\n",
+ CacheDescription->Type,
+ CacheDescription->Description
+ );
+ }
+ }
+ }
+}
+
+/**
+ Display CPUID_SERIAL_NUMBER leaf if it is supported.
+
+**/
+VOID
+CpuidSerialNumber (
+ VOID
+ )
+{
+ CPUID_VERSION_INFO_EDX VersionInfoEdx;
+ UINT32 Ecx;
+ UINT32 Edx;
+
+ Print (L"CPUID_SERIAL_NUMBER (Leaf %08x)\n", CPUID_SERIAL_NUMBER);
+
+ if (CPUID_SERIAL_NUMBER > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
+ if (VersionInfoEdx.Bits.PSN == 0) {
+ Print (L" Not Supported\n");
+ return;
+ }
+
+ AsmCpuid (CPUID_SERIAL_NUMBER, NULL, NULL, &Ecx, &Edx);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, 0, Ecx, Edx);
+ Print (L" Processor Serial Number = %08x%08x%08x\n", 0, Edx, Ecx);
+}
+
+/**
+ Display CPUID_CACHE_PARAMS for all supported sub-leafs.
+
+**/
+VOID
+CpuidCacheParams (
+ VOID
+ )
+{
+ UINT32 CacheLevel;
+ CPUID_CACHE_PARAMS_EAX Eax;
+ CPUID_CACHE_PARAMS_EBX Ebx;
+ UINT32 Ecx;
+ CPUID_CACHE_PARAMS_EDX Edx;
+
+ if (CPUID_CACHE_PARAMS > gMaximumBasicFunction) {
+ return;
+ }
+
+ CacheLevel = 0;
+ do {
+ AsmCpuidEx (
+ CPUID_CACHE_PARAMS, CacheLevel,
+ &Eax.Uint32, &Ebx.Uint32, &Ecx, &Edx.Uint32
+ );
+ if (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL) {
+ Print (L"CPUID_CACHE_PARAMS (Leaf %08x, Sub-Leaf %08x)\n", CPUID_CACHE_PARAMS, CacheLevel);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx, Edx.Uint32);
+ PRINT_BIT_FIELD (Eax, CacheType);
+ PRINT_BIT_FIELD (Eax, CacheLevel);
+ PRINT_BIT_FIELD (Eax, SelfInitializingCache);
+ PRINT_BIT_FIELD (Eax, FullyAssociativeCache);
+ PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForLogicalProcessors);
+ PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForProcessorCores);
+ PRINT_BIT_FIELD (Ebx, LineSize);
+ PRINT_BIT_FIELD (Ebx, LinePartitions);
+ PRINT_BIT_FIELD (Ebx, Ways);
+ PRINT_VALUE (Ecx, NumberOfSets);
+ PRINT_BIT_FIELD (Edx, Invalidate);
+ PRINT_BIT_FIELD (Edx, CacheInclusiveness);
+ PRINT_BIT_FIELD (Edx, ComplexCacheIndexing);
+ }
+ CacheLevel++;
+ } while (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL);
+}
+
+/**
+ Display CPUID_MONITOR_MWAIT leaf.
+
+**/
+VOID
+CpuidMonitorMwait (
+ VOID
+ )
+{
+ CPUID_MONITOR_MWAIT_EAX Eax;
+ CPUID_MONITOR_MWAIT_EBX Ebx;
+ CPUID_MONITOR_MWAIT_ECX Ecx;
+ CPUID_MONITOR_MWAIT_EDX Edx;
+
+ if (CPUID_MONITOR_MWAIT > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_MONITOR_MWAIT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+
+ Print (L"CPUID_MONITOR_MWAIT (Leaf %08x)\n", CPUID_MONITOR_MWAIT);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+
+ PRINT_BIT_FIELD (Eax, SmallestMonitorLineSize);
+ PRINT_BIT_FIELD (Ebx, LargestMonitorLineSize);
+ PRINT_BIT_FIELD (Ecx, ExtensionsSupported);
+ PRINT_BIT_FIELD (Ecx, InterruptAsBreak);
+ PRINT_BIT_FIELD (Edx, C0States);
+ PRINT_BIT_FIELD (Edx, C1States);
+ PRINT_BIT_FIELD (Edx, C2States);
+ PRINT_BIT_FIELD (Edx, C3States);
+ PRINT_BIT_FIELD (Edx, C4States);
+ PRINT_BIT_FIELD (Edx, C5States);
+ PRINT_BIT_FIELD (Edx, C6States);
+ PRINT_BIT_FIELD (Edx, C7States);
+}
+
+/**
+ Display CPUID_THERMAL_POWER_MANAGEMENT leaf.
+
+**/
+VOID
+CpuidThermalPowerManagement (
+ VOID
+ )
+{
+ CPUID_THERMAL_POWER_MANAGEMENT_EAX Eax;
+ CPUID_THERMAL_POWER_MANAGEMENT_EBX Ebx;
+ CPUID_THERMAL_POWER_MANAGEMENT_ECX Ecx;
+
+ if (CPUID_THERMAL_POWER_MANAGEMENT > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, NULL);
+
+ Print (L"CPUID_THERMAL_POWER_MANAGEMENT (Leaf %08x)\n", CPUID_THERMAL_POWER_MANAGEMENT);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, 0);
+
+ PRINT_BIT_FIELD (Eax, DigitalTemperatureSensor);
+ PRINT_BIT_FIELD (Eax, TurboBoostTechnology);
+ PRINT_BIT_FIELD (Eax, ARAT);
+ PRINT_BIT_FIELD (Eax, PLN);
+ PRINT_BIT_FIELD (Eax, ECMD);
+ PRINT_BIT_FIELD (Eax, PTM);
+ PRINT_BIT_FIELD (Eax, HWP);
+ PRINT_BIT_FIELD (Eax, HWP_Notification);
+ PRINT_BIT_FIELD (Eax, HWP_Activity_Window);
+ PRINT_BIT_FIELD (Eax, HWP_Energy_Performance_Preference);
+ PRINT_BIT_FIELD (Eax, HWP_Package_Level_Request);
+ PRINT_BIT_FIELD (Eax, HDC);
+ PRINT_BIT_FIELD (Ebx, InterruptThresholds);
+ PRINT_BIT_FIELD (Ecx, HardwareCoordinationFeedback);
+ PRINT_BIT_FIELD (Ecx, PerformanceEnergyBias);
+}
+
+/**
+ Display CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS for all supported sub-leafs.
+
+**/
+VOID
+CpuidStructuredExtendedFeatureFlags (
+ VOID
+ )
+{
+ UINT32 Eax;
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX Ebx;
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX Ecx;
+ UINT32 SubLeaf;
+
+ if (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
+ &Eax, NULL, NULL, NULL
+ );
+ for (SubLeaf = 0; SubLeaf <= Eax; SubLeaf++) {
+ AsmCpuidEx (
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
+ SubLeaf,
+ NULL, &Ebx.Uint32, &Ecx.Uint32, NULL
+ );
+ if (Ebx.Uint32 != 0 || Ecx.Uint32 != 0) {
+ Print (L"CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS (Leaf %08x, Sub-Leaf %08x)\n", CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, SubLeaf);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx.Uint32, Ecx.Uint32, 0);
+ PRINT_BIT_FIELD (Ebx, FSGSBASE);
+ PRINT_BIT_FIELD (Ebx, IA32_TSC_ADJUST);
+ PRINT_BIT_FIELD (Ebx, BMI1);
+ PRINT_BIT_FIELD (Ebx, HLE);
+ PRINT_BIT_FIELD (Ebx, AVX2);
+ PRINT_BIT_FIELD (Ebx, FDP_EXCPTN_ONLY);
+ PRINT_BIT_FIELD (Ebx, SMEP);
+ PRINT_BIT_FIELD (Ebx, BMI2);
+ PRINT_BIT_FIELD (Ebx, EnhancedRepMovsbStosb);
+ PRINT_BIT_FIELD (Ebx, INVPCID);
+ PRINT_BIT_FIELD (Ebx, RTM);
+ PRINT_BIT_FIELD (Ebx, PQM);
+ PRINT_BIT_FIELD (Ebx, DeprecateFpuCsDs);
+ PRINT_BIT_FIELD (Ebx, MPX);
+ PRINT_BIT_FIELD (Ebx, PQE);
+ PRINT_BIT_FIELD (Ebx, RDSEED);
+ PRINT_BIT_FIELD (Ebx, ADX);
+ PRINT_BIT_FIELD (Ebx, SMAP);
+ PRINT_BIT_FIELD (Ebx, CLFLUSHOPT);
+ PRINT_BIT_FIELD (Ebx, IntelProcessorTrace);
+ PRINT_BIT_FIELD (Ecx, PREFETCHWT1);
+ PRINT_BIT_FIELD (Ecx, PKU);
+ PRINT_BIT_FIELD (Ecx, OSPKE);
+ }
+ SubLeaf++;
+ } while (SubLeaf <= Eax);
+}
+
+/**
+ Display CPUID_DIRECT_CACHE_ACCESS_INFO leaf.
+
+**/
+VOID
+CpuidDirectCacheAccessInfo (
+ VOID
+ )
+{
+ UINT32 Eax;
+
+ if (CPUID_DIRECT_CACHE_ACCESS_INFO > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_DIRECT_CACHE_ACCESS_INFO, &Eax, NULL, NULL, NULL);
+ Print (L"CPUID_DIRECT_CACHE_ACCESS_INFO (Leaf %08x)\n", CPUID_DIRECT_CACHE_ACCESS_INFO);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, 0, 0);
+}
+
+/**
+ Display CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING leaf.
+
+**/
+VOID
+CpuidArchitecturalPerformanceMonitoring (
+ VOID
+ )
+{
+ CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EAX Eax;
+ CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EBX Ebx;
+ CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EDX Edx;
+
+ if (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING, &Eax.Uint32, &Ebx.Uint32, NULL, &Edx.Uint32);
+ Print (L"CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING (Leaf %08x)\n", CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, 0, Edx.Uint32);
+ PRINT_BIT_FIELD (Eax, ArchPerfMonVerID);
+ PRINT_BIT_FIELD (Eax, PerformanceMonitorCounters);
+ PRINT_BIT_FIELD (Eax, PerformanceMonitorCounterWidth);
+ PRINT_BIT_FIELD (Eax, EbxBitVectorLength);
+ PRINT_BIT_FIELD (Ebx, UnhaltedCoreCycles);
+ PRINT_BIT_FIELD (Ebx, InstructionsRetired);
+ PRINT_BIT_FIELD (Ebx, UnhaltedReferenceCycles);
+ PRINT_BIT_FIELD (Ebx, LastLevelCacheReferences);
+ PRINT_BIT_FIELD (Ebx, LastLevelCacheMisses);
+ PRINT_BIT_FIELD (Ebx, BranchInstructionsRetired);
+ PRINT_BIT_FIELD (Ebx, AllBranchMispredictRetired);
+ PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounters);
+ PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounterWidth);
+}
+
+/**
+ Display CPUID_EXTENDED_TOPOLOGY leafs for all supported levels.
+
+**/
+VOID
+CpuidExtendedTopology (
+ VOID
+ )
+{
+ CPUID_EXTENDED_TOPOLOGY_EAX Eax;
+ CPUID_EXTENDED_TOPOLOGY_EBX Ebx;
+ CPUID_EXTENDED_TOPOLOGY_ECX Ecx;
+ UINT32 Edx;
+ UINT32 LevelNumber;
+
+ if (CPUID_EXTENDED_TOPOLOGY > gMaximumBasicFunction) {
+ return;
+ }
+
+ LevelNumber = 0;
+ do {
+ AsmCpuidEx (
+ CPUID_EXTENDED_TOPOLOGY, LevelNumber,
+ &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx
+ );
+ if (Eax.Bits.ApicIdShift != 0) {
+ Print (L"CPUID_EXTENDED_TOPOLOGY (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_TOPOLOGY, LevelNumber);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx);
+ PRINT_BIT_FIELD (Eax, ApicIdShift);
+ PRINT_BIT_FIELD (Ebx, LogicalProcessors);
+ PRINT_BIT_FIELD (Ecx, LevelNumber);
+ PRINT_BIT_FIELD (Ecx, LevelType);
+ PRINT_VALUE (Edx, x2APIC_ID);
+ }
+ LevelNumber++;
+ } while (Eax.Bits.ApicIdShift != 0);
+}
+
+/**
+ Display CPUID_EXTENDED_STATE sub-leaf.
+
+**/
+VOID
+CpuidExtendedStateSubLeaf (
+ VOID
+ )
+{
+ CPUID_EXTENDED_STATE_SUB_LEAF_EAX Eax;
+ UINT32 Ebx;
+ CPUID_EXTENDED_STATE_SUB_LEAF_ECX Ecx;
+ UINT32 Edx;
+
+ AsmCpuidEx (
+ CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF,
+ &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx
+ );
+ Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx, Ecx.Uint32, Edx);
+ PRINT_BIT_FIELD (Eax, XSAVEOPT);
+ PRINT_BIT_FIELD (Eax, XSAVEC);
+ PRINT_BIT_FIELD (Eax, XGETBV);
+ PRINT_BIT_FIELD (Eax, XSAVES);
+ PRINT_VALUE (Ebx, EnabledSaveStateSize_XCR0_IA32_XSS);
+ PRINT_BIT_FIELD (Ecx, XCR0);
+ PRINT_BIT_FIELD (Ecx, PT);
+ PRINT_BIT_FIELD (Ecx, XCR0_1);
+ PRINT_VALUE (Edx, IA32_XSS_Supported_32_63);
+}
+
+/**
+ Display CPUID_EXTENDED_STATE size and offset information sub-leaf.
+
+**/
+VOID
+CpuidExtendedStateSizeOffset (
+ VOID
+ )
+{
+ UINT32 Eax;
+ UINT32 Ebx;
+ CPUID_EXTENDED_STATE_SIZE_OFFSET_ECX Ecx;
+ UINT32 Edx;
+ UINT32 SubLeaf;
+
+ for (SubLeaf = CPUID_EXTENDED_STATE_SIZE_OFFSET; SubLeaf < 32; SubLeaf++) {
+ AsmCpuidEx (
+ CPUID_EXTENDED_STATE, SubLeaf,
+ &Eax, &Ebx, &Ecx.Uint32, &Edx
+ );
+ if (Edx != 0) {
+ Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, SubLeaf);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, Ecx.Uint32, Edx);
+ PRINT_VALUE (Eax, FeatureSaveStateSize);
+ PRINT_VALUE (Ebx, FeatureSaveStateOffset);
+ PRINT_BIT_FIELD (Ecx, XSS);
+ PRINT_BIT_FIELD (Ecx, Compacted);
+ }
+ }
+}
+
+/**
+ Display CPUID_EXTENDED_STATE main leaf and sub-leafs.
+
+**/
+VOID
+CpuidExtendedStateMainLeaf (
+ VOID
+ )
+{
+ CPUID_EXTENDED_STATE_MAIN_LEAF_EAX Eax;
+ UINT32 Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+
+ if (CPUID_EXTENDED_STATE > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF,
+ &Eax.Uint32, &Ebx, &Ecx, &Edx
+ );
+ Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx, Ecx, Edx);
+ PRINT_BIT_FIELD (Eax, x87);
+ PRINT_BIT_FIELD (Eax, SSE);
+ PRINT_BIT_FIELD (Eax, AVX);
+ PRINT_BIT_FIELD (Eax, MPX);
+ PRINT_BIT_FIELD (Eax, AVX_512);
+ PRINT_BIT_FIELD (Eax, IA32_XSS);
+ PRINT_BIT_FIELD (Eax, PKRU);
+ PRINT_VALUE (Ebx, EnabledSaveStateSize);
+ PRINT_VALUE (Ecx, SupportedSaveStateSize);
+ PRINT_VALUE (Edx, XCR0_Supported_32_63);
+
+ CpuidExtendedStateSubLeaf ();
+ CpuidExtendedStateSizeOffset ();
+}
+
+/**
+ Display CPUID_PLATFORM_QOS_MONITORING enumeration sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosMonitoringEnumerationSubLeaf (
+ VOID
+ )
+{
+ UINT32 Ebx;
+ CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF_EDX Edx;
+
+ if (CPUID_PLATFORM_QOS_MONITORING > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_PLATFORM_QOS_MONITORING, CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF,
+ NULL, &Ebx, NULL, &Edx.Uint32
+ );
+ Print (L"CPUID_PLATFORM_QOS_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", CPUID_PLATFORM_QOS_MONITORING, CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, Ebx, 0, Edx.Uint32);
+ PRINT_VALUE (Ebx, Maximum_RMID_Range);
+ PRINT_BIT_FIELD (Edx, L3CacheQosEnforcement);
+}
+
+/**
+ Display CPUID_PLATFORM_QOS_MONITORING capability sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosMonitoringCapabilitySubLeaf (
+ VOID
+ )
+{
+ UINT32 Ebx;
+ UINT32 Ecx;
+ CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF_EDX Edx;
+
+ if (CPUID_PLATFORM_QOS_MONITORING > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_PLATFORM_QOS_MONITORING, CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF,
+ NULL, &Ebx, &Ecx, &Edx.Uint32
+ );
+ Print (L"CPUID_PLATFORM_QOS_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", CPUID_PLATFORM_QOS_MONITORING, CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, Ebx, Ecx, Edx.Uint32);
+ PRINT_VALUE (Ebx, OccupancyConversionFactor);
+ PRINT_VALUE (Ecx, Maximum_RMID_Range);
+ PRINT_BIT_FIELD (Edx, L3CacheOccupancyMonitoring);
+}
+
+/**
+ Display CPUID_PLATFORM_QOS_ENFORCEMENT sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosEnforcementResidSubLeaf (
+ VOID
+ )
+{
+ CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_EAX Eax;
+ UINT32 Ebx;
+ CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_ECX Ecx;
+ CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_EDX Edx;
+
+ AsmCpuidEx (
+ CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF,
+ &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx.Uint32
+ );
+ Print (L"CPUID_PLATFORM_QOS_ENFORCEMENT (Leaf %08x, Sub-Leaf %08x)\n", CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx, Ecx.Uint32, Edx.Uint32);
+ PRINT_BIT_FIELD (Eax, CapacityLength);
+ PRINT_VALUE (Ebx, AllocationUnitBitMap);
+ PRINT_BIT_FIELD (Ecx, CosUpdatesInfrequent);
+ PRINT_BIT_FIELD (Ecx, CodeDataPrioritization);
+ PRINT_BIT_FIELD (Edx, HighestCosNumber);
+}
+
+/**
+ Display CPUID_PLATFORM_QOS_ENFORCEMENT main leaf and sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosEnforcementMainLeaf (
+ VOID
+ )
+{
+ CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF_EBX Ebx;
+
+ if (CPUID_PLATFORM_QOS_ENFORCEMENT > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF,
+ NULL, &Ebx.Uint32, NULL, NULL
+ );
+ Print (L"CPUID_PLATFORM_QOS_ENFORCEMENT (Leaf %08x, Sub-Leaf %08x)\n", CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, Ebx.Uint32, 0, 0);
+ PRINT_BIT_FIELD (Ebx, L3CacheQosEnforcement);
+
+ CpuidPlatformQosEnforcementResidSubLeaf ();
+}
+
+/**
+ Display CPUID_INTEL_PROCESSOR_TRACE sub-leafs.
+
+ @param[in] MaximumSubLeaf Maximum sub-leaf index for CPUID_INTEL_PROCESSOR_TRACE.
+
+**/
+VOID
+CpuidIntelProcessorTraceSubLeaf (
+ UINT32 MaximumSubLeaf
+ )
+{
+ UINT32 SubLeaf;
+ CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EAX Eax;
+ CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EBX Ebx;
+
+ for (SubLeaf = CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF; SubLeaf <= MaximumSubLeaf; SubLeaf++) {
+ AsmCpuidEx (
+ CPUID_INTEL_PROCESSOR_TRACE, SubLeaf,
+ &Eax.Uint32, &Ebx.Uint32, NULL, NULL
+ );
+ Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_PROCESSOR_TRACE, SubLeaf);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, 0, 0);
+ PRINT_BIT_FIELD (Eax, ConfigurableAddressRanges);
+ PRINT_BIT_FIELD (Eax, MtcPeriodEncodings);
+ PRINT_BIT_FIELD (Ebx, CycleThresholdEncodings);
+ PRINT_BIT_FIELD (Ebx, PsbFrequencyEncodings);
+ }
+}
+
+/**
+ Display CPUID_INTEL_PROCESSOR_TRACE main leaf and sub-leafs.
+
+**/
+VOID
+CpuidIntelProcessorTraceMainLeaf (
+ VOID
+ )
+{
+ UINT32 Eax;
+ CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_EBX Ebx;
+ CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX Ecx;
+
+ if (CPUID_INTEL_PROCESSOR_TRACE > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF,
+ &Eax, &Ebx.Uint32, &Ecx.Uint32, NULL
+ );
+ Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx.Uint32, Ecx.Uint32, 0);
+ PRINT_VALUE (Eax, MaximumSubLeaf);
+ PRINT_BIT_FIELD (Ebx, Cr3Filter);
+ PRINT_BIT_FIELD (Ebx, ConfigurablePsb);
+ PRINT_BIT_FIELD (Ebx, IpTraceStopFiltering);
+ PRINT_BIT_FIELD (Ebx, Mtc);
+ PRINT_BIT_FIELD (Ecx, RTIT);
+ PRINT_BIT_FIELD (Ecx, ToPA);
+ PRINT_BIT_FIELD (Ecx, SingleRangeOutput);
+ PRINT_BIT_FIELD (Ecx, TraceTransportSubsystem);
+ PRINT_BIT_FIELD (Ecx, LIP);
+
+ CpuidIntelProcessorTraceSubLeaf (Eax);
+}
+
+/**
+ Display CPUID_TIME_STAMP_COUNTER leaf.
+
+**/
+VOID
+CpuidTimeStampCounter (
+ VOID
+ )
+{
+ UINT32 Eax;
+ UINT32 Ebx;
+
+ if (CPUID_TIME_STAMP_COUNTER > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_TIME_STAMP_COUNTER, &Eax, &Ebx, NULL, NULL);
+ Print (L"CPUID_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_TIME_STAMP_COUNTER);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, 0, 0);
+}
+
+/**
+ Display CPUID_PROCESSOR_FREQUENCY leaf.
+
+**/
+VOID
+CpuidProcessorFrequency (
+ VOID
+ )
+{
+ CPUID_PROCESSOR_FREQUENCY_EAX Eax;
+ CPUID_PROCESSOR_FREQUENCY_EBX Ebx;
+ CPUID_PROCESSOR_FREQUENCY_ECX Ecx;
+
+ if (CPUID_PROCESSOR_FREQUENCY > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_PROCESSOR_FREQUENCY, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, NULL);
+ Print (L"CPUID_PROCESSOR_FREQUENCY (Leaf %08x)\n", CPUID_PROCESSOR_FREQUENCY);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, 0);
+ PRINT_BIT_FIELD (Eax, ProcessorBaseFrequency);
+ PRINT_BIT_FIELD (Ebx, MaximumFrequency);
+ PRINT_BIT_FIELD (Ecx, BusFrequency);
+}
+
+/**
+ Display CPUID_SOC_VENDOR sub-leafs that contain the SoC Vendor Brand String.
+ Also display these sub-leafs as a single SoC Vendor Brand String.
+
+**/
+VOID
+CpuidSocVendorBrandString (
+ VOID
+ )
+{
+ CPUID_SOC_VENDOR_BRAND_STRING_DATA Eax;
+ CPUID_SOC_VENDOR_BRAND_STRING_DATA Ebx;
+ CPUID_SOC_VENDOR_BRAND_STRING_DATA Ecx;
+ CPUID_SOC_VENDOR_BRAND_STRING_DATA Edx;
+ //
+ // Array to store brand string from 3 brand string leafs with
+ // 4 32-bit brand string values per leaf and an extra value to
+ // null terminate the string.
+ //
+ UINT32 BrandString[3 * 4 + 1];
+
+ AsmCpuidEx (
+ CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING1,
+ &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+ );
+ Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING1);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[0] = Eax.Uint32;
+ BrandString[1] = Ebx.Uint32;
+ BrandString[2] = Ecx.Uint32;
+ BrandString[3] = Edx.Uint32;
+
+ AsmCpuidEx (
+ CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING2,
+ &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+ );
+ Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING2);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[4] = Eax.Uint32;
+ BrandString[5] = Ebx.Uint32;
+ BrandString[6] = Ecx.Uint32;
+ BrandString[7] = Edx.Uint32;
+
+ AsmCpuidEx (
+ CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING3,
+ &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+ );
+ Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING3);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[8] = Eax.Uint32;
+ BrandString[9] = Ebx.Uint32;
+ BrandString[10] = Ecx.Uint32;
+ BrandString[11] = Edx.Uint32;
+
+ BrandString[12] = 0;
+
+ Print (L"Vendor Brand String = %a\n", (CHAR8 *)BrandString);
+}
+
+/**
+ Display CPUID_SOC_VENDOR main leaf and sub-leafs.
+
+**/
+VOID
+CpuidSocVendor (
+ VOID
+ )
+{
+ UINT32 Eax;
+ CPUID_SOC_VENDOR_MAIN_LEAF_EBX Ebx;
+ UINT32 Ecx;
+ UINT32 Edx;
+
+ if (CPUID_SOC_VENDOR > gMaximumBasicFunction) {
+ return;
+ }
+
+ AsmCpuidEx (
+ CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_MAIN_LEAF,
+ &Eax, &Ebx.Uint32, &Ecx, &Edx
+ );
+ Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_MAIN_LEAF);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx.Uint32, Ecx, Edx);
+ if (Eax < 3) {
+ Print (L" Not Supported\n");
+ return;
+ }
+ PRINT_VALUE (Eax, MaxSOCID_Index);
+ PRINT_BIT_FIELD (Ebx, SocVendorId);
+ PRINT_BIT_FIELD (Ebx, IsVendorScheme);
+ PRINT_VALUE (Ecx, ProjectID);
+ PRINT_VALUE (Edx, SteppingID);
+ CpuidSocVendorBrandString ();
+}
+
+/**
+ Display CPUID_EXTENDED_FUNCTION leaf.
+
+**/
+VOID
+CpuidExtendedFunction (
+ VOID
+ )
+{
+ UINT32 Eax;
+
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
+ Print (L"CPUID_EXTENDED_FUNCTION (Leaf %08x)\n", CPUID_EXTENDED_FUNCTION);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, 0, 0);
+ PRINT_VALUE (Eax, MaximumExtendedFunction);
+
+ gMaximumExtendedFunction = Eax;
+}
+
+/**
+ Display CPUID_EXTENDED_CPU_SIG leaf.
+
+**/
+VOID
+CpuidExtendedCpuSig (
+ VOID
+ )
+{
+ UINT32 Eax;
+ CPUID_EXTENDED_CPU_SIG_ECX Ecx;
+ CPUID_EXTENDED_CPU_SIG_EDX Edx;
+
+ if (CPUID_EXTENDED_CPU_SIG > gMaximumExtendedFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, &Eax, NULL, &Ecx.Uint32, &Edx.Uint32);
+ Print (L"CPUID_EXTENDED_CPU_SIG (Leaf %08x)\n", CPUID_EXTENDED_CPU_SIG);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, 0, Ecx.Uint32, Edx.Uint32);
+ PRINT_BIT_FIELD (Ecx, LAHF_SAHF);
+ PRINT_BIT_FIELD (Ecx, LZCNT);
+ PRINT_BIT_FIELD (Ecx, PREFETCHW);
+ PRINT_BIT_FIELD (Edx, SYSCALL_SYSRET);
+ PRINT_BIT_FIELD (Edx, NX);
+ PRINT_BIT_FIELD (Edx, Page1GB);
+ PRINT_BIT_FIELD (Edx, RDTSCP);
+ PRINT_BIT_FIELD (Edx, LM);
+}
+
+/**
+ Display CPUID_BRAND_STRING1, CPUID_BRAND_STRING2 and CPUID_BRAND_STRING3
+ leafs. Also display these three leafs as a single brand string.
+
+**/
+VOID
+CpuidProcessorBrandString (
+ VOID
+ )
+{
+ CPUID_BRAND_STRING_DATA Eax;
+ CPUID_BRAND_STRING_DATA Ebx;
+ CPUID_BRAND_STRING_DATA Ecx;
+ CPUID_BRAND_STRING_DATA Edx;
+ //
+ // Array to store brand string from 3 brand string leafs with
+ // 4 32-bit brand string values per leaf and an extra value to
+ // null terminate the string.
+ //
+ UINT32 BrandString[3 * 4 + 1];
+
+ if (CPUID_BRAND_STRING1 <= gMaximumExtendedFunction) {
+ AsmCpuid (CPUID_BRAND_STRING1, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+ Print (L"CPUID_BRAND_STRING1 (Leaf %08x)\n", CPUID_BRAND_STRING1);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[0] = Eax.Uint32;
+ BrandString[1] = Ebx.Uint32;
+ BrandString[2] = Ecx.Uint32;
+ BrandString[3] = Edx.Uint32;
+ }
+
+ if (CPUID_BRAND_STRING2 <= gMaximumExtendedFunction) {
+ AsmCpuid (CPUID_BRAND_STRING2, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+ Print (L"CPUID_BRAND_STRING2 (Leaf %08x)\n", CPUID_BRAND_STRING2);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[4] = Eax.Uint32;
+ BrandString[5] = Ebx.Uint32;
+ BrandString[6] = Ecx.Uint32;
+ BrandString[7] = Edx.Uint32;
+ }
+
+ if (CPUID_BRAND_STRING3 <= gMaximumExtendedFunction) {
+ AsmCpuid (CPUID_BRAND_STRING3, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
+ Print (L"CPUID_BRAND_STRING3 (Leaf %08x)\n", CPUID_BRAND_STRING3);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+ BrandString[8] = Eax.Uint32;
+ BrandString[9] = Ebx.Uint32;
+ BrandString[10] = Ecx.Uint32;
+ BrandString[11] = Edx.Uint32;
+ }
+
+ BrandString[12] = 0;
+
+ Print (L"Brand String = %a\n", (CHAR8 *)BrandString);
+}
+
+/**
+ Display CPUID_EXTENDED_CACHE_INFO leaf.
+
+**/
+VOID
+CpuidExtendedCacheInfo (
+ VOID
+ )
+{
+ CPUID_EXTENDED_CACHE_INFO_ECX Ecx;
+
+ if (CPUID_EXTENDED_CACHE_INFO > gMaximumExtendedFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_EXTENDED_CACHE_INFO, NULL, NULL, &Ecx.Uint32, NULL);
+ Print (L"CPUID_EXTENDED_CACHE_INFO (Leaf %08x)\n", CPUID_EXTENDED_CACHE_INFO);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, 0, Ecx.Uint32, 0);
+ PRINT_BIT_FIELD (Ecx, CacheLineSize);
+ PRINT_BIT_FIELD (Ecx, L2Associativity);
+ PRINT_BIT_FIELD (Ecx, CacheSize);
+}
+
+/**
+ Display CPUID_EXTENDED_TIME_STAMP_COUNTER leaf.
+
+**/
+VOID
+CpuidExtendedTimeStampCounter (
+ VOID
+ )
+{
+ CPUID_EXTENDED_TIME_STAMP_COUNTER_EDX Edx;
+
+ if (CPUID_EXTENDED_TIME_STAMP_COUNTER > gMaximumExtendedFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_EXTENDED_TIME_STAMP_COUNTER, NULL, NULL, NULL, &Edx.Uint32);
+ Print (L"CPUID_EXTENDED_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_EXTENDED_TIME_STAMP_COUNTER);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", 0, 0, 0, Edx.Uint32);
+ PRINT_BIT_FIELD (Edx, InvariantTsc);
+}
+
+/**
+ Display CPUID_VIR_PHY_ADDRESS_SIZE leaf.
+
+**/
+VOID
+CpuidVirPhyAddressSize (
+ VOID
+ )
+{
+ CPUID_VIR_PHY_ADDRESS_SIZE_EAX Eax;
+
+ if (CPUID_VIR_PHY_ADDRESS_SIZE > gMaximumExtendedFunction) {
+ return;
+ }
+
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Eax.Uint32, NULL, NULL, NULL);
+ Print (L"CPUID_VIR_PHY_ADDRESS_SIZE (Leaf %08x)\n", CPUID_VIR_PHY_ADDRESS_SIZE);
+ Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, 0, 0, 0);
+ PRINT_BIT_FIELD (Eax, PhysicalAddressBits);
+ PRINT_BIT_FIELD (Eax, LinearAddressBits);
+}
+
+/**
+ The user Entry Point for Application. The user code starts with this function
+ as the real entry point for the application.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ Print (L"UEFI CPUID Version 0.5\n");
+
+ CpuidSignature ();
+ CpuidVersionInfo ();
+ CpuidCacheInfo ();
+ CpuidSerialNumber ();
+ CpuidCacheParams();
+ CpuidMonitorMwait ();
+ CpuidThermalPowerManagement ();
+ CpuidStructuredExtendedFeatureFlags ();
+ CpuidDirectCacheAccessInfo();
+ CpuidArchitecturalPerformanceMonitoring ();
+ CpuidExtendedTopology ();
+ CpuidExtendedStateMainLeaf ();
+ CpuidPlatformQosMonitoringEnumerationSubLeaf ();
+ CpuidPlatformQosMonitoringCapabilitySubLeaf ();
+ CpuidPlatformQosEnforcementMainLeaf ();
+ CpuidIntelProcessorTraceMainLeaf ();
+ CpuidTimeStampCounter ();
+ CpuidProcessorFrequency ();
+ CpuidSocVendor ();
+ CpuidExtendedFunction ();
+ CpuidExtendedCpuSig ();
+ CpuidProcessorBrandString ();
+ CpuidExtendedCacheInfo ();
+ CpuidExtendedTimeStampCounter ();
+ CpuidVirPhyAddressSize ();
+
+ return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.inf b/UefiCpuPkg/Application/Cpuid/Cpuid.inf
new file mode 100644
index 0000000000..0d71b115d9
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.inf
@@ -0,0 +1,48 @@
+## @file
+# UEFI Application to display CPUID leaf information.
+#
+# This UEFI application displays the registers values returned by CPUID for
+# all the CPUID leafs and sub-leafs that a CPU supports. It also displays
+# the values of all the bit fields in the registers returned by each CPUID
+# leaf and sub-leaf.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Cpuid
+ MODULE_UNI_FILE = Cpuid.uni
+ FILE_GUID = 4AE7E1E8-9DFE-4e3e-85B4-A5F6ABD470FB
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 0.5
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ Cpuid.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ UefiApplicationEntryPoint
+ BaseLib
+ UefiLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ CpuidExtra.uni
diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.uni b/UefiCpuPkg/Application/Cpuid/Cpuid.uni
new file mode 100644
index 0000000000..32dee43414
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.uni
@@ -0,0 +1,22 @@
+// /** @file
+// UEFI Application to display CPUID leaf information.
+//
+// This UEFI application displays the registers values returned by CPUID for
+// all the CPUID leafs and sub-leafs that a CPU supports. It also displays
+// the values of all the bit fields in the registers returned by each CPUID
+// leaf and sub-leaf.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "UEFI Application to display CPUID leaf information"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This UEFI application displays the registers values returned by CPUID for all the CPUID leafs and sub-leafs that a CPU supports. It also displays the values of all the bit fields in the registers returned by each CPUID leaf and sub-leaf."
diff --git a/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni b/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni
new file mode 100644
index 0000000000..b4251e23cc
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni
@@ -0,0 +1,22 @@
+// /** @file
+// UEFI Application to display CPUID leaf information.
+//
+// This UEFI application displays the registers values returned by CPUID for
+// all the CPUID leafs and sub-leafs that a CPU supports. It also displays
+// the values of all the bit fields in the registers returned by each CPUID
+// leaf and sub-leaf.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"CPUID Application"
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 31e60bbe77..731915286c 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -88,6 +88,10 @@
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+[LibraryClasses.common.UEFI_APPLICATION]
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
#
# Drivers/Libraries within this package
#
@@ -96,6 +100,7 @@
UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
UefiCpuPkg/CpuIoPei/CpuIoPei.inf
UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
+ UefiCpuPkg/Application/Cpuid/Cpuid.inf
[Components.IA32, Components.X64]
UefiCpuPkg/CpuDxe/CpuDxe.inf