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: 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>
This commit is contained in:
parent
f3e2a51f56
commit
4167709bbf
@ -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 @@
|
|||||||
#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)
|
|||||||
(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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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 */
|
rev = intel_get_microcode_revision();
|
||||||
native_cpuid_eax(1);
|
|
||||||
|
|
||||||
/* get the current revision from MSR 0x8B */
|
if (rev != mc->hdr.rev) {
|
||||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
|
||||||
|
|
||||||
if (val[1] != 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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user