Commit 4167709b authored by Borislav Petkov's avatar Borislav Petkov Committed by Thomas Gleixner

x86/microcode/intel: Add a helper which gives the microcode revision

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: default avatarBorislav Petkov <bp@suse.de>
Link: http://lkml.kernel.org/r/20170109114147.5082-4-bp@alien8.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent f3e2a51f
...@@ -52,6 +52,21 @@ struct extended_sigtable { ...@@ -52,6 +52,21 @@ struct extended_sigtable {
#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE) #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 */
native_cpuid_eax(1);
/* get the current revision from MSR 0x8B */
native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
return rev;
}
#ifdef CONFIG_MICROCODE_INTEL #ifdef CONFIG_MICROCODE_INTEL
extern void __init load_ucode_intel_bsp(void); extern void __init load_ucode_intel_bsp(void);
extern void load_ucode_intel_ap(void); extern void load_ucode_intel_ap(void);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/bugs.h> #include <asm/bugs.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#include <asm/intel-family.h> #include <asm/intel-family.h>
#include <asm/microcode_intel.h>
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#include <linux/topology.h> #include <linux/topology.h>
...@@ -78,14 +79,8 @@ static void early_init_intel(struct cpuinfo_x86 *c) ...@@ -78,14 +79,8 @@ static void early_init_intel(struct cpuinfo_x86 *c)
(c->x86 == 0x6 && c->x86_model >= 0x0e)) (c->x86 == 0x6 && c->x86_model >= 0x0e))
set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64)) { if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
unsigned lower_word; c->microcode = intel_get_microcode_revision();
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
/* Required by the SDM */
native_cpuid_eax(1);
rdmsr(MSR_IA32_UCODE_REV, lower_word, c->microcode);
}
/* /*
* Atom erratum AAE44/AAF40/AAG38/AAH41: * Atom erratum AAE44/AAF40/AAG38/AAH41:
......
...@@ -390,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) ...@@ -390,15 +390,8 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci)
native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
csig.pf = 1 << ((val[1] >> 18) & 7); csig.pf = 1 << ((val[1] >> 18) & 7);
} }
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
/* As documented in the SDM: Do a CPUID 1 here */ csig.rev = intel_get_microcode_revision();
native_cpuid_eax(1);
/* get the current revision from MSR 0x8B */
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
csig.rev = val[1];
uci->cpu_sig = csig; uci->cpu_sig = csig;
uci->valid = 1; uci->valid = 1;
...@@ -582,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci) ...@@ -582,7 +575,7 @@ static inline void print_ucode(struct ucode_cpu_info *uci)
static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
{ {
struct microcode_intel *mc; struct microcode_intel *mc;
unsigned int val[2]; u32 rev;
mc = uci->mc; mc = uci->mc;
if (!mc) if (!mc)
...@@ -590,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) ...@@ -590,21 +583,16 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
/* write microcode via MSR 0x79 */ /* write microcode via MSR 0x79 */
native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
native_wrmsrl(MSR_IA32_UCODE_REV, 0);
/* As documented in the SDM: Do a CPUID 1 here */ rev = intel_get_microcode_revision();
native_cpuid_eax(1); if (rev != mc->hdr.rev)
/* get the current revision from MSR 0x8B */
native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
if (val[1] != mc->hdr.rev)
return -1; return -1;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/* Flush global tlb. This is precaution. */ /* Flush global tlb. This is precaution. */
flush_tlb_early(); flush_tlb_early();
#endif #endif
uci->cpu_sig.rev = val[1]; uci->cpu_sig.rev = rev;
if (early) if (early)
print_ucode(uci); print_ucode(uci);
...@@ -784,8 +772,8 @@ static int apply_microcode_intel(int cpu) ...@@ -784,8 +772,8 @@ static int apply_microcode_intel(int cpu)
struct microcode_intel *mc; struct microcode_intel *mc;
struct ucode_cpu_info *uci; struct ucode_cpu_info *uci;
struct cpuinfo_x86 *c; struct cpuinfo_x86 *c;
unsigned int val[2];
static int prev_rev; static int prev_rev;
u32 rev;
/* We should bind the task to the CPU */ /* We should bind the task to the CPU */
if (WARN_ON(raw_smp_processor_id() != cpu)) if (WARN_ON(raw_smp_processor_id() != cpu))
...@@ -802,33 +790,28 @@ static int apply_microcode_intel(int cpu) ...@@ -802,33 +790,28 @@ static int apply_microcode_intel(int cpu)
/* write microcode via MSR 0x79 */ /* write microcode via MSR 0x79 */
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
wrmsrl(MSR_IA32_UCODE_REV, 0);
/* As documented in the SDM: Do a CPUID 1 here */
native_cpuid_eax(1);
/* get the current revision from MSR 0x8B */ rev = intel_get_microcode_revision();
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
if (val[1] != mc->hdr.rev) { if (rev != mc->hdr.rev) {
pr_err("CPU%d update to revision 0x%x failed\n", pr_err("CPU%d update to revision 0x%x failed\n",
cpu, mc->hdr.rev); cpu, mc->hdr.rev);
return -1; return -1;
} }
if (val[1] != prev_rev) { if (rev != prev_rev) {
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n", pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
val[1], rev,
mc->hdr.date & 0xffff, mc->hdr.date & 0xffff,
mc->hdr.date >> 24, mc->hdr.date >> 24,
(mc->hdr.date >> 16) & 0xff); (mc->hdr.date >> 16) & 0xff);
prev_rev = val[1]; prev_rev = rev;
} }
c = &cpu_data(cpu); c = &cpu_data(cpu);
uci->cpu_sig.rev = val[1]; uci->cpu_sig.rev = rev;
c->microcode = val[1]; c->microcode = rev;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment