@@ -26,6 +26,8 @@ struct x86_cpu {
struct cpu cpu;
};
+void apply_forced_caps(struct cpuinfo_x86 *c);
+
#ifdef CONFIG_HOTPLUG_CPU
extern int arch_register_cpu(int num);
extern void arch_unregister_cpu(int);
@@ -758,13 +758,14 @@ void cpu_detect(struct cpuinfo_x86 *c)
}
}
-static void apply_forced_caps(struct cpuinfo_x86 *c)
+void apply_forced_caps(struct cpuinfo_x86 *c)
{
int i;
for (i = 0; i < NCAPINTS + NBUGINTS; i++) {
- c->x86_capability[i] &= ~cpu_caps_cleared[i];
+ /* Bits may be cleared after they are set. */
c->x86_capability[i] |= cpu_caps_set[i];
+ c->x86_capability[i] &= ~cpu_caps_cleared[i];
}
}
@@ -5,6 +5,7 @@
#include <asm/tlbflush.h>
#include <asm/setup.h>
#include <asm/cmdline.h>
+#include <asm/cpu.h>
#include <linux/sched.h>
#include <linux/sched/task.h>
@@ -261,6 +262,7 @@ static void __init clear_cpuid(void)
bit >= 0 && bit < NCAPINTS * 32)
setup_clear_cpu_cap(bit);
}
+ apply_forced_caps(&boot_cpu_data);
}
/*
Some CPU feature bits are forced set and stored in cpuinfo_x86 before handling clearcpuid options. To clear those bits from cpuinfo_x86, apply_forced_cap() is called after handling the options. Please note, apply_forced_cap() is called twice on boot CPU. But this code is simple and there is no functionality issue. Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> --- arch/x86/include/asm/cpu.h | 2 ++ arch/x86/kernel/cpu/common.c | 5 +++-- arch/x86/kernel/fpu/init.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-)