]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/microcode/intel: Add a helper which gives the microcode revision
authorBorislav Petkov <bp@suse.de>
Mon, 9 Jan 2017 11:41:45 +0000 (12:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 16 May 2019 17:45:07 +0000 (19:45 +0200)
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>
arch/x86/include/asm/microcode_intel.h
arch/x86/kernel/cpu/intel.c
arch/x86/kernel/cpu/microcode/intel.c

index 8559b0102ea1f14dfc840c28df6e1fcc0f813965..90343ba50485b729543ecb8b20c7f9597a81e4dd 100644 (file)
@@ -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);
index b18fe3d245fed0e6be26be08e83dbcb8042e7425..b0e0c7a12e61adc7004f6f8c99671e1ba2a79b9b 100644 (file)
@@ -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) ||
index 2f38a99cdb98232835767c9c2a990f72f7be7e2a..f3bc28f7ce3959e6228b378a546e8aa83ac68fff 100644 (file)
@@ -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();
 
-       /* get the current revision from MSR 0x8B */
-       rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+       rev = intel_get_microcode_revision();
 
-       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;
 }