Home | History | Annotate | Download | only in Cpuid
      1 /** @file
      2   UEFI Application to display CPUID leaf information.
      3 
      4   Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include <Uefi.h>
     16 #include <Library/BaseLib.h>
     17 #include <Library/UefiLib.h>
     18 #include <Register/Cpuid.h>
     19 
     20 ///
     21 /// Macro used to display the value of a bit field in a register returned by CPUID.
     22 ///
     23 #define PRINT_BIT_FIELD(Variable, FieldName) \
     24   Print (L"%5a%42a: %x\n", #Variable, #FieldName, Variable.Bits.FieldName);
     25 
     26 ///
     27 /// Macro used to display the value of a register returned by CPUID.
     28 ///
     29 #define PRINT_VALUE(Variable, Description) \
     30   Print (L"%5a%42a: %x\n", #Variable, #Description, Variable);
     31 
     32 ///
     33 /// Structure for cache description lookup table
     34 ///
     35 typedef struct {
     36   UINT8  CacheDescriptor;
     37   CHAR8  *Type;
     38   CHAR8  *Description;
     39 } CPUID_CACHE_INFO_DESCRIPTION;
     40 
     41 ///
     42 /// Cache description lookup table
     43 ///
     44 CPUID_CACHE_INFO_DESCRIPTION  mCpuidCacheInfoDescription[] = {
     45   { 0x00 , "General"  , "Null descriptor, this byte contains no information" },
     46   { 0x01 , "TLB"      , "Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries" },
     47   { 0x02 , "TLB"      , "Instruction TLB: 4 MByte pages, fully associative, 2 entries" },
     48   { 0x03 , "TLB"      , "Data TLB: 4 KByte pages, 4-way set associative, 64 entries" },
     49   { 0x04 , "TLB"      , "Data TLB: 4 MByte pages, 4-way set associative, 8 entries" },
     50   { 0x05 , "TLB"      , "Data TLB1: 4 MByte pages, 4-way set associative, 32 entries" },
     51   { 0x06 , "Cache"    , "1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size" },
     52   { 0x08 , "Cache"    , "1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size" },
     53   { 0x09 , "Cache"    , "1st-level instruction cache: 32KBytes, 4-way set associative, 64 byte line size" },
     54   { 0x0A , "Cache"    , "1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size" },
     55   { 0x0B , "TLB"      , "Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries" },
     56   { 0x0C , "Cache"    , "1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size" },
     57   { 0x0D , "Cache"    , "1st-level data cache: 16 KBytes, 4-way set associative, 64 byte line size" },
     58   { 0x0E , "Cache"    , "1st-level data cache: 24 KBytes, 6-way set associative, 64 byte line size" },
     59   { 0x1D , "Cache"    , "2nd-level cache: 128 KBytes, 2-way set associative, 64 byte line size" },
     60   { 0x21 , "Cache"    , "2nd-level cache: 256 KBytes, 8-way set associative, 64 byte line size" },
     61   { 0x22 , "Cache"    , "3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector" },
     62   { 0x23 , "Cache"    , "3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
     63   { 0x24 , "Cache"    , "2nd-level cache: 1 MBytes, 16-way set associative, 64 byte line size" },
     64   { 0x25 , "Cache"    , "3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
     65   { 0x29 , "Cache"    , "3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector" },
     66   { 0x2C , "Cache"    , "1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size" },
     67   { 0x30 , "Cache"    , "1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size" },
     68   { 0x40 , "Cache"    , "No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache" },
     69   { 0x41 , "Cache"    , "2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size" },
     70   { 0x42 , "Cache"    , "2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size" },
     71   { 0x43 , "Cache"    , "2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size" },
     72   { 0x44 , "Cache"    , "2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size" },
     73   { 0x45 , "Cache"    , "2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size" },
     74   { 0x46 , "Cache"    , "3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size" },
     75   { 0x47 , "Cache"    , "3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size" },
     76   { 0x48 , "Cache"    , "2nd-level cache: 3MByte, 12-way set associative, 64 byte line size" },
     77   { 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" },
     78   { 0x4A , "Cache"    , "3rd-level cache: 6MByte, 12-way set associative, 64 byte line size" },
     79   { 0x4B , "Cache"    , "3rd-level cache: 8MByte, 16-way set associative, 64 byte line size" },
     80   { 0x4C , "Cache"    , "3rd-level cache: 12MByte, 12-way set associative, 64 byte line size" },
     81   { 0x4D , "Cache"    , "3rd-level cache: 16MByte, 16-way set associative, 64 byte line size" },
     82   { 0x4E , "Cache"    , "2nd-level cache: 6MByte, 24-way set associative, 64 byte line size" },
     83   { 0x4F , "TLB"      , "Instruction TLB: 4 KByte pages, 32 entries" },
     84   { 0x50 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries" },
     85   { 0x51 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries" },
     86   { 0x52 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries" },
     87   { 0x55 , "TLB"      , "Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries" },
     88   { 0x56 , "TLB"      , "Data TLB0: 4 MByte pages, 4-way set associative, 16 entries" },
     89   { 0x57 , "TLB"      , "Data TLB0: 4 KByte pages, 4-way associative, 16 entries" },
     90   { 0x59 , "TLB"      , "Data TLB0: 4 KByte pages, fully associative, 16 entries" },
     91   { 0x5A , "TLB"      , "Data TLB0: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries" },
     92   { 0x5B , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages, 64 entries" },
     93   { 0x5C , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages,128 entries" },
     94   { 0x5D , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages,256 entries" },
     95   { 0x60 , "Cache"    , "1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size" },
     96   { 0x61 , "TLB"      , "Instruction TLB: 4 KByte pages, fully associative, 48 entries" },
     97   { 0x63 , "TLB"      , "Data TLB: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries and a separate array with 1 GByte pages, 4-way set associative, 4 entries" },
     98   { 0x64 , "TLB"      , "Data TLB: 4 KByte pages, 4-way set associative, 512 entries" },
     99   { 0x66 , "Cache"    , "1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size" },
    100   { 0x67 , "Cache"    , "1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size" },
    101   { 0x68 , "Cache"    , "1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size" },
    102   { 0x6A , "Cache"    , "uTLB: 4 KByte pages, 8-way set associative, 64 entries" },
    103   { 0x6B , "Cache"    , "DTLB: 4 KByte pages, 8-way set associative, 256 entries" },
    104   { 0x6C , "Cache"    , "DTLB: 2M/4M pages, 8-way set associative, 128 entries" },
    105   { 0x6D , "Cache"    , "DTLB: 1 GByte pages, fully associative, 16 entries" },
    106   { 0x70 , "Cache"    , "Trace cache: 12 K-uop, 8-way set associative" },
    107   { 0x71 , "Cache"    , "Trace cache: 16 K-uop, 8-way set associative" },
    108   { 0x72 , "Cache"    , "Trace cache: 32 K-uop, 8-way set associative" },
    109   { 0x76 , "TLB"      , "Instruction TLB: 2M/4M pages, fully associative, 8 entries" },
    110   { 0x78 , "Cache"    , "2nd-level cache: 1 MByte, 4-way set associative, 64byte line size" },
    111   { 0x79 , "Cache"    , "2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
    112   { 0x7A , "Cache"    , "2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
    113   { 0x7B , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
    114   { 0x7C , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector" },
    115   { 0x7D , "Cache"    , "2nd-level cache: 2 MByte, 8-way set associative, 64byte line size" },
    116   { 0x7F , "Cache"    , "2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size" },
    117   { 0x80 , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 64-byte line size" },
    118   { 0x82 , "Cache"    , "2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size" },
    119   { 0x83 , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size" },
    120   { 0x84 , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size" },
    121   { 0x85 , "Cache"    , "2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size" },
    122   { 0x86 , "Cache"    , "2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size" },
    123   { 0x87 , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size" },
    124   { 0xA0 , "DTLB"     , "DTLB: 4k pages, fully associative, 32 entries" },
    125   { 0xB0 , "TLB"      , "Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries" },
    126   { 0xB1 , "TLB"      , "Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries" },
    127   { 0xB2 , "TLB"      , "Instruction TLB: 4KByte pages, 4-way set associative, 64 entries" },
    128   { 0xB3 , "TLB"      , "Data TLB: 4 KByte pages, 4-way set associative, 128 entries" },
    129   { 0xB4 , "TLB"      , "Data TLB1: 4 KByte pages, 4-way associative, 256 entries" },
    130   { 0xB5 , "TLB"      , "Instruction TLB: 4KByte pages, 8-way set associative, 64 entries" },
    131   { 0xB6 , "TLB"      , "Instruction TLB: 4KByte pages, 8-way set associative, 128 entries" },
    132   { 0xBA , "TLB"      , "Data TLB1: 4 KByte pages, 4-way associative, 64 entries" },
    133   { 0xC0 , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages, 4-way associative, 8 entries" },
    134   { 0xC1 , "STLB"     , "Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries" },
    135   { 0xC2 , "DTLB"     , "DTLB: 4 KByte/2 MByte pages, 4-way associative, 16 entries" },
    136   { 0xC3 , "STLB"     , "Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries." },
    137   { 0xC4 , "DTLB"     , "DTLB: 2M/4M Byte pages, 4-way associative, 32 entries" },
    138   { 0xCA , "STLB"     , "Shared 2nd-Level TLB: 4 KByte pages, 4-way associative, 512 entries" },
    139   { 0xD0 , "Cache"    , "3rd-level cache: 512 KByte, 4-way set associative, 64 byte line size" },
    140   { 0xD1 , "Cache"    , "3rd-level cache: 1 MByte, 4-way set associative, 64 byte line size" },
    141   { 0xD2 , "Cache"    , "3rd-level cache: 2 MByte, 4-way set associative, 64 byte line size" },
    142   { 0xD6 , "Cache"    , "3rd-level cache: 1 MByte, 8-way set associative, 64 byte line size" },
    143   { 0xD7 , "Cache"    , "3rd-level cache: 2 MByte, 8-way set associative, 64 byte line size" },
    144   { 0xD8 , "Cache"    , "3rd-level cache: 4 MByte, 8-way set associative, 64 byte line size" },
    145   { 0xDC , "Cache"    , "3rd-level cache: 1.5 MByte, 12-way set associative, 64 byte line size" },
    146   { 0xDD , "Cache"    , "3rd-level cache: 3 MByte, 12-way set associative, 64 byte line size" },
    147   { 0xDE , "Cache"    , "3rd-level cache: 6 MByte, 12-way set associative, 64 byte line size" },
    148   { 0xE2 , "Cache"    , "3rd-level cache: 2 MByte, 16-way set associative, 64 byte line size" },
    149   { 0xE3 , "Cache"    , "3rd-level cache: 4 MByte, 16-way set associative, 64 byte line size" },
    150   { 0xE4 , "Cache"    , "3rd-level cache: 8 MByte, 16-way set associative, 64 byte line size" },
    151   { 0xEA , "Cache"    , "3rd-level cache: 12MByte, 24-way set associative, 64 byte line size" },
    152   { 0xEB , "Cache"    , "3rd-level cache: 18MByte, 24-way set associative, 64 byte line size" },
    153   { 0xEC , "Cache"    , "3rd-level cache: 24MByte, 24-way set associative, 64 byte line size" },
    154   { 0xF0 , "Prefetch" , "64-Byte prefetching" },
    155   { 0xF1 , "Prefetch" , "128-Byte prefetching" },
    156   { 0xFF , "General"  , "CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters" }
    157 };
    158 
    159 ///
    160 /// The maximum supported CPUID leaf index starting from leaf 0x00000000.
    161 ///
    162 UINT32  gMaximumBasicFunction    = CPUID_SIGNATURE;
    163 
    164 ///
    165 /// The maximum supported CPUID leaf index starting from leaf 0x80000000.
    166 ///
    167 UINT32  gMaximumExtendedFunction = CPUID_EXTENDED_FUNCTION;
    168 
    169 /**
    170   Display CPUID_SIGNATURE leaf.
    171 
    172 **/
    173 VOID
    174 CpuidSignature (
    175   VOID
    176   )
    177 {
    178   UINT32 Eax;
    179   UINT32 Ebx;
    180   UINT32 Ecx;
    181   UINT32 Edx;
    182   CHAR8  Signature[13];
    183 
    184   AsmCpuid (CPUID_SIGNATURE, &Eax, &Ebx, &Ecx, &Edx);
    185 
    186   Print (L"CPUID_SIGNATURE (Leaf %08x)\n", CPUID_SIGNATURE);
    187   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, Ecx, Edx);
    188   PRINT_VALUE (Eax, MaximumLeaf);
    189   *(UINT32 *)(Signature + 0) = Ebx;
    190   *(UINT32 *)(Signature + 4) = Edx;
    191   *(UINT32 *)(Signature + 8) = Ecx;
    192   Signature [12] = 0;
    193   Print (L"  Signature = %a\n", Signature);
    194 
    195   gMaximumBasicFunction = Eax;
    196 }
    197 
    198 /**
    199   Display CPUID_VERSION_INFO leaf.
    200 
    201 **/
    202 VOID
    203 CpuidVersionInfo (
    204   VOID
    205   )
    206 {
    207   CPUID_VERSION_INFO_EAX  Eax;
    208   CPUID_VERSION_INFO_EBX  Ebx;
    209   CPUID_VERSION_INFO_ECX  Ecx;
    210   CPUID_VERSION_INFO_EDX  Edx;
    211   UINT32                  DisplayFamily;
    212   UINT32                  DisplayModel;
    213 
    214   if (CPUID_VERSION_INFO > gMaximumBasicFunction) {
    215     return;
    216   }
    217 
    218   AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
    219 
    220   Print (L"CPUID_VERSION_INFO (Leaf %08x)\n", CPUID_VERSION_INFO);
    221   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
    222 
    223   DisplayFamily = Eax.Bits.FamilyId;
    224   if (Eax.Bits.FamilyId == 0x0F) {
    225     DisplayFamily |= (Eax.Bits.ExtendedFamilyId << 4);
    226   }
    227 
    228   DisplayModel = Eax.Bits.Model;
    229   if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
    230     DisplayModel |= (Eax.Bits.ExtendedModelId << 4);
    231   }
    232 
    233   Print (L"  Family = %x  Model = %x  Stepping = %x\n", DisplayFamily, DisplayModel, Eax.Bits.SteppingId);
    234 
    235   PRINT_BIT_FIELD (Eax, SteppingId);
    236   PRINT_BIT_FIELD (Eax, Model);
    237   PRINT_BIT_FIELD (Eax, FamilyId);
    238   PRINT_BIT_FIELD (Eax, ProcessorType);
    239   PRINT_BIT_FIELD (Eax, ExtendedModelId);
    240   PRINT_BIT_FIELD (Eax, ExtendedFamilyId);
    241   PRINT_BIT_FIELD (Ebx, BrandIndex);
    242   PRINT_BIT_FIELD (Ebx, CacheLineSize);
    243   PRINT_BIT_FIELD (Ebx, MaximumAddressableIdsForLogicalProcessors);
    244   PRINT_BIT_FIELD (Ebx, InitialLocalApicId);
    245   PRINT_BIT_FIELD (Ecx, SSE3);
    246   PRINT_BIT_FIELD (Ecx, PCLMULQDQ);
    247   PRINT_BIT_FIELD (Ecx, DTES64);
    248   PRINT_BIT_FIELD (Ecx, MONITOR);
    249   PRINT_BIT_FIELD (Ecx, DS_CPL);
    250   PRINT_BIT_FIELD (Ecx, VMX);
    251   PRINT_BIT_FIELD (Ecx, SMX);
    252   PRINT_BIT_FIELD (Ecx, TM2);
    253   PRINT_BIT_FIELD (Ecx, SSSE3);
    254   PRINT_BIT_FIELD (Ecx, CNXT_ID);
    255   PRINT_BIT_FIELD (Ecx, SDBG);
    256   PRINT_BIT_FIELD (Ecx, FMA);
    257   PRINT_BIT_FIELD (Ecx, CMPXCHG16B);
    258   PRINT_BIT_FIELD (Ecx, xTPR_Update_Control);
    259   PRINT_BIT_FIELD (Ecx, PDCM);
    260   PRINT_BIT_FIELD (Ecx, PCID);
    261   PRINT_BIT_FIELD (Ecx, DCA);
    262   PRINT_BIT_FIELD (Ecx, SSE4_1);
    263   PRINT_BIT_FIELD (Ecx, SSE4_2);
    264   PRINT_BIT_FIELD (Ecx, x2APIC);
    265   PRINT_BIT_FIELD (Ecx, MOVBE);
    266   PRINT_BIT_FIELD (Ecx, POPCNT);
    267   PRINT_BIT_FIELD (Ecx, TSC_Deadline);
    268   PRINT_BIT_FIELD (Ecx, AESNI);
    269   PRINT_BIT_FIELD (Ecx, XSAVE);
    270   PRINT_BIT_FIELD (Ecx, OSXSAVE);
    271   PRINT_BIT_FIELD (Ecx, AVX);
    272   PRINT_BIT_FIELD (Ecx, F16C);
    273   PRINT_BIT_FIELD (Ecx, RDRAND);
    274   PRINT_BIT_FIELD (Edx, FPU);
    275   PRINT_BIT_FIELD (Edx, VME);
    276   PRINT_BIT_FIELD (Edx, DE);
    277   PRINT_BIT_FIELD (Edx, PSE);
    278   PRINT_BIT_FIELD (Edx, TSC);
    279   PRINT_BIT_FIELD (Edx, MSR);
    280   PRINT_BIT_FIELD (Edx, PAE);
    281   PRINT_BIT_FIELD (Edx, MCE);
    282   PRINT_BIT_FIELD (Edx, CX8);
    283   PRINT_BIT_FIELD (Edx, APIC);
    284   PRINT_BIT_FIELD (Edx, SEP);
    285   PRINT_BIT_FIELD (Edx, MTRR);
    286   PRINT_BIT_FIELD (Edx, PGE);
    287   PRINT_BIT_FIELD (Edx, MCA);
    288   PRINT_BIT_FIELD (Edx, CMOV);
    289   PRINT_BIT_FIELD (Edx, PAT);
    290   PRINT_BIT_FIELD (Edx, PSE_36);
    291   PRINT_BIT_FIELD (Edx, PSN);
    292   PRINT_BIT_FIELD (Edx, CLFSH);
    293   PRINT_BIT_FIELD (Edx, DS);
    294   PRINT_BIT_FIELD (Edx, ACPI);
    295   PRINT_BIT_FIELD (Edx, MMX);
    296   PRINT_BIT_FIELD (Edx, FXSR);
    297   PRINT_BIT_FIELD (Edx, SSE);
    298   PRINT_BIT_FIELD (Edx, SSE2);
    299   PRINT_BIT_FIELD (Edx, SS);
    300   PRINT_BIT_FIELD (Edx, HTT);
    301   PRINT_BIT_FIELD (Edx, TM);
    302   PRINT_BIT_FIELD (Edx, PBE);
    303 }
    304 
    305 /**
    306   Lookup a cache description string from the mCpuidCacheInfoDescription table.
    307 
    308   @param[in] CacheDescriptor  Cache descriptor value from CPUID_CACHE_INFO.
    309 
    310 **/
    311 CPUID_CACHE_INFO_DESCRIPTION *
    312 LookupCacheDescription (
    313   UINT8  CacheDescriptor
    314   )
    315 {
    316   UINTN  NumDescriptors;
    317   UINTN  Descriptor;
    318 
    319   if (CacheDescriptor == 0x00) {
    320     return NULL;
    321   }
    322   NumDescriptors = sizeof (mCpuidCacheInfoDescription)/sizeof (mCpuidCacheInfoDescription[0]);
    323   for (Descriptor = 0; Descriptor < NumDescriptors; Descriptor++) {
    324     if (CacheDescriptor == mCpuidCacheInfoDescription[Descriptor].CacheDescriptor) {
    325       return &mCpuidCacheInfoDescription[Descriptor];
    326     }
    327   }
    328   return NULL;
    329 }
    330 
    331 /**
    332   Display CPUID_CACHE_INFO leaf for each supported cache descriptor.
    333 
    334 **/
    335 VOID
    336 CpuidCacheInfo (
    337   VOID
    338   )
    339 {
    340   CPUID_CACHE_INFO_CACHE_TLB    Eax;
    341   CPUID_CACHE_INFO_CACHE_TLB    Ebx;
    342   CPUID_CACHE_INFO_CACHE_TLB    Ecx;
    343   CPUID_CACHE_INFO_CACHE_TLB    Edx;
    344   UINTN                         Index;
    345   CPUID_CACHE_INFO_DESCRIPTION  *CacheDescription;
    346 
    347   if (CPUID_CACHE_INFO > gMaximumBasicFunction) {
    348     return;
    349   }
    350 
    351   AsmCpuid (CPUID_CACHE_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
    352 
    353   Print (L"CPUID_CACHE_INFO (Leaf %08x)\n", CPUID_CACHE_INFO);
    354   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
    355   if (Eax.Bits.NotValid == 0) {
    356     //
    357     // Process Eax.CacheDescriptor[1..3].  Ignore Eax.CacheDescriptor[0]
    358     //
    359     for (Index = 1; Index < 4; Index++) {
    360       CacheDescription = LookupCacheDescription (Eax.CacheDescriptor[Index]);
    361       if (CacheDescription != NULL) {
    362         Print (L"  %-8a %a\n",
    363           CacheDescription->Type,
    364           CacheDescription->Description
    365           );
    366       }
    367     }
    368   }
    369   if (Ebx.Bits.NotValid == 0) {
    370     //
    371     // Process Ebx.CacheDescriptor[0..3]
    372     //
    373     for (Index = 0; Index < 4; Index++) {
    374       CacheDescription = LookupCacheDescription (Ebx.CacheDescriptor[Index]);
    375       if (CacheDescription != NULL) {
    376         Print (L"  %-8a %a\n",
    377           CacheDescription->Type,
    378           CacheDescription->Description
    379           );
    380       }
    381     }
    382   }
    383   if (Ecx.Bits.NotValid == 0) {
    384     //
    385     // Process Ecx.CacheDescriptor[0..3]
    386     //
    387     for (Index = 0; Index < 4; Index++) {
    388       CacheDescription = LookupCacheDescription (Ecx.CacheDescriptor[Index]);
    389       if (CacheDescription != NULL) {
    390         Print (L"  %-8a %a\n",
    391           CacheDescription->Type,
    392           CacheDescription->Description
    393           );
    394       }
    395     }
    396   }
    397   if (Edx.Bits.NotValid == 0) {
    398     //
    399     // Process Edx.CacheDescriptor[0..3]
    400     //
    401     for (Index = 0; Index < 4; Index++) {
    402       CacheDescription = LookupCacheDescription (Edx.CacheDescriptor[Index]);
    403       if (CacheDescription != NULL) {
    404         Print (L"  %-8a %a\n",
    405           CacheDescription->Type,
    406           CacheDescription->Description
    407           );
    408       }
    409     }
    410   }
    411 }
    412 
    413 /**
    414   Display CPUID_SERIAL_NUMBER leaf if it is supported.
    415 
    416 **/
    417 VOID
    418 CpuidSerialNumber (
    419   VOID
    420   )
    421 {
    422   CPUID_VERSION_INFO_EDX  VersionInfoEdx;
    423   UINT32                  Ecx;
    424   UINT32                  Edx;
    425 
    426   Print (L"CPUID_SERIAL_NUMBER (Leaf %08x)\n", CPUID_SERIAL_NUMBER);
    427 
    428   if (CPUID_SERIAL_NUMBER > gMaximumBasicFunction) {
    429     return;
    430   }
    431 
    432   AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
    433   if (VersionInfoEdx.Bits.PSN == 0) {
    434     Print (L"  Not Supported\n");
    435     return;
    436   }
    437 
    438   AsmCpuid (CPUID_SERIAL_NUMBER, NULL, NULL, &Ecx, &Edx);
    439   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, Ecx, Edx);
    440   Print (L"  Processor Serial Number = %08x%08x%08x\n", 0, Edx, Ecx);
    441 }
    442 
    443 /**
    444   Display CPUID_CACHE_PARAMS for all supported sub-leafs.
    445 
    446 **/
    447 VOID
    448 CpuidCacheParams (
    449   VOID
    450   )
    451 {
    452   UINT32                  CacheLevel;
    453   CPUID_CACHE_PARAMS_EAX  Eax;
    454   CPUID_CACHE_PARAMS_EBX  Ebx;
    455   UINT32                  Ecx;
    456   CPUID_CACHE_PARAMS_EDX  Edx;
    457 
    458   if (CPUID_CACHE_PARAMS > gMaximumBasicFunction) {
    459     return;
    460   }
    461 
    462   CacheLevel = 0;
    463   do {
    464     AsmCpuidEx (
    465       CPUID_CACHE_PARAMS, CacheLevel,
    466       &Eax.Uint32, &Ebx.Uint32, &Ecx, &Edx.Uint32
    467       );
    468     if (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL) {
    469       Print (L"CPUID_CACHE_PARAMS (Leaf %08x, Sub-Leaf %08x)\n", CPUID_CACHE_PARAMS, CacheLevel);
    470       Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx, Edx.Uint32);
    471       PRINT_BIT_FIELD (Eax, CacheType);
    472       PRINT_BIT_FIELD (Eax, CacheLevel);
    473       PRINT_BIT_FIELD (Eax, SelfInitializingCache);
    474       PRINT_BIT_FIELD (Eax, FullyAssociativeCache);
    475       PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForLogicalProcessors);
    476       PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForProcessorCores);
    477       PRINT_BIT_FIELD (Ebx, LineSize);
    478       PRINT_BIT_FIELD (Ebx, LinePartitions);
    479       PRINT_BIT_FIELD (Ebx, Ways);
    480       PRINT_VALUE     (Ecx, NumberOfSets);
    481       PRINT_BIT_FIELD (Edx, Invalidate);
    482       PRINT_BIT_FIELD (Edx, CacheInclusiveness);
    483       PRINT_BIT_FIELD (Edx, ComplexCacheIndexing);
    484     }
    485     CacheLevel++;
    486   } while (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL);
    487 }
    488 
    489 /**
    490   Display CPUID_MONITOR_MWAIT leaf.
    491 
    492 **/
    493 VOID
    494 CpuidMonitorMwait (
    495   VOID
    496   )
    497 {
    498   CPUID_MONITOR_MWAIT_EAX  Eax;
    499   CPUID_MONITOR_MWAIT_EBX  Ebx;
    500   CPUID_MONITOR_MWAIT_ECX  Ecx;
    501   CPUID_MONITOR_MWAIT_EDX  Edx;
    502 
    503   if (CPUID_MONITOR_MWAIT > gMaximumBasicFunction) {
    504     return;
    505   }
    506 
    507   AsmCpuid (CPUID_MONITOR_MWAIT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
    508 
    509   Print (L"CPUID_MONITOR_MWAIT (Leaf %08x)\n", CPUID_MONITOR_MWAIT);
    510   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
    511 
    512   PRINT_BIT_FIELD (Eax, SmallestMonitorLineSize);
    513   PRINT_BIT_FIELD (Ebx, LargestMonitorLineSize);
    514   PRINT_BIT_FIELD (Ecx, ExtensionsSupported);
    515   PRINT_BIT_FIELD (Ecx, InterruptAsBreak);
    516   PRINT_BIT_FIELD (Edx, C0States);
    517   PRINT_BIT_FIELD (Edx, C1States);
    518   PRINT_BIT_FIELD (Edx, C2States);
    519   PRINT_BIT_FIELD (Edx, C3States);
    520   PRINT_BIT_FIELD (Edx, C4States);
    521   PRINT_BIT_FIELD (Edx, C5States);
    522   PRINT_BIT_FIELD (Edx, C6States);
    523   PRINT_BIT_FIELD (Edx, C7States);
    524 }
    525 
    526 /**
    527   Display CPUID_THERMAL_POWER_MANAGEMENT leaf.
    528 
    529 **/
    530 VOID
    531 CpuidThermalPowerManagement (
    532   VOID
    533   )
    534 {
    535   CPUID_THERMAL_POWER_MANAGEMENT_EAX  Eax;
    536   CPUID_THERMAL_POWER_MANAGEMENT_EBX  Ebx;
    537   CPUID_THERMAL_POWER_MANAGEMENT_ECX  Ecx;
    538 
    539   if (CPUID_THERMAL_POWER_MANAGEMENT > gMaximumBasicFunction) {
    540     return;
    541   }
    542 
    543   AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, NULL);
    544 
    545   Print (L"CPUID_THERMAL_POWER_MANAGEMENT (Leaf %08x)\n", CPUID_THERMAL_POWER_MANAGEMENT);
    546   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, 0);
    547 
    548   PRINT_BIT_FIELD (Eax, DigitalTemperatureSensor);
    549   PRINT_BIT_FIELD (Eax, TurboBoostTechnology);
    550   PRINT_BIT_FIELD (Eax, ARAT);
    551   PRINT_BIT_FIELD (Eax, PLN);
    552   PRINT_BIT_FIELD (Eax, ECMD);
    553   PRINT_BIT_FIELD (Eax, PTM);
    554   PRINT_BIT_FIELD (Eax, HWP);
    555   PRINT_BIT_FIELD (Eax, HWP_Notification);
    556   PRINT_BIT_FIELD (Eax, HWP_Activity_Window);
    557   PRINT_BIT_FIELD (Eax, HWP_Energy_Performance_Preference);
    558   PRINT_BIT_FIELD (Eax, HWP_Package_Level_Request);
    559   PRINT_BIT_FIELD (Eax, HDC);
    560   PRINT_BIT_FIELD (Ebx, InterruptThresholds);
    561   PRINT_BIT_FIELD (Ecx, HardwareCoordinationFeedback);
    562   PRINT_BIT_FIELD (Ecx, PerformanceEnergyBias);
    563 }
    564 
    565 /**
    566   Display CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS for all supported sub-leafs.
    567 
    568 **/
    569 VOID
    570 CpuidStructuredExtendedFeatureFlags (
    571   VOID
    572   )
    573 {
    574   UINT32                                       Eax;
    575   CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX  Ebx;
    576   CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX  Ecx;
    577   UINT32                                       SubLeaf;
    578 
    579   if (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS > gMaximumBasicFunction) {
    580     return;
    581   }
    582 
    583   AsmCpuidEx (
    584     CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
    585     CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
    586     &Eax, NULL, NULL, NULL
    587     );
    588   for (SubLeaf = 0; SubLeaf <= Eax; SubLeaf++) {
    589     AsmCpuidEx (
    590       CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
    591       SubLeaf,
    592       NULL, &Ebx.Uint32, &Ecx.Uint32, NULL
    593       );
    594     if (Ebx.Uint32 != 0 || Ecx.Uint32 != 0) {
    595       Print (L"CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS (Leaf %08x, Sub-Leaf %08x)\n", CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, SubLeaf);
    596       Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, Ecx.Uint32, 0);
    597       PRINT_BIT_FIELD (Ebx, FSGSBASE);
    598       PRINT_BIT_FIELD (Ebx, IA32_TSC_ADJUST);
    599       PRINT_BIT_FIELD (Ebx, SGX);
    600       PRINT_BIT_FIELD (Ebx, BMI1);
    601       PRINT_BIT_FIELD (Ebx, HLE);
    602       PRINT_BIT_FIELD (Ebx, AVX2);
    603       PRINT_BIT_FIELD (Ebx, FDP_EXCPTN_ONLY);
    604       PRINT_BIT_FIELD (Ebx, SMEP);
    605       PRINT_BIT_FIELD (Ebx, BMI2);
    606       PRINT_BIT_FIELD (Ebx, EnhancedRepMovsbStosb);
    607       PRINT_BIT_FIELD (Ebx, INVPCID);
    608       PRINT_BIT_FIELD (Ebx, RTM);
    609       PRINT_BIT_FIELD (Ebx, RDT_M);
    610       PRINT_BIT_FIELD (Ebx, DeprecateFpuCsDs);
    611       PRINT_BIT_FIELD (Ebx, MPX);
    612       PRINT_BIT_FIELD (Ebx, RDT_A);
    613       PRINT_BIT_FIELD (Ebx, RDSEED);
    614       PRINT_BIT_FIELD (Ebx, ADX);
    615       PRINT_BIT_FIELD (Ebx, SMAP);
    616       PRINT_BIT_FIELD (Ebx, CLFLUSHOPT);
    617       PRINT_BIT_FIELD (Ebx, CLWB);
    618       PRINT_BIT_FIELD (Ebx, IntelProcessorTrace);
    619       PRINT_BIT_FIELD (Ebx, SHA);
    620       PRINT_BIT_FIELD (Ecx, PREFETCHWT1);
    621       PRINT_BIT_FIELD (Ecx, UMIP);
    622       PRINT_BIT_FIELD (Ecx, PKU);
    623       PRINT_BIT_FIELD (Ecx, OSPKE);
    624       PRINT_BIT_FIELD (Ecx, MAWAU);
    625       PRINT_BIT_FIELD (Ecx, RDPID);
    626       PRINT_BIT_FIELD (Ecx, SGX_LC);
    627     }
    628   }
    629 }
    630 
    631 /**
    632   Display CPUID_DIRECT_CACHE_ACCESS_INFO leaf.
    633 
    634 **/
    635 VOID
    636 CpuidDirectCacheAccessInfo (
    637   VOID
    638   )
    639 {
    640   UINT32  Eax;
    641 
    642   if (CPUID_DIRECT_CACHE_ACCESS_INFO > gMaximumBasicFunction) {
    643     return;
    644   }
    645 
    646   AsmCpuid (CPUID_DIRECT_CACHE_ACCESS_INFO, &Eax, NULL, NULL, NULL);
    647   Print (L"CPUID_DIRECT_CACHE_ACCESS_INFO (Leaf %08x)\n", CPUID_DIRECT_CACHE_ACCESS_INFO);
    648   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, 0, 0);
    649 }
    650 
    651 /**
    652   Display CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING leaf.
    653 
    654 **/
    655 VOID
    656 CpuidArchitecturalPerformanceMonitoring (
    657   VOID
    658   )
    659 {
    660   CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EAX  Eax;
    661   CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EBX  Ebx;
    662   CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EDX  Edx;
    663 
    664   if (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING > gMaximumBasicFunction) {
    665     return;
    666   }
    667 
    668   AsmCpuid (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING, &Eax.Uint32, &Ebx.Uint32, NULL, &Edx.Uint32);
    669   Print (L"CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING (Leaf %08x)\n", CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING);
    670   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, 0, Edx.Uint32);
    671   PRINT_BIT_FIELD (Eax, ArchPerfMonVerID);
    672   PRINT_BIT_FIELD (Eax, PerformanceMonitorCounters);
    673   PRINT_BIT_FIELD (Eax, PerformanceMonitorCounterWidth);
    674   PRINT_BIT_FIELD (Eax, EbxBitVectorLength);
    675   PRINT_BIT_FIELD (Ebx, UnhaltedCoreCycles);
    676   PRINT_BIT_FIELD (Ebx, InstructionsRetired);
    677   PRINT_BIT_FIELD (Ebx, UnhaltedReferenceCycles);
    678   PRINT_BIT_FIELD (Ebx, LastLevelCacheReferences);
    679   PRINT_BIT_FIELD (Ebx, LastLevelCacheMisses);
    680   PRINT_BIT_FIELD (Ebx, BranchInstructionsRetired);
    681   PRINT_BIT_FIELD (Ebx, AllBranchMispredictRetired);
    682   PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounters);
    683   PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounterWidth);
    684 }
    685 
    686 /**
    687   Display CPUID_EXTENDED_TOPOLOGY leafs for all supported levels.
    688 
    689 **/
    690 VOID
    691 CpuidExtendedTopology (
    692   VOID
    693   )
    694 {
    695   CPUID_EXTENDED_TOPOLOGY_EAX  Eax;
    696   CPUID_EXTENDED_TOPOLOGY_EBX  Ebx;
    697   CPUID_EXTENDED_TOPOLOGY_ECX  Ecx;
    698   UINT32                       Edx;
    699   UINT32                       LevelNumber;
    700 
    701   if (CPUID_EXTENDED_TOPOLOGY > gMaximumBasicFunction) {
    702     return;
    703   }
    704 
    705   LevelNumber = 0;
    706   do {
    707     AsmCpuidEx (
    708       CPUID_EXTENDED_TOPOLOGY, LevelNumber,
    709       &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx
    710       );
    711     if (Eax.Bits.ApicIdShift != 0) {
    712       Print (L"CPUID_EXTENDED_TOPOLOGY (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_TOPOLOGY, LevelNumber);
    713       Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx);
    714       PRINT_BIT_FIELD (Eax, ApicIdShift);
    715       PRINT_BIT_FIELD (Ebx, LogicalProcessors);
    716       PRINT_BIT_FIELD (Ecx, LevelNumber);
    717       PRINT_BIT_FIELD (Ecx, LevelType);
    718       PRINT_VALUE     (Edx, x2APIC_ID);
    719     }
    720     LevelNumber++;
    721   } while (Eax.Bits.ApicIdShift != 0);
    722 }
    723 
    724 /**
    725   Display CPUID_EXTENDED_STATE sub-leaf.
    726 
    727 **/
    728 VOID
    729 CpuidExtendedStateSubLeaf (
    730   VOID
    731   )
    732 {
    733   CPUID_EXTENDED_STATE_SUB_LEAF_EAX  Eax;
    734   UINT32                             Ebx;
    735   CPUID_EXTENDED_STATE_SUB_LEAF_ECX  Ecx;
    736   UINT32                             Edx;
    737 
    738   AsmCpuidEx (
    739     CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF,
    740     &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx
    741     );
    742   Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF);
    743   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, Ecx.Uint32, Edx);
    744   PRINT_BIT_FIELD (Eax, XSAVEOPT);
    745   PRINT_BIT_FIELD (Eax, XSAVEC);
    746   PRINT_BIT_FIELD (Eax, XGETBV);
    747   PRINT_BIT_FIELD (Eax, XSAVES);
    748   PRINT_VALUE     (Ebx, EnabledSaveStateSize_XCR0_IA32_XSS);
    749   PRINT_BIT_FIELD (Ecx, XCR0);
    750   PRINT_BIT_FIELD (Ecx, PT);
    751   PRINT_BIT_FIELD (Ecx, XCR0_1);
    752   PRINT_VALUE     (Edx, IA32_XSS_Supported_32_63);
    753 }
    754 
    755 /**
    756   Display CPUID_EXTENDED_STATE size and offset information sub-leaf.
    757 
    758 **/
    759 VOID
    760 CpuidExtendedStateSizeOffset (
    761   VOID
    762   )
    763 {
    764   UINT32                                Eax;
    765   UINT32                                Ebx;
    766   CPUID_EXTENDED_STATE_SIZE_OFFSET_ECX  Ecx;
    767   UINT32                                Edx;
    768   UINT32                                SubLeaf;
    769 
    770   for (SubLeaf = CPUID_EXTENDED_STATE_SIZE_OFFSET; SubLeaf < 32; SubLeaf++) {
    771     AsmCpuidEx (
    772       CPUID_EXTENDED_STATE, SubLeaf,
    773       &Eax, &Ebx, &Ecx.Uint32, &Edx
    774       );
    775     if (Edx != 0) {
    776       Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, SubLeaf);
    777       Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, Ecx.Uint32, Edx);
    778       PRINT_VALUE     (Eax, FeatureSaveStateSize);
    779       PRINT_VALUE     (Ebx, FeatureSaveStateOffset);
    780       PRINT_BIT_FIELD (Ecx, XSS);
    781       PRINT_BIT_FIELD (Ecx, Compacted);
    782     }
    783   }
    784 }
    785 
    786 /**
    787   Display CPUID_EXTENDED_STATE main leaf and sub-leafs.
    788 
    789 **/
    790 VOID
    791 CpuidExtendedStateMainLeaf (
    792   VOID
    793   )
    794 {
    795   CPUID_EXTENDED_STATE_MAIN_LEAF_EAX  Eax;
    796   UINT32                              Ebx;
    797   UINT32                              Ecx;
    798   UINT32                              Edx;
    799 
    800   if (CPUID_EXTENDED_STATE > gMaximumBasicFunction) {
    801     return;
    802   }
    803 
    804   AsmCpuidEx (
    805     CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF,
    806     &Eax.Uint32, &Ebx, &Ecx, &Edx
    807     );
    808   Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF);
    809   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, Ecx, Edx);
    810   PRINT_BIT_FIELD (Eax, x87);
    811   PRINT_BIT_FIELD (Eax, SSE);
    812   PRINT_BIT_FIELD (Eax, AVX);
    813   PRINT_BIT_FIELD (Eax, MPX);
    814   PRINT_BIT_FIELD (Eax, AVX_512);
    815   PRINT_BIT_FIELD (Eax, IA32_XSS);
    816   PRINT_BIT_FIELD (Eax, PKRU);
    817   PRINT_VALUE     (Ebx, EnabledSaveStateSize);
    818   PRINT_VALUE     (Ecx, SupportedSaveStateSize);
    819   PRINT_VALUE     (Edx, XCR0_Supported_32_63);
    820 
    821   CpuidExtendedStateSubLeaf ();
    822   CpuidExtendedStateSizeOffset ();
    823 }
    824 
    825 /**
    826   Display CPUID_INTEL_RDT_MONITORING enumeration sub-leaf.
    827 
    828 **/
    829 VOID
    830 CpuidIntelRdtMonitoringEnumerationSubLeaf (
    831   VOID
    832   )
    833 {
    834   UINT32                                                  Ebx;
    835   CPUID_INTEL_RDT_MONITORING_ENUMERATION_SUB_LEAF_EDX     Edx;
    836 
    837   if (CPUID_INTEL_RDT_MONITORING > gMaximumBasicFunction) {
    838     return;
    839   }
    840 
    841   AsmCpuidEx (
    842     CPUID_INTEL_RDT_MONITORING, CPUID_INTEL_RDT_MONITORING_ENUMERATION_SUB_LEAF,
    843     NULL, &Ebx, NULL, &Edx.Uint32
    844     );
    845   Print (L"CPUID_INTEL_RDT_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_RDT_MONITORING, CPUID_INTEL_RDT_MONITORING_ENUMERATION_SUB_LEAF);
    846   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx, 0, Edx.Uint32);
    847   PRINT_VALUE     (Ebx, Maximum_RMID_Range);
    848   PRINT_BIT_FIELD (Edx, L3CacheRDT_M);
    849 }
    850 
    851 /**
    852   Display CPUID_INTEL_RDT_MONITORING L3 cache capability sub-leaf.
    853 
    854 **/
    855 VOID
    856 CpuidIntelRdtMonitoringL3CacheCapabilitySubLeaf (
    857   VOID
    858   )
    859 {
    860   UINT32                                                 Ebx;
    861   UINT32                                                 Ecx;
    862   CPUID_INTEL_RDT_MONITORING_L3_CACHE_SUB_LEAF_EDX       Edx;
    863 
    864   if (CPUID_INTEL_RDT_MONITORING > gMaximumBasicFunction) {
    865     return;
    866   }
    867 
    868   AsmCpuidEx (
    869     CPUID_INTEL_RDT_MONITORING, CPUID_INTEL_RDT_MONITORING_L3_CACHE_SUB_LEAF,
    870     NULL, &Ebx, &Ecx, &Edx.Uint32
    871     );
    872   Print (L"CPUID_INTEL_RDT_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_RDT_MONITORING, CPUID_INTEL_RDT_MONITORING_L3_CACHE_SUB_LEAF);
    873   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx, Ecx, Edx.Uint32);
    874   PRINT_VALUE     (Ebx, OccupancyConversionFactor);
    875   PRINT_VALUE     (Ecx, Maximum_RMID_Range);
    876   PRINT_BIT_FIELD (Edx, L3CacheOccupancyMonitoring);
    877   PRINT_BIT_FIELD (Edx, L3CacheTotalBandwidthMonitoring);
    878   PRINT_BIT_FIELD (Edx, L3CacheLocalBandwidthMonitoring);
    879 }
    880 
    881 /**
    882   Display CPUID_INTEL_RDT_ALLOCATION L3 cache allocation technology enumeration
    883   sub-leaf.
    884 
    885 **/
    886 VOID
    887 CpuidIntelRdtAllocationL3CacheSubLeaf (
    888   VOID
    889   )
    890 {
    891   CPUID_INTEL_RDT_ALLOCATION_L3_CACHE_SUB_LEAF_EAX  Eax;
    892   UINT32                                            Ebx;
    893   CPUID_INTEL_RDT_ALLOCATION_L3_CACHE_SUB_LEAF_ECX  Ecx;
    894   CPUID_INTEL_RDT_ALLOCATION_L3_CACHE_SUB_LEAF_EDX  Edx;
    895 
    896   AsmCpuidEx (
    897     CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_L3_CACHE_SUB_LEAF,
    898     &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx.Uint32
    899     );
    900   Print (L"CPUID_INTEL_RDT_ALLOCATION (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_L3_CACHE_SUB_LEAF);
    901   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, Ecx.Uint32, Edx.Uint32);
    902   PRINT_BIT_FIELD (Eax, CapacityLength);
    903   PRINT_VALUE     (Ebx, AllocationUnitBitMap);
    904   PRINT_BIT_FIELD (Ecx, CosUpdatesInfrequent);
    905   PRINT_BIT_FIELD (Ecx, CodeDataPrioritization);
    906   PRINT_BIT_FIELD (Edx, HighestCosNumber);
    907 }
    908 
    909 /**
    910   Display CPUID_INTEL_RDT_ALLOCATION L2 cache allocation technology enumeration
    911   sub-leaf.
    912 
    913 **/
    914 VOID
    915 CpuidIntelRdtAllocationL2CacheSubLeaf (
    916   VOID
    917   )
    918 {
    919   CPUID_INTEL_RDT_ALLOCATION_L2_CACHE_SUB_LEAF_EAX  Eax;
    920   UINT32                                            Ebx;
    921   CPUID_INTEL_RDT_ALLOCATION_L2_CACHE_SUB_LEAF_EDX  Edx;
    922 
    923   AsmCpuidEx (
    924     CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_L2_CACHE_SUB_LEAF,
    925     &Eax.Uint32, &Ebx, NULL, &Edx.Uint32
    926     );
    927   Print (L"CPUID_INTEL_RDT_ALLOCATION (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_L2_CACHE_SUB_LEAF);
    928   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, 0, Edx.Uint32);
    929   PRINT_BIT_FIELD (Eax, CapacityLength);
    930   PRINT_VALUE     (Ebx, AllocationUnitBitMap);
    931   PRINT_BIT_FIELD (Edx, HighestCosNumber);
    932 }
    933 
    934 /**
    935   Display CPUID_INTEL_RDT_ALLOCATION main leaf and sub-leaves.
    936 
    937 **/
    938 VOID
    939 CpuidIntelRdtAllocationMainLeaf (
    940   VOID
    941   )
    942 {
    943   CPUID_INTEL_RDT_ALLOCATION_ENUMERATION_SUB_LEAF_EBX  Ebx;
    944 
    945   if (CPUID_INTEL_RDT_ALLOCATION > gMaximumBasicFunction) {
    946     return;
    947   }
    948 
    949   AsmCpuidEx (
    950     CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_ENUMERATION_SUB_LEAF,
    951     NULL, &Ebx.Uint32, NULL, NULL
    952     );
    953   Print (L"CPUID_INTEL_RDT_ALLOCATION (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_RDT_ALLOCATION, CPUID_INTEL_RDT_ALLOCATION_ENUMERATION_SUB_LEAF);
    954   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx.Uint32, 0, 0);
    955   PRINT_BIT_FIELD (Ebx, L3CacheAllocation);
    956   PRINT_BIT_FIELD (Ebx, L2CacheAllocation);
    957 
    958   CpuidIntelRdtAllocationL3CacheSubLeaf ();
    959   CpuidIntelRdtAllocationL2CacheSubLeaf ();
    960 }
    961 
    962 /**
    963   Display Sub-Leaf 0 Enumeration of Intel SGX Capabilities.
    964 
    965 **/
    966 VOID
    967 CpuidEnumerationOfIntelSgxCapabilities0SubLeaf (
    968   VOID
    969   )
    970 {
    971   CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF_EAX  Eax;
    972   UINT32                                       Ebx;
    973   CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF_EDX  Edx;
    974 
    975   AsmCpuidEx (
    976     CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF,
    977     &Eax.Uint32, &Ebx, NULL, &Edx.Uint32
    978     );
    979   Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_0_SUB_LEAF);
    980   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, 0, Edx.Uint32);
    981   PRINT_BIT_FIELD (Eax, SGX1);
    982   PRINT_BIT_FIELD (Eax, SGX2);
    983   PRINT_BIT_FIELD (Edx, MaxEnclaveSize_Not64);
    984   PRINT_BIT_FIELD (Edx, MaxEnclaveSize_64);
    985 }
    986 
    987 /**
    988   Display Sub-Leaf 1 Enumeration of Intel SGX Capabilities.
    989 
    990 **/
    991 VOID
    992 CpuidEnumerationOfIntelSgxCapabilities1SubLeaf (
    993   VOID
    994   )
    995 {
    996   UINT32                                       Eax;
    997   UINT32                                       Ebx;
    998   UINT32                                       Ecx;
    999   UINT32                                       Edx;
   1000 
   1001   AsmCpuidEx (
   1002     CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_1_SUB_LEAF,
   1003     &Eax, &Ebx, &Ecx, &Edx
   1004     );
   1005   Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, CPUID_INTEL_SGX_CAPABILITIES_1_SUB_LEAF);
   1006   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, Ecx, Edx);
   1007 }
   1008 
   1009 /**
   1010   Display Sub-Leaf Index 2 or Higher Enumeration of Intel SGX Resources.
   1011 
   1012 **/
   1013 VOID
   1014 CpuidEnumerationOfIntelSgxResourcesSubLeaf (
   1015   VOID
   1016   )
   1017 {
   1018   CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EAX  Eax;
   1019   CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EBX  Ebx;
   1020   CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_ECX  Ecx;
   1021   CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF_EDX  Edx;
   1022   UINT32                                               SubLeaf;
   1023 
   1024   SubLeaf = CPUID_INTEL_SGX_CAPABILITIES_RESOURCES_SUB_LEAF;
   1025   do {
   1026     AsmCpuidEx (
   1027       CPUID_INTEL_SGX, SubLeaf,
   1028       &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
   1029       );
   1030     if (Eax.Bits.SubLeafType == 0x1) {
   1031       Print (L"CPUID_INTEL_SGX (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_SGX, SubLeaf);
   1032       Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1033       PRINT_BIT_FIELD (Eax, SubLeafType);
   1034       PRINT_BIT_FIELD (Eax, LowAddressOfEpcSection);
   1035       PRINT_BIT_FIELD (Ebx, HighAddressOfEpcSection);
   1036       PRINT_BIT_FIELD (Ecx, EpcSection);
   1037       PRINT_BIT_FIELD (Ecx, LowSizeOfEpcSection);
   1038       PRINT_BIT_FIELD (Edx, HighSizeOfEpcSection);
   1039     }
   1040     SubLeaf++;
   1041   } while (Eax.Bits.SubLeafType == 0x1);
   1042 }
   1043 
   1044 /**
   1045   Display Intel SGX Resource Enumeration.
   1046 
   1047 **/
   1048 VOID
   1049 CpuidEnumerationOfIntelSgx (
   1050   VOID
   1051   )
   1052 {
   1053   CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX  Ebx;
   1054 
   1055   if (CPUID_INTEL_SGX > gMaximumBasicFunction) {
   1056     return;
   1057   }
   1058 
   1059   AsmCpuidEx (
   1060     CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
   1061     CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
   1062     NULL, &Ebx.Uint32, NULL, NULL
   1063     );
   1064   if (Ebx.Bits.SGX != 1) {
   1065     //
   1066     // Only if CPUID.(EAX=07H, ECX=0H):EBX.SGX = 1, the processor has support
   1067     // for Intel SGX.
   1068     //
   1069     return;
   1070   }
   1071 
   1072   CpuidEnumerationOfIntelSgxCapabilities0SubLeaf ();
   1073   CpuidEnumerationOfIntelSgxCapabilities1SubLeaf ();
   1074   CpuidEnumerationOfIntelSgxResourcesSubLeaf ();
   1075 }
   1076 
   1077 /**
   1078   Display CPUID_INTEL_PROCESSOR_TRACE sub-leafs.
   1079 
   1080   @param[in] MaximumSubLeaf  Maximum sub-leaf index for CPUID_INTEL_PROCESSOR_TRACE.
   1081 
   1082 **/
   1083 VOID
   1084 CpuidIntelProcessorTraceSubLeaf (
   1085   UINT32  MaximumSubLeaf
   1086   )
   1087 {
   1088   UINT32                                    SubLeaf;
   1089   CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EAX  Eax;
   1090   CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EBX  Ebx;
   1091 
   1092   for (SubLeaf = CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF; SubLeaf <= MaximumSubLeaf; SubLeaf++) {
   1093     AsmCpuidEx (
   1094       CPUID_INTEL_PROCESSOR_TRACE, SubLeaf,
   1095       &Eax.Uint32, &Ebx.Uint32, NULL, NULL
   1096       );
   1097     Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_PROCESSOR_TRACE, SubLeaf);
   1098     Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, 0, 0);
   1099     PRINT_BIT_FIELD (Eax, ConfigurableAddressRanges);
   1100     PRINT_BIT_FIELD (Eax, MtcPeriodEncodings);
   1101     PRINT_BIT_FIELD (Ebx, CycleThresholdEncodings);
   1102     PRINT_BIT_FIELD (Ebx, PsbFrequencyEncodings);
   1103   }
   1104 }
   1105 
   1106 /**
   1107   Display CPUID_INTEL_PROCESSOR_TRACE main leaf and sub-leafs.
   1108 
   1109 **/
   1110 VOID
   1111 CpuidIntelProcessorTraceMainLeaf (
   1112   VOID
   1113   )
   1114 {
   1115   UINT32                                     Eax;
   1116   CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_EBX  Ebx;
   1117   CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX  Ecx;
   1118 
   1119   if (CPUID_INTEL_PROCESSOR_TRACE > gMaximumBasicFunction) {
   1120     return;
   1121   }
   1122 
   1123   AsmCpuidEx (
   1124     CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF,
   1125     &Eax, &Ebx.Uint32, &Ecx.Uint32, NULL
   1126     );
   1127   Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF);
   1128   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, Ecx.Uint32, 0);
   1129   PRINT_VALUE     (Eax, MaximumSubLeaf);
   1130   PRINT_BIT_FIELD (Ebx, Cr3Filter);
   1131   PRINT_BIT_FIELD (Ebx, ConfigurablePsb);
   1132   PRINT_BIT_FIELD (Ebx, IpTraceStopFiltering);
   1133   PRINT_BIT_FIELD (Ebx, Mtc);
   1134   PRINT_BIT_FIELD (Ebx, PTWrite);
   1135   PRINT_BIT_FIELD (Ebx, PowerEventTrace);
   1136   PRINT_BIT_FIELD (Ecx, RTIT);
   1137   PRINT_BIT_FIELD (Ecx, ToPA);
   1138   PRINT_BIT_FIELD (Ecx, SingleRangeOutput);
   1139   PRINT_BIT_FIELD (Ecx, TraceTransportSubsystem);
   1140   PRINT_BIT_FIELD (Ecx, LIP);
   1141 
   1142   CpuidIntelProcessorTraceSubLeaf (Eax);
   1143 }
   1144 
   1145 /**
   1146   Display CPUID_TIME_STAMP_COUNTER leaf.
   1147 
   1148 **/
   1149 VOID
   1150 CpuidTimeStampCounter (
   1151   VOID
   1152   )
   1153 {
   1154   UINT32  Eax;
   1155   UINT32  Ebx;
   1156   UINT32  Ecx;
   1157 
   1158   if (CPUID_TIME_STAMP_COUNTER > gMaximumBasicFunction) {
   1159     return;
   1160   }
   1161 
   1162   AsmCpuid (CPUID_TIME_STAMP_COUNTER, &Eax, &Ebx, &Ecx, NULL);
   1163   Print (L"CPUID_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_TIME_STAMP_COUNTER);
   1164   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, Ecx, 0);
   1165 }
   1166 
   1167 /**
   1168   Display CPUID_PROCESSOR_FREQUENCY leaf.
   1169 
   1170 **/
   1171 VOID
   1172 CpuidProcessorFrequency (
   1173   VOID
   1174   )
   1175 {
   1176   CPUID_PROCESSOR_FREQUENCY_EAX  Eax;
   1177   CPUID_PROCESSOR_FREQUENCY_EBX  Ebx;
   1178   CPUID_PROCESSOR_FREQUENCY_ECX  Ecx;
   1179 
   1180   if (CPUID_PROCESSOR_FREQUENCY > gMaximumBasicFunction) {
   1181     return;
   1182   }
   1183 
   1184   AsmCpuid (CPUID_PROCESSOR_FREQUENCY, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, NULL);
   1185   Print (L"CPUID_PROCESSOR_FREQUENCY (Leaf %08x)\n", CPUID_PROCESSOR_FREQUENCY);
   1186   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, 0);
   1187   PRINT_BIT_FIELD (Eax, ProcessorBaseFrequency);
   1188   PRINT_BIT_FIELD (Ebx, MaximumFrequency);
   1189   PRINT_BIT_FIELD (Ecx, BusFrequency);
   1190 }
   1191 
   1192 /**
   1193   Display CPUID_SOC_VENDOR sub-leafs that contain the SoC Vendor Brand String.
   1194   Also display these sub-leafs as a single SoC Vendor Brand String.
   1195 
   1196 **/
   1197 VOID
   1198 CpuidSocVendorBrandString (
   1199   VOID
   1200   )
   1201 {
   1202   CPUID_SOC_VENDOR_BRAND_STRING_DATA  Eax;
   1203   CPUID_SOC_VENDOR_BRAND_STRING_DATA  Ebx;
   1204   CPUID_SOC_VENDOR_BRAND_STRING_DATA  Ecx;
   1205   CPUID_SOC_VENDOR_BRAND_STRING_DATA  Edx;
   1206   //
   1207   // Array to store brand string from 3 brand string leafs with
   1208   // 4 32-bit brand string values per leaf and an extra value to
   1209   // null terminate the string.
   1210   //
   1211   UINT32                              BrandString[3 * 4 + 1];
   1212 
   1213   AsmCpuidEx (
   1214     CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING1,
   1215     &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
   1216     );
   1217   Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING1);
   1218   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1219   BrandString[0] = Eax.Uint32;
   1220   BrandString[1] = Ebx.Uint32;
   1221   BrandString[2] = Ecx.Uint32;
   1222   BrandString[3] = Edx.Uint32;
   1223 
   1224   AsmCpuidEx (
   1225     CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING2,
   1226     &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
   1227     );
   1228   Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING2);
   1229   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1230   BrandString[4] = Eax.Uint32;
   1231   BrandString[5] = Ebx.Uint32;
   1232   BrandString[6] = Ecx.Uint32;
   1233   BrandString[7] = Edx.Uint32;
   1234 
   1235   AsmCpuidEx (
   1236     CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING3,
   1237     &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
   1238     );
   1239   Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING3);
   1240   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1241   BrandString[8]  = Eax.Uint32;
   1242   BrandString[9]  = Ebx.Uint32;
   1243   BrandString[10] = Ecx.Uint32;
   1244   BrandString[11] = Edx.Uint32;
   1245 
   1246   BrandString[12] = 0;
   1247 
   1248   Print (L"Vendor Brand String = %a\n", (CHAR8 *)BrandString);
   1249 }
   1250 
   1251 /**
   1252   Display CPUID_SOC_VENDOR main leaf and sub-leafs.
   1253 
   1254 **/
   1255 VOID
   1256 CpuidSocVendor (
   1257   VOID
   1258   )
   1259 {
   1260   UINT32                          Eax;
   1261   CPUID_SOC_VENDOR_MAIN_LEAF_EBX  Ebx;
   1262   UINT32                          Ecx;
   1263   UINT32                          Edx;
   1264 
   1265   if (CPUID_SOC_VENDOR > gMaximumBasicFunction) {
   1266     return;
   1267   }
   1268 
   1269   AsmCpuidEx (
   1270     CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_MAIN_LEAF,
   1271     &Eax, &Ebx.Uint32, &Ecx, &Edx
   1272     );
   1273   Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_MAIN_LEAF);
   1274   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, Ecx, Edx);
   1275   if (Eax < 3) {
   1276     Print (L"  Not Supported\n");
   1277     return;
   1278   }
   1279   PRINT_VALUE     (Eax, MaxSOCID_Index);
   1280   PRINT_BIT_FIELD (Ebx, SocVendorId);
   1281   PRINT_BIT_FIELD (Ebx, IsVendorScheme);
   1282   PRINT_VALUE     (Ecx, ProjectID);
   1283   PRINT_VALUE     (Edx, SteppingID);
   1284   CpuidSocVendorBrandString ();
   1285 }
   1286 
   1287 /**
   1288   Display CPUID_EXTENDED_FUNCTION leaf.
   1289 
   1290 **/
   1291 VOID
   1292 CpuidExtendedFunction (
   1293   VOID
   1294   )
   1295 {
   1296   UINT32  Eax;
   1297 
   1298   AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
   1299   Print (L"CPUID_EXTENDED_FUNCTION (Leaf %08x)\n", CPUID_EXTENDED_FUNCTION);
   1300   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, 0, 0);
   1301   PRINT_VALUE     (Eax, MaximumExtendedFunction);
   1302 
   1303   gMaximumExtendedFunction = Eax;
   1304 }
   1305 
   1306 /**
   1307   Display CPUID_EXTENDED_CPU_SIG leaf.
   1308 
   1309 **/
   1310 VOID
   1311 CpuidExtendedCpuSig (
   1312   VOID
   1313   )
   1314 {
   1315   UINT32                      Eax;
   1316   CPUID_EXTENDED_CPU_SIG_ECX  Ecx;
   1317   CPUID_EXTENDED_CPU_SIG_EDX  Edx;
   1318 
   1319   if (CPUID_EXTENDED_CPU_SIG > gMaximumExtendedFunction) {
   1320     return;
   1321   }
   1322 
   1323   AsmCpuid (CPUID_EXTENDED_CPU_SIG, &Eax, NULL, &Ecx.Uint32, &Edx.Uint32);
   1324   Print (L"CPUID_EXTENDED_CPU_SIG (Leaf %08x)\n", CPUID_EXTENDED_CPU_SIG);
   1325   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, Ecx.Uint32, Edx.Uint32);
   1326   PRINT_BIT_FIELD (Ecx, LAHF_SAHF);
   1327   PRINT_BIT_FIELD (Ecx, LZCNT);
   1328   PRINT_BIT_FIELD (Ecx, PREFETCHW);
   1329   PRINT_BIT_FIELD (Edx, SYSCALL_SYSRET);
   1330   PRINT_BIT_FIELD (Edx, NX);
   1331   PRINT_BIT_FIELD (Edx, Page1GB);
   1332   PRINT_BIT_FIELD (Edx, RDTSCP);
   1333   PRINT_BIT_FIELD (Edx, LM);
   1334 }
   1335 
   1336 /**
   1337   Display CPUID_BRAND_STRING1, CPUID_BRAND_STRING2 and  CPUID_BRAND_STRING3
   1338   leafs.  Also display these three leafs as a single brand string.
   1339 
   1340 **/
   1341 VOID
   1342 CpuidProcessorBrandString (
   1343   VOID
   1344   )
   1345 {
   1346   CPUID_BRAND_STRING_DATA  Eax;
   1347   CPUID_BRAND_STRING_DATA  Ebx;
   1348   CPUID_BRAND_STRING_DATA  Ecx;
   1349   CPUID_BRAND_STRING_DATA  Edx;
   1350   //
   1351   // Array to store brand string from 3 brand string leafs with
   1352   // 4 32-bit brand string values per leaf and an extra value to
   1353   // null terminate the string.
   1354   //
   1355   UINT32                   BrandString[3 * 4 + 1];
   1356 
   1357   if (CPUID_BRAND_STRING1 <= gMaximumExtendedFunction) {
   1358     AsmCpuid (CPUID_BRAND_STRING1, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
   1359     Print (L"CPUID_BRAND_STRING1 (Leaf %08x)\n", CPUID_BRAND_STRING1);
   1360     Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1361     BrandString[0] = Eax.Uint32;
   1362     BrandString[1] = Ebx.Uint32;
   1363     BrandString[2] = Ecx.Uint32;
   1364     BrandString[3] = Edx.Uint32;
   1365   }
   1366 
   1367   if (CPUID_BRAND_STRING2 <= gMaximumExtendedFunction) {
   1368     AsmCpuid (CPUID_BRAND_STRING2, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
   1369     Print (L"CPUID_BRAND_STRING2 (Leaf %08x)\n", CPUID_BRAND_STRING2);
   1370     Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1371     BrandString[4] = Eax.Uint32;
   1372     BrandString[5] = Ebx.Uint32;
   1373     BrandString[6] = Ecx.Uint32;
   1374     BrandString[7] = Edx.Uint32;
   1375   }
   1376 
   1377   if (CPUID_BRAND_STRING3 <= gMaximumExtendedFunction) {
   1378     AsmCpuid (CPUID_BRAND_STRING3, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32);
   1379     Print (L"CPUID_BRAND_STRING3 (Leaf %08x)\n", CPUID_BRAND_STRING3);
   1380     Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
   1381     BrandString[8]  = Eax.Uint32;
   1382     BrandString[9]  = Ebx.Uint32;
   1383     BrandString[10] = Ecx.Uint32;
   1384     BrandString[11] = Edx.Uint32;
   1385   }
   1386 
   1387   BrandString[12] = 0;
   1388 
   1389   Print (L"Brand String = %a\n", (CHAR8 *)BrandString);
   1390 }
   1391 
   1392 /**
   1393   Display CPUID_EXTENDED_CACHE_INFO leaf.
   1394 
   1395 **/
   1396 VOID
   1397 CpuidExtendedCacheInfo (
   1398   VOID
   1399   )
   1400 {
   1401   CPUID_EXTENDED_CACHE_INFO_ECX  Ecx;
   1402 
   1403   if (CPUID_EXTENDED_CACHE_INFO > gMaximumExtendedFunction) {
   1404     return;
   1405   }
   1406 
   1407   AsmCpuid (CPUID_EXTENDED_CACHE_INFO, NULL, NULL, &Ecx.Uint32, NULL);
   1408   Print (L"CPUID_EXTENDED_CACHE_INFO (Leaf %08x)\n", CPUID_EXTENDED_CACHE_INFO);
   1409   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, Ecx.Uint32, 0);
   1410   PRINT_BIT_FIELD (Ecx, CacheLineSize);
   1411   PRINT_BIT_FIELD (Ecx, L2Associativity);
   1412   PRINT_BIT_FIELD (Ecx, CacheSize);
   1413 }
   1414 
   1415 /**
   1416   Display CPUID_EXTENDED_TIME_STAMP_COUNTER leaf.
   1417 
   1418 **/
   1419 VOID
   1420 CpuidExtendedTimeStampCounter (
   1421   VOID
   1422   )
   1423 {
   1424   CPUID_EXTENDED_TIME_STAMP_COUNTER_EDX  Edx;
   1425 
   1426   if (CPUID_EXTENDED_TIME_STAMP_COUNTER > gMaximumExtendedFunction) {
   1427     return;
   1428   }
   1429 
   1430   AsmCpuid (CPUID_EXTENDED_TIME_STAMP_COUNTER, NULL, NULL, NULL, &Edx.Uint32);
   1431   Print (L"CPUID_EXTENDED_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_EXTENDED_TIME_STAMP_COUNTER);
   1432   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, 0, Edx.Uint32);
   1433   PRINT_BIT_FIELD (Edx, InvariantTsc);
   1434 }
   1435 
   1436 /**
   1437   Display CPUID_VIR_PHY_ADDRESS_SIZE leaf.
   1438 
   1439 **/
   1440 VOID
   1441 CpuidVirPhyAddressSize (
   1442   VOID
   1443   )
   1444 {
   1445   CPUID_VIR_PHY_ADDRESS_SIZE_EAX  Eax;
   1446 
   1447   if (CPUID_VIR_PHY_ADDRESS_SIZE > gMaximumExtendedFunction) {
   1448     return;
   1449   }
   1450 
   1451   AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Eax.Uint32, NULL, NULL, NULL);
   1452   Print (L"CPUID_VIR_PHY_ADDRESS_SIZE (Leaf %08x)\n", CPUID_VIR_PHY_ADDRESS_SIZE);
   1453   Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 0, 0, 0);
   1454   PRINT_BIT_FIELD (Eax, PhysicalAddressBits);
   1455   PRINT_BIT_FIELD (Eax, LinearAddressBits);
   1456 }
   1457 
   1458 /**
   1459   The user Entry Point for Application. The user code starts with this function
   1460   as the real entry point for the application.
   1461 
   1462   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1463   @param[in] SystemTable    A pointer to the EFI System Table.
   1464 
   1465   @retval EFI_SUCCESS       The entry point is executed successfully.
   1466   @retval other             Some error occurs when executing this entry point.
   1467 
   1468 **/
   1469 EFI_STATUS
   1470 EFIAPI
   1471 UefiMain (
   1472   IN EFI_HANDLE        ImageHandle,
   1473   IN EFI_SYSTEM_TABLE  *SystemTable
   1474   )
   1475 {
   1476   Print (L"UEFI CPUID Version 0.5\n");
   1477 
   1478   CpuidSignature ();
   1479   CpuidVersionInfo ();
   1480   CpuidCacheInfo ();
   1481   CpuidSerialNumber ();
   1482   CpuidCacheParams();
   1483   CpuidMonitorMwait ();
   1484   CpuidThermalPowerManagement ();
   1485   CpuidStructuredExtendedFeatureFlags ();
   1486   CpuidDirectCacheAccessInfo();
   1487   CpuidArchitecturalPerformanceMonitoring ();
   1488   CpuidExtendedTopology ();
   1489   CpuidExtendedStateMainLeaf ();
   1490   CpuidIntelRdtMonitoringEnumerationSubLeaf ();
   1491   CpuidIntelRdtMonitoringL3CacheCapabilitySubLeaf ();
   1492   CpuidIntelRdtAllocationMainLeaf ();
   1493   CpuidEnumerationOfIntelSgx ();
   1494   CpuidIntelProcessorTraceMainLeaf ();
   1495   CpuidTimeStampCounter ();
   1496   CpuidProcessorFrequency ();
   1497   CpuidSocVendor ();
   1498   CpuidExtendedFunction ();
   1499   CpuidExtendedCpuSig ();
   1500   CpuidProcessorBrandString ();
   1501   CpuidExtendedCacheInfo ();
   1502   CpuidExtendedTimeStampCounter ();
   1503   CpuidVirPhyAddressSize ();
   1504 
   1505   return EFI_SUCCESS;
   1506 }
   1507