ReactOS 0.4.17-dev-1133-gc25e4fd
cacheinfo.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Routines for x86 / x64 cache information gathering
5 * COPYRIGHT: Copyright 2026 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8/* INCLUDES *****************************************************************/
9
10#include <ntoskrnl.h>
11#include <x86x64/Cpuid.h>
12#define NDEBUG
13#include <debug.h>
14
15/* DATA **********************************************************************/
16
17typedef struct
18{
26
28
40{
41 // 00H General Null descriptor, this byte contains no information.
42 // 01H TLB Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries.
43 // 02H TLB Instruction TLB: 4 MByte pages, fully associative, 2 entries.
44 // 03H TLB Data TLB: 4 KByte pages, 4-way set associative, 64 entries.
45 // 04H TLB Data TLB: 4 MByte pages, 4-way set associative, 8 entries.
46 // 05H TLB Data TLB1: 4 MByte pages, 4-way set associative, 32 entries.
47 { 0x06, 1, CacheInstruction, 8, 4, 32, },// 06H Cache 1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size.
48 { 0x08, 1, CacheInstruction, 16, 4, 32, }, // 08H Cache 1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size.
49 { 0x09, 1, CacheInstruction, 32, 4, 64, }, // 09H Cache 1st-level instruction cache: 32KBytes, 4-way set associative, 64 byte line size.
50 { 0x0A, 1, CacheData, 8, 2, 32, }, // 0AH Cache 1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size.
51 // 0BH TLB Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries.
52 { 0x0C, 1, CacheData, 16, 4, 32, }, // 0CH Cache 1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size.
53 { 0x0D, 1, CacheData, 16, 4, 64, }, // 0DH Cache 1st-level data cache: 16 KBytes, 4-way set associative, 64 byte line size.
54 { 0x0E, 1, CacheData, 24, 6, 64, }, // 0EH Cache 1st-level data cache: 24 KBytes, 6-way set associative, 64 byte line size.
55 { 0x1D, 2, CacheUnified, 128, 2, 64, }, // 1DH Cache 2nd-level cache: 128 KBytes, 2-way set associative, 64 byte line size.
56 { 0x21, 2, CacheUnified, 256, 8, 64, }, // 21H Cache 2nd-level cache: 256 KBytes, 8-way set associative, 64 byte line size.
57 { 0x22, 3, CacheUnified, 512, 4, 64, }, // 22H Cache 3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector.
58 { 0x23, 3, CacheUnified, 1024, 8, 64, }, // 23H Cache 3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector.
59 { 0x24, 2, CacheUnified, 1 * 1024, 16, 64, }, // 24H Cache 2nd-level cache: 1 MBytes, 16-way set associative, 64 byte line size.
60 { 0x25, 3, CacheUnified, 2 * 1024, 8, 64, }, // 25H Cache 3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector.
61 { 0x29, 3, CacheUnified, 4 * 1024, 8, 64, }, // 29H Cache 3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector.
62 { 0x2C, 1, CacheData, 32, 8, 64, }, // 2CH Cache 1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size.
63 { 0x30, 1, CacheInstruction, 32, 8, 64, }, // 30H Cache 1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size.
64 // 40H Cache No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache.
65 { 0x41, 2, CacheUnified, 128, 4, 32, }, // 41H Cache 2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size.
66 { 0x42, 2, CacheUnified, 256, 4, 32, }, // 42H Cache 2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size.
67 { 0x43, 2, CacheUnified, 512, 4, 32, }, // 43H Cache 2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size.
68 { 0x44, 2, CacheUnified, 1 * 1024, 4, 32, }, // 44H Cache 2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size.
69 { 0x45, 2, CacheUnified, 2 * 1024, 4, 32, }, // 45H Cache 2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size.
70 { 0x46, 3, CacheUnified, 4 * 1024, 4, 64, }, // 46H Cache 3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size.
71 { 0x47, 3, CacheUnified, 8 * 1024, 8, 64, }, // 47H Cache 3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size.
72 { 0x48, 2, CacheUnified, 3 * 1024, 12, 64, }, // 48H Cache 2nd-level cache: 3MByte, 12-way set associative, 64 byte line size.
73 { 0x49, 3, CacheUnified, 4 * 1024, 16, 64, }, // 49H 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.
74 { 0x4A, 3, CacheUnified, 6 * 1024, 12, 64, }, // 4AH Cache 3rd-level cache: 6MByte, 12-way set associative, 64 byte line size.
75 { 0x4B, 3, CacheUnified, 8 * 1024, 16, 64, }, // 4BH Cache 3rd-level cache: 8MByte, 16-way set associative, 64 byte line size.
76 { 0x4C, 3, CacheUnified, 12 * 1024, 12, 64, }, // 4CH Cache 3rd-level cache: 12MByte, 12-way set associative, 64 byte line size.
77 { 0x4D, 3, CacheUnified, 16 * 1024, 16, 64, }, // 4DH Cache 3rd-level cache: 16MByte, 16-way set associative, 64 byte line size.
78 { 0x4E, 2, CacheUnified, 6 * 1024, 24, 64, }, // 4EH Cache 2nd-level cache: 6MByte, 24-way set associative, 64 byte line size.
79 // 4FH TLB Instruction TLB: 4 KByte pages, 32 entries.
80 // 50H TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries.
81 // 51H TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries.
82 // 52H TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries.
83 // 55H TLB Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries.
84 // 56H TLB Data TLB0: 4 MByte pages, 4-way set associative, 16 entries.
85 // 57H TLB Data TLB0: 4 KByte pages, 4-way associative, 16 entries.
86 // 59H TLB Data TLB0: 4 KByte pages, fully associative, 16 entries.
87 // 5AH TLB Data TLB0: 2 MByte or 4 MByte pages, 4-way set associative, 32 entries.
88 // 5BH TLB Data TLB: 4 KByte and 4 MByte pages, 64 entries.
89 // 5CH TLB Data TLB: 4 KByte and 4 MByte pages,128 entries.
90 // 5DH TLB Data TLB: 4 KByte and 4 MByte pages,256 entries.
91 { 0x60, 1, CacheData, 16, 8, 64, }, // 60H Cache 1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size.
92 // 61H TLB Instruction TLB: 4 KByte pages, fully associative, 48 entries.
93 // 63H 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.
94 // 64H TLB Data TLB: 4 KByte pages, 4-way set associative, 512 entries.
95 { 0x66, 1, CacheData, 8, 4, 64, }, // 66H Cache 1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size.
96 { 0x67, 1, CacheData, 16, 4, 64, }, // 67H Cache 1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size.
97 { 0x68, 1, CacheData, 32, 4, 64, }, // 68H Cache 1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size.
98 // 6AH Cache uTLB: 4 KByte pages, 8-way set associative, 64 entries.
99 // 6BH Cache DTLB: 4 KByte pages, 8-way set associative, 256 entries.
100 // 6CH Cache DTLB: 2M/4M pages, 8-way set associative, 128 entries.
101 // 6DH Cache DTLB: 1 GByte pages, fully associative, 16 entries.
102 // 70H Cache Trace cache: 12 K-μop, 8-way set associative.
103 // 71H Cache Trace cache: 16 K-μop, 8-way set associative.
104 // 72H Cache Trace cache: 32 K-μop, 8-way set associative.
105 // 76H TLB Instruction TLB: 2M/4M pages, fully associative, 8 entries.
106 { 0x78, 2, CacheUnified, 1 * 1024, 4, 64, }, // 78H Cache 2nd-level cache: 1 MByte, 4-way set associative, 64byte line size.
107 { 0x79, 2, CacheUnified, 128, 8, 64, }, // 79H Cache 2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector.
108 { 0x7A, 2, CacheUnified, 256, 8, 64, }, // 7AH Cache 2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector.
109 { 0x7B, 2, CacheUnified, 512, 8, 64, }, // 7BH Cache 2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector.
110 { 0x7C, 2, CacheUnified, 1 * 1024, 8, 64, }, // 7CH Cache 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector.
111 { 0x7D, 2, CacheUnified, 2 * 1024, 8, 64, }, // 7DH Cache 2nd-level cache: 2 MByte, 8-way set associative, 64 byte line size.
112 { 0x7F, 2, CacheUnified, 512, 2, 64, }, // 7FH Cache 2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size.
113 { 0x80, 2, CacheUnified, 512, 8, 64, }, // 80H Cache 2nd-level cache: 512 KByte, 8-way set associative, 64-byte line size.
114 { 0x82, 2, CacheUnified, 256, 8, 32, }, // 82H Cache 2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size.
115 { 0x83, 2, CacheUnified, 512, 8, 32, }, // 83H Cache 2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size.
116 { 0x84, 2, CacheUnified, 1 * 1024, 8, 32, }, // 84H Cache 2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size.
117 { 0x85, 2, CacheUnified, 2 * 1024, 8, 32, }, // 85H Cache 2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size.
118 { 0x86, 2, CacheUnified, 512, 4, 64, }, // 86H Cache 2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size.
119 { 0x87, 2, CacheUnified, 1 * 1024, 8, 64, }, // 87H Cache 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size.
120 // A0H DTLB DTLB: 4k pages, fully associative, 32 entries.
121 // B0H TLB Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries.
122 // B1H TLB Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries.
123 // B2H TLB Instruction TLB: 4KByte pages, 4-way set associative, 64 entries.
124 // B3H TLB Data TLB: 4 KByte pages, 4-way set associative, 128 entries.
125 // B4H TLB Data TLB1: 4 KByte pages, 4-way associative, 256 entries.
126 // B5H TLB Instruction TLB: 4KByte pages, 8-way set associative, 64 entries.
127 // B6H TLB Instruction TLB: 4KByte pages, 8-way set associative, 128 entries.
128 // BAH TLB Data TLB1: 4 KByte pages, 4-way associative, 64 entries.
129 // C0H TLB Data TLB: 4 KByte and 4 MByte pages, 4-way associative, 8 entries.
130 // C1H STLB Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries.
131 // C2H DTLB DTLB: 2 MByte/4 MByte pages, 4-way associative, 16 entries.
132 // C3H STLB Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries.
133 // C4H DTLB DTLB: 2 MByte/4 MByte pages, 4-way associative, 32 entries.
134 // CAH STLB Shared 2nd-Level TLB: 4 KByte pages, 4-way associative, 512 entries.
135 { 0xD0, 3, CacheUnified, 512, 4, 64, }, // D0H Cache 3rd-level cache: 512 KByte, 4-way set associative, 64 byte line size.
136 { 0xD1, 3, CacheUnified, 1 * 1024, 4, 64, }, // D1H Cache 3rd-level cache: 1 MByte, 4-way set associative, 64 byte line size.
137 { 0xD2, 3, CacheUnified, 2 * 1024, 4, 64, }, // D2H Cache 3rd-level cache: 2 MByte, 4-way set associative, 64 byte line size.
138 { 0xD6, 3, CacheUnified, 1 * 1024, 8, 64, }, // D6H Cache 3rd-level cache: 1 MByte, 8-way set associative, 64 byte line size.
139 { 0xD7, 3, CacheUnified, 2 * 1024, 8, 64, }, // D7H Cache 3rd-level cache: 2 MByte, 8-way set associative, 64 byte line size.
140 { 0xD8, 3, CacheUnified, 4 * 1024, 8, 64, }, // D8H Cache 3rd-level cache: 4 MByte, 8-way set associative, 64 byte line size.
141 { 0xDC, 3, CacheUnified, 1 * 1024 + 512, 12, 64, }, // DCH Cache 3rd-level cache: 1.5 MByte, 12-way set associative, 64 byte line size.
142 { 0xDD, 3, CacheUnified, 3 * 1024, 12, 64, }, // DDH Cache 3rd-level cache: 3 MByte, 12-way set associative, 64 byte line size.
143 { 0xDE, 3, CacheUnified, 6 * 1024, 12, 64, }, // DEH Cache 3rd-level cache: 6 MByte, 12-way set associative, 64 byte line size.
144 { 0xE2, 3, CacheUnified, 2 * 1024, 16, 64, }, // E2H Cache 3rd-level cache: 2 MByte, 16-way set associative, 64 byte line size.
145 { 0xE3, 3, CacheUnified, 4 * 1024, 16, 64, }, // E3H Cache 3rd-level cache: 4 MByte, 16-way set associative, 64 byte line size.
146 { 0xE4, 3, CacheUnified, 8 * 1024, 16, 64, }, // E4H Cache 3rd-level cache: 8 MByte, 16-way set associative, 64 byte line size.
147 { 0xEA, 3, CacheUnified, 12 * 1024, 24, 64, }, // EAH Cache 3rd-level cache: 12MByte, 24-way set associative, 64 byte line size.
148 { 0xEB, 3, CacheUnified, 18 * 1024, 24, 64, }, // EBH Cache 3rd-level cache: 18MByte, 24-way set associative, 64 byte line size.
149 { 0xEC, 3, CacheUnified, 24 * 1024, 24, 64, }, // ECH Cache 3rd-level cache: 24MByte, 24-way set associative, 64 byte line size.
150 // F0H Prefetch 64-Byte prefetching.
151 // F1H Prefetch 128-Byte prefetching.
152 // FEH General CPUID leaf 2 does not report TLB descriptor information; use CPUID leaf 18H to query TLB and other address translation parameters.
153 // FFH General CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters.
154};
155
156
157/* FUNCTIONS *****************************************************************/
158
166static
169{
170 ULONG Low = 0;
172
173 while (Low < High)
174 {
175 ULONG Mid = Low + (High - Low) / 2;
176 const INTEL_CACHE_DESCRIPTOR* CacheDesc = &IntelCacheDescriptors[Mid];
177 if (DescriptorCode < CacheDesc->Code)
178 {
179 High = Mid;
180 }
181 else if (DescriptorCode > CacheDesc->Code)
182 {
183 Low = Mid + 1;
184 }
185 else
186 {
187 return CacheDesc;
188 }
189 }
190
191 return NULL;
192}
193
205static
206ULONG
208 _Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors,
209 _In_ ULONG MaxCount)
210{
211 CPUID_CACHE_INFO_REGS CacheInfoRegs;
212 ULONG Passes, Pass, Reg, Byte;
213 ULONG Count = 0;
214
215 /* Query the cache info. The number of passes is stored in EAX[7..0] */
216 __cpuid(CacheInfoRegs.AsInt32, CPUID_CACHE_INFO);
217 Passes = CacheInfoRegs.Eax.CacheDescriptor[0];
218
219 /* Now loop through each pass. Every CPUID call gives the next chunk
220 of information. After n passes we have all info. The order is not
221 deterministic. */
222 for (Pass = 0; Pass < Passes; Pass++)
223 {
224 /* Query the information for the next pass */
225 __cpuid(CacheInfoRegs.AsInt32, CPUID_CACHE_INFO);
226
227 /* Loop through each register in the cache info */
228 for (Reg = 0; Reg < ARRAYSIZE(CacheInfoRegs.Regs); Reg++)
229 {
230 const CPUID_CACHE_INFO_CACHE_TLB *CpuidReg = &CacheInfoRegs.Regs[Reg];
231
232 if (CpuidReg->Bits.NotValid)
233 continue;
234
235 /* Loop through each byte in the register. For EAX we need to skip the first. */
236 for (Byte = (Reg == 0) ? 1 : 0; Byte < 4; Byte++)
237 {
238 const INTEL_CACHE_DESCRIPTOR* IntelCacheDesc;
239 UCHAR DescriptorCode = CpuidReg->CacheDescriptor[Byte];
240 if (DescriptorCode == 0)
241 continue;
242
243 IntelCacheDesc = FindIntelCacheDescriptor(DescriptorCode);
244 if (IntelCacheDesc != NULL)
245 {
246 /* Make sure there is enough space in the array */
247 if (Count >= MaxCount)
248 {
249 return Count;
250 }
251
252 CacheDescriptors[Count].Level = IntelCacheDesc->Level;
253 CacheDescriptors[Count].Associativity = IntelCacheDesc->Associativity;
254 CacheDescriptors[Count].LineSize = IntelCacheDesc->LineSize;
255 CacheDescriptors[Count].Size = IntelCacheDesc->SizeinKB * 1024;
256 CacheDescriptors[Count].Type = IntelCacheDesc->Type;
257 Count++;
258 }
259 }
260 }
261 }
262
263 return Count;
264}
265
279static
280ULONG
282 _Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors,
283 _In_ ULONG MaxCount)
284{
285 CPUID_L1_TLB_INFO_REGS L1TlbInfo;
287 ULONG Count = 0;
288 static const UCHAR AssocMap[16] =
289 {
290 0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 0xFF
291 };
292
294
295 /* L1 data cache */
296 if ((L1TlbInfo.Amd.Ecx.Bits.L1DcSize != 0) && (Count < MaxCount))
297 {
298 CacheDescriptors[Count].Level = 1;
299 CacheDescriptors[Count].Type = CacheData;
300 CacheDescriptors[Count].Size = L1TlbInfo.Amd.Ecx.Bits.L1DcSize * 1024;
301 CacheDescriptors[Count].Associativity = L1TlbInfo.Amd.Ecx.Bits.L1DcAssoc;
302 CacheDescriptors[Count].LineSize = L1TlbInfo.Amd.Ecx.Bits.L1DcLineSize;
303 Count++;
304 }
305
306 /* L1 instruction cache */
307 if ((L1TlbInfo.Amd.Edx.Bits.L1IcSize != 0) && (Count < MaxCount))
308 {
309 CacheDescriptors[Count].Level = 1;
310 CacheDescriptors[Count].Type = CacheInstruction;
311 CacheDescriptors[Count].Size = L1TlbInfo.Amd.Edx.Bits.L1IcSize * 1024;
312 CacheDescriptors[Count].Associativity = L1TlbInfo.Amd.Edx.Bits.L1IcAssoc;
313 CacheDescriptors[Count].LineSize = L1TlbInfo.Amd.Edx.Bits.L1IcLineSize;
314 Count++;
315 }
316
318
319 /* L2 unified cache (Assoc 9 means look at leaf 0x8000001D) */
320 if ((CacheInfoRegs.Ecx.Bits.L2Size != 0) && (CacheInfoRegs.Ecx.Bits.L2Assoc != 9) && (Count < MaxCount))
321 {
322 CacheDescriptors[Count].Level = 2;
323 CacheDescriptors[Count].Type = CacheUnified;
324 CacheDescriptors[Count].Size = CacheInfoRegs.Ecx.Bits.L2Size * 1024;
325 CacheDescriptors[Count].Associativity = AssocMap[CacheInfoRegs.Ecx.Bits.L2Assoc];
326 CacheDescriptors[Count].LineSize = CacheInfoRegs.Ecx.Bits.L2LineSize;
327 Count++;
328 }
329
330 /* L3 unified cache (Assoc 9 means look at leaf 0x8000001D) */
331 if ((CacheInfoRegs.Edx.Bits.L3Size != 0) && (CacheInfoRegs.Edx.Bits.L3Assoc != 9) && (Count < MaxCount))
332 {
333 CacheDescriptors[Count].Level = 3;
334 CacheDescriptors[Count].Type = CacheUnified;
335 CacheDescriptors[Count].Size = CacheInfoRegs.Edx.Bits.L3Size * 512 * 1024;
336 CacheDescriptors[Count].Associativity = AssocMap[CacheInfoRegs.Edx.Bits.L3Assoc];
337 CacheDescriptors[Count].LineSize = CacheInfoRegs.Edx.Bits.L3LineSize;
338 Count++;
339 }
340
341 return Count;
342}
343
353static
354ULONG
356 _Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors,
357 _In_ ULONG MaxCount,
358 _In_ ULONG CpuIdLeaf)
359{
361 ULONG Subleaf;
362 ULONG Count;
363
364 Count = 0;
365
366 /* Iterate through subleaves, bail out at 32 or when all descriptors are filled */
367 for (Subleaf = 0; (Subleaf < 32) && (Count < MaxCount); Subleaf++)
368 {
369 __cpuidex(Regs.AsInt32, CpuIdLeaf, Subleaf);
370
371 switch (Regs.Eax.Bits.CacheType)
372 {
374 CacheDescriptors[Count].Type = CacheData;
375 break;
376
378 CacheDescriptors[Count].Type = CacheInstruction;
379 break;
380
382 CacheDescriptors[Count].Type = CacheUnified;
383 break;
384
386 return Count;
387
388 default:
389 continue;
390 }
391
392 if (Regs.Eax.Bits.FullyAssociativeCache)
393 {
394 CacheDescriptors[Count].Associativity = 0xFF;
395 }
396 else
397 {
398 ULONG Ways = Regs.Ebx.Bits.Ways + 1;
399 CacheDescriptors[Count].Associativity = (Ways > 0xFE) ? 0xFE : (UCHAR)Ways;
400 }
401
402 CacheDescriptors[Count].Level = (UCHAR)Regs.Eax.Bits.CacheLevel;
403 CacheDescriptors[Count].LineSize = (USHORT)(Regs.Ebx.Bits.LineSize + 1);
404 CacheDescriptors[Count].Size = (Regs.Ebx.Bits.Ways + 1) *
405 (Regs.Ebx.Bits.LinePartitions + 1) *
406 (Regs.Ebx.Bits.LineSize + 1) *
407 (Regs.NumberOfSets + 1);
408 Count++;
409 }
410
411 return Count;
412}
413
423static
424ULONG
426 _Inout_updates_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors,
427 _In_ ULONG CacheCount,
428 _In_ ULONG MaxCount)
429{
430 ULONG l, r, i;
431 ULONG NewCount = 0;
432
433 /* Sort the array */
434 for (l = 0; l < CacheCount; l++)
435 {
436 for (r = l + 1; r < CacheCount; r++)
437 {
438 /* Sort order: 1. Level (ascending), 2. Type (enum value, descending) */
439 if ((CacheDescriptors[l].Level > CacheDescriptors[r].Level) ||
440 ((CacheDescriptors[l].Level == CacheDescriptors[r].Level) &&
441 (CacheDescriptors[l].Type < CacheDescriptors[r].Type)))
442 {
443 CACHE_DESCRIPTOR Temp = CacheDescriptors[l];
444 CacheDescriptors[l] = CacheDescriptors[r];
445 CacheDescriptors[r] = Temp;
446 }
447 }
448 }
449
450 /* Remove duplicates */
451 if (CacheCount > 0)
452 {
453 CacheDescriptors[0] = CacheDescriptors[0];
454 NewCount = 1;
455 for (i = 1; i < CacheCount; i++)
456 {
457 if ((CacheDescriptors[i].Level != CacheDescriptors[i - 1].Level) ||
458 (CacheDescriptors[i].Type != CacheDescriptors[i - 1].Type))
459 {
460 CacheDescriptors[NewCount] = CacheDescriptors[i];
461 NewCount++;
462 }
463 }
464 }
465
466 /* Clear stray entries */
467 RtlZeroMemory(&CacheDescriptors[NewCount],
468 sizeof(CACHE_DESCRIPTOR) * (MaxCount - NewCount));
469
470 return NewCount;
471}
472
482ULONG
483NTAPI
485 _Out_writes_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors,
486 _In_ ULONG MaxCount,
487 _In_ CPU_VENDORS Vendor)
488{
490 CPUID_EXTENDED_FUNCTION_REGS ExtendedFunction;
491 ULONG Count = 0;
492
493 /* Get the maximum leaf and maximum extended leaf */
495 __cpuid(ExtendedFunction.AsInt32, CPUID_EXTENDED_FUNCTION);
496
497 /* Distinguish by vendor: AMD (and Hygon) have their own custom cpuid leaves. */
498 if (Vendor == CPU_AMD)
499 {
500 if (ExtendedFunction.MaxLeaf >= CPUID_CACHE_PARAMS_AMD)
501 {
502 Count = KiGetCacheInfoModern(CacheDescriptors, MaxCount, CPUID_CACHE_PARAMS_AMD);
503 }
504
505 if ((Count == 0) && (ExtendedFunction.MaxLeaf >= CPUID_EXTENDED_CACHE_INFO))
506 {
507 Count = GetCacheInfoAmdLegacy(CacheDescriptors, MaxCount);
508 }
509 }
510 else
511 {
512 if (Signature.MaxLeaf >= CPUID_CACHE_PARAMS)
513 {
514 Count = KiGetCacheInfoModern(CacheDescriptors, MaxCount, CPUID_CACHE_PARAMS);
515 }
516
517 if ((Count == 0) && (Signature.MaxLeaf >= CPUID_CACHE_INFO))
518 {
519 Count = GetCacheInfoIntelLeaf2(CacheDescriptors, MaxCount);
520 }
521 }
522
523 /* Normalize the descriptors */
524 Count = NormalizeCacheDescriptors(CacheDescriptors, Count, MaxCount);
525
526 return Count;
527}
#define CPUID_L1_TLB_INFO
Definition: Cpuid.h:180
#define CPUID_CACHE_PARAMS_AMD
Definition: Cpuid.h:393
#define CPUID_CACHE_PARAMS_CACHE_TYPE_UNIFIED
Definition: Cpuid.h:869
#define CPUID_EXTENDED_FUNCTION
Definition: Cpuid.h:3802
#define CPUID_SIGNATURE
Definition: Cpuid.h:45
#define CPUID_CACHE_PARAMS_CACHE_TYPE_NULL
Definition: Cpuid.h:866
#define CPUID_CACHE_PARAMS
Definition: Cpuid.h:802
#define CPUID_CACHE_INFO
Definition: Cpuid.h:710
#define CPUID_CACHE_PARAMS_CACHE_TYPE_INSTRUCTION
Definition: Cpuid.h:868
#define CPUID_CACHE_PARAMS_CACHE_TYPE_DATA
Definition: Cpuid.h:867
#define CPUID_EXTENDED_CACHE_INFO
Definition: Cpuid.h:3998
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
r l[0]
Definition: byte_order.h:168
static const INTEL_CACHE_DESCRIPTOR * FindIntelCacheDescriptor(_In_ UCHAR DescriptorCode)
Finds the cache descriptor for the given descriptor value.
Definition: cacheinfo.c:168
ULONG NTAPI KiGetCpuCacheDescriptors(_Out_writes_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors, _In_ ULONG MaxCount, _In_ CPU_VENDORS Vendor)
Retrieves cache descriptors for the current CPU.
Definition: cacheinfo.c:484
static const INTEL_CACHE_DESCRIPTOR IntelCacheDescriptors[]
Table of known Intel cache descriptors, as defined in the Intel SDM.
Definition: cacheinfo.c:39
static ULONG NormalizeCacheDescriptors(_Inout_updates_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors, _In_ ULONG CacheCount, _In_ ULONG MaxCount)
Normalizes the cache descriptors by removing duplicates and sorting them.
Definition: cacheinfo.c:425
static ULONG GetCacheInfoIntelLeaf2(_Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors, _In_ ULONG MaxCount)
Retrieves cache information using CPUID leaf 2 for Intel processors.
Definition: cacheinfo.c:207
static ULONG KiGetCacheInfoModern(_Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors, _In_ ULONG MaxCount, _In_ ULONG CpuIdLeaf)
Retrieves cache information for modern Intel/AMD processors.
Definition: cacheinfo.c:355
static ULONG GetCacheInfoAmdLegacy(_Out_cap_(MaxCount) PCACHE_DESCRIPTOR CacheDescriptors, _In_ ULONG MaxCount)
Retrieves cache information for legacy AMD processors.
Definition: cacheinfo.c:281
#define ARRAYSIZE(a)
Definition: cat.c:25
_In_ ULONG _In_ UCHAR Level
Definition: dispmprt.h:1329
#define NULL
Definition: types.h:112
unsigned char Byte
Definition: zlib.h:37
static const WCHAR Signature[]
Definition: parser.c:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PPC_QUAL void __cpuid(int CPUInfo[], const int InfoType)
Definition: intrin_ppc.h:682
__INTRIN_INLINE void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
Definition: intrin_x86.h:1680
#define C_ASSERT(e)
Definition: intsafe.h:73
static struct proto Pass[]
Definition: mkg3states.c:56
#define _Out_cap_(size)
Definition: ms_sal.h:852
CPU_VENDORS
Definition: ketypes.h:97
@ CPU_AMD
Definition: ketypes.h:99
#define _Inout_updates_(s)
Definition: no_sal2.h:182
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
unsigned short USHORT
Definition: pedump.c:61
@ High
Definition: strmini.h:378
@ Low
Definition: strmini.h:380
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG
Definition: typedefs.h:59
struct CPUID_AMD_EXTENDED_CACHE_INFO_ECX::@4435 Bits
struct CPUID_AMD_EXTENDED_CACHE_INFO_EDX::@4436 Bits
CPUID_AMD_EXTENDED_CACHE_INFO_EDX Edx
Definition: Cpuid.h:317
CPUID_AMD_EXTENDED_CACHE_INFO_ECX Ecx
Definition: Cpuid.h:316
struct CPUID_CACHE_INFO_CACHE_TLB::@4514 Bits
UINT8 CacheDescriptor[4]
Definition: Cpuid.h:731
CPUID_CACHE_INFO_CACHE_TLB Eax
Definition: Cpuid.h:43
CPUID_CACHE_INFO_CACHE_TLB Regs[4]
Definition: Cpuid.h:48
INT32 AsInt32[4]
Definition: Cpuid.h:40
struct CPUID_CACHE_PARAMS_EAX::@4515 Bits
struct CPUID_CACHE_PARAMS_EBX::@4516 Bits
INT32 AsInt32[4]
Definition: Cpuid.h:54
CPUID_CACHE_PARAMS_EBX Ebx
Definition: Cpuid.h:58
CPUID_CACHE_PARAMS_EAX Eax
Definition: Cpuid.h:57
struct CPUID_L1_TLB_INFO_REGS::@4431 Amd
INT32 AsInt32[4]
Definition: Cpuid.h:233
_In_ UCHAR _In_ UCHAR _In_ ULONG Code
Definition: wdfdevice.h:1707
@ CacheInstruction
Definition: ketypes.h:45
@ CacheUnified
Definition: ketypes.h:44
@ CacheData
Definition: ketypes.h:46