Skip to content

Commit 47bdf33

Browse files
He ChenKAGA-KOKO
authored andcommitted
x86/cpuid: Provide get_scattered_cpuid_leaf()
Sparse populated CPUID leafs are collected in a software provided leaf to avoid bloat of the x86_capability array, but there is no way to rebuild the real leafs (e.g. for KVM CPUID enumeration) other than rereading the CPUID leaf from the CPU. While this is possible it is problematic as it does not take software disabled features into account. If a feature is disabled on the host it should not be exposed to a guest either. Add get_scattered_cpuid_leaf() which rebuilds the leaf from the scattered cpuid table information and the active CPU features. [ tglx: Rewrote changelog ] Signed-off-by: He Chen <[email protected]> Reviewed-by: Borislav Petkov <[email protected]> Cc: Luwei Kang <[email protected]> Cc: [email protected] Cc: Radim Krčmář <[email protected]> Cc: Piotr Luc <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Paolo Bonzini <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent 47f10a3 commit 47bdf33

File tree

2 files changed

+40
-12
lines changed

2 files changed

+40
-12
lines changed

arch/x86/include/asm/processor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
189189
extern void print_cpu_info(struct cpuinfo_x86 *);
190190
void print_cpu_msr(struct cpuinfo_x86 *);
191191
extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
192+
extern u32 get_scattered_cpuid_leaf(unsigned int level,
193+
unsigned int sub_leaf,
194+
enum cpuid_regs_idx reg);
192195
extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
193196
extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
194197

arch/x86/kernel/cpu/scattered.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,25 @@ struct cpuid_bit {
1717
u32 sub_leaf;
1818
};
1919

20+
/* Please keep the leaf sorted by cpuid_bit.level for faster search. */
21+
static const struct cpuid_bit cpuid_bits[] = {
22+
{ X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
23+
{ X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
24+
{ X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x00000007, 0 },
25+
{ X86_FEATURE_AVX512_4VNNIW, CPUID_EDX, 2, 0x00000007, 0 },
26+
{ X86_FEATURE_AVX512_4FMAPS, CPUID_EDX, 3, 0x00000007, 0 },
27+
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
28+
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
29+
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
30+
{ 0, 0, 0, 0, 0 }
31+
};
32+
2033
void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
2134
{
2235
u32 max_level;
2336
u32 regs[4];
2437
const struct cpuid_bit *cb;
2538

26-
static const struct cpuid_bit cpuid_bits[] = {
27-
{ X86_FEATURE_INTEL_PT, CPUID_EBX, 25, 0x00000007, 0 },
28-
{ X86_FEATURE_AVX512_4VNNIW, CPUID_EDX, 2, 0x00000007, 0 },
29-
{ X86_FEATURE_AVX512_4FMAPS, CPUID_EDX, 3, 0x00000007, 0 },
30-
{ X86_FEATURE_APERFMPERF, CPUID_ECX, 0, 0x00000006, 0 },
31-
{ X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
32-
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
33-
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
34-
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
35-
{ 0, 0, 0, 0, 0 }
36-
};
37-
3839
for (cb = cpuid_bits; cb->feature; cb++) {
3940

4041
/* Verify that the level is valid */
@@ -51,3 +52,27 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
5152
set_cpu_cap(c, cb->feature);
5253
}
5354
}
55+
56+
u32 get_scattered_cpuid_leaf(unsigned int level, unsigned int sub_leaf,
57+
enum cpuid_regs_idx reg)
58+
{
59+
const struct cpuid_bit *cb;
60+
u32 cpuid_val = 0;
61+
62+
for (cb = cpuid_bits; cb->feature; cb++) {
63+
64+
if (level > cb->level)
65+
continue;
66+
67+
if (level < cb->level)
68+
break;
69+
70+
if (reg == cb->reg && sub_leaf == cb->sub_leaf) {
71+
if (cpu_has(&boot_cpu_data, cb->feature))
72+
cpuid_val |= BIT(cb->bit);
73+
}
74+
}
75+
76+
return cpuid_val;
77+
}
78+
EXPORT_SYMBOL_GPL(get_scattered_cpuid_leaf);

0 commit comments

Comments
 (0)