@@ -160,6 +160,10 @@ static inline void __cpuid_read_reg(u32 leaf, u32 subleaf,
160
160
__cpuid_read_reg(leaf, 0, regidx, (u32 *)(reg)); \
161
161
}
162
162
163
+ /*
164
+ * Hypervisor-related APIs:
165
+ */
166
+
163
167
static __always_inline bool cpuid_function_is_indexed (u32 function )
164
168
{
165
169
switch (function ) {
@@ -208,7 +212,76 @@ static inline u32 hypervisor_cpuid_base(const char *sig, u32 leaves)
208
212
}
209
213
210
214
/*
211
- * CPUID(0x80000006) parsing helpers
215
+ * CPUID(0x2) parsing:
216
+ */
217
+
218
+ /**
219
+ * cpuid_get_leaf_0x2_regs() - Return sanitized leaf 0x2 register output
220
+ * @regs: Output parameter
221
+ *
222
+ * Query CPUID leaf 0x2 and store its output in @regs. Force set any
223
+ * invalid 1-byte descriptor returned by the hardware to zero (the NULL
224
+ * cache/TLB descriptor) before returning it to the caller.
225
+ *
226
+ * Use for_each_leaf_0x2_entry() to iterate over the register output in
227
+ * parsed form.
228
+ */
229
+ static inline void cpuid_get_leaf_0x2_regs (union leaf_0x2_regs * regs )
230
+ {
231
+ cpuid_leaf (0x2 , regs );
232
+
233
+ /*
234
+ * All Intel CPUs must report an iteration count of 1. In case
235
+ * of bogus hardware, treat all returned descriptors as NULL.
236
+ */
237
+ if (regs -> desc [0 ] != 0x01 ) {
238
+ for (int i = 0 ; i < 4 ; i ++ )
239
+ regs -> regv [i ] = 0 ;
240
+ return ;
241
+ }
242
+
243
+ /*
244
+ * The most significant bit (MSB) of each register must be clear.
245
+ * If a register is invalid, replace its descriptors with NULL.
246
+ */
247
+ for (int i = 0 ; i < 4 ; i ++ ) {
248
+ if (regs -> reg [i ].invalid )
249
+ regs -> regv [i ] = 0 ;
250
+ }
251
+ }
252
+
253
+ /**
254
+ * for_each_leaf_0x2_entry() - Iterator for parsed leaf 0x2 descriptors
255
+ * @regs: Leaf 0x2 register output, returned by cpuid_get_leaf_0x2_regs()
256
+ * @__ptr: u8 pointer, for macro internal use only
257
+ * @entry: Pointer to parsed descriptor information at each iteration
258
+ *
259
+ * Loop over the 1-byte descriptors in the passed leaf 0x2 output registers
260
+ * @regs. Provide the parsed information for each descriptor through @entry.
261
+ *
262
+ * To handle cache-specific descriptors, switch on @entry->c_type. For TLB
263
+ * descriptors, switch on @entry->t_type.
264
+ *
265
+ * Example usage for cache descriptors::
266
+ *
267
+ * const struct leaf_0x2_table *entry;
268
+ * union leaf_0x2_regs regs;
269
+ * u8 *ptr;
270
+ *
271
+ * cpuid_get_leaf_0x2_regs(®s);
272
+ * for_each_leaf_0x2_entry(regs, ptr, entry) {
273
+ * switch (entry->c_type) {
274
+ * ...
275
+ * }
276
+ * }
277
+ */
278
+ #define for_each_leaf_0x2_entry (regs , __ptr , entry ) \
279
+ for (__ptr = &(regs).desc[1]; \
280
+ __ptr < &(regs).desc[16] && (entry = &cpuid_0x2_table[*__ptr]); \
281
+ __ptr++)
282
+
283
+ /*
284
+ * CPUID(0x80000006) parsing:
212
285
*/
213
286
214
287
static inline bool cpuid_amd_hygon_has_l3_cache (void )
0 commit comments