aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c4
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c30
-rw-r--r--arch/x86/kernel/cpu/microcode/internal.h1
3 files changed, 20 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index de3eb97bc2b3..2b742fe82893 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -397,6 +397,10 @@ static int microcode_reload_late(void)
store_cpu_caps(&prev_info);
ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
+
+ if (microcode_ops->finalize_late_load)
+ microcode_ops->finalize_late_load(ret);
+
if (!ret) {
pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
old, boot_cpu_data.microcode);
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 9b6614490113..076133b09cc7 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -36,6 +36,7 @@ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
/* Current microcode patch used in early patching on the APs. */
static struct microcode_intel *ucode_patch_va __read_mostly;
+static struct microcode_intel *ucode_patch_late __read_mostly;
/* last level cache size per core */
static unsigned int llc_size_per_core __ro_after_init;
@@ -470,12 +471,9 @@ static enum ucode_state apply_microcode_intel(int cpu)
if (WARN_ON(raw_smp_processor_id() != cpu))
return UCODE_ERROR;
- mc = ucode_patch_va;
- if (!mc) {
- mc = uci->mc;
- if (!mc)
- return UCODE_NFOUND;
- }
+ mc = ucode_patch_late;
+ if (!mc)
+ return UCODE_NFOUND;
/*
* Save us the MSR write below - which is a particular expensive
@@ -594,15 +592,7 @@ static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
if (!new_mc)
return UCODE_NFOUND;
- /* Save for CPU hotplug */
- save_microcode_patch((struct microcode_intel *)new_mc);
- uci->mc = ucode_patch_va;
-
- vfree(new_mc);
-
- pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
- cpu, cur_rev, uci->cpu_sig.rev);
-
+ ucode_patch_late = (struct microcode_intel *)new_mc;
return UCODE_NEW;
}
@@ -659,10 +649,20 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device)
return ret;
}
+static void finalize_late_load(int result)
+{
+ if (!result)
+ save_microcode_patch(ucode_patch_late);
+
+ vfree(ucode_patch_late);
+ ucode_patch_late = NULL;
+}
+
static struct microcode_ops microcode_intel_ops = {
.request_microcode_fw = request_microcode_fw,
.collect_cpu_info = collect_cpu_info,
.apply_microcode = apply_microcode_intel,
+ .finalize_late_load = finalize_late_load,
};
static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h
index 1cfc6ece2ec3..32f6ad593ef9 100644
--- a/arch/x86/kernel/cpu/microcode/internal.h
+++ b/arch/x86/kernel/cpu/microcode/internal.h
@@ -31,6 +31,7 @@ struct microcode_ops {
*/
enum ucode_state (*apply_microcode)(int cpu);
int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
+ void (*finalize_late_load)(int result);
};
extern struct ucode_cpu_info ucode_cpu_info[];