x86/microcode/intel: Add a helper which gives the microcode revision
commit 4167709bbf826512a52ebd6aafda2be104adaec9 upstream. Since on Intel we're required to do CPUID(1) first, before reading the microcode revision MSR, let's add a special helper which does the required steps so that we don't forget to do them next time, when we want to read the microcode revision. Signed-off-by: Borislav Petkov <bp@suse.de> Link: http://lkml.kernel.org/r/20170109114147.5082-4-bp@alien8.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de> [bwh: Backported to 4.4: - Don't touch prev_rev variable in apply_microcode() - Keep using sync_core(), which will alway includes the necessary CPUID - Adjust context] Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
5ec6421c21
commit
98cc1464cf
@ -53,6 +53,21 @@ struct extended_sigtable {
|
||||
|
||||
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
|
||||
|
||||
static inline u32 intel_get_microcode_revision(void)
|
||||
{
|
||||
u32 rev, dummy;
|
||||
|
||||
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
|
||||
|
||||
/* As documented in the SDM: Do a CPUID 1 here */
|
||||
sync_core();
|
||||
|
||||
/* get the current revision from MSR 0x8B */
|
||||
native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
|
||||
|
||||
return rev;
|
||||
}
|
||||
|
||||
extern int has_newer_microcode(void *mc, unsigned int csig, int cpf, int rev);
|
||||
extern int microcode_sanity_check(void *mc, int print_err);
|
||||
extern int find_matching_signature(void *mc, unsigned int csig, int cpf);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <asm/bugs.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/microcode_intel.h>
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#include <linux/topology.h>
|
||||
@ -102,14 +103,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
|
||||
(c->x86 == 0x6 && c->x86_model >= 0x0e))
|
||||
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
|
||||
|
||||
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) {
|
||||
unsigned lower_word;
|
||||
|
||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
/* Required by the SDM */
|
||||
sync_core();
|
||||
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
|
||||
}
|
||||
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
|
||||
c->microcode = intel_get_microcode_revision();
|
||||
|
||||
/* Now if any of them are set, check the blacklist and clear the lot */
|
||||
if ((cpu_has(c, X86_FEATURE_SPEC_CTRL) ||
|
||||
|
@ -376,15 +376,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
|
||||
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
|
||||
csig.pf = 1 << ((val[1] >> 18) & 7);
|
||||
}
|
||||
native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
|
||||
/* As documented in the SDM: Do a CPUID 1 here */
|
||||
sync_core();
|
||||
|
||||
/* get the current revision from MSR 0x8B */
|
||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
||||
|
||||
csig.rev = val[1];
|
||||
csig.rev = intel_get_microcode_revision();
|
||||
|
||||
uci->cpu_sig = csig;
|
||||
uci->valid = 1;
|
||||
@ -654,7 +647,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
|
||||
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||
{
|
||||
struct microcode_intel *mc_intel;
|
||||
unsigned int val[2];
|
||||
u32 rev;
|
||||
|
||||
mc_intel = uci->mc;
|
||||
if (mc_intel == NULL)
|
||||
@ -664,21 +657,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||||
native_wrmsr(MSR_IA32_UCODE_WRITE,
|
||||
(unsigned long) mc_intel->bits,
|
||||
(unsigned long) mc_intel->bits >> 16 >> 16);
|
||||
native_wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
|
||||
/* As documented in the SDM: Do a CPUID 1 here */
|
||||
sync_core();
|
||||
|
||||
/* get the current revision from MSR 0x8B */
|
||||
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
||||
if (val[1] != mc_intel->hdr.rev)
|
||||
rev = intel_get_microcode_revision();
|
||||
if (rev != mc_intel->hdr.rev)
|
||||
return -1;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/* Flush global tlb. This is precaution. */
|
||||
flush_tlb_early();
|
||||
#endif
|
||||
uci->cpu_sig.rev = val[1];
|
||||
uci->cpu_sig.rev = rev;
|
||||
|
||||
if (early)
|
||||
print_ucode(uci);
|
||||
@ -852,7 +840,7 @@ static int apply_microcode_intel(int cpu)
|
||||
{
|
||||
struct microcode_intel *mc_intel;
|
||||
struct ucode_cpu_info *uci;
|
||||
unsigned int val[2];
|
||||
u32 rev;
|
||||
int cpu_num = raw_smp_processor_id();
|
||||
struct cpuinfo_x86 *c = &cpu_data(cpu_num);
|
||||
|
||||
@ -877,27 +865,22 @@ static int apply_microcode_intel(int cpu)
|
||||
wrmsr(MSR_IA32_UCODE_WRITE,
|
||||
(unsigned long) mc_intel->bits,
|
||||
(unsigned long) mc_intel->bits >> 16 >> 16);
|
||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
|
||||
/* As documented in the SDM: Do a CPUID 1 here */
|
||||
sync_core();
|
||||
rev = intel_get_microcode_revision();
|
||||
|
||||
/* get the current revision from MSR 0x8B */
|
||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
||||
|
||||
if (val[1] != mc_intel->hdr.rev) {
|
||||
if (rev != mc_intel->hdr.rev) {
|
||||
pr_err("CPU%d update to revision 0x%x failed\n",
|
||||
cpu_num, mc_intel->hdr.rev);
|
||||
return -1;
|
||||
}
|
||||
pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
||||
cpu_num, val[1],
|
||||
cpu_num, rev,
|
||||
mc_intel->hdr.date & 0xffff,
|
||||
mc_intel->hdr.date >> 24,
|
||||
(mc_intel->hdr.date >> 16) & 0xff);
|
||||
|
||||
uci->cpu_sig.rev = val[1];
|
||||
c->microcode = val[1];
|
||||
uci->cpu_sig.rev = rev;
|
||||
c->microcode = rev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user