mirror of
https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
synced 2024-09-21 01:47:28 +00:00
155 lines
5.0 KiB
Diff
155 lines
5.0 KiB
Diff
From 2613f36ed965d0e5a595a1d931fd3b480e82d6fd Mon Sep 17 00:00:00 2001
|
|
From: Borislav Petkov <bp@suse.de>
|
|
Date: Wed, 14 Mar 2018 19:36:14 +0100
|
|
Subject: x86/microcode: Attempt late loading only when new microcode is
|
|
present
|
|
|
|
Return UCODE_NEW from the scanning functions to denote that new microcode
|
|
was found and only then attempt the expensive synchronization dance.
|
|
|
|
Reported-by: Emanuel Czirai <xftroxgpx@protonmail.com>
|
|
Signed-off-by: Borislav Petkov <bp@suse.de>
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
Tested-by: Emanuel Czirai <xftroxgpx@protonmail.com>
|
|
Tested-by: Ashok Raj <ashok.raj@intel.com>
|
|
Tested-by: Tom Lendacky <thomas.lendacky@amd.com>
|
|
Link: https://lkml.kernel.org/r/20180314183615.17629-1-bp@alien8.de
|
|
---
|
|
arch/x86/include/asm/microcode.h | 1 +
|
|
arch/x86/kernel/cpu/microcode/amd.c | 34 +++++++++++++++++++++-------------
|
|
arch/x86/kernel/cpu/microcode/core.c | 8 +++-----
|
|
arch/x86/kernel/cpu/microcode/intel.c | 4 +++-
|
|
4 files changed, 28 insertions(+), 19 deletions(-)
|
|
|
|
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
|
|
index 7fb1047..6cf0e4c 100644
|
|
--- a/arch/x86/include/asm/microcode.h
|
|
+++ b/arch/x86/include/asm/microcode.h
|
|
@@ -39,6 +39,7 @@ struct device;
|
|
|
|
enum ucode_state {
|
|
UCODE_OK = 0,
|
|
+ UCODE_NEW,
|
|
UCODE_UPDATED,
|
|
UCODE_NFOUND,
|
|
UCODE_ERROR,
|
|
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
|
|
index a998e1a..4817992 100644
|
|
--- a/arch/x86/kernel/cpu/microcode/amd.c
|
|
+++ b/arch/x86/kernel/cpu/microcode/amd.c
|
|
@@ -339,7 +339,7 @@ int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
|
|
return -EINVAL;
|
|
|
|
ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
|
|
- if (ret != UCODE_OK)
|
|
+ if (ret > UCODE_UPDATED)
|
|
return -EINVAL;
|
|
|
|
return 0;
|
|
@@ -683,27 +683,35 @@ static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
|
static enum ucode_state
|
|
load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
|
|
{
|
|
+ struct ucode_patch *p;
|
|
enum ucode_state ret;
|
|
|
|
/* free old equiv table */
|
|
free_equiv_cpu_table();
|
|
|
|
ret = __load_microcode_amd(family, data, size);
|
|
-
|
|
- if (ret != UCODE_OK)
|
|
+ if (ret != UCODE_OK) {
|
|
cleanup();
|
|
+ return ret;
|
|
+ }
|
|
|
|
-#ifdef CONFIG_X86_32
|
|
- /* save BSP's matching patch for early load */
|
|
- if (save) {
|
|
- struct ucode_patch *p = find_patch(0);
|
|
- if (p) {
|
|
- memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
|
|
- memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data),
|
|
- PATCH_MAX_SIZE));
|
|
- }
|
|
+ p = find_patch(0);
|
|
+ if (!p) {
|
|
+ return ret;
|
|
+ } else {
|
|
+ if (boot_cpu_data.microcode == p->patch_id)
|
|
+ return ret;
|
|
+
|
|
+ ret = UCODE_NEW;
|
|
}
|
|
-#endif
|
|
+
|
|
+ /* save BSP's matching patch for early load */
|
|
+ if (!save)
|
|
+ return ret;
|
|
+
|
|
+ memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
|
|
+ memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), PATCH_MAX_SIZE));
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
|
|
index 70ecbc8..9f0fe5b 100644
|
|
--- a/arch/x86/kernel/cpu/microcode/core.c
|
|
+++ b/arch/x86/kernel/cpu/microcode/core.c
|
|
@@ -607,7 +607,7 @@ static ssize_t reload_store(struct device *dev,
|
|
return size;
|
|
|
|
tmp_ret = microcode_ops->request_microcode_fw(bsp, µcode_pdev->dev, true);
|
|
- if (tmp_ret != UCODE_OK)
|
|
+ if (tmp_ret != UCODE_NEW)
|
|
return size;
|
|
|
|
get_online_cpus();
|
|
@@ -691,10 +691,8 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
|
|
if (system_state != SYSTEM_RUNNING)
|
|
return UCODE_NFOUND;
|
|
|
|
- ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev,
|
|
- refresh_fw);
|
|
-
|
|
- if (ustate == UCODE_OK) {
|
|
+ ustate = microcode_ops->request_microcode_fw(cpu, µcode_pdev->dev, refresh_fw);
|
|
+ if (ustate == UCODE_NEW) {
|
|
pr_debug("CPU%d updated upon init\n", cpu);
|
|
apply_microcode_on_target(cpu);
|
|
}
|
|
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
|
|
index 2aded9d..32b8e57 100644
|
|
--- a/arch/x86/kernel/cpu/microcode/intel.c
|
|
+++ b/arch/x86/kernel/cpu/microcode/intel.c
|
|
@@ -862,6 +862,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
|
unsigned int leftover = size;
|
|
unsigned int curr_mc_size = 0, new_mc_size = 0;
|
|
unsigned int csig, cpf;
|
|
+ enum ucode_state ret = UCODE_OK;
|
|
|
|
while (leftover) {
|
|
struct microcode_header_intel mc_header;
|
|
@@ -903,6 +904,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
|
new_mc = mc;
|
|
new_mc_size = mc_size;
|
|
mc = NULL; /* trigger new vmalloc */
|
|
+ ret = UCODE_NEW;
|
|
}
|
|
|
|
ucode_ptr += mc_size;
|
|
@@ -932,7 +934,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
|
|
pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
|
|
cpu, new_rev, uci->cpu_sig.rev);
|
|
|
|
- return UCODE_OK;
|
|
+ return ret;
|
|
}
|
|
|
|
static int get_ucode_fw(void *to, const void *from, size_t n)
|
|
--
|
|
cgit v1.1
|
|
|