144 lines
4.2 KiB
Diff
144 lines
4.2 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Ashok Raj <ashok.raj@intel.com>
|
||
|
Date: Sat, 20 Jul 2019 14:14:47 +0000
|
||
|
Subject: [PATCH] x86/microcode: Force update a uCode even if the rev is the
|
||
|
same
|
||
|
|
||
|
Signed-off-by: Ashok Raj <ashok.raj@intel.com>
|
||
|
---
|
||
|
arch/x86/kernel/cpu/microcode/core.c | 1 +
|
||
|
arch/x86/kernel/cpu/microcode/intel.c | 57 +++++++++++++++++++++++++--
|
||
|
2 files changed, 55 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
|
||
|
index cb0fdcaf1415..d44fe3e5c028 100644
|
||
|
--- a/arch/x86/kernel/cpu/microcode/core.c
|
||
|
+++ b/arch/x86/kernel/cpu/microcode/core.c
|
||
|
@@ -601,6 +601,7 @@ static int microcode_reload_late(void)
|
||
|
atomic_set(&late_cpus_in, 0);
|
||
|
atomic_set(&late_cpus_out, 0);
|
||
|
|
||
|
+ printk ("Going to do stop_machine\n");
|
||
|
ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
|
||
|
if (ret > 0)
|
||
|
microcode_check();
|
||
|
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
|
||
|
index ce799cfe9434..9e85d785b226 100644
|
||
|
--- a/arch/x86/kernel/cpu/microcode/intel.c
|
||
|
+++ b/arch/x86/kernel/cpu/microcode/intel.c
|
||
|
@@ -30,6 +30,7 @@
|
||
|
#include <linux/uio.h>
|
||
|
#include <linux/mm.h>
|
||
|
|
||
|
+#include <asm/cmdline.h>
|
||
|
#include <asm/microcode_intel.h>
|
||
|
#include <asm/intel-family.h>
|
||
|
#include <asm/processor.h>
|
||
|
@@ -38,6 +39,7 @@
|
||
|
#include <asm/msr.h>
|
||
|
|
||
|
static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
|
||
|
+static bool force_ucode_load = false;
|
||
|
|
||
|
/* Current microcode patch used in early patching on the APs. */
|
||
|
static struct microcode_intel *intel_ucode_patch;
|
||
|
@@ -94,8 +96,18 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev
|
||
|
{
|
||
|
struct microcode_header_intel *mc_hdr = mc;
|
||
|
|
||
|
- if (mc_hdr->rev <= new_rev)
|
||
|
+ //if (mc_hdr->rev <= new_rev)
|
||
|
+ if (mc_hdr->rev < new_rev) {
|
||
|
+ printk ("Returning NO_NEW old = 0x%x new = 0x%x\n",
|
||
|
+ mc_hdr->rev, new_rev);
|
||
|
return 0;
|
||
|
+ }
|
||
|
+ if ((mc_hdr->rev == new_rev) && !force_ucode_load) {
|
||
|
+ printk ("SAME REV: no_force Returning NO_NEW old = 0x%x new = 0x%x\n",
|
||
|
+ mc_hdr->rev, new_rev);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ printk ("ucode: force loading same rev\n");
|
||
|
|
||
|
return find_matching_signature(mc, csig, cpf);
|
||
|
}
|
||
|
@@ -593,11 +605,20 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
|
||
|
* already.
|
||
|
*/
|
||
|
rev = intel_get_microcode_revision();
|
||
|
- if (rev >= mc->hdr.rev) {
|
||
|
+ if (rev > mc->hdr.rev) {
|
||
|
uci->cpu_sig.rev = rev;
|
||
|
return UCODE_OK;
|
||
|
}
|
||
|
|
||
|
+ if (rev == mc->hdr.rev) {
|
||
|
+ if (!force_ucode_load) {
|
||
|
+ printk ("Matching ucode rev, no update\n");
|
||
|
+ return UCODE_OK;
|
||
|
+ } else {
|
||
|
+ printk ("Matching ucode rev.. force updating\n");
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
/*
|
||
|
* Writeback and invalidate caches before updating microcode to avoid
|
||
|
* internal issues depending on what the microcode is updating.
|
||
|
@@ -649,6 +670,29 @@ int __init save_microcode_in_initrd_intel(void)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static bool check_force_ucode_bsp(void)
|
||
|
+{
|
||
|
+ static const char *__force_ucode_str = "force_ucode_load";
|
||
|
+
|
||
|
+#ifdef CONFIG_X86_32
|
||
|
+ const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
|
||
|
+ const char *option = (const char *)__pa_nodebug(__force_ucode_str);
|
||
|
+ bool *res = (bool *)__pa_nodebug(&force_ucode_load);
|
||
|
+
|
||
|
+#else /* CONFIG_X86_64 */
|
||
|
+ const char *cmdline = boot_command_line;
|
||
|
+ const char *option = __force_ucode_str;
|
||
|
+ bool *res = &force_ucode_load;
|
||
|
+#endif
|
||
|
+
|
||
|
+ if (cmdline_find_option_bool(cmdline, option)) {
|
||
|
+ printk("cmdline forcing ucode update for same rev\n");
|
||
|
+ *res = true;
|
||
|
+ }
|
||
|
+
|
||
|
+ return *res;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* @res_patch, output: a pointer to the patch we found.
|
||
|
*/
|
||
|
@@ -682,6 +726,9 @@ void __init load_ucode_intel_bsp(void)
|
||
|
{
|
||
|
struct microcode_intel *patch;
|
||
|
struct ucode_cpu_info uci;
|
||
|
+ bool force_bsp;
|
||
|
+
|
||
|
+ force_bsp = check_force_ucode_bsp();
|
||
|
|
||
|
patch = __load_ucode_intel(&uci);
|
||
|
if (!patch)
|
||
|
@@ -730,8 +777,12 @@ static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
|
||
|
|
||
|
phdr = (struct microcode_header_intel *)iter->data;
|
||
|
|
||
|
- if (phdr->rev <= uci->cpu_sig.rev)
|
||
|
+ if (phdr->rev < uci->cpu_sig.rev)
|
||
|
continue;
|
||
|
+ if (phdr->rev == uci->cpu_sig.rev && !force_ucode_load)
|
||
|
+ continue;
|
||
|
+ else
|
||
|
+ printk ("same rev forcing ucode\n");
|
||
|
|
||
|
if (!find_matching_signature(phdr,
|
||
|
uci->cpu_sig.sig,
|
||
|
--
|
||
|
https://clearlinux.org
|
||
|
|