audk/UefiCpuPkg/Application/Cpuid/Cpuid.c

1466 lines
51 KiB
C

/** @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];
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;
UINT32 DisplayFamily;
UINT32 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, SGX);
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);
}
}
}
/**
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 Sub-Leaf 0 Enumeration of Intel SGX Capabilities.
**/
VOID
CpuidEnumerationOfIntelSgxCapabilities0SubLeaf (
VOID
)
{
CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF_EAX Eax;
UINT32 Ebx;
CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF_EDX Edx;
AsmCpuidEx (
CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF,
&Eax.Uint32, &Ebx, NULL, &Edx.Uint32
);
Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF);
Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx, 0, Edx.Uint32);
PRINT_BIT_FIELD (Eax, SGX1);
PRINT_BIT_FIELD (Eax, SGX2);
PRINT_BIT_FIELD (Edx, MaxEnclaveSize_Not64);
PRINT_BIT_FIELD (Edx, MaxEnclaveSize_64);
}
/**
Display Sub-Leaf 1 Enumeration of Intel SGX Capabilities.
**/
VOID
CpuidEnumerationOfIntelSgxCapabilities1SubLeaf (
VOID
)
{
UINT32 Eax;
UINT32 Ebx;
UINT32 Ecx;
UINT32 Edx;
AsmCpuidEx (
CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_1_SUB_LEAF,
&Eax, &Ebx, &Ecx, &Edx
);
Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_1_SUB_LEAF);
Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax, Ebx, Ecx, Edx);
}
/**
Display Sub-Leaf Index 2 or Higher Enumeration of Intel SGX Resources.
**/
VOID
CpuidEnumerationOfIntelSgxResourcesSubLeaf (
VOID
)
{
CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EAX Eax;
CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EBX Ebx;
CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_ECX Ecx;
CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EDX Edx;
UINT32 SubLeaf;
SubLeaf = CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF;
do {
AsmCpuidEx (
CPUID_INTEL_SGX, SubLeaf,
&Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
);
if (Eax.Bits.SubLeafType == 0x1) {
Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, SubLeaf);
Print (L" EAX:%08x EBX:%08x ECX:%08x EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
PRINT_BIT_FIELD (Eax, SubLeafType);
PRINT_BIT_FIELD (Eax, LowAddressOfEpcSection);
PRINT_BIT_FIELD (Ebx, HighAddressOfEpcSection);
PRINT_BIT_FIELD (Ecx, EpcSection);
PRINT_BIT_FIELD (Ecx, LowSizeOfEpcSection);
PRINT_BIT_FIELD (Edx, HighSizeOfEpcSection);
}
SubLeaf++;
} while (Eax.Bits.SubLeafType == 0x1);
}
/**
Display Intel SGX Resource Enumeration.
**/
VOID
CpuidEnumerationOfIntelSgx (
VOID
)
{
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX Ebx;
if (CPUID_INTEL_SGX > gMaximumBasicFunction) {
return;
}
AsmCpuidEx (
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
NULL, &Ebx.Uint32, NULL, NULL
);
if (Ebx.Bits.SGX != 1) {
//
// Only if CPUID.(EAX=07H, ECX=0H):EBX.SGX = 1, the processor has support
// for Intel SGX.
//
return;
}
CpuidEnumerationOfIntelSgxCapabilities0SubLeaf ();
CpuidEnumerationOfIntelSgxCapabilities1SubLeaf ();
CpuidEnumerationOfIntelSgxResourcesSubLeaf ();
}
/**
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 ();
CpuidEnumerationOfIntelSgx ();
CpuidIntelProcessorTraceMainLeaf ();
CpuidTimeStampCounter ();
CpuidProcessorFrequency ();
CpuidSocVendor ();
CpuidExtendedFunction ();
CpuidExtendedCpuSig ();
CpuidProcessorBrandString ();
CpuidExtendedCacheInfo ();
CpuidExtendedTimeStampCounter ();
CpuidVirPhyAddressSize ();
return EFI_SUCCESS;
}