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