gve-set-xdp-redirect-target-only-when-it-is-available.patch
intel_idle-handle-older-cpus-which-stop-the-tsc-in-deeper-c-states-correctly.patch
arm64-dts-rockchip-disable-dma-for-uart5-on-px30-ringneck.patch
+x86-microcode-32-move-early-loading-after-paging-enable.patch
+x86-microcode-intel-rip-out-mixed-stepping-support-for-intel-cpus.patch
+x86-microcode-intel-simplify-scan_microcode.patch
+x86-microcode-intel-simplify-and-rename-generic_load_microcode.patch
+x86-microcode-intel-cleanup-code-further.patch
+x86-microcode-intel-simplify-early-loading.patch
+x86-microcode-intel-save-the-microcode-only-after-a-successful-late-load.patch
+x86-microcode-intel-switch-to-kvmalloc.patch
+x86-microcode-intel-unify-microcode-apply-functions.patch
+x86-microcode-intel-rework-intel_cpu_collect_info.patch
+x86-microcode-intel-reuse-intel_cpu_collect_info.patch
+x86-microcode-intel-rework-intel_find_matching_signature.patch
+x86-microcode-remove-pointless-apply-invocation.patch
+x86-microcode-amd-use-correct-per-cpu-ucode_cpu_info.patch
+x86-microcode-amd-cache-builtin-microcode-too.patch
+x86-microcode-amd-cache-builtin-initrd-microcode-early.patch
+x86-microcode-amd-use-cached-microcode-for-ap-load.patch
+x86-microcode-mop-up-early-loading-leftovers.patch
+x86-microcode-get-rid-of-the-schedule-work-indirection.patch
+x86-microcode-clean-up-mc_cpu_down_prep.patch
+x86-microcode-handle-nosmt-correctly.patch
+x86-microcode-clarify-the-late-load-logic.patch
+x86-microcode-sanitize-__wait_for_cpus.patch
+x86-microcode-add-per-cpu-result-state.patch
+x86-microcode-add-per-cpu-control-field.patch
+x86-microcode-provide-new-control-functions.patch
+x86-microcode-replace-the-all-in-one-rendevous-handler.patch
+x86-microcode-rendezvous-and-load-in-nmi.patch
+x86-microcode-protect-against-instrumentation.patch
+x86-apic-provide-apic_force_nmi_on_cpu.patch
+x86-microcode-handle-offline-cpus-correctly.patch
+x86-microcode-prepare-for-minimal-revision-check.patch
+x86-microcode-rework-early-revisions-reporting.patch
+x86-microcode-intel-set-new-revision-only-after-a-successful-update.patch
+x86-microcode-amd-use-the-family-model-stepping-encoded-in-the-patch-id.patch
+x86-microcode-amd-pay-attention-to-the-stepping-dynamically.patch
+x86-microcode-amd-split-load_microcode_amd.patch
+x86-microcode-intel-remove-unnecessary-cache-writeback-and-invalidation.patch
+x86-microcode-amd-flush-patch-buffer-mapping-after-application.patch
+x86-microcode-amd-return-bool-from-find_blobs_in_containers.patch
+x86-microcode-amd-make-__verify_patch_size-return-bool.patch
+x86-microcode-amd-have-__apply_microcode_amd-return-bool.patch
+x86-microcode-amd-merge-early_apply_microcode-into-its-single-callsite.patch
+x86-microcode-amd-get-rid-of-the-_load_microcode_amd-forward-declaration.patch
+x86-microcode-amd-add-get_patch_level.patch
+x86-microcode-amd-load-only-sha256-checksummed-patches.patch
--- /dev/null
+From 086f78d30a378e824e4743080fc6fe22254a42c4 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:07 +0200
+Subject: x86/apic: Provide apic_force_nmi_on_cpu()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 9cab5fb776d4367e26950cf759211e948335288e upstream
+
+When SMT siblings are soft-offlined and parked in one of the play_dead()
+variants they still react on NMI, which is problematic on affected Intel
+CPUs. The default play_dead() variant uses MWAIT on modern CPUs, which is
+not guaranteed to be safe when updated concurrently.
+
+Right now late loading is prevented when not all SMT siblings are online,
+but as they still react on NMI, it is possible to bring them out of their
+park position into a trivial rendezvous handler.
+
+Provide a function which allows to do that. I does sanity checks whether
+the target is in the cpus_booted_once_mask and whether the APIC driver
+supports it.
+
+Mark X2APIC and XAPIC as capable, but exclude 32bit and the UV and NUMACHIP
+variants as that needs feedback from the relevant experts.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.603100036@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/apic.h | 5 ++++-
+ arch/x86/kernel/apic/apic_flat_64.c | 2 ++
+ arch/x86/kernel/apic/ipi.c | 8 ++++++++
+ arch/x86/kernel/apic/x2apic_cluster.c | 1 +
+ arch/x86/kernel/apic/x2apic_phys.c | 1 +
+ 5 files changed, 16 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/include/asm/apic.h
++++ b/arch/x86/include/asm/apic.h
+@@ -277,7 +277,8 @@ struct apic {
+
+ u32 disable_esr : 1,
+ dest_mode_logical : 1,
+- x2apic_set_max_apicid : 1;
++ x2apic_set_max_apicid : 1,
++ nmi_to_offline_cpu : 1;
+
+ u32 (*calc_dest_apicid)(unsigned int cpu);
+
+@@ -543,6 +544,8 @@ extern bool default_check_apicid_used(ph
+ extern void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap);
+ extern int default_cpu_present_to_apicid(int mps_cpu);
+
++void apic_send_nmi_to_offline_cpu(unsigned int cpu);
++
+ #else /* CONFIG_X86_LOCAL_APIC */
+
+ static inline unsigned int read_apic_id(void) { return 0; }
+--- a/arch/x86/kernel/apic/apic_flat_64.c
++++ b/arch/x86/kernel/apic/apic_flat_64.c
+@@ -103,6 +103,7 @@ static struct apic apic_flat __ro_after_
+ .send_IPI_allbutself = default_send_IPI_allbutself,
+ .send_IPI_all = default_send_IPI_all,
+ .send_IPI_self = default_send_IPI_self,
++ .nmi_to_offline_cpu = true,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+@@ -175,6 +176,7 @@ static struct apic apic_physflat __ro_af
+ .send_IPI_allbutself = default_send_IPI_allbutself,
+ .send_IPI_all = default_send_IPI_all,
+ .send_IPI_self = default_send_IPI_self,
++ .nmi_to_offline_cpu = true,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+--- a/arch/x86/kernel/apic/ipi.c
++++ b/arch/x86/kernel/apic/ipi.c
+@@ -97,6 +97,14 @@ sendmask:
+ __apic_send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
+ }
+
++void apic_send_nmi_to_offline_cpu(unsigned int cpu)
++{
++ if (WARN_ON_ONCE(!apic->nmi_to_offline_cpu))
++ return;
++ if (WARN_ON_ONCE(!cpumask_test_cpu(cpu, &cpus_booted_once_mask)))
++ return;
++ apic->send_IPI(cpu, NMI_VECTOR);
++}
+ #endif /* CONFIG_SMP */
+
+ static inline int __prepare_ICR2(unsigned int mask)
+--- a/arch/x86/kernel/apic/x2apic_cluster.c
++++ b/arch/x86/kernel/apic/x2apic_cluster.c
+@@ -251,6 +251,7 @@ static struct apic apic_x2apic_cluster _
+ .send_IPI_allbutself = x2apic_send_IPI_allbutself,
+ .send_IPI_all = x2apic_send_IPI_all,
+ .send_IPI_self = x2apic_send_IPI_self,
++ .nmi_to_offline_cpu = true,
+
+ .read = native_apic_msr_read,
+ .write = native_apic_msr_write,
+--- a/arch/x86/kernel/apic/x2apic_phys.c
++++ b/arch/x86/kernel/apic/x2apic_phys.c
+@@ -166,6 +166,7 @@ static struct apic apic_x2apic_phys __ro
+ .send_IPI_allbutself = x2apic_send_IPI_allbutself,
+ .send_IPI_all = x2apic_send_IPI_all,
+ .send_IPI_self = x2apic_send_IPI_self,
++ .nmi_to_offline_cpu = true,
+
+ .read = native_apic_msr_read,
+ .write = native_apic_msr_write,
--- /dev/null
+From a78cf1d31b4ae70395034948d005a1b3ee252746 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:32 +0200
+Subject: x86/microcode/32: Move early loading after paging enable
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 0b62f6cb07738d7211d926c39f6946b87f72e792 upstream.
+
+32-bit loads microcode before paging is enabled. The commit which
+introduced that has zero justification in the changelog. The cover
+letter has slightly more content, but it does not give any technical
+justification either:
+
+ "The problem in current microcode loading method is that we load a
+ microcode way, way too late; ideally we should load it before turning
+ paging on. This may only be practical on 32 bits since we can't get
+ to 64-bit mode without paging on, but we should still do it as early
+ as at all possible."
+
+Handwaving word salad with zero technical content.
+
+Someone claimed in an offlist conversation that this is required for
+curing the ATOM erratum AAE44/AAF40/AAG38/AAH41. That erratum requires
+an microcode update in order to make the usage of PSE safe. But during
+early boot, PSE is completely irrelevant and it is evaluated way later.
+
+Neither is it relevant for the AP on single core HT enabled CPUs as the
+microcode loading on the AP is not doing anything.
+
+On dual core CPUs there is a theoretical problem if a split of an
+executable large page between enabling paging including PSE and loading
+the microcode happens. But that's only theoretical, it's practically
+irrelevant because the affected dual core CPUs are 64bit enabled and
+therefore have paging and PSE enabled before loading the microcode on
+the second core. So why would it work on 64-bit but not on 32-bit?
+
+The erratum:
+
+ "AAG38 Code Fetch May Occur to Incorrect Address After a Large Page is
+ Split Into 4-Kbyte Pages
+
+ Problem: If software clears the PS (page size) bit in a present PDE
+ (page directory entry), that will cause linear addresses mapped through
+ this PDE to use 4-KByte pages instead of using a large page after old
+ TLB entries are invalidated. Due to this erratum, if a code fetch uses
+ this PDE before the TLB entry for the large page is invalidated then it
+ may fetch from a different physical address than specified by either the
+ old large page translation or the new 4-KByte page translation. This
+ erratum may also cause speculative code fetches from incorrect addresses."
+
+The practical relevance for this is exactly zero because there is no
+splitting of large text pages during early boot-time, i.e. between paging
+enable and microcode loading, and neither during CPU hotplug.
+
+IOW, this load microcode before paging enable is yet another voodoo
+programming solution in search of a problem. What's worse is that it causes
+at least two serious problems:
+
+ 1) When stackprotector is enabled, the microcode loader code has the
+ stackprotector mechanics enabled. The read from the per CPU variable
+ __stack_chk_guard is always accessing the virtual address either
+ directly on UP or via %fs on SMP. In physical address mode this
+ results in an access to memory above 3GB. So this works by chance as
+ the hardware returns the same value when there is no RAM at this
+ physical address. When there is RAM populated above 3G then the read
+ is by chance the same as nothing changes that memory during the very
+ early boot stage. That's not necessarily true during runtime CPU
+ hotplug.
+
+ 2) When function tracing is enabled, the relevant microcode loader
+ functions and the functions invoked from there will call into the
+ tracing code and evaluate global and per CPU variables in physical
+ address mode. What could potentially go wrong?
+
+Cure this and move the microcode loading after the early paging enable, use
+the new temporary initrd mapping and remove the gunk in the microcode
+loader which is required to handle physical address mode.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211722.348298216@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/microcode.h | 5 -
+ arch/x86/kernel/cpu/common.c | 12 ---
+ arch/x86/kernel/cpu/microcode/amd.c | 103 ++++++++-------------------
+ arch/x86/kernel/cpu/microcode/core.c | 78 ++++----------------
+ arch/x86/kernel/cpu/microcode/intel.c | 116 ++++---------------------------
+ arch/x86/kernel/cpu/microcode/internal.h | 2
+ arch/x86/kernel/head32.c | 3
+ arch/x86/kernel/head_32.S | 10 --
+ arch/x86/kernel/smpboot.c | 12 +--
+ 9 files changed, 72 insertions(+), 269 deletions(-)
+
+--- a/arch/x86/include/asm/microcode.h
++++ b/arch/x86/include/asm/microcode.h
+@@ -68,11 +68,6 @@ static inline u32 intel_get_microcode_re
+
+ return rev;
+ }
+-
+-void show_ucode_info_early(void);
+-
+-#else /* CONFIG_CPU_SUP_INTEL */
+-static inline void show_ucode_info_early(void) { }
+ #endif /* !CONFIG_CPU_SUP_INTEL */
+
+ #endif /* _ASM_X86_MICROCODE_H */
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -2224,8 +2224,6 @@ static inline void setup_getcpu(int cpu)
+ }
+
+ #ifdef CONFIG_X86_64
+-static inline void ucode_cpu_init(int cpu) { }
+-
+ static inline void tss_setup_ist(struct tss_struct *tss)
+ {
+ /* Set up the per-CPU TSS IST stacks */
+@@ -2236,16 +2234,8 @@ static inline void tss_setup_ist(struct
+ /* Only mapped when SEV-ES is active */
+ tss->x86_tss.ist[IST_INDEX_VC] = __this_cpu_ist_top_va(VC);
+ }
+-
+ #else /* CONFIG_X86_64 */
+-
+-static inline void ucode_cpu_init(int cpu)
+-{
+- show_ucode_info_early();
+-}
+-
+ static inline void tss_setup_ist(struct tss_struct *tss) { }
+-
+ #endif /* !CONFIG_X86_64 */
+
+ static inline void tss_setup_io_bitmap(struct tss_struct *tss)
+@@ -2301,8 +2291,6 @@ void cpu_init(void)
+ struct task_struct *cur = current;
+ int cpu = raw_smp_processor_id();
+
+- ucode_cpu_init(cpu);
+-
+ #ifdef CONFIG_NUMA
+ if (this_cpu_read(numa_node) == 0 &&
+ early_cpu_to_node(cpu) != NUMA_NO_NODE)
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -121,24 +121,20 @@ static u16 find_equiv_id(struct equiv_cp
+
+ /*
+ * Check whether there is a valid microcode container file at the beginning
+- * of @buf of size @buf_size. Set @early to use this function in the early path.
++ * of @buf of size @buf_size.
+ */
+-static bool verify_container(const u8 *buf, size_t buf_size, bool early)
++static bool verify_container(const u8 *buf, size_t buf_size)
+ {
+ u32 cont_magic;
+
+ if (buf_size <= CONTAINER_HDR_SZ) {
+- if (!early)
+- pr_debug("Truncated microcode container header.\n");
+-
++ pr_debug("Truncated microcode container header.\n");
+ return false;
+ }
+
+ cont_magic = *(const u32 *)buf;
+ if (cont_magic != UCODE_MAGIC) {
+- if (!early)
+- pr_debug("Invalid magic value (0x%08x).\n", cont_magic);
+-
++ pr_debug("Invalid magic value (0x%08x).\n", cont_magic);
+ return false;
+ }
+
+@@ -147,23 +143,20 @@ static bool verify_container(const u8 *b
+
+ /*
+ * Check whether there is a valid, non-truncated CPU equivalence table at the
+- * beginning of @buf of size @buf_size. Set @early to use this function in the
+- * early path.
++ * beginning of @buf of size @buf_size.
+ */
+-static bool verify_equivalence_table(const u8 *buf, size_t buf_size, bool early)
++static bool verify_equivalence_table(const u8 *buf, size_t buf_size)
+ {
+ const u32 *hdr = (const u32 *)buf;
+ u32 cont_type, equiv_tbl_len;
+
+- if (!verify_container(buf, buf_size, early))
++ if (!verify_container(buf, buf_size))
+ return false;
+
+ cont_type = hdr[1];
+ if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) {
+- if (!early)
+- pr_debug("Wrong microcode container equivalence table type: %u.\n",
+- cont_type);
+-
++ pr_debug("Wrong microcode container equivalence table type: %u.\n",
++ cont_type);
+ return false;
+ }
+
+@@ -172,9 +165,7 @@ static bool verify_equivalence_table(con
+ equiv_tbl_len = hdr[2];
+ if (equiv_tbl_len < sizeof(struct equiv_cpu_entry) ||
+ buf_size < equiv_tbl_len) {
+- if (!early)
+- pr_debug("Truncated equivalence table.\n");
+-
++ pr_debug("Truncated equivalence table.\n");
+ return false;
+ }
+
+@@ -183,22 +174,19 @@ static bool verify_equivalence_table(con
+
+ /*
+ * Check whether there is a valid, non-truncated microcode patch section at the
+- * beginning of @buf of size @buf_size. Set @early to use this function in the
+- * early path.
++ * beginning of @buf of size @buf_size.
+ *
+ * On success, @sh_psize returns the patch size according to the section header,
+ * to the caller.
+ */
+ static bool
+-__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize, bool early)
++__verify_patch_section(const u8 *buf, size_t buf_size, u32 *sh_psize)
+ {
+ u32 p_type, p_size;
+ const u32 *hdr;
+
+ if (buf_size < SECTION_HDR_SIZE) {
+- if (!early)
+- pr_debug("Truncated patch section.\n");
+-
++ pr_debug("Truncated patch section.\n");
+ return false;
+ }
+
+@@ -207,17 +195,13 @@ __verify_patch_section(const u8 *buf, si
+ p_size = hdr[1];
+
+ if (p_type != UCODE_UCODE_TYPE) {
+- if (!early)
+- pr_debug("Invalid type field (0x%x) in container file section header.\n",
+- p_type);
+-
++ pr_debug("Invalid type field (0x%x) in container file section header.\n",
++ p_type);
+ return false;
+ }
+
+ if (p_size < sizeof(struct microcode_header_amd)) {
+- if (!early)
+- pr_debug("Patch of size %u too short.\n", p_size);
+-
++ pr_debug("Patch of size %u too short.\n", p_size);
+ return false;
+ }
+
+@@ -269,7 +253,7 @@ static unsigned int __verify_patch_size(
+ * 0: success
+ */
+ static int
+-verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size, bool early)
++verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size)
+ {
+ struct microcode_header_amd *mc_hdr;
+ unsigned int ret;
+@@ -277,7 +261,7 @@ verify_patch(u8 family, const u8 *buf, s
+ u16 proc_id;
+ u8 patch_fam;
+
+- if (!__verify_patch_section(buf, buf_size, &sh_psize, early))
++ if (!__verify_patch_section(buf, buf_size, &sh_psize))
+ return -1;
+
+ /*
+@@ -292,16 +276,13 @@ verify_patch(u8 family, const u8 *buf, s
+ * size sh_psize, as the section claims.
+ */
+ if (buf_size < sh_psize) {
+- if (!early)
+- pr_debug("Patch of size %u truncated.\n", sh_psize);
+-
++ pr_debug("Patch of size %u truncated.\n", sh_psize);
+ return -1;
+ }
+
+ ret = __verify_patch_size(family, sh_psize, buf_size);
+ if (!ret) {
+- if (!early)
+- pr_debug("Per-family patch size mismatch.\n");
++ pr_debug("Per-family patch size mismatch.\n");
+ return -1;
+ }
+
+@@ -309,8 +290,7 @@ verify_patch(u8 family, const u8 *buf, s
+
+ mc_hdr = (struct microcode_header_amd *)(buf + SECTION_HDR_SIZE);
+ if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
+- if (!early)
+- pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id);
++ pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n", mc_hdr->patch_id);
+ return -1;
+ }
+
+@@ -337,7 +317,7 @@ static size_t parse_container(u8 *ucode,
+ u16 eq_id;
+ u8 *buf;
+
+- if (!verify_equivalence_table(ucode, size, true))
++ if (!verify_equivalence_table(ucode, size))
+ return 0;
+
+ buf = ucode;
+@@ -364,7 +344,7 @@ static size_t parse_container(u8 *ucode,
+ u32 patch_size;
+ int ret;
+
+- ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size, true);
++ ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size);
+ if (ret < 0) {
+ /*
+ * Patch verification failed, skip to the next container, if
+@@ -456,14 +436,8 @@ static bool early_apply_microcode(u32 cp
+ {
+ struct cont_desc desc = { 0 };
+ struct microcode_amd *mc;
+- u32 rev, dummy, *new_rev;
+ bool ret = false;
+-
+-#ifdef CONFIG_X86_32
+- new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+-#else
+- new_rev = &ucode_new_rev;
+-#endif
++ u32 rev, dummy;
+
+ desc.cpuid_1_eax = cpuid_1_eax;
+
+@@ -484,8 +458,8 @@ static bool early_apply_microcode(u32 cp
+ return ret;
+
+ if (!__apply_microcode_amd(mc)) {
+- *new_rev = mc->hdr.patch_id;
+- ret = true;
++ ucode_new_rev = mc->hdr.patch_id;
++ ret = true;
+ }
+
+ return ret;
+@@ -514,26 +488,13 @@ static bool get_builtin_microcode(struct
+
+ static void find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
+ {
+- struct ucode_cpu_info *uci;
+ struct cpio_data cp;
+- const char *path;
+- bool use_pa;
+-
+- if (IS_ENABLED(CONFIG_X86_32)) {
+- uci = (struct ucode_cpu_info *)__pa_nodebug(ucode_cpu_info);
+- path = (const char *)__pa_nodebug(ucode_path);
+- use_pa = true;
+- } else {
+- uci = ucode_cpu_info;
+- path = ucode_path;
+- use_pa = false;
+- }
+
+ if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)))
+- cp = find_microcode_in_initrd(path, use_pa);
++ cp = find_microcode_in_initrd(ucode_path);
+
+ /* Needed in load_microcode_amd() */
+- uci->cpu_sig.sig = cpuid_1_eax;
++ ucode_cpu_info->cpu_sig.sig = cpuid_1_eax;
+
+ *ret = cp;
+ }
+@@ -562,7 +523,7 @@ int __init save_microcode_in_initrd_amd(
+ enum ucode_state ret;
+ struct cpio_data cp;
+
+- cp = find_microcode_in_initrd(ucode_path, false);
++ cp = find_microcode_in_initrd(ucode_path);
+ if (!(cp.data && cp.size))
+ return -EINVAL;
+
+@@ -738,7 +699,7 @@ static size_t install_equiv_cpu_table(co
+ u32 equiv_tbl_len;
+ const u32 *hdr;
+
+- if (!verify_equivalence_table(buf, buf_size, false))
++ if (!verify_equivalence_table(buf, buf_size))
+ return 0;
+
+ hdr = (const u32 *)buf;
+@@ -784,7 +745,7 @@ static int verify_and_add_patch(u8 famil
+ u16 proc_id;
+ int ret;
+
+- ret = verify_patch(family, fw, leftover, patch_size, false);
++ ret = verify_patch(family, fw, leftover, patch_size);
+ if (ret)
+ return ret;
+
+@@ -918,7 +879,7 @@ static enum ucode_state request_microcod
+ }
+
+ ret = UCODE_ERROR;
+- if (!verify_container(fw->data, fw->size, false))
++ if (!verify_container(fw->data, fw->size))
+ goto fw_release;
+
+ ret = load_microcode_amd(c->x86, fw->data, fw->size);
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -90,10 +90,7 @@ static bool amd_check_current_patch_leve
+
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, lvl, dummy);
+
+- if (IS_ENABLED(CONFIG_X86_32))
+- levels = (u32 *)__pa_nodebug(&final_levels);
+- else
+- levels = final_levels;
++ levels = final_levels;
+
+ for (i = 0; levels[i]; i++) {
+ if (lvl == levels[i])
+@@ -105,17 +102,8 @@ static bool amd_check_current_patch_leve
+ static bool __init check_loader_disabled_bsp(void)
+ {
+ static const char *__dis_opt_str = "dis_ucode_ldr";
+-
+-#ifdef CONFIG_X86_32
+- const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
+- const char *option = (const char *)__pa_nodebug(__dis_opt_str);
+- bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
+-
+-#else /* CONFIG_X86_64 */
+ const char *cmdline = boot_command_line;
+ const char *option = __dis_opt_str;
+- bool *res = &dis_ucode_ldr;
+-#endif
+
+ /*
+ * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not
+@@ -123,17 +111,17 @@ static bool __init check_loader_disabled
+ * that's good enough as they don't land on the BSP path anyway.
+ */
+ if (native_cpuid_ecx(1) & BIT(31))
+- return *res;
++ return true;
+
+ if (x86_cpuid_vendor() == X86_VENDOR_AMD) {
+ if (amd_check_current_patch_level())
+- return *res;
++ return true;
+ }
+
+ if (cmdline_find_option_bool(cmdline, option) <= 0)
+- *res = false;
++ dis_ucode_ldr = false;
+
+- return *res;
++ return dis_ucode_ldr;
+ }
+
+ void __init load_ucode_bsp(void)
+@@ -171,20 +159,11 @@ void __init load_ucode_bsp(void)
+ load_ucode_amd_early(cpuid_1_eax);
+ }
+
+-static bool check_loader_disabled_ap(void)
+-{
+-#ifdef CONFIG_X86_32
+- return *((bool *)__pa_nodebug(&dis_ucode_ldr));
+-#else
+- return dis_ucode_ldr;
+-#endif
+-}
+-
+ void load_ucode_ap(void)
+ {
+ unsigned int cpuid_1_eax;
+
+- if (check_loader_disabled_ap())
++ if (dis_ucode_ldr)
+ return;
+
+ cpuid_1_eax = native_cpuid_eax(1);
+@@ -232,40 +211,28 @@ out:
+ return ret;
+ }
+
+-struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
++struct cpio_data find_microcode_in_initrd(const char *path)
+ {
+ #ifdef CONFIG_BLK_DEV_INITRD
+ unsigned long start = 0;
+ size_t size;
+
+ #ifdef CONFIG_X86_32
+- struct boot_params *params;
+-
+- if (use_pa)
+- params = (struct boot_params *)__pa_nodebug(&boot_params);
+- else
+- params = &boot_params;
+-
+- size = params->hdr.ramdisk_size;
+-
+- /*
+- * Set start only if we have an initrd image. We cannot use initrd_start
+- * because it is not set that early yet.
+- */
++ size = boot_params.hdr.ramdisk_size;
++ /* Early load on BSP has a temporary mapping. */
+ if (size)
+- start = params->hdr.ramdisk_image;
++ start = initrd_start_early;
+
+-# else /* CONFIG_X86_64 */
++#else /* CONFIG_X86_64 */
+ size = (unsigned long)boot_params.ext_ramdisk_size << 32;
+ size |= boot_params.hdr.ramdisk_size;
+
+ if (size) {
+ start = (unsigned long)boot_params.ext_ramdisk_image << 32;
+ start |= boot_params.hdr.ramdisk_image;
+-
+ start += PAGE_OFFSET;
+ }
+-# endif
++#endif
+
+ /*
+ * Fixup the start address: after reserve_initrd() runs, initrd_start
+@@ -276,23 +243,10 @@ struct cpio_data find_microcode_in_initr
+ * initrd_gone is for the hotplug case where we've thrown out initrd
+ * already.
+ */
+- if (!use_pa) {
+- if (initrd_gone)
+- return (struct cpio_data){ NULL, 0, "" };
+- if (initrd_start)
+- start = initrd_start;
+- } else {
+- /*
+- * The picture with physical addresses is a bit different: we
+- * need to get the *physical* address to which the ramdisk was
+- * relocated, i.e., relocated_ramdisk (not initrd_start) and
+- * since we're running from physical addresses, we need to access
+- * relocated_ramdisk through its *physical* address too.
+- */
+- u64 *rr = (u64 *)__pa_nodebug(&relocated_ramdisk);
+- if (*rr)
+- start = *rr;
+- }
++ if (initrd_gone)
++ return (struct cpio_data){ NULL, 0, "" };
++ if (initrd_start)
++ start = initrd_start;
+
+ return find_cpio_data(path, (void *)start, size, NULL);
+ #else /* !CONFIG_BLK_DEV_INITRD */
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -319,15 +319,8 @@ static void save_microcode_patch(struct
+ if (!intel_find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ return;
+
+- /*
+- * Save for early loading. On 32-bit, that needs to be a physical
+- * address as the APs are running from physical addresses, before
+- * paging has been enabled.
+- */
+- if (IS_ENABLED(CONFIG_X86_32))
+- intel_ucode_patch = (struct microcode_intel *)__pa_nodebug(p->data);
+- else
+- intel_ucode_patch = p->data;
++ /* Save for early loading */
++ intel_ucode_patch = p->data;
+ }
+
+ /*
+@@ -420,66 +413,10 @@ static bool load_builtin_intel_microcode
+ return false;
+ }
+
+-static void print_ucode_info(int old_rev, int new_rev, unsigned int date)
+-{
+- pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
+- old_rev,
+- new_rev,
+- date & 0xffff,
+- date >> 24,
+- (date >> 16) & 0xff);
+-}
+-
+-#ifdef CONFIG_X86_32
+-
+-static int delay_ucode_info;
+-static int current_mc_date;
+-static int early_old_rev;
+-
+-/*
+- * Print early updated ucode info after printk works. This is delayed info dump.
+- */
+-void show_ucode_info_early(void)
+-{
+- struct ucode_cpu_info uci;
+-
+- if (delay_ucode_info) {
+- intel_cpu_collect_info(&uci);
+- print_ucode_info(early_old_rev, uci.cpu_sig.rev, current_mc_date);
+- delay_ucode_info = 0;
+- }
+-}
+-
+-/*
+- * At this point, we can not call printk() yet. Delay printing microcode info in
+- * show_ucode_info_early() until printk() works.
+- */
+-static void print_ucode(int old_rev, int new_rev, int date)
+-{
+- int *delay_ucode_info_p;
+- int *current_mc_date_p;
+- int *early_old_rev_p;
+-
+- delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
+- current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date);
+- early_old_rev_p = (int *)__pa_nodebug(&early_old_rev);
+-
+- *delay_ucode_info_p = 1;
+- *current_mc_date_p = date;
+- *early_old_rev_p = old_rev;
+-}
+-#else
+-
+-static inline void print_ucode(int old_rev, int new_rev, int date)
+-{
+- print_ucode_info(old_rev, new_rev, date);
+-}
+-#endif
+-
+-static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
++static int apply_microcode_early(struct ucode_cpu_info *uci)
+ {
+ struct microcode_intel *mc;
+- u32 rev, old_rev;
++ u32 rev, old_rev, date;
+
+ mc = uci->mc;
+ if (!mc)
+@@ -513,11 +450,9 @@ static int apply_microcode_early(struct
+
+ uci->cpu_sig.rev = rev;
+
+- if (early)
+- print_ucode(old_rev, uci->cpu_sig.rev, mc->hdr.date);
+- else
+- print_ucode_info(old_rev, uci->cpu_sig.rev, mc->hdr.date);
+-
++ date = mc->hdr.date;
++ pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
++ old_rev, rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
+ return 0;
+ }
+
+@@ -535,7 +470,7 @@ int __init save_microcode_in_initrd_inte
+ intel_ucode_patch = NULL;
+
+ if (!load_builtin_intel_microcode(&cp))
+- cp = find_microcode_in_initrd(ucode_path, false);
++ cp = find_microcode_in_initrd(ucode_path);
+
+ if (!(cp.data && cp.size))
+ return 0;
+@@ -551,21 +486,11 @@ int __init save_microcode_in_initrd_inte
+ */
+ static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
+ {
+- static const char *path;
+ struct cpio_data cp;
+- bool use_pa;
+-
+- if (IS_ENABLED(CONFIG_X86_32)) {
+- path = (const char *)__pa_nodebug(ucode_path);
+- use_pa = true;
+- } else {
+- path = ucode_path;
+- use_pa = false;
+- }
+
+ /* try built-in microcode first */
+ if (!load_builtin_intel_microcode(&cp))
+- cp = find_microcode_in_initrd(path, use_pa);
++ cp = find_microcode_in_initrd(ucode_path);
+
+ if (!(cp.data && cp.size))
+ return NULL;
+@@ -586,30 +511,21 @@ void __init load_ucode_intel_bsp(void)
+
+ uci.mc = patch;
+
+- apply_microcode_early(&uci, true);
++ apply_microcode_early(&uci);
+ }
+
+ void load_ucode_intel_ap(void)
+ {
+- struct microcode_intel *patch, **iup;
+ struct ucode_cpu_info uci;
+
+- if (IS_ENABLED(CONFIG_X86_32))
+- iup = (struct microcode_intel **) __pa_nodebug(&intel_ucode_patch);
+- else
+- iup = &intel_ucode_patch;
+-
+- if (!*iup) {
+- patch = __load_ucode_intel(&uci);
+- if (!patch)
++ if (!intel_ucode_patch) {
++ intel_ucode_patch = __load_ucode_intel(&uci);
++ if (!intel_ucode_patch)
+ return;
+-
+- *iup = patch;
+ }
+
+- uci.mc = *iup;
+-
+- apply_microcode_early(&uci, true);
++ uci.mc = intel_ucode_patch;
++ apply_microcode_early(&uci);
+ }
+
+ static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
+@@ -647,7 +563,7 @@ void reload_ucode_intel(void)
+
+ uci.mc = p;
+
+- apply_microcode_early(&uci, false);
++ apply_microcode_early(&uci);
+ }
+
+ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -44,7 +44,7 @@ struct microcode_ops {
+ };
+
+ extern struct ucode_cpu_info ucode_cpu_info[];
+-struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa);
++struct cpio_data find_microcode_in_initrd(const char *path);
+
+ #define MAX_UCODE_COUNT 128
+
+--- a/arch/x86/kernel/head32.c
++++ b/arch/x86/kernel/head32.c
+@@ -19,6 +19,7 @@
+ #include <asm/apic.h>
+ #include <asm/io_apic.h>
+ #include <asm/bios_ebda.h>
++#include <asm/microcode.h>
+ #include <asm/tlbflush.h>
+ #include <asm/bootparam_utils.h>
+
+@@ -34,6 +35,8 @@ asmlinkage __visible void __init __noret
+ /* Make sure IDT is set up before any exception happens */
+ idt_setup_early_handler();
+
++ load_ucode_bsp();
++
+ cr4_init_shadow();
+
+ sanitize_boot_params(&boot_params);
+--- a/arch/x86/kernel/head_32.S
++++ b/arch/x86/kernel/head_32.S
+@@ -118,11 +118,6 @@ SYM_CODE_START(startup_32)
+ movl %eax, pa(olpc_ofw_pgd)
+ #endif
+
+-#ifdef CONFIG_MICROCODE
+- /* Early load ucode on BSP. */
+- call load_ucode_bsp
+-#endif
+-
+ /* Create early pagetables. */
+ call mk_early_pgtbl_32
+
+@@ -157,11 +152,6 @@ SYM_FUNC_START(startup_32_smp)
+ movl %eax,%ss
+ leal -__PAGE_OFFSET(%ecx),%esp
+
+-#ifdef CONFIG_MICROCODE
+- /* Early load ucode on AP. */
+- call load_ucode_ap
+-#endif
+-
+ .Ldefault_entry:
+ movl $(CR0_STATE & ~X86_CR0_PG),%eax
+ movl %eax,%cr0
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -259,12 +259,9 @@ static void notrace start_secondary(void
+ cpu_init_exception_handling();
+
+ /*
+- * 32-bit systems load the microcode from the ASM startup code for
+- * historical reasons.
+- *
+- * On 64-bit systems load it before reaching the AP alive
+- * synchronization point below so it is not part of the full per
+- * CPU serialized bringup part when "parallel" bringup is enabled.
++ * Load the microcode before reaching the AP alive synchronization
++ * point below so it is not part of the full per CPU serialized
++ * bringup part when "parallel" bringup is enabled.
+ *
+ * That's even safe when hyperthreading is enabled in the CPU as
+ * the core code starts the primary threads first and leaves the
+@@ -277,8 +274,7 @@ static void notrace start_secondary(void
+ * CPUID, MSRs etc. must be strictly serialized to maintain
+ * software state correctness.
+ */
+- if (IS_ENABLED(CONFIG_X86_64))
+- load_ucode_ap();
++ load_ucode_ap();
+
+ /*
+ * Synchronization point with the hotplug core. Sets this CPUs
--- /dev/null
+From d996a8d18c72a9cd3ed58ab98e3a06db064ac520 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:01 +0200
+Subject: x86/microcode: Add per CPU control field
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit ba3aeb97cb2c53025356f31c5a0a294385194115 upstream
+
+Add a per CPU control field to ucode_ctrl and define constants for it
+which are going to be used to control the loading state machine.
+
+In theory this could be a global control field, but a global control does
+not cover the following case:
+
+ 15 primary CPUs load microcode successfully
+ 1 primary CPU fails and returns with an error code
+
+With global control the sibling of the failed CPU would either try again or
+the whole operation would be aborted with the consequence that the 15
+siblings do not invoke the apply path and end up with inconsistent software
+state. The result in dmesg would be inconsistent too.
+
+There are two additional fields added and initialized:
+
+ctrl_cpu and secondaries. ctrl_cpu is the CPU number of the primary thread
+for now, but with the upcoming uniform loading at package or system scope
+this will be one CPU per package or just one CPU. Secondaries hands the
+control CPU a CPU mask which will be required to release the secondary CPUs
+out of the wait loop.
+
+Preparatory change for implementing a properly split control flow for
+primary and secondary CPUs.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.319959519@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -252,8 +252,19 @@ static struct platform_device *microcode
+ * requirement can be relaxed in the future. Right now, this is conservative
+ * and good.
+ */
++enum sibling_ctrl {
++ /* Spinwait with timeout */
++ SCTRL_WAIT,
++ /* Invoke the microcode_apply() callback */
++ SCTRL_APPLY,
++ /* Proceed without invoking the microcode_apply() callback */
++ SCTRL_DONE,
++};
++
+ struct microcode_ctrl {
++ enum sibling_ctrl ctrl;
+ enum ucode_state result;
++ unsigned int ctrl_cpu;
+ };
+
+ static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
+@@ -398,7 +409,7 @@ static int load_late_stop_cpus(void)
+ */
+ static bool setup_cpus(void)
+ {
+- struct microcode_ctrl ctrl = { .result = -1, };
++ struct microcode_ctrl ctrl = { .ctrl = SCTRL_WAIT, .result = -1, };
+ unsigned int cpu;
+
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+@@ -408,7 +419,12 @@ static bool setup_cpus(void)
+ return false;
+ }
+ }
+- /* Initialize the per CPU state */
++
++ /*
++ * Initialize the per CPU state. This is core scope for now,
++ * but prepared to take package or system scope into account.
++ */
++ ctrl.ctrl_cpu = cpumask_first(topology_sibling_cpumask(cpu));
+ per_cpu(ucode_ctrl, cpu) = ctrl;
+ }
+ return true;
--- /dev/null
+From facaa441b953dc69f317559214cb4ecc66b91b12 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:24:05 +0200
+Subject: x86/microcode: Add per CPU result state
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 4b753955e9151ad2f722137a7bcbafda756186b3 upstream
+
+The microcode rendezvous is purely acting on global state, which does
+not allow to analyze fails in a coherent way.
+
+Introduce per CPU state where the results are written into, which allows to
+analyze the return codes of the individual CPUs.
+
+Initialize the state when walking the cpu_present_mask in the online
+check to avoid another for_each_cpu() loop.
+
+Enhance the result print out with that.
+
+The structure is intentionally named ucode_ctrl as it will gain control
+fields in subsequent changes.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211723.632681010@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 112 ++++++++++++++++++-------------
+ arch/x86/kernel/cpu/microcode/internal.h | 1
+ 2 files changed, 67 insertions(+), 46 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -252,6 +252,11 @@ static struct platform_device *microcode
+ * requirement can be relaxed in the future. Right now, this is conservative
+ * and good.
+ */
++struct microcode_ctrl {
++ enum ucode_state result;
++};
++
++static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
+ static atomic_t late_cpus_in, late_cpus_out;
+
+ static bool wait_for_cpus(atomic_t *cnt)
+@@ -274,23 +279,19 @@ static bool wait_for_cpus(atomic_t *cnt)
+ return false;
+ }
+
+-/*
+- * Returns:
+- * < 0 - on error
+- * 0 - success (no update done or microcode was updated)
+- */
+-static int __reload_late(void *info)
++static int load_cpus_stopped(void *unused)
+ {
+ int cpu = smp_processor_id();
+- enum ucode_state err;
+- int ret = 0;
++ enum ucode_state ret;
+
+ /*
+ * Wait for all CPUs to arrive. A load will not be attempted unless all
+ * CPUs show up.
+ * */
+- if (!wait_for_cpus(&late_cpus_in))
+- return -1;
++ if (!wait_for_cpus(&late_cpus_in)) {
++ this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
++ return 0;
++ }
+
+ /*
+ * On an SMT system, it suffices to load the microcode on one sibling of
+@@ -299,17 +300,11 @@ static int __reload_late(void *info)
+ * loading attempts happen on multiple threads of an SMT core. See
+ * below.
+ */
+- if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
+- err = microcode_ops->apply_microcode(cpu);
+- else
++ if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
+ goto wait_for_siblings;
+
+- if (err >= UCODE_NFOUND) {
+- if (err == UCODE_ERROR) {
+- pr_warn("Error reloading microcode on CPU %d\n", cpu);
+- ret = -1;
+- }
+- }
++ ret = microcode_ops->apply_microcode(cpu);
++ this_cpu_write(ucode_ctrl.result, ret);
+
+ wait_for_siblings:
+ if (!wait_for_cpus(&late_cpus_out))
+@@ -321,19 +316,18 @@ wait_for_siblings:
+ * per-cpu cpuinfo can be updated with right microcode
+ * revision.
+ */
+- if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
+- err = microcode_ops->apply_microcode(cpu);
++ if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
++ return 0;
+
+- return ret;
++ ret = microcode_ops->apply_microcode(cpu);
++ this_cpu_write(ucode_ctrl.result, ret);
++ return 0;
+ }
+
+-/*
+- * Reload microcode late on all CPUs. Wait for a sec until they
+- * all gather together.
+- */
+-static int microcode_reload_late(void)
++static int load_late_stop_cpus(void)
+ {
+- int old = boot_cpu_data.microcode, ret;
++ unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
++ int old_rev = boot_cpu_data.microcode;
+ struct cpuinfo_x86 prev_info;
+
+ pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
+@@ -348,26 +342,47 @@ static int microcode_reload_late(void)
+ */
+ store_cpu_caps(&prev_info);
+
+- ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask);
++ stop_machine_cpuslocked(load_cpus_stopped, NULL, cpu_online_mask);
++
++ /* Analyze the results */
++ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
++ switch (per_cpu(ucode_ctrl.result, cpu)) {
++ case UCODE_UPDATED: updated++; break;
++ case UCODE_TIMEOUT: timedout++; break;
++ case UCODE_OK: siblings++; break;
++ default: failed++; break;
++ }
++ }
+
+ if (microcode_ops->finalize_late_load)
+- microcode_ops->finalize_late_load(ret);
++ microcode_ops->finalize_late_load(!updated);
+
+- if (!ret) {
+- pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
+- old, boot_cpu_data.microcode);
+- microcode_check(&prev_info);
+- add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+- } else {
+- pr_info("Reload failed, current microcode revision: 0x%x\n",
+- boot_cpu_data.microcode);
++ if (!updated) {
++ /* Nothing changed. */
++ if (!failed && !timedout)
++ return 0;
++ pr_err("update failed: %u CPUs failed %u CPUs timed out\n",
++ failed, timedout);
++ return -EIO;
+ }
+- return ret;
++
++ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
++ pr_info("load: updated on %u primary CPUs with %u siblings\n", updated, siblings);
++ if (failed || timedout) {
++ pr_err("load incomplete. %u CPUs timed out or failed\n",
++ num_online_cpus() - (updated + siblings));
++ }
++ pr_info("revision: 0x%x -> 0x%x\n", old_rev, boot_cpu_data.microcode);
++ microcode_check(&prev_info);
++
++ return updated + siblings == num_online_cpus() ? 0 : -EIO;
+ }
+
+ /*
+- * Ensure that all required CPUs which are present and have been booted
+- * once are online.
++ * This function does two things:
++ *
++ * 1) Ensure that all required CPUs which are present and have been booted
++ * once are online.
+ *
+ * To pass this check, all primary threads must be online.
+ *
+@@ -378,9 +393,12 @@ static int microcode_reload_late(void)
+ * behaviour is undefined. The default play_dead() implementation on
+ * modern CPUs uses MWAIT, which is also not guaranteed to be safe
+ * against a microcode update which affects MWAIT.
++ *
++ * 2) Initialize the per CPU control structure
+ */
+-static bool ensure_cpus_are_online(void)
++static bool setup_cpus(void)
+ {
++ struct microcode_ctrl ctrl = { .result = -1, };
+ unsigned int cpu;
+
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+@@ -390,18 +408,20 @@ static bool ensure_cpus_are_online(void)
+ return false;
+ }
+ }
++ /* Initialize the per CPU state */
++ per_cpu(ucode_ctrl, cpu) = ctrl;
+ }
+ return true;
+ }
+
+-static int ucode_load_late_locked(void)
++static int load_late_locked(void)
+ {
+- if (!ensure_cpus_are_online())
++ if (!setup_cpus())
+ return -EBUSY;
+
+ switch (microcode_ops->request_microcode_fw(0, µcode_pdev->dev)) {
+ case UCODE_NEW:
+- return microcode_reload_late();
++ return load_late_stop_cpus();
+ case UCODE_NFOUND:
+ return -ENOENT;
+ default:
+@@ -421,7 +441,7 @@ static ssize_t reload_store(struct devic
+ return -EINVAL;
+
+ cpus_read_lock();
+- ret = ucode_load_late_locked();
++ ret = load_late_locked();
+ cpus_read_unlock();
+
+ return ret ? : size;
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -16,6 +16,7 @@ enum ucode_state {
+ UCODE_UPDATED,
+ UCODE_NFOUND,
+ UCODE_ERROR,
++ UCODE_TIMEOUT,
+ };
+
+ struct microcode_ops {
--- /dev/null
+From dcfc9697e6569d326cfef8ae6e068f94ce9cc947 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Thu, 23 Jan 2025 13:02:32 +0100
+Subject: x86/microcode/AMD: Add get_patch_level()
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 037e81fb9d2dfe7b31fd97e5f578854e38f09887 upstream
+
+Put the MSR_AMD64_PATCH_LEVEL reading of the current microcode revision
+the hw has, into a separate function.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20250211163648.30531-6-bp@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 46 ++++++++++++++++++------------------
+ 1 file changed, 24 insertions(+), 22 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -147,6 +147,15 @@ ucode_path[] __maybe_unused = "kernel/x8
+ */
+ static u32 bsp_cpuid_1_eax __ro_after_init;
+
++static u32 get_patch_level(void)
++{
++ u32 rev, dummy __always_unused;
++
++ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
++
++ return rev;
++}
++
+ static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val)
+ {
+ union zen_patch_rev p;
+@@ -486,10 +495,10 @@ static void scan_containers(u8 *ucode, s
+ }
+ }
+
+-static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
++static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
++ unsigned int psize)
+ {
+ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
+- u32 rev, dummy;
+
+ native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
+
+@@ -507,9 +516,8 @@ static bool __apply_microcode_amd(struct
+ }
+
+ /* verify patch application was successful */
+- native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+-
+- if (rev != mc->hdr.patch_id)
++ *cur_rev = get_patch_level();
++ if (*cur_rev != mc->hdr.patch_id)
+ return false;
+
+ return true;
+@@ -567,11 +575,12 @@ void __init load_ucode_amd_bsp(struct ea
+ struct cont_desc desc = { };
+ struct microcode_amd *mc;
+ struct cpio_data cp = { };
+- u32 dummy;
++ u32 rev;
+
+ bsp_cpuid_1_eax = cpuid_1_eax;
+
+- native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
++ rev = get_patch_level();
++ ed->old_rev = rev;
+
+ /* Needed in load_microcode_amd() */
+ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
+@@ -593,8 +602,8 @@ void __init load_ucode_amd_bsp(struct ea
+ if (ed->old_rev > mc->hdr.patch_id)
+ return;
+
+- if (__apply_microcode_amd(mc, desc.psize))
+- native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
++ if (__apply_microcode_amd(mc, &rev, desc.psize))
++ ed->new_rev = rev;
+ }
+
+ static inline bool patch_cpus_equivalent(struct ucode_patch *p,
+@@ -696,14 +705,9 @@ static void free_cache(void)
+ static struct ucode_patch *find_patch(unsigned int cpu)
+ {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+- u32 rev, dummy __always_unused;
+ u16 equiv_id;
+
+- /* fetch rev if not populated yet: */
+- if (!uci->cpu_sig.rev) {
+- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+- uci->cpu_sig.rev = rev;
+- }
++ uci->cpu_sig.rev = get_patch_level();
+
+ if (x86_family(bsp_cpuid_1_eax) < 0x17) {
+ equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
+@@ -726,22 +730,20 @@ void reload_ucode_amd(unsigned int cpu)
+
+ mc = p->data;
+
+- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+-
++ rev = get_patch_level();
+ if (rev < mc->hdr.patch_id) {
+- if (__apply_microcode_amd(mc, p->size))
+- pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
++ if (__apply_microcode_amd(mc, &rev, p->size))
++ pr_info_once("reload revision: 0x%08x\n", rev);
+ }
+ }
+
+ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
+ {
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ struct ucode_patch *p;
+
+ csig->sig = cpuid_eax(0x00000001);
+- csig->rev = c->microcode;
++ csig->rev = get_patch_level();
+
+ /*
+ * a patch could have been loaded early, set uci->mc so that
+@@ -782,7 +784,7 @@ static enum ucode_state apply_microcode_
+ goto out;
+ }
+
+- if (!__apply_microcode_amd(mc_amd, p->size)) {
++ if (!__apply_microcode_amd(mc_amd, &rev, p->size)) {
+ pr_err("CPU%d: update failed for patch_level=0x%08x\n",
+ cpu, mc_amd->hdr.patch_id);
+ return UCODE_ERROR;
--- /dev/null
+From 774c3e2de69911f2baaaaab1b3ef55ea25776a30 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:53 +0200
+Subject: x86/microcode/amd: Cache builtin/initrd microcode early
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit a7939f01672034a58ad3fdbce69bb6c665ce0024 upstream
+
+There is no reason to scan builtin/initrd microcode on each AP.
+
+Cache the builtin/initrd microcode in an early initcall so that the
+early AP loader can utilize the cache.
+
+The existing fs initcall which invoked save_microcode_in_initrd_amd() is
+still required to maintain the initrd_gone flag. Rename it accordingly.
+This will be removed once the AP loader code is converted to use the
+cache.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211723.187566507@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 8 +++++++-
+ arch/x86/kernel/cpu/microcode/core.c | 26 ++++----------------------
+ 2 files changed, 11 insertions(+), 23 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -527,12 +527,17 @@ void load_ucode_amd_early(unsigned int c
+
+ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
+
+-int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
++static int __init save_microcode_in_initrd(void)
+ {
++ unsigned int cpuid_1_eax = native_cpuid_eax(1);
++ struct cpuinfo_x86 *c = &boot_cpu_data;
+ struct cont_desc desc = { 0 };
+ enum ucode_state ret;
+ struct cpio_data cp;
+
++ if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
++ return 0;
++
+ find_blobs_in_containers(cpuid_1_eax, &cp);
+ if (!(cp.data && cp.size))
+ return -EINVAL;
+@@ -549,6 +554,7 @@ int __init save_microcode_in_initrd_amd(
+
+ return 0;
+ }
++early_initcall(save_microcode_in_initrd);
+
+ /*
+ * a small, trivial cache of per-family ucode patches
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -180,30 +180,13 @@ void load_ucode_ap(void)
+ }
+ }
+
+-static int __init save_microcode_in_initrd(void)
++/* Temporary workaround until find_microcode_in_initrd() is __init */
++static int __init mark_initrd_gone(void)
+ {
+- struct cpuinfo_x86 *c = &boot_cpu_data;
+- int ret = -EINVAL;
+-
+- if (dis_ucode_ldr) {
+- ret = 0;
+- goto out;
+- }
+-
+- switch (c->x86_vendor) {
+- case X86_VENDOR_AMD:
+- if (c->x86 >= 0x10)
+- ret = save_microcode_in_initrd_amd(cpuid_eax(1));
+- break;
+- default:
+- break;
+- }
+-
+-out:
+ initrd_gone = true;
+-
+- return ret;
++ return 0;
+ }
++fs_initcall(mark_initrd_gone);
+
+ struct cpio_data find_microcode_in_initrd(const char *path)
+ {
+@@ -621,5 +604,4 @@ static int __init microcode_init(void)
+ return error;
+
+ }
+-fs_initcall(save_microcode_in_initrd);
+ late_initcall(microcode_init);
--- /dev/null
+From 743fc38b6a60d7764b20ec7c383f327ff80d29c0 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 10 Oct 2023 17:08:43 +0200
+Subject: x86/microcode/amd: Cache builtin microcode too
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit d419d28261e72e1c9ec418711b3da41df2265139 upstream
+
+save_microcode_in_initrd_amd() fails to cache builtin microcode and only
+scans initrd.
+
+Use find_blobs_in_containers() instead which covers both.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231010150702.495139089@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -533,7 +533,7 @@ int __init save_microcode_in_initrd_amd(
+ enum ucode_state ret;
+ struct cpio_data cp;
+
+- cp = find_microcode_in_initrd(ucode_path);
++ find_blobs_in_containers(cpuid_1_eax, &cp);
+ if (!(cp.data && cp.size))
+ return -EINVAL;
+
--- /dev/null
+From 43796fa7351ee4f2b5bcc747e69a73d3fe722c34 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Tue, 19 Nov 2024 12:21:33 +0100
+Subject: x86/microcode/AMD: Flush patch buffer mapping after application
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit c809b0d0e52d01c30066367b2952c4c4186b1047 upstream
+
+Due to specific requirements while applying microcode patches on Zen1
+and 2, the patch buffer mapping needs to be flushed from the TLB after
+application. Do so.
+
+If not, unnecessary and unnatural delays happen in the boot process.
+
+Reported-by: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
+Cc: <stable@kernel.org> # f1d84b59cbb9 ("x86/mm: Carve out INVLPG inline asm for use by others")
+Link: https://lore.kernel.org/r/ZyulbYuvrkshfsd2@antipodes
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -34,6 +34,7 @@
+ #include <asm/setup.h>
+ #include <asm/cpu.h>
+ #include <asm/msr.h>
++#include <asm/tlb.h>
+
+ #include "internal.h"
+
+@@ -485,11 +486,25 @@ static void scan_containers(u8 *ucode, s
+ }
+ }
+
+-static int __apply_microcode_amd(struct microcode_amd *mc)
++static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
+ {
++ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
+ u32 rev, dummy;
+
+- native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc->hdr.data_code);
++ native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
++
++ if (x86_family(bsp_cpuid_1_eax) == 0x17) {
++ unsigned long p_addr_end = p_addr + psize - 1;
++
++ invlpg(p_addr);
++
++ /*
++ * Flush next page too if patch image is crossing a page
++ * boundary.
++ */
++ if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT)
++ invlpg(p_addr_end);
++ }
+
+ /* verify patch application was successful */
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+@@ -531,7 +546,7 @@ static bool early_apply_microcode(u32 ol
+ if (old_rev > mc->hdr.patch_id)
+ return ret;
+
+- return !__apply_microcode_amd(mc);
++ return !__apply_microcode_amd(mc, desc.psize);
+ }
+
+ static bool get_builtin_microcode(struct cpio_data *cp)
+@@ -747,7 +762,7 @@ void reload_ucode_amd(unsigned int cpu)
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ if (rev < mc->hdr.patch_id) {
+- if (!__apply_microcode_amd(mc))
++ if (!__apply_microcode_amd(mc, p->size))
+ pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
+ }
+ }
+@@ -800,7 +815,7 @@ static enum ucode_state apply_microcode_
+ goto out;
+ }
+
+- if (__apply_microcode_amd(mc_amd)) {
++ if (__apply_microcode_amd(mc_amd, p->size)) {
+ pr_err("CPU%d: update failed for patch_level=0x%08x\n",
+ cpu, mc_amd->hdr.patch_id);
+ return UCODE_ERROR;
--- /dev/null
+From 4dd1f715003bc4b5d86f83d849f069c3243bdcf4 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Thu, 23 Jan 2025 12:51:37 +0100
+Subject: x86/microcode/AMD: Get rid of the _load_microcode_amd() forward declaration
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit b39c387164879eef71886fc93cee5ca7dd7bf500 upstream
+
+Simply move save_microcode_in_initrd() down.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20250211163648.30531-5-bp@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 54 +++++++++++++++++-------------------
+ 1 file changed, 26 insertions(+), 28 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -597,34 +597,6 @@ void __init load_ucode_amd_bsp(struct ea
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
+ }
+
+-static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size);
+-
+-static int __init save_microcode_in_initrd(void)
+-{
+- unsigned int cpuid_1_eax = native_cpuid_eax(1);
+- struct cpuinfo_x86 *c = &boot_cpu_data;
+- struct cont_desc desc = { 0 };
+- enum ucode_state ret;
+- struct cpio_data cp;
+-
+- if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
+- return 0;
+-
+- if (!find_blobs_in_containers(&cp))
+- return -EINVAL;
+-
+- scan_containers(cp.data, cp.size, &desc);
+- if (!desc.mc)
+- return -EINVAL;
+-
+- ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
+- if (ret > UCODE_UPDATED)
+- return -EINVAL;
+-
+- return 0;
+-}
+-early_initcall(save_microcode_in_initrd);
+-
+ static inline bool patch_cpus_equivalent(struct ucode_patch *p,
+ struct ucode_patch *n,
+ bool ignore_stepping)
+@@ -1008,6 +980,32 @@ static enum ucode_state load_microcode_a
+ return ret;
+ }
+
++static int __init save_microcode_in_initrd(void)
++{
++ unsigned int cpuid_1_eax = native_cpuid_eax(1);
++ struct cpuinfo_x86 *c = &boot_cpu_data;
++ struct cont_desc desc = { 0 };
++ enum ucode_state ret;
++ struct cpio_data cp;
++
++ if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
++ return 0;
++
++ if (!find_blobs_in_containers(&cp))
++ return -EINVAL;
++
++ scan_containers(cp.data, cp.size, &desc);
++ if (!desc.mc)
++ return -EINVAL;
++
++ ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
++ if (ret > UCODE_UPDATED)
++ return -EINVAL;
++
++ return 0;
++}
++early_initcall(save_microcode_in_initrd);
++
+ /*
+ * AMD microcode firmware naming convention, up to family 15h they are in
+ * the legacy file:
--- /dev/null
+From 51afb39e8de36dc4e1f48cb1ad1109c734d5f085 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Mon, 18 Nov 2024 17:17:24 +0100
+Subject: x86/microcode/AMD: Have __apply_microcode_amd() return bool
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 78e0aadbd4c6807a06a9d25bc190fe515d3f3c42 upstream
+
+This is the natural thing to do anyway.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -486,7 +486,7 @@ static void scan_containers(u8 *ucode, s
+ }
+ }
+
+-static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
++static bool __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
+ {
+ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
+ u32 rev, dummy;
+@@ -510,9 +510,9 @@ static int __apply_microcode_amd(struct
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ if (rev != mc->hdr.patch_id)
+- return -1;
++ return false;
+
+- return 0;
++ return true;
+ }
+
+ /*
+@@ -546,7 +546,7 @@ static bool early_apply_microcode(u32 ol
+ if (old_rev > mc->hdr.patch_id)
+ return ret;
+
+- return !__apply_microcode_amd(mc, desc.psize);
++ return __apply_microcode_amd(mc, desc.psize);
+ }
+
+ static bool get_builtin_microcode(struct cpio_data *cp)
+@@ -765,7 +765,7 @@ void reload_ucode_amd(unsigned int cpu)
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ if (rev < mc->hdr.patch_id) {
+- if (!__apply_microcode_amd(mc, p->size))
++ if (__apply_microcode_amd(mc, p->size))
+ pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
+ }
+ }
+@@ -818,7 +818,7 @@ static enum ucode_state apply_microcode_
+ goto out;
+ }
+
+- if (__apply_microcode_amd(mc_amd, p->size)) {
++ if (!__apply_microcode_amd(mc_amd, p->size)) {
+ pr_err("CPU%d: update failed for patch_level=0x%08x\n",
+ cpu, mc_amd->hdr.patch_id);
+ return UCODE_ERROR;
--- /dev/null
+From 261d80764841b43ba45e79bf1798a4472a30e5b4 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Thu, 23 Jan 2025 14:44:53 +0100
+Subject: x86/microcode/AMD: Load only SHA256-checksummed patches
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 50cef76d5cb0e199cda19f026842560f6eedc4f7 upstream
+
+Load patches for which the driver carries a SHA256 checksum of the patch
+blob.
+
+This can be disabled by adding "microcode.amd_sha_check=off" on the
+kernel cmdline. But it is highly NOT recommended.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/Kconfig | 1
+ arch/x86/kernel/cpu/microcode/amd.c | 111 +++++++
+ arch/x86/kernel/cpu/microcode/amd_shas.c | 444 +++++++++++++++++++++++++++++++
+ 3 files changed, 554 insertions(+), 2 deletions(-)
+ create mode 100644 arch/x86/kernel/cpu/microcode/amd_shas.c
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1313,6 +1313,7 @@ config X86_REBOOTFIXUPS
+ config MICROCODE
+ def_bool y
+ depends on CPU_SUP_AMD || CPU_SUP_INTEL
++ select CRYPTO_LIB_SHA256 if CPU_SUP_AMD
+
+ config MICROCODE_LATE_LOADING
+ bool "Late microcode loading (DANGEROUS)"
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -23,14 +23,18 @@
+
+ #include <linux/earlycpio.h>
+ #include <linux/firmware.h>
++#include <linux/bsearch.h>
+ #include <linux/uaccess.h>
+ #include <linux/vmalloc.h>
+ #include <linux/initrd.h>
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+
++#include <crypto/sha2.h>
++
+ #include <asm/microcode.h>
+ #include <asm/processor.h>
++#include <asm/cmdline.h>
+ #include <asm/setup.h>
+ #include <asm/cpu.h>
+ #include <asm/msr.h>
+@@ -147,6 +151,98 @@ ucode_path[] __maybe_unused = "kernel/x8
+ */
+ static u32 bsp_cpuid_1_eax __ro_after_init;
+
++static bool sha_check = true;
++
++struct patch_digest {
++ u32 patch_id;
++ u8 sha256[SHA256_DIGEST_SIZE];
++};
++
++#include "amd_shas.c"
++
++static int cmp_id(const void *key, const void *elem)
++{
++ struct patch_digest *pd = (struct patch_digest *)elem;
++ u32 patch_id = *(u32 *)key;
++
++ if (patch_id == pd->patch_id)
++ return 0;
++ else if (patch_id < pd->patch_id)
++ return -1;
++ else
++ return 1;
++}
++
++static bool need_sha_check(u32 cur_rev)
++{
++ switch (cur_rev >> 8) {
++ case 0x80012: return cur_rev <= 0x800126f; break;
++ case 0x83010: return cur_rev <= 0x830107c; break;
++ case 0x86001: return cur_rev <= 0x860010e; break;
++ case 0x86081: return cur_rev <= 0x8608108; break;
++ case 0x87010: return cur_rev <= 0x8701034; break;
++ case 0x8a000: return cur_rev <= 0x8a0000a; break;
++ case 0xa0011: return cur_rev <= 0xa0011da; break;
++ case 0xa0012: return cur_rev <= 0xa001243; break;
++ case 0xa1011: return cur_rev <= 0xa101153; break;
++ case 0xa1012: return cur_rev <= 0xa10124e; break;
++ case 0xa1081: return cur_rev <= 0xa108109; break;
++ case 0xa2010: return cur_rev <= 0xa20102f; break;
++ case 0xa2012: return cur_rev <= 0xa201212; break;
++ case 0xa6012: return cur_rev <= 0xa60120a; break;
++ case 0xa7041: return cur_rev <= 0xa704109; break;
++ case 0xa7052: return cur_rev <= 0xa705208; break;
++ case 0xa7080: return cur_rev <= 0xa708009; break;
++ case 0xa70c0: return cur_rev <= 0xa70C009; break;
++ case 0xaa002: return cur_rev <= 0xaa00218; break;
++ default: break;
++ }
++
++ pr_info("You should not be seeing this. Please send the following couple of lines to x86-<at>-kernel.org\n");
++ pr_info("CPUID(1).EAX: 0x%x, current revision: 0x%x\n", bsp_cpuid_1_eax, cur_rev);
++ return true;
++}
++
++static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsigned int len)
++{
++ struct patch_digest *pd = NULL;
++ u8 digest[SHA256_DIGEST_SIZE];
++ struct sha256_state s;
++ int i;
++
++ if (x86_family(bsp_cpuid_1_eax) < 0x17 ||
++ x86_family(bsp_cpuid_1_eax) > 0x19)
++ return true;
++
++ if (!need_sha_check(cur_rev))
++ return true;
++
++ if (!sha_check)
++ return true;
++
++ pd = bsearch(&patch_id, phashes, ARRAY_SIZE(phashes), sizeof(struct patch_digest), cmp_id);
++ if (!pd) {
++ pr_err("No sha256 digest for patch ID: 0x%x found\n", patch_id);
++ return false;
++ }
++
++ sha256_init(&s);
++ sha256_update(&s, data, len);
++ sha256_final(&s, digest);
++
++ if (memcmp(digest, pd->sha256, sizeof(digest))) {
++ pr_err("Patch 0x%x SHA256 digest mismatch!\n", patch_id);
++
++ for (i = 0; i < SHA256_DIGEST_SIZE; i++)
++ pr_cont("0x%x ", digest[i]);
++ pr_info("\n");
++
++ return false;
++ }
++
++ return true;
++}
++
+ static u32 get_patch_level(void)
+ {
+ u32 rev, dummy __always_unused;
+@@ -500,6 +596,9 @@ static bool __apply_microcode_amd(struct
+ {
+ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
+
++ if (!verify_sha256_digest(mc->hdr.patch_id, *cur_rev, (const u8 *)p_addr, psize))
++ return -1;
++
+ native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
+
+ if (x86_family(bsp_cpuid_1_eax) == 0x17) {
+@@ -575,8 +674,17 @@ void __init load_ucode_amd_bsp(struct ea
+ struct cont_desc desc = { };
+ struct microcode_amd *mc;
+ struct cpio_data cp = { };
++ char buf[4];
+ u32 rev;
+
++ if (cmdline_find_option(boot_command_line, "microcode.amd_sha_check", buf, 4)) {
++ if (!strncmp(buf, "off", 3)) {
++ sha_check = false;
++ pr_warn_once("It is a very very bad idea to disable the blobs SHA check!\n");
++ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
++ }
++ }
++
+ bsp_cpuid_1_eax = cpuid_1_eax;
+
+ rev = get_patch_level();
+@@ -906,8 +1014,7 @@ static int verify_and_add_patch(u8 famil
+ }
+
+ /* Scan the blob in @data and add microcode patches to the cache. */
+-static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
+- size_t size)
++static enum ucode_state __load_microcode_amd(u8 family, const u8 *data, size_t size)
+ {
+ u8 *fw = (u8 *)data;
+ size_t offset;
+--- /dev/null
++++ b/arch/x86/kernel/cpu/microcode/amd_shas.c
+@@ -0,0 +1,444 @@
++/* Keep 'em sorted. */
++static const struct patch_digest phashes[] = {
++ { 0x8001227, {
++ 0x99,0xc0,0x9b,0x2b,0xcc,0x9f,0x52,0x1b,
++ 0x1a,0x5f,0x1d,0x83,0xa1,0x6c,0xc4,0x46,
++ 0xe2,0x6c,0xda,0x73,0xfb,0x2d,0x23,0xa8,
++ 0x77,0xdc,0x15,0x31,0x33,0x4a,0x46,0x18,
++ }
++ },
++ { 0x8001250, {
++ 0xc0,0x0b,0x6b,0x19,0xfd,0x5c,0x39,0x60,
++ 0xd5,0xc3,0x57,0x46,0x54,0xe4,0xd1,0xaa,
++ 0xa8,0xf7,0x1f,0xa8,0x6a,0x60,0x3e,0xe3,
++ 0x27,0x39,0x8e,0x53,0x30,0xf8,0x49,0x19,
++ }
++ },
++ { 0x800126e, {
++ 0xf3,0x8b,0x2b,0xb6,0x34,0xe3,0xc8,0x2c,
++ 0xef,0xec,0x63,0x6d,0xc8,0x76,0x77,0xb3,
++ 0x25,0x5a,0xb7,0x52,0x8c,0x83,0x26,0xe6,
++ 0x4c,0xbe,0xbf,0xe9,0x7d,0x22,0x6a,0x43,
++ }
++ },
++ { 0x800126f, {
++ 0x2b,0x5a,0xf2,0x9c,0xdd,0xd2,0x7f,0xec,
++ 0xec,0x96,0x09,0x57,0xb0,0x96,0x29,0x8b,
++ 0x2e,0x26,0x91,0xf0,0x49,0x33,0x42,0x18,
++ 0xdd,0x4b,0x65,0x5a,0xd4,0x15,0x3d,0x33,
++ }
++ },
++ { 0x800820d, {
++ 0x68,0x98,0x83,0xcd,0x22,0x0d,0xdd,0x59,
++ 0x73,0x2c,0x5b,0x37,0x1f,0x84,0x0e,0x67,
++ 0x96,0x43,0x83,0x0c,0x46,0x44,0xab,0x7c,
++ 0x7b,0x65,0x9e,0x57,0xb5,0x90,0x4b,0x0e,
++ }
++ },
++ { 0x8301025, {
++ 0xe4,0x7d,0xdb,0x1e,0x14,0xb4,0x5e,0x36,
++ 0x8f,0x3e,0x48,0x88,0x3c,0x6d,0x76,0xa1,
++ 0x59,0xc6,0xc0,0x72,0x42,0xdf,0x6c,0x30,
++ 0x6f,0x0b,0x28,0x16,0x61,0xfc,0x79,0x77,
++ }
++ },
++ { 0x8301055, {
++ 0x81,0x7b,0x99,0x1b,0xae,0x2d,0x4f,0x9a,
++ 0xef,0x13,0xce,0xb5,0x10,0xaf,0x6a,0xea,
++ 0xe5,0xb0,0x64,0x98,0x10,0x68,0x34,0x3b,
++ 0x9d,0x7a,0xd6,0x22,0x77,0x5f,0xb3,0x5b,
++ }
++ },
++ { 0x8301072, {
++ 0xcf,0x76,0xa7,0x1a,0x49,0xdf,0x2a,0x5e,
++ 0x9e,0x40,0x70,0xe5,0xdd,0x8a,0xa8,0x28,
++ 0x20,0xdc,0x91,0xd8,0x2c,0xa6,0xa0,0xb1,
++ 0x2d,0x22,0x26,0x94,0x4b,0x40,0x85,0x30,
++ }
++ },
++ { 0x830107a, {
++ 0x2a,0x65,0x8c,0x1a,0x5e,0x07,0x21,0x72,
++ 0xdf,0x90,0xa6,0x51,0x37,0xd3,0x4b,0x34,
++ 0xc4,0xda,0x03,0xe1,0x8a,0x6c,0xfb,0x20,
++ 0x04,0xb2,0x81,0x05,0xd4,0x87,0xf4,0x0a,
++ }
++ },
++ { 0x830107b, {
++ 0xb3,0x43,0x13,0x63,0x56,0xc1,0x39,0xad,
++ 0x10,0xa6,0x2b,0xcc,0x02,0xe6,0x76,0x2a,
++ 0x1e,0x39,0x58,0x3e,0x23,0x6e,0xa4,0x04,
++ 0x95,0xea,0xf9,0x6d,0xc2,0x8a,0x13,0x19,
++ }
++ },
++ { 0x830107c, {
++ 0x21,0x64,0xde,0xfb,0x9f,0x68,0x96,0x47,
++ 0x70,0x5c,0xe2,0x8f,0x18,0x52,0x6a,0xac,
++ 0xa4,0xd2,0x2e,0xe0,0xde,0x68,0x66,0xc3,
++ 0xeb,0x1e,0xd3,0x3f,0xbc,0x51,0x1d,0x38,
++ }
++ },
++ { 0x860010d, {
++ 0x86,0xb6,0x15,0x83,0xbc,0x3b,0x9c,0xe0,
++ 0xb3,0xef,0x1d,0x99,0x84,0x35,0x15,0xf7,
++ 0x7c,0x2a,0xc6,0x42,0xdb,0x73,0x07,0x5c,
++ 0x7d,0xc3,0x02,0xb5,0x43,0x06,0x5e,0xf8,
++ }
++ },
++ { 0x8608108, {
++ 0x14,0xfe,0x57,0x86,0x49,0xc8,0x68,0xe2,
++ 0x11,0xa3,0xcb,0x6e,0xff,0x6e,0xd5,0x38,
++ 0xfe,0x89,0x1a,0xe0,0x67,0xbf,0xc4,0xcc,
++ 0x1b,0x9f,0x84,0x77,0x2b,0x9f,0xaa,0xbd,
++ }
++ },
++ { 0x8701034, {
++ 0xc3,0x14,0x09,0xa8,0x9c,0x3f,0x8d,0x83,
++ 0x9b,0x4c,0xa5,0xb7,0x64,0x8b,0x91,0x5d,
++ 0x85,0x6a,0x39,0x26,0x1e,0x14,0x41,0xa8,
++ 0x75,0xea,0xa6,0xf9,0xc9,0xd1,0xea,0x2b,
++ }
++ },
++ { 0x8a00008, {
++ 0xd7,0x2a,0x93,0xdc,0x05,0x2f,0xa5,0x6e,
++ 0x0c,0x61,0x2c,0x07,0x9f,0x38,0xe9,0x8e,
++ 0xef,0x7d,0x2a,0x05,0x4d,0x56,0xaf,0x72,
++ 0xe7,0x56,0x47,0x6e,0x60,0x27,0xd5,0x8c,
++ }
++ },
++ { 0x8a0000a, {
++ 0x73,0x31,0x26,0x22,0xd4,0xf9,0xee,0x3c,
++ 0x07,0x06,0xe7,0xb9,0xad,0xd8,0x72,0x44,
++ 0x33,0x31,0xaa,0x7d,0xc3,0x67,0x0e,0xdb,
++ 0x47,0xb5,0xaa,0xbc,0xf5,0xbb,0xd9,0x20,
++ }
++ },
++ { 0xa00104c, {
++ 0x3c,0x8a,0xfe,0x04,0x62,0xd8,0x6d,0xbe,
++ 0xa7,0x14,0x28,0x64,0x75,0xc0,0xa3,0x76,
++ 0xb7,0x92,0x0b,0x97,0x0a,0x8e,0x9c,0x5b,
++ 0x1b,0xc8,0x9d,0x3a,0x1e,0x81,0x3d,0x3b,
++ }
++ },
++ { 0xa00104e, {
++ 0xc4,0x35,0x82,0x67,0xd2,0x86,0xe5,0xb2,
++ 0xfd,0x69,0x12,0x38,0xc8,0x77,0xba,0xe0,
++ 0x70,0xf9,0x77,0x89,0x10,0xa6,0x74,0x4e,
++ 0x56,0x58,0x13,0xf5,0x84,0x70,0x28,0x0b,
++ }
++ },
++ { 0xa001053, {
++ 0x92,0x0e,0xf4,0x69,0x10,0x3b,0xf9,0x9d,
++ 0x31,0x1b,0xa6,0x99,0x08,0x7d,0xd7,0x25,
++ 0x7e,0x1e,0x89,0xba,0x35,0x8d,0xac,0xcb,
++ 0x3a,0xb4,0xdf,0x58,0x12,0xcf,0xc0,0xc3,
++ }
++ },
++ { 0xa001058, {
++ 0x33,0x7d,0xa9,0xb5,0x4e,0x62,0x13,0x36,
++ 0xef,0x66,0xc9,0xbd,0x0a,0xa6,0x3b,0x19,
++ 0xcb,0xf5,0xc2,0xc3,0x55,0x47,0x20,0xec,
++ 0x1f,0x7b,0xa1,0x44,0x0e,0x8e,0xa4,0xb2,
++ }
++ },
++ { 0xa001075, {
++ 0x39,0x02,0x82,0xd0,0x7c,0x26,0x43,0xe9,
++ 0x26,0xa3,0xd9,0x96,0xf7,0x30,0x13,0x0a,
++ 0x8a,0x0e,0xac,0xe7,0x1d,0xdc,0xe2,0x0f,
++ 0xcb,0x9e,0x8d,0xbc,0xd2,0xa2,0x44,0xe0,
++ }
++ },
++ { 0xa001078, {
++ 0x2d,0x67,0xc7,0x35,0xca,0xef,0x2f,0x25,
++ 0x4c,0x45,0x93,0x3f,0x36,0x01,0x8c,0xce,
++ 0xa8,0x5b,0x07,0xd3,0xc1,0x35,0x3c,0x04,
++ 0x20,0xa2,0xfc,0xdc,0xe6,0xce,0x26,0x3e,
++ }
++ },
++ { 0xa001079, {
++ 0x43,0xe2,0x05,0x9c,0xfd,0xb7,0x5b,0xeb,
++ 0x5b,0xe9,0xeb,0x3b,0x96,0xf4,0xe4,0x93,
++ 0x73,0x45,0x3e,0xac,0x8d,0x3b,0xe4,0xdb,
++ 0x10,0x31,0xc1,0xe4,0xa2,0xd0,0x5a,0x8a,
++ }
++ },
++ { 0xa00107a, {
++ 0x5f,0x92,0xca,0xff,0xc3,0x59,0x22,0x5f,
++ 0x02,0xa0,0x91,0x3b,0x4a,0x45,0x10,0xfd,
++ 0x19,0xe1,0x8a,0x6d,0x9a,0x92,0xc1,0x3f,
++ 0x75,0x78,0xac,0x78,0x03,0x1d,0xdb,0x18,
++ }
++ },
++ { 0xa001143, {
++ 0x56,0xca,0xf7,0x43,0x8a,0x4c,0x46,0x80,
++ 0xec,0xde,0xe5,0x9c,0x50,0x84,0x9a,0x42,
++ 0x27,0xe5,0x51,0x84,0x8f,0x19,0xc0,0x8d,
++ 0x0c,0x25,0xb4,0xb0,0x8f,0x10,0xf3,0xf8,
++ }
++ },
++ { 0xa001144, {
++ 0x42,0xd5,0x9b,0xa7,0xd6,0x15,0x29,0x41,
++ 0x61,0xc4,0x72,0x3f,0xf3,0x06,0x78,0x4b,
++ 0x65,0xf3,0x0e,0xfa,0x9c,0x87,0xde,0x25,
++ 0xbd,0xb3,0x9a,0xf4,0x75,0x13,0x53,0xdc,
++ }
++ },
++ { 0xa00115d, {
++ 0xd4,0xc4,0x49,0x36,0x89,0x0b,0x47,0xdd,
++ 0xfb,0x2f,0x88,0x3b,0x5f,0xf2,0x8e,0x75,
++ 0xc6,0x6c,0x37,0x5a,0x90,0x25,0x94,0x3e,
++ 0x36,0x9c,0xae,0x02,0x38,0x6c,0xf5,0x05,
++ }
++ },
++ { 0xa001173, {
++ 0x28,0xbb,0x9b,0xd1,0xa0,0xa0,0x7e,0x3a,
++ 0x59,0x20,0xc0,0xa9,0xb2,0x5c,0xc3,0x35,
++ 0x53,0x89,0xe1,0x4c,0x93,0x2f,0x1d,0xc3,
++ 0xe5,0xf7,0xf3,0xc8,0x9b,0x61,0xaa,0x9e,
++ }
++ },
++ { 0xa0011a8, {
++ 0x97,0xc6,0x16,0x65,0x99,0xa4,0x85,0x3b,
++ 0xf6,0xce,0xaa,0x49,0x4a,0x3a,0xc5,0xb6,
++ 0x78,0x25,0xbc,0x53,0xaf,0x5d,0xcf,0xf4,
++ 0x23,0x12,0xbb,0xb1,0xbc,0x8a,0x02,0x2e,
++ }
++ },
++ { 0xa0011ce, {
++ 0xcf,0x1c,0x90,0xa3,0x85,0x0a,0xbf,0x71,
++ 0x94,0x0e,0x80,0x86,0x85,0x4f,0xd7,0x86,
++ 0xae,0x38,0x23,0x28,0x2b,0x35,0x9b,0x4e,
++ 0xfe,0xb8,0xcd,0x3d,0x3d,0x39,0xc9,0x6a,
++ }
++ },
++ { 0xa0011d1, {
++ 0xdf,0x0e,0xca,0xde,0xf6,0xce,0x5c,0x1e,
++ 0x4c,0xec,0xd7,0x71,0x83,0xcc,0xa8,0x09,
++ 0xc7,0xc5,0xfe,0xb2,0xf7,0x05,0xd2,0xc5,
++ 0x12,0xdd,0xe4,0xf3,0x92,0x1c,0x3d,0xb8,
++ }
++ },
++ { 0xa0011d3, {
++ 0x91,0xe6,0x10,0xd7,0x57,0xb0,0x95,0x0b,
++ 0x9a,0x24,0xee,0xf7,0xcf,0x56,0xc1,0xa6,
++ 0x4a,0x52,0x7d,0x5f,0x9f,0xdf,0xf6,0x00,
++ 0x65,0xf7,0xea,0xe8,0x2a,0x88,0xe2,0x26,
++ }
++ },
++ { 0xa0011d5, {
++ 0xed,0x69,0x89,0xf4,0xeb,0x64,0xc2,0x13,
++ 0xe0,0x51,0x1f,0x03,0x26,0x52,0x7d,0xb7,
++ 0x93,0x5d,0x65,0xca,0xb8,0x12,0x1d,0x62,
++ 0x0d,0x5b,0x65,0x34,0x69,0xb2,0x62,0x21,
++ }
++ },
++ { 0xa001223, {
++ 0xfb,0x32,0x5f,0xc6,0x83,0x4f,0x8c,0xb8,
++ 0xa4,0x05,0xf9,0x71,0x53,0x01,0x16,0xc4,
++ 0x83,0x75,0x94,0xdd,0xeb,0x7e,0xb7,0x15,
++ 0x8e,0x3b,0x50,0x29,0x8a,0x9c,0xcc,0x45,
++ }
++ },
++ { 0xa001224, {
++ 0x0e,0x0c,0xdf,0xb4,0x89,0xee,0x35,0x25,
++ 0xdd,0x9e,0xdb,0xc0,0x69,0x83,0x0a,0xad,
++ 0x26,0xa9,0xaa,0x9d,0xfc,0x3c,0xea,0xf9,
++ 0x6c,0xdc,0xd5,0x6d,0x8b,0x6e,0x85,0x4a,
++ }
++ },
++ { 0xa001227, {
++ 0xab,0xc6,0x00,0x69,0x4b,0x50,0x87,0xad,
++ 0x5f,0x0e,0x8b,0xea,0x57,0x38,0xce,0x1d,
++ 0x0f,0x75,0x26,0x02,0xf6,0xd6,0x96,0xe9,
++ 0x87,0xb9,0xd6,0x20,0x27,0x7c,0xd2,0xe0,
++ }
++ },
++ { 0xa001229, {
++ 0x7f,0x49,0x49,0x48,0x46,0xa5,0x50,0xa6,
++ 0x28,0x89,0x98,0xe2,0x9e,0xb4,0x7f,0x75,
++ 0x33,0xa7,0x04,0x02,0xe4,0x82,0xbf,0xb4,
++ 0xa5,0x3a,0xba,0x24,0x8d,0x31,0x10,0x1d,
++ }
++ },
++ { 0xa00122e, {
++ 0x56,0x94,0xa9,0x5d,0x06,0x68,0xfe,0xaf,
++ 0xdf,0x7a,0xff,0x2d,0xdf,0x74,0x0f,0x15,
++ 0x66,0xfb,0x00,0xb5,0x51,0x97,0x9b,0xfa,
++ 0xcb,0x79,0x85,0x46,0x25,0xb4,0xd2,0x10,
++ }
++ },
++ { 0xa001231, {
++ 0x0b,0x46,0xa5,0xfc,0x18,0x15,0xa0,0x9e,
++ 0xa6,0xdc,0xb7,0xff,0x17,0xf7,0x30,0x64,
++ 0xd4,0xda,0x9e,0x1b,0xc3,0xfc,0x02,0x3b,
++ 0xe2,0xc6,0x0e,0x41,0x54,0xb5,0x18,0xdd,
++ }
++ },
++ { 0xa001234, {
++ 0x88,0x8d,0xed,0xab,0xb5,0xbd,0x4e,0xf7,
++ 0x7f,0xd4,0x0e,0x95,0x34,0x91,0xff,0xcc,
++ 0xfb,0x2a,0xcd,0xf7,0xd5,0xdb,0x4c,0x9b,
++ 0xd6,0x2e,0x73,0x50,0x8f,0x83,0x79,0x1a,
++ }
++ },
++ { 0xa001236, {
++ 0x3d,0x30,0x00,0xb9,0x71,0xba,0x87,0x78,
++ 0xa8,0x43,0x55,0xc4,0x26,0x59,0xcf,0x9d,
++ 0x93,0xce,0x64,0x0e,0x8b,0x72,0x11,0x8b,
++ 0xa3,0x8f,0x51,0xe9,0xca,0x98,0xaa,0x25,
++ }
++ },
++ { 0xa001238, {
++ 0x72,0xf7,0x4b,0x0c,0x7d,0x58,0x65,0xcc,
++ 0x00,0xcc,0x57,0x16,0x68,0x16,0xf8,0x2a,
++ 0x1b,0xb3,0x8b,0xe1,0xb6,0x83,0x8c,0x7e,
++ 0xc0,0xcd,0x33,0xf2,0x8d,0xf9,0xef,0x59,
++ }
++ },
++ { 0xa00820c, {
++ 0xa8,0x0c,0x81,0xc0,0xa6,0x00,0xe7,0xf3,
++ 0x5f,0x65,0xd3,0xb9,0x6f,0xea,0x93,0x63,
++ 0xf1,0x8c,0x88,0x45,0xd7,0x82,0x80,0xd1,
++ 0xe1,0x3b,0x8d,0xb2,0xf8,0x22,0x03,0xe2,
++ }
++ },
++ { 0xa10113e, {
++ 0x05,0x3c,0x66,0xd7,0xa9,0x5a,0x33,0x10,
++ 0x1b,0xf8,0x9c,0x8f,0xed,0xfc,0xa7,0xa0,
++ 0x15,0xe3,0x3f,0x4b,0x1d,0x0d,0x0a,0xd5,
++ 0xfa,0x90,0xc4,0xed,0x9d,0x90,0xaf,0x53,
++ }
++ },
++ { 0xa101144, {
++ 0xb3,0x0b,0x26,0x9a,0xf8,0x7c,0x02,0x26,
++ 0x35,0x84,0x53,0xa4,0xd3,0x2c,0x7c,0x09,
++ 0x68,0x7b,0x96,0xb6,0x93,0xef,0xde,0xbc,
++ 0xfd,0x4b,0x15,0xd2,0x81,0xd3,0x51,0x47,
++ }
++ },
++ { 0xa101148, {
++ 0x20,0xd5,0x6f,0x40,0x4a,0xf6,0x48,0x90,
++ 0xc2,0x93,0x9a,0xc2,0xfd,0xac,0xef,0x4f,
++ 0xfa,0xc0,0x3d,0x92,0x3c,0x6d,0x01,0x08,
++ 0xf1,0x5e,0xb0,0xde,0xb4,0x98,0xae,0xc4,
++ }
++ },
++ { 0xa10123e, {
++ 0x03,0xb9,0x2c,0x76,0x48,0x93,0xc9,0x18,
++ 0xfb,0x56,0xfd,0xf7,0xe2,0x1d,0xca,0x4d,
++ 0x1d,0x13,0x53,0x63,0xfe,0x42,0x6f,0xfc,
++ 0x19,0x0f,0xf1,0xfc,0xa7,0xdd,0x89,0x1b,
++ }
++ },
++ { 0xa101244, {
++ 0x71,0x56,0xb5,0x9f,0x21,0xbf,0xb3,0x3c,
++ 0x8c,0xd7,0x36,0xd0,0x34,0x52,0x1b,0xb1,
++ 0x46,0x2f,0x04,0xf0,0x37,0xd8,0x1e,0x72,
++ 0x24,0xa2,0x80,0x84,0x83,0x65,0x84,0xc0,
++ }
++ },
++ { 0xa101248, {
++ 0xed,0x3b,0x95,0xa6,0x68,0xa7,0x77,0x3e,
++ 0xfc,0x17,0x26,0xe2,0x7b,0xd5,0x56,0x22,
++ 0x2c,0x1d,0xef,0xeb,0x56,0xdd,0xba,0x6e,
++ 0x1b,0x7d,0x64,0x9d,0x4b,0x53,0x13,0x75,
++ }
++ },
++ { 0xa108108, {
++ 0xed,0xc2,0xec,0xa1,0x15,0xc6,0x65,0xe9,
++ 0xd0,0xef,0x39,0xaa,0x7f,0x55,0x06,0xc6,
++ 0xf5,0xd4,0x3f,0x7b,0x14,0xd5,0x60,0x2c,
++ 0x28,0x1e,0x9c,0x59,0x69,0x99,0x4d,0x16,
++ }
++ },
++ { 0xa20102d, {
++ 0xf9,0x6e,0xf2,0x32,0xd3,0x0f,0x5f,0x11,
++ 0x59,0xa1,0xfe,0xcc,0xcd,0x9b,0x42,0x89,
++ 0x8b,0x89,0x2f,0xb5,0xbb,0x82,0xef,0x23,
++ 0x8c,0xe9,0x19,0x3e,0xcc,0x3f,0x7b,0xb4,
++ }
++ },
++ { 0xa201210, {
++ 0xe8,0x6d,0x51,0x6a,0x8e,0x72,0xf3,0xfe,
++ 0x6e,0x16,0xbc,0x62,0x59,0x40,0x17,0xe9,
++ 0x6d,0x3d,0x0e,0x6b,0xa7,0xac,0xe3,0x68,
++ 0xf7,0x55,0xf0,0x13,0xbb,0x22,0xf6,0x41,
++ }
++ },
++ { 0xa404107, {
++ 0xbb,0x04,0x4e,0x47,0xdd,0x5e,0x26,0x45,
++ 0x1a,0xc9,0x56,0x24,0xa4,0x4c,0x82,0xb0,
++ 0x8b,0x0d,0x9f,0xf9,0x3a,0xdf,0xc6,0x81,
++ 0x13,0xbc,0xc5,0x25,0xe4,0xc5,0xc3,0x99,
++ }
++ },
++ { 0xa500011, {
++ 0x23,0x3d,0x70,0x7d,0x03,0xc3,0xc4,0xf4,
++ 0x2b,0x82,0xc6,0x05,0xda,0x80,0x0a,0xf1,
++ 0xd7,0x5b,0x65,0x3a,0x7d,0xab,0xdf,0xa2,
++ 0x11,0x5e,0x96,0x7e,0x71,0xe9,0xfc,0x74,
++ }
++ },
++ { 0xa601209, {
++ 0x66,0x48,0xd4,0x09,0x05,0xcb,0x29,0x32,
++ 0x66,0xb7,0x9a,0x76,0xcd,0x11,0xf3,0x30,
++ 0x15,0x86,0xcc,0x5d,0x97,0x0f,0xc0,0x46,
++ 0xe8,0x73,0xe2,0xd6,0xdb,0xd2,0x77,0x1d,
++ }
++ },
++ { 0xa704107, {
++ 0xf3,0xc6,0x58,0x26,0xee,0xac,0x3f,0xd6,
++ 0xce,0xa1,0x72,0x47,0x3b,0xba,0x2b,0x93,
++ 0x2a,0xad,0x8e,0x6b,0xea,0x9b,0xb7,0xc2,
++ 0x64,0x39,0x71,0x8c,0xce,0xe7,0x41,0x39,
++ }
++ },
++ { 0xa705206, {
++ 0x8d,0xc0,0x76,0xbd,0x58,0x9f,0x8f,0xa4,
++ 0x12,0x9d,0x21,0xfb,0x48,0x21,0xbc,0xe7,
++ 0x67,0x6f,0x04,0x18,0xae,0x20,0x87,0x4b,
++ 0x03,0x35,0xe9,0xbe,0xfb,0x06,0xdf,0xfc,
++ }
++ },
++ { 0xa708007, {
++ 0x6b,0x76,0xcc,0x78,0xc5,0x8a,0xa3,0xe3,
++ 0x32,0x2d,0x79,0xe4,0xc3,0x80,0xdb,0xb2,
++ 0x07,0xaa,0x3a,0xe0,0x57,0x13,0x72,0x80,
++ 0xdf,0x92,0x73,0x84,0x87,0x3c,0x73,0x93,
++ }
++ },
++ { 0xa70c005, {
++ 0x88,0x5d,0xfb,0x79,0x64,0xd8,0x46,0x3b,
++ 0x4a,0x83,0x8e,0x77,0x7e,0xcf,0xb3,0x0f,
++ 0x1f,0x1f,0xf1,0x97,0xeb,0xfe,0x56,0x55,
++ 0xee,0x49,0xac,0xe1,0x8b,0x13,0xc5,0x13,
++ }
++ },
++ { 0xaa00116, {
++ 0xe8,0x4c,0x2c,0x88,0xa1,0xac,0x24,0x63,
++ 0x65,0xe5,0xaa,0x2d,0x16,0xa9,0xc3,0xf5,
++ 0xfe,0x1d,0x5e,0x65,0xc7,0xaa,0x92,0x4d,
++ 0x91,0xee,0x76,0xbb,0x4c,0x66,0x78,0xc9,
++ }
++ },
++ { 0xaa00212, {
++ 0xbd,0x57,0x5d,0x0a,0x0a,0x30,0xc1,0x75,
++ 0x95,0x58,0x5e,0x93,0x02,0x28,0x43,0x71,
++ 0xed,0x42,0x29,0xc8,0xec,0x34,0x2b,0xb2,
++ 0x1a,0x65,0x4b,0xfe,0x07,0x0f,0x34,0xa1,
++ }
++ },
++ { 0xaa00213, {
++ 0xed,0x58,0xb7,0x76,0x81,0x7f,0xd9,0x3a,
++ 0x1a,0xff,0x8b,0x34,0xb8,0x4a,0x99,0x0f,
++ 0x28,0x49,0x6c,0x56,0x2b,0xdc,0xb7,0xed,
++ 0x96,0xd5,0x9d,0xc1,0x7a,0xd4,0x51,0x9b,
++ }
++ },
++ { 0xaa00215, {
++ 0x55,0xd3,0x28,0xcb,0x87,0xa9,0x32,0xe9,
++ 0x4e,0x85,0x4b,0x7c,0x6b,0xd5,0x7c,0xd4,
++ 0x1b,0x51,0x71,0x3a,0x0e,0x0b,0xdc,0x9b,
++ 0x68,0x2f,0x46,0xee,0xfe,0xc6,0x6d,0xef,
++ }
++ },
++};
--- /dev/null
+From 251ca274aa7d61a36f63239b72a6fca05ec00875 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nik.borisov@suse.com>
+Date: Fri, 18 Oct 2024 18:51:50 +0300
+Subject: x86/microcode/AMD: Make __verify_patch_size() return bool
+
+From: Nikolay Borisov <nik.borisov@suse.com>
+
+commit d8317f3d8e6b412ff51ea66f1de2b2f89835f811 upstream
+
+The result of that function is in essence boolean, so simplify to return the
+result of the relevant expression. It also makes it follow the convention used
+by __verify_patch_section().
+
+No functional changes.
+
+Signed-off-by: Nikolay Borisov <nik.borisov@suse.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20241018155151.702350-3-nik.borisov@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -285,13 +285,13 @@ __verify_patch_section(const u8 *buf, si
+ * exceed the per-family maximum). @sh_psize is the size read from the section
+ * header.
+ */
+-static unsigned int __verify_patch_size(u32 sh_psize, size_t buf_size)
++static bool __verify_patch_size(u32 sh_psize, size_t buf_size)
+ {
+ u8 family = x86_family(bsp_cpuid_1_eax);
+ u32 max_size;
+
+ if (family >= 0x15)
+- return min_t(u32, sh_psize, buf_size);
++ goto ret;
+
+ #define F1XH_MPB_MAX_SIZE 2048
+ #define F14H_MPB_MAX_SIZE 1824
+@@ -305,13 +305,15 @@ static unsigned int __verify_patch_size(
+ break;
+ default:
+ WARN(1, "%s: WTF family: 0x%x\n", __func__, family);
+- return 0;
++ return false;
+ }
+
+- if (sh_psize > min_t(u32, buf_size, max_size))
+- return 0;
++ if (sh_psize > max_size)
++ return false;
+
+- return sh_psize;
++ret:
++ /* Working with the whole buffer so < is ok. */
++ return sh_psize <= buf_size;
+ }
+
+ /*
+@@ -326,7 +328,6 @@ static int verify_patch(const u8 *buf, s
+ {
+ u8 family = x86_family(bsp_cpuid_1_eax);
+ struct microcode_header_amd *mc_hdr;
+- unsigned int ret;
+ u32 sh_psize;
+ u16 proc_id;
+ u8 patch_fam;
+@@ -350,8 +351,7 @@ static int verify_patch(const u8 *buf, s
+ return -1;
+ }
+
+- ret = __verify_patch_size(sh_psize, buf_size);
+- if (!ret) {
++ if (!__verify_patch_size(sh_psize, buf_size)) {
+ pr_debug("Per-family patch size mismatch.\n");
+ return -1;
+ }
--- /dev/null
+From d0ac6b03dd875fe519561db889f5ba3466d1a53b Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Thu, 23 Jan 2025 12:46:45 +0100
+Subject: x86/microcode/AMD: Merge early_apply_microcode() into its single callsite
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit dc15675074dcfd79a2f10a6e39f96b0244961a01 upstream
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20250211163648.30531-4-bp@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 60 +++++++++++++++---------------------
+ 1 file changed, 26 insertions(+), 34 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -515,39 +515,6 @@ static bool __apply_microcode_amd(struct
+ return true;
+ }
+
+-/*
+- * Early load occurs before we can vmalloc(). So we look for the microcode
+- * patch container file in initrd, traverse equivalent cpu table, look for a
+- * matching microcode patch, and update, all in initrd memory in place.
+- * When vmalloc() is available for use later -- on 64-bit during first AP load,
+- * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
+- * load_microcode_amd() to save equivalent cpu table and microcode patches in
+- * kernel heap memory.
+- *
+- * Returns true if container found (sets @desc), false otherwise.
+- */
+-static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
+-{
+- struct cont_desc desc = { 0 };
+- struct microcode_amd *mc;
+- bool ret = false;
+-
+- scan_containers(ucode, size, &desc);
+-
+- mc = desc.mc;
+- if (!mc)
+- return ret;
+-
+- /*
+- * Allow application of the same revision to pick up SMT-specific
+- * changes even if the revision of the other SMT thread is already
+- * up-to-date.
+- */
+- if (old_rev > mc->hdr.patch_id)
+- return ret;
+-
+- return __apply_microcode_amd(mc, desc.psize);
+-}
+
+ static bool get_builtin_microcode(struct cpio_data *cp)
+ {
+@@ -586,8 +553,19 @@ static bool __init find_blobs_in_contain
+ return found;
+ }
+
++/*
++ * Early load occurs before we can vmalloc(). So we look for the microcode
++ * patch container file in initrd, traverse equivalent cpu table, look for a
++ * matching microcode patch, and update, all in initrd memory in place.
++ * When vmalloc() is available for use later -- on 64-bit during first AP load,
++ * and on 32-bit during save_microcode_in_initrd() -- we can call
++ * load_microcode_amd() to save equivalent cpu table and microcode patches in
++ * kernel heap memory.
++ */
+ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
+ {
++ struct cont_desc desc = { };
++ struct microcode_amd *mc;
+ struct cpio_data cp = { };
+ u32 dummy;
+
+@@ -601,7 +579,21 @@ void __init load_ucode_amd_bsp(struct ea
+ if (!find_blobs_in_containers(&cp))
+ return;
+
+- if (early_apply_microcode(ed->old_rev, cp.data, cp.size))
++ scan_containers(cp.data, cp.size, &desc);
++
++ mc = desc.mc;
++ if (!mc)
++ return;
++
++ /*
++ * Allow application of the same revision to pick up SMT-specific
++ * changes even if the revision of the other SMT thread is already
++ * up-to-date.
++ */
++ if (ed->old_rev > mc->hdr.patch_id)
++ return;
++
++ if (__apply_microcode_amd(mc, desc.psize))
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
+ }
+
--- /dev/null
+From d3b57478de5a355a804aea35da762a9c9e345b46 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Mon, 21 Oct 2024 10:27:52 +0200
+Subject: x86/microcode/AMD: Pay attention to the stepping dynamically
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit d1744a4c975b1acbe8b498356d28afbc46c88428 upstream
+
+Commit in Fixes changed how a microcode patch is loaded on Zen and newer but
+the patch matching needs to happen with different rigidity, depending on what
+is being done:
+
+1) When the patch is added to the patches cache, the stepping must be ignored
+ because the driver still supports different steppings per system
+
+2) When the patch is matched for loading, then the stepping must be taken into
+ account because each CPU needs the patch matching its exact stepping
+
+Take care of that by making the matching smarter.
+
+Fixes: 94838d230a6c ("x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID")
+Reported-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Jens Axboe <axboe@kernel.dk>
+Link: https://lore.kernel.org/r/91194406-3fdf-4e38-9838-d334af538f74@kernel.dk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -615,16 +615,19 @@ static int __init save_microcode_in_init
+ }
+ early_initcall(save_microcode_in_initrd);
+
+-static inline bool patch_cpus_equivalent(struct ucode_patch *p, struct ucode_patch *n)
++static inline bool patch_cpus_equivalent(struct ucode_patch *p,
++ struct ucode_patch *n,
++ bool ignore_stepping)
+ {
+ /* Zen and newer hardcode the f/m/s in the patch ID */
+ if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
+ union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id);
+ union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id);
+
+- /* Zap stepping */
+- p_cid.stepping = 0;
+- n_cid.stepping = 0;
++ if (ignore_stepping) {
++ p_cid.stepping = 0;
++ n_cid.stepping = 0;
++ }
+
+ return p_cid.full == n_cid.full;
+ } else {
+@@ -646,13 +649,13 @@ static struct ucode_patch *cache_find_pa
+ WARN_ON_ONCE(!n.patch_id);
+
+ list_for_each_entry(p, µcode_cache, plist)
+- if (patch_cpus_equivalent(p, &n))
++ if (patch_cpus_equivalent(p, &n, false))
+ return p;
+
+ return NULL;
+ }
+
+-static inline bool patch_newer(struct ucode_patch *p, struct ucode_patch *n)
++static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n)
+ {
+ /* Zen and newer hardcode the f/m/s in the patch ID */
+ if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
+@@ -661,6 +664,9 @@ static inline bool patch_newer(struct uc
+ zp.ucode_rev = p->patch_id;
+ zn.ucode_rev = n->patch_id;
+
++ if (zn.stepping != zp.stepping)
++ return -1;
++
+ return zn.rev > zp.rev;
+ } else {
+ return n->patch_id > p->patch_id;
+@@ -670,10 +676,14 @@ static inline bool patch_newer(struct uc
+ static void update_cache(struct ucode_patch *new_patch)
+ {
+ struct ucode_patch *p;
++ int ret;
+
+ list_for_each_entry(p, µcode_cache, plist) {
+- if (patch_cpus_equivalent(p, new_patch)) {
+- if (!patch_newer(p, new_patch)) {
++ if (patch_cpus_equivalent(p, new_patch, true)) {
++ ret = patch_newer(p, new_patch);
++ if (ret < 0)
++ continue;
++ else if (!ret) {
+ /* we already have the latest patch */
+ kfree(new_patch->data);
+ kfree(new_patch);
--- /dev/null
+From 10f93d372e36136bd6b87c6f818cba54da688ed4 Mon Sep 17 00:00:00 2001
+From: Nikolay Borisov <nik.borisov@suse.com>
+Date: Fri, 18 Oct 2024 18:51:49 +0300
+Subject: x86/microcode/AMD: Return bool from find_blobs_in_containers()
+
+From: Nikolay Borisov <nik.borisov@suse.com>
+
+commit a85c08aaa665b5436d325f6d7138732a0e1315ce upstream
+
+Instead of open-coding the check for size/data move it inside the
+function and make it return a boolean indicating whether data was found
+or not.
+
+No functional changes.
+
+ [ bp: Write @ret in find_blobs_in_containers() only on success. ]
+
+Signed-off-by: Nikolay Borisov <nik.borisov@suse.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20241018155151.702350-2-nik.borisov@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -571,14 +571,19 @@ static bool get_builtin_microcode(struct
+ return false;
+ }
+
+-static void __init find_blobs_in_containers(struct cpio_data *ret)
++static bool __init find_blobs_in_containers(struct cpio_data *ret)
+ {
+ struct cpio_data cp;
++ bool found;
+
+ if (!get_builtin_microcode(&cp))
+ cp = find_microcode_in_initrd(ucode_path);
+
+- *ret = cp;
++ found = cp.data && cp.size;
++ if (found)
++ *ret = cp;
++
++ return found;
+ }
+
+ void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
+@@ -593,8 +598,7 @@ void __init load_ucode_amd_bsp(struct ea
+ /* Needed in load_microcode_amd() */
+ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
+
+- find_blobs_in_containers(&cp);
+- if (!(cp.data && cp.size))
++ if (!find_blobs_in_containers(&cp))
+ return;
+
+ if (early_apply_microcode(ed->old_rev, cp.data, cp.size))
+@@ -614,8 +618,7 @@ static int __init save_microcode_in_init
+ if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
+ return 0;
+
+- find_blobs_in_containers(&cp);
+- if (!(cp.data && cp.size))
++ if (!find_blobs_in_containers(&cp))
+ return -EINVAL;
+
+ scan_containers(cp.data, cp.size, &desc);
--- /dev/null
+From a33c9b7c9df314a89aa8c43889a6a92495a6f29b Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Mon, 21 Oct 2024 10:38:21 +0200
+Subject: x86/microcode/AMD: Split load_microcode_amd()
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 1d81d85d1a19e50d5237dc67d6b825c34ae13de8 upstream
+
+This function should've been split a long time ago because it is used in
+two paths:
+
+1) On the late loading path, when the microcode is loaded through the
+ request_firmware interface
+
+2) In the save_microcode_in_initrd() path which collects all the
+ microcode patches which are relevant for the current system before
+ the initrd with the microcode container has been jettisoned.
+
+ In that path, it is not really necessary to iterate over the nodes on
+ a system and match a patch however it didn't cause any trouble so it
+ was left for a later cleanup
+
+However, that later cleanup was expedited by the fact that Jens was
+enabling "Use L3 as a NUMA node" in the BIOS setting in his machine and
+so this causes the NUMA CPU masks used in cpumask_of_node() to be
+generated *after* 2) above happened on the first node. Which means, all
+those masks were funky, wrong, uninitialized and whatnot, leading to
+explosions when dereffing c->microcode in load_microcode_amd().
+
+So split that function and do only the necessary work needed at each
+stage.
+
+Fixes: 94838d230a6c ("x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID")
+Reported-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Jens Axboe <axboe@kernel.dk>
+Link: https://lore.kernel.org/r/91194406-3fdf-4e38-9838-d334af538f74@kernel.dk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -586,7 +586,7 @@ void __init load_ucode_amd_bsp(struct ea
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
+ }
+
+-static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
++static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size);
+
+ static int __init save_microcode_in_initrd(void)
+ {
+@@ -607,7 +607,7 @@ static int __init save_microcode_in_init
+ if (!desc.mc)
+ return -EINVAL;
+
+- ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
++ ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
+ if (ret > UCODE_UPDATED)
+ return -EINVAL;
+
+@@ -956,21 +956,30 @@ static enum ucode_state __load_microcode
+ return UCODE_OK;
+ }
+
+-static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
++static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size)
+ {
+- struct cpuinfo_x86 *c;
+- unsigned int nid, cpu;
+- 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;
++}
++
++static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
++{
++ struct cpuinfo_x86 *c;
++ unsigned int nid, cpu;
++ struct ucode_patch *p;
++ enum ucode_state ret;
++
++ ret = _load_microcode_amd(family, data, size);
++ if (ret != UCODE_OK)
+ return ret;
+- }
+
+ for_each_node(nid) {
+ cpu = cpumask_first(cpumask_of_node(nid));
--- /dev/null
+From b22b6b6d2a1cf29b63c249b79a3fe6416d6c210f Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:55 +0200
+Subject: x86/microcode/amd: Use cached microcode for AP load
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 5af05b8d51a8e3ff5905663655c0f46d1aaae44a upstream
+
+Now that the microcode cache is initialized before the APs are brought
+up, there is no point in scanning builtin/initrd microcode during AP
+loading.
+
+Convert the AP loader to utilize the cache, which in turn makes the CPU
+hotplug callback which applies the microcode after initrd/builtin is
+gone, obsolete as the early loading during late hotplug operations
+including the resume path depends now only on the cache.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211723.243426023@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 20 +++++++++++---------
+ arch/x86/kernel/cpu/microcode/core.c | 15 ++-------------
+ arch/x86/kernel/cpu/microcode/internal.h | 2 --
+ 3 files changed, 13 insertions(+), 24 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -496,7 +496,7 @@ static bool get_builtin_microcode(struct
+ return false;
+ }
+
+-static void find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
++static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
+ {
+ struct cpio_data cp;
+
+@@ -506,12 +506,12 @@ static void find_blobs_in_containers(uns
+ *ret = cp;
+ }
+
+-static void apply_ucode_from_containers(unsigned int cpuid_1_eax)
++void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
+ {
+ struct cpio_data cp = { };
+
+ /* Needed in load_microcode_amd() */
+- ucode_cpu_info[smp_processor_id()].cpu_sig.sig = cpuid_1_eax;
++ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
+
+ find_blobs_in_containers(cpuid_1_eax, &cp);
+ if (!(cp.data && cp.size))
+@@ -520,11 +520,6 @@ static void apply_ucode_from_containers(
+ early_apply_microcode(cpuid_1_eax, cp.data, cp.size);
+ }
+
+-void load_ucode_amd_early(unsigned int cpuid_1_eax)
+-{
+- return apply_ucode_from_containers(cpuid_1_eax);
+-}
+-
+ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
+
+ static int __init save_microcode_in_initrd(void)
+@@ -608,7 +603,6 @@ static struct ucode_patch *find_patch(un
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ u16 equiv_id;
+
+-
+ equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
+ if (!equiv_id)
+ return NULL;
+@@ -710,6 +704,14 @@ out:
+ return ret;
+ }
+
++void load_ucode_amd_ap(unsigned int cpuid_1_eax)
++{
++ unsigned int cpu = smp_processor_id();
++
++ ucode_cpu_info[cpu].cpu_sig.sig = cpuid_1_eax;
++ apply_microcode_amd(cpu);
++}
++
+ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size)
+ {
+ u32 equiv_tbl_len;
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -154,7 +154,7 @@ void __init load_ucode_bsp(void)
+ if (intel)
+ load_ucode_intel_bsp();
+ else
+- load_ucode_amd_early(cpuid_1_eax);
++ load_ucode_amd_bsp(cpuid_1_eax);
+ }
+
+ void load_ucode_ap(void)
+@@ -173,7 +173,7 @@ void load_ucode_ap(void)
+ break;
+ case X86_VENDOR_AMD:
+ if (x86_family(cpuid_1_eax) >= 0x10)
+- load_ucode_amd_early(cpuid_1_eax);
++ load_ucode_amd_ap(cpuid_1_eax);
+ break;
+ default:
+ break;
+@@ -494,15 +494,6 @@ static struct syscore_ops mc_syscore_ops
+ .resume = microcode_bsp_resume,
+ };
+
+-static int mc_cpu_starting(unsigned int cpu)
+-{
+- enum ucode_state err = microcode_ops->apply_microcode(cpu);
+-
+- pr_debug("%s: CPU%d, err: %d\n", __func__, cpu, err);
+-
+- return err == UCODE_ERROR;
+-}
+-
+ static int mc_cpu_online(unsigned int cpu)
+ {
+ struct device *dev = get_cpu_device(cpu);
+@@ -590,8 +581,6 @@ static int __init microcode_init(void)
+ schedule_on_each_cpu(setup_online_cpu);
+
+ register_syscore_ops(&mc_syscore_ops);
+- cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
+- mc_cpu_starting, NULL);
+ cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
+ mc_cpu_online, mc_cpu_down_prep);
+
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -91,7 +91,6 @@ extern bool initrd_gone;
+ #ifdef CONFIG_CPU_SUP_AMD
+ void load_ucode_amd_bsp(unsigned int family);
+ void load_ucode_amd_ap(unsigned int family);
+-void load_ucode_amd_early(unsigned int cpuid_1_eax);
+ int save_microcode_in_initrd_amd(unsigned int family);
+ void reload_ucode_amd(unsigned int cpu);
+ struct microcode_ops *init_amd_microcode(void);
+@@ -99,7 +98,6 @@ void exit_amd_microcode(void);
+ #else /* CONFIG_CPU_SUP_AMD */
+ static inline void load_ucode_amd_bsp(unsigned int family) { }
+ static inline void load_ucode_amd_ap(unsigned int family) { }
+-static inline void load_ucode_amd_early(unsigned int family) { }
+ static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
+ static inline void reload_ucode_amd(unsigned int cpu) { }
+ static inline struct microcode_ops *init_amd_microcode(void) { return NULL; }
--- /dev/null
+From 52739801d858deb1410e3847a998ba8227c555ec Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 10 Oct 2023 17:08:41 +0200
+Subject: x86/microcode/amd: Use correct per CPU ucode_cpu_info
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit ecfd41089348fa4cc767dc588367e9fdf8cb6b9d upstream
+
+find_blobs_in_containers() is invoked on every CPU but overwrites
+unconditionally ucode_cpu_info of CPU0.
+
+Fix this by using the proper CPU data and move the assignment into the
+call site apply_ucode_from_containers() so that the function can be
+reused.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231010150702.433454320@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -503,9 +503,6 @@ static void find_blobs_in_containers(uns
+ if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)))
+ cp = find_microcode_in_initrd(ucode_path);
+
+- /* Needed in load_microcode_amd() */
+- ucode_cpu_info->cpu_sig.sig = cpuid_1_eax;
+-
+ *ret = cp;
+ }
+
+@@ -513,6 +510,9 @@ static void apply_ucode_from_containers(
+ {
+ struct cpio_data cp = { };
+
++ /* Needed in load_microcode_amd() */
++ ucode_cpu_info[smp_processor_id()].cpu_sig.sig = cpuid_1_eax;
++
+ find_blobs_in_containers(cpuid_1_eax, &cp);
+ if (!(cp.data && cp.size))
+ return;
--- /dev/null
+From 00b063b90e31be03012dea13cf6190ac39a5d2e5 Mon Sep 17 00:00:00 2001
+From: Borislav Petkov <bp@alien8.de>
+Date: Thu, 25 Jul 2024 13:20:37 +0200
+Subject: x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID
+
+From: Borislav Petkov <bp@alien8.de>
+
+commit 94838d230a6c835ced1bad06b8759e0a5f19c1d3 upstream
+
+On Zen and newer, the family, model and stepping is part of the
+microcode patch ID so that the equivalence table the driver has been
+using, is not needed anymore.
+
+So switch the driver to use that from now on.
+
+The equivalence table in the microcode blob should still remain in case
+there's need to pass some additional information to the kernel loader.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20240725112037.GBZqI1BbUk1KMlOJ_D@fat_crate.local
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 190 +++++++++++++++++++++++++++++-------
+ 1 file changed, 158 insertions(+), 32 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -91,6 +91,31 @@ static struct equiv_cpu_table {
+ struct equiv_cpu_entry *entry;
+ } equiv_table;
+
++union zen_patch_rev {
++ struct {
++ __u32 rev : 8,
++ stepping : 4,
++ model : 4,
++ __reserved : 4,
++ ext_model : 4,
++ ext_fam : 8;
++ };
++ __u32 ucode_rev;
++};
++
++union cpuid_1_eax {
++ struct {
++ __u32 stepping : 4,
++ model : 4,
++ family : 4,
++ __reserved0 : 4,
++ ext_model : 4,
++ ext_fam : 8,
++ __reserved1 : 4;
++ };
++ __u32 full;
++};
++
+ /*
+ * This points to the current valid container of microcode patches which we will
+ * save from the initrd/builtin before jettisoning its contents. @mc is the
+@@ -98,7 +123,6 @@ static struct equiv_cpu_table {
+ */
+ struct cont_desc {
+ struct microcode_amd *mc;
+- u32 cpuid_1_eax;
+ u32 psize;
+ u8 *data;
+ size_t size;
+@@ -111,10 +135,42 @@ struct cont_desc {
+ static const char
+ ucode_path[] __maybe_unused = "kernel/x86/microcode/AuthenticAMD.bin";
+
++/*
++ * This is CPUID(1).EAX on the BSP. It is used in two ways:
++ *
++ * 1. To ignore the equivalence table on Zen1 and newer.
++ *
++ * 2. To match which patches to load because the patch revision ID
++ * already contains the f/m/s for which the microcode is destined
++ * for.
++ */
++static u32 bsp_cpuid_1_eax __ro_after_init;
++
++static union cpuid_1_eax ucode_rev_to_cpuid(unsigned int val)
++{
++ union zen_patch_rev p;
++ union cpuid_1_eax c;
++
++ p.ucode_rev = val;
++ c.full = 0;
++
++ c.stepping = p.stepping;
++ c.model = p.model;
++ c.ext_model = p.ext_model;
++ c.family = 0xf;
++ c.ext_fam = p.ext_fam;
++
++ return c;
++}
++
+ static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig)
+ {
+ unsigned int i;
+
++ /* Zen and newer do not need an equivalence table. */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17)
++ return 0;
++
+ if (!et || !et->num_entries)
+ return 0;
+
+@@ -161,6 +217,10 @@ static bool verify_equivalence_table(con
+ if (!verify_container(buf, buf_size))
+ return false;
+
++ /* Zen and newer do not need an equivalence table. */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17)
++ return true;
++
+ cont_type = hdr[1];
+ if (cont_type != UCODE_EQUIV_CPU_TABLE_TYPE) {
+ pr_debug("Wrong microcode container equivalence table type: %u.\n",
+@@ -224,8 +284,9 @@ __verify_patch_section(const u8 *buf, si
+ * exceed the per-family maximum). @sh_psize is the size read from the section
+ * header.
+ */
+-static unsigned int __verify_patch_size(u8 family, u32 sh_psize, size_t buf_size)
++static unsigned int __verify_patch_size(u32 sh_psize, size_t buf_size)
+ {
++ u8 family = x86_family(bsp_cpuid_1_eax);
+ u32 max_size;
+
+ if (family >= 0x15)
+@@ -260,9 +321,9 @@ static unsigned int __verify_patch_size(
+ * positive: patch is not for this family, skip it
+ * 0: success
+ */
+-static int
+-verify_patch(u8 family, const u8 *buf, size_t buf_size, u32 *patch_size)
++static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size)
+ {
++ u8 family = x86_family(bsp_cpuid_1_eax);
+ struct microcode_header_amd *mc_hdr;
+ unsigned int ret;
+ u32 sh_psize;
+@@ -288,7 +349,7 @@ verify_patch(u8 family, const u8 *buf, s
+ return -1;
+ }
+
+- ret = __verify_patch_size(family, sh_psize, buf_size);
++ ret = __verify_patch_size(sh_psize, buf_size);
+ if (!ret) {
+ pr_debug("Per-family patch size mismatch.\n");
+ return -1;
+@@ -310,6 +371,15 @@ verify_patch(u8 family, const u8 *buf, s
+ return 0;
+ }
+
++static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id)
++{
++ /* Zen and newer do not need an equivalence table. */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17)
++ return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax;
++ else
++ return eq_id == mc->hdr.processor_rev_id;
++}
++
+ /*
+ * This scans the ucode blob for the proper container as we can have multiple
+ * containers glued together. Returns the equivalence ID from the equivalence
+@@ -338,7 +408,7 @@ static size_t parse_container(u8 *ucode,
+ * doesn't contain a patch for the CPU, scan through the whole container
+ * so that it can be skipped in case there are other containers appended.
+ */
+- eq_id = find_equiv_id(&table, desc->cpuid_1_eax);
++ eq_id = find_equiv_id(&table, bsp_cpuid_1_eax);
+
+ buf += hdr[2] + CONTAINER_HDR_SZ;
+ size -= hdr[2] + CONTAINER_HDR_SZ;
+@@ -352,7 +422,7 @@ static size_t parse_container(u8 *ucode,
+ u32 patch_size;
+ int ret;
+
+- ret = verify_patch(x86_family(desc->cpuid_1_eax), buf, size, &patch_size);
++ ret = verify_patch(buf, size, &patch_size);
+ if (ret < 0) {
+ /*
+ * Patch verification failed, skip to the next container, if
+@@ -365,7 +435,7 @@ static size_t parse_container(u8 *ucode,
+ }
+
+ mc = (struct microcode_amd *)(buf + SECTION_HDR_SIZE);
+- if (eq_id == mc->hdr.processor_rev_id) {
++ if (mc_patch_matches(mc, eq_id)) {
+ desc->psize = patch_size;
+ desc->mc = mc;
+ }
+@@ -423,6 +493,7 @@ static int __apply_microcode_amd(struct
+
+ /* verify patch application was successful */
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
++
+ if (rev != mc->hdr.patch_id)
+ return -1;
+
+@@ -440,14 +511,12 @@ static int __apply_microcode_amd(struct
+ *
+ * Returns true if container found (sets @desc), false otherwise.
+ */
+-static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size)
++static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
+ {
+ struct cont_desc desc = { 0 };
+ struct microcode_amd *mc;
+ bool ret = false;
+
+- desc.cpuid_1_eax = cpuid_1_eax;
+-
+ scan_containers(ucode, size, &desc);
+
+ mc = desc.mc;
+@@ -465,9 +534,10 @@ static bool early_apply_microcode(u32 cp
+ return !__apply_microcode_amd(mc);
+ }
+
+-static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
++static bool get_builtin_microcode(struct cpio_data *cp)
+ {
+ char fw_name[36] = "amd-ucode/microcode_amd.bin";
++ u8 family = x86_family(bsp_cpuid_1_eax);
+ struct firmware fw;
+
+ if (IS_ENABLED(CONFIG_X86_32))
+@@ -486,11 +556,11 @@ static bool get_builtin_microcode(struct
+ return false;
+ }
+
+-static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpio_data *ret)
++static void __init find_blobs_in_containers(struct cpio_data *ret)
+ {
+ struct cpio_data cp;
+
+- if (!get_builtin_microcode(&cp, x86_family(cpuid_1_eax)))
++ if (!get_builtin_microcode(&cp))
+ cp = find_microcode_in_initrd(ucode_path);
+
+ *ret = cp;
+@@ -501,16 +571,18 @@ void __init load_ucode_amd_bsp(struct ea
+ struct cpio_data cp = { };
+ u32 dummy;
+
++ bsp_cpuid_1_eax = cpuid_1_eax;
++
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
+
+ /* Needed in load_microcode_amd() */
+ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
+
+- find_blobs_in_containers(cpuid_1_eax, &cp);
++ find_blobs_in_containers(&cp);
+ if (!(cp.data && cp.size))
+ return;
+
+- if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size))
++ if (early_apply_microcode(ed->old_rev, cp.data, cp.size))
+ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
+ }
+
+@@ -527,12 +599,10 @@ static int __init save_microcode_in_init
+ if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10)
+ return 0;
+
+- find_blobs_in_containers(cpuid_1_eax, &cp);
++ find_blobs_in_containers(&cp);
+ if (!(cp.data && cp.size))
+ return -EINVAL;
+
+- desc.cpuid_1_eax = cpuid_1_eax;
+-
+ scan_containers(cp.data, cp.size, &desc);
+ if (!desc.mc)
+ return -EINVAL;
+@@ -545,26 +615,65 @@ static int __init save_microcode_in_init
+ }
+ early_initcall(save_microcode_in_initrd);
+
++static inline bool patch_cpus_equivalent(struct ucode_patch *p, struct ucode_patch *n)
++{
++ /* Zen and newer hardcode the f/m/s in the patch ID */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
++ union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id);
++ union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id);
++
++ /* Zap stepping */
++ p_cid.stepping = 0;
++ n_cid.stepping = 0;
++
++ return p_cid.full == n_cid.full;
++ } else {
++ return p->equiv_cpu == n->equiv_cpu;
++ }
++}
++
+ /*
+ * a small, trivial cache of per-family ucode patches
+ */
+-static struct ucode_patch *cache_find_patch(u16 equiv_cpu)
++static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equiv_cpu)
+ {
+ struct ucode_patch *p;
++ struct ucode_patch n;
++
++ n.equiv_cpu = equiv_cpu;
++ n.patch_id = uci->cpu_sig.rev;
++
++ WARN_ON_ONCE(!n.patch_id);
+
+ list_for_each_entry(p, µcode_cache, plist)
+- if (p->equiv_cpu == equiv_cpu)
++ if (patch_cpus_equivalent(p, &n))
+ return p;
++
+ return NULL;
+ }
+
++static inline bool patch_newer(struct ucode_patch *p, struct ucode_patch *n)
++{
++ /* Zen and newer hardcode the f/m/s in the patch ID */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
++ union zen_patch_rev zp, zn;
++
++ zp.ucode_rev = p->patch_id;
++ zn.ucode_rev = n->patch_id;
++
++ return zn.rev > zp.rev;
++ } else {
++ return n->patch_id > p->patch_id;
++ }
++}
++
+ static void update_cache(struct ucode_patch *new_patch)
+ {
+ struct ucode_patch *p;
+
+ list_for_each_entry(p, µcode_cache, plist) {
+- if (p->equiv_cpu == new_patch->equiv_cpu) {
+- if (p->patch_id >= new_patch->patch_id) {
++ if (patch_cpus_equivalent(p, new_patch)) {
++ if (!patch_newer(p, new_patch)) {
+ /* we already have the latest patch */
+ kfree(new_patch->data);
+ kfree(new_patch);
+@@ -595,13 +704,22 @@ static void free_cache(void)
+ static struct ucode_patch *find_patch(unsigned int cpu)
+ {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
++ u32 rev, dummy __always_unused;
+ u16 equiv_id;
+
+- equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
+- if (!equiv_id)
+- return NULL;
++ /* fetch rev if not populated yet: */
++ if (!uci->cpu_sig.rev) {
++ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
++ uci->cpu_sig.rev = rev;
++ }
++
++ if (x86_family(bsp_cpuid_1_eax) < 0x17) {
++ equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
++ if (!equiv_id)
++ return NULL;
++ }
+
+- return cache_find_patch(equiv_id);
++ return cache_find_patch(uci, equiv_id);
+ }
+
+ void reload_ucode_amd(unsigned int cpu)
+@@ -651,7 +769,7 @@ static enum ucode_state apply_microcode_
+ struct ucode_cpu_info *uci;
+ struct ucode_patch *p;
+ enum ucode_state ret;
+- u32 rev, dummy __always_unused;
++ u32 rev;
+
+ BUG_ON(raw_smp_processor_id() != cpu);
+
+@@ -661,11 +779,11 @@ static enum ucode_state apply_microcode_
+ if (!p)
+ return UCODE_NFOUND;
+
++ rev = uci->cpu_sig.rev;
++
+ mc_amd = p->data;
+ uci->mc = p->data;
+
+- rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+-
+ /* need to apply patch? */
+ if (rev > mc_amd->hdr.patch_id) {
+ ret = UCODE_OK;
+@@ -711,6 +829,10 @@ static size_t install_equiv_cpu_table(co
+ hdr = (const u32 *)buf;
+ equiv_tbl_len = hdr[2];
+
++ /* Zen and newer do not need an equivalence table. */
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17)
++ goto out;
++
+ equiv_table.entry = vmalloc(equiv_tbl_len);
+ if (!equiv_table.entry) {
+ pr_err("failed to allocate equivalent CPU table\n");
+@@ -720,12 +842,16 @@ static size_t install_equiv_cpu_table(co
+ memcpy(equiv_table.entry, buf + CONTAINER_HDR_SZ, equiv_tbl_len);
+ equiv_table.num_entries = equiv_tbl_len / sizeof(struct equiv_cpu_entry);
+
++out:
+ /* add header length */
+ return equiv_tbl_len + CONTAINER_HDR_SZ;
+ }
+
+ static void free_equiv_cpu_table(void)
+ {
++ if (x86_family(bsp_cpuid_1_eax) >= 0x17)
++ return;
++
+ vfree(equiv_table.entry);
+ memset(&equiv_table, 0, sizeof(equiv_table));
+ }
+@@ -751,7 +877,7 @@ static int verify_and_add_patch(u8 famil
+ u16 proc_id;
+ int ret;
+
+- ret = verify_patch(family, fw, leftover, patch_size);
++ ret = verify_patch(fw, leftover, patch_size);
+ if (ret)
+ return ret;
+
+@@ -776,7 +902,7 @@ static int verify_and_add_patch(u8 famil
+ patch->patch_id = mc_hdr->patch_id;
+ patch->equiv_cpu = proc_id;
+
+- pr_debug("%s: Added patch_id: 0x%08x, proc_id: 0x%04x\n",
++ pr_debug("%s: Adding patch_id: 0x%08x, proc_id: 0x%04x\n",
+ __func__, patch->patch_id, proc_id);
+
+ /* ... and add to cache. */
--- /dev/null
+From 17f713d29969a723f51eb4d4d1cdccb545b035ae Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:57 +0200
+Subject: x86/microcode: Clarify the late load logic
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 6f059e634dcd0d725854514c94c114bbdd83950d upstream
+
+reload_store() is way too complicated. Split the inner workings out and
+make the following enhancements:
+
+ - Taint the kernel only when the microcode was actually updated. If. e.g.
+ the rendezvous fails, then nothing happened and there is no reason for
+ tainting.
+
+ - Return useful error codes
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
+Link: https://lore.kernel.org/r/20231002115903.145048840@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 41 ++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 22 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -362,11 +362,11 @@ static int microcode_reload_late(void)
+ pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
+ old, boot_cpu_data.microcode);
+ microcode_check(&prev_info);
++ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+ } else {
+ pr_info("Reload failed, current microcode revision: 0x%x\n",
+ boot_cpu_data.microcode);
+ }
+-
+ return ret;
+ }
+
+@@ -399,40 +399,37 @@ static bool ensure_cpus_are_online(void)
+ return true;
+ }
+
++static int ucode_load_late_locked(void)
++{
++ if (!ensure_cpus_are_online())
++ return -EBUSY;
++
++ switch (microcode_ops->request_microcode_fw(0, µcode_pdev->dev)) {
++ case UCODE_NEW:
++ return microcode_reload_late();
++ case UCODE_NFOUND:
++ return -ENOENT;
++ default:
++ return -EBADFD;
++ }
++}
++
+ static ssize_t reload_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+ {
+- enum ucode_state tmp_ret = UCODE_OK;
+- int bsp = boot_cpu_data.cpu_index;
+ unsigned long val;
+- ssize_t ret = 0;
++ ssize_t ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret || val != 1)
+ return -EINVAL;
+
+ cpus_read_lock();
+-
+- if (!ensure_cpus_are_online()) {
+- ret = -EBUSY;
+- goto put;
+- }
+-
+- tmp_ret = microcode_ops->request_microcode_fw(bsp, µcode_pdev->dev);
+- if (tmp_ret != UCODE_NEW)
+- goto put;
+-
+- ret = microcode_reload_late();
+-put:
++ ret = ucode_load_late_locked();
+ cpus_read_unlock();
+
+- if (ret == 0)
+- ret = size;
+-
+- add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+-
+- return ret;
++ return ret ? : size;
+ }
+
+ static DEVICE_ATTR_WO(reload);
--- /dev/null
+From 6759862c3c76d50ae5b05490ffe9c83964e64bc8 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:55 +0200
+Subject: x86/microcode: Clean up mc_cpu_down_prep()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit ba48aa32388ac652256baa8d0a6092d350160da0 upstream
+
+This function has nothing to do with suspend. It's a hotplug
+callback. Remove the bogus comment.
+
+Drop the pointless debug printk. The hotplug core provides tracepoints
+which track the invocation of those callbacks.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.028651784@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 8 +-------
+ 1 file changed, 1 insertion(+), 7 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -498,16 +498,10 @@ static int mc_cpu_online(unsigned int cp
+
+ static int mc_cpu_down_prep(unsigned int cpu)
+ {
+- struct device *dev;
+-
+- dev = get_cpu_device(cpu);
++ struct device *dev = get_cpu_device(cpu);
+
+ microcode_fini_cpu(cpu);
+-
+- /* Suspend is in progress, only remove the interface */
+ sysfs_remove_group(&dev->kobj, &mc_attr_group);
+- pr_debug("%s: CPU%d\n", __func__, cpu);
+-
+ return 0;
+ }
+
--- /dev/null
+From 1b43c9ce45068f82226605c7e253aee7ff8ec634 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:58 +0200
+Subject: x86/microcode: Get rid of the schedule work indirection
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 2e1997335ceb6fc819862804f51d4fe83593c138 upstream
+
+Scheduling work on all CPUs to collect the microcode information is just
+another extra step for no value. Let the CPU hotplug callback registration
+do it.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211723.354748138@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 29 ++++++++++-------------------
+ 1 file changed, 10 insertions(+), 19 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -481,8 +481,16 @@ static struct syscore_ops mc_syscore_ops
+
+ static int mc_cpu_online(unsigned int cpu)
+ {
++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ struct device *dev = get_cpu_device(cpu);
+
++ memset(uci, 0, sizeof(*uci));
++
++ microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
++ cpu_data(cpu).microcode = uci->cpu_sig.rev;
++ if (!cpu)
++ boot_cpu_data.microcode = uci->cpu_sig.rev;
++
+ if (sysfs_create_group(&dev->kobj, &mc_attr_group))
+ pr_err("Failed to create group for CPU%d\n", cpu);
+ return 0;
+@@ -503,20 +511,6 @@ static int mc_cpu_down_prep(unsigned int
+ return 0;
+ }
+
+-static void setup_online_cpu(struct work_struct *work)
+-{
+- int cpu = smp_processor_id();
+- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+-
+- memset(uci, 0, sizeof(*uci));
+-
+- microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
+- cpu_data(cpu).microcode = uci->cpu_sig.rev;
+- if (!cpu)
+- boot_cpu_data.microcode = uci->cpu_sig.rev;
+- mc_cpu_online(cpu);
+-}
+-
+ static struct attribute *cpu_root_microcode_attrs[] = {
+ #ifdef CONFIG_MICROCODE_LATE_LOADING
+ &dev_attr_reload.attr,
+@@ -562,12 +556,9 @@ static int __init microcode_init(void)
+ }
+ }
+
+- /* Do per-CPU setup */
+- schedule_on_each_cpu(setup_online_cpu);
+-
+ register_syscore_ops(&mc_syscore_ops);
+- cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
+- mc_cpu_online, mc_cpu_down_prep);
++ cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
++ mc_cpu_online, mc_cpu_down_prep);
+
+ pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
+
--- /dev/null
+From 760ac4ae4059a69e68c07e4bfa151a733fa059c8 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:56 +0200
+Subject: x86/microcode: Handle "nosmt" correctly
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 634ac23ad609b3ddd9e0e478bd5afbf49d3a2556 upstream
+
+On CPUs where microcode loading is not NMI-safe the SMT siblings which
+are parked in one of the play_dead() variants still react to NMIs.
+
+So if an NMI hits while the primary thread updates the microcode the
+resulting behaviour is undefined. The default play_dead() implementation on
+modern CPUs is using MWAIT which is not guaranteed to be safe against
+a microcode update which affects MWAIT.
+
+Take the cpus_booted_once_mask into account to detect this case and
+refuse to load late if the vendor specific driver does not advertise
+that late loading is NMI safe.
+
+AMD stated that this is safe, so mark the AMD driver accordingly.
+
+This requirement will be partially lifted in later changes.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.087472735@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/Kconfig | 2 -
+ arch/x86/kernel/cpu/microcode/amd.c | 9 +++--
+ arch/x86/kernel/cpu/microcode/core.c | 51 +++++++++++++++++++------------
+ arch/x86/kernel/cpu/microcode/internal.h | 13 +++----
+ 4 files changed, 44 insertions(+), 31 deletions(-)
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1317,7 +1317,7 @@ config MICROCODE
+ config MICROCODE_LATE_LOADING
+ bool "Late microcode loading (DANGEROUS)"
+ default n
+- depends on MICROCODE
++ depends on MICROCODE && SMP
+ help
+ Loading microcode late, when the system is up and executing instructions
+ is a tricky business and should be avoided if possible. Just the sequence
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -917,10 +917,11 @@ static void microcode_fini_cpu_amd(int c
+ }
+
+ static struct microcode_ops microcode_amd_ops = {
+- .request_microcode_fw = request_microcode_amd,
+- .collect_cpu_info = collect_cpu_info_amd,
+- .apply_microcode = apply_microcode_amd,
+- .microcode_fini_cpu = microcode_fini_cpu_amd,
++ .request_microcode_fw = request_microcode_amd,
++ .collect_cpu_info = collect_cpu_info_amd,
++ .apply_microcode = apply_microcode_amd,
++ .microcode_fini_cpu = microcode_fini_cpu_amd,
++ .nmi_safe = true,
+ };
+
+ struct microcode_ops * __init init_amd_microcode(void)
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -254,23 +254,6 @@ static struct platform_device *microcode
+ */
+ #define SPINUNIT 100 /* 100 nsec */
+
+-static int check_online_cpus(void)
+-{
+- unsigned int cpu;
+-
+- /*
+- * Make sure all CPUs are online. It's fine for SMT to be disabled if
+- * all the primary threads are still online.
+- */
+- for_each_present_cpu(cpu) {
+- if (topology_is_primary_thread(cpu) && !cpu_online(cpu)) {
+- pr_err("Not all CPUs online, aborting microcode update.\n");
+- return -EINVAL;
+- }
+- }
+-
+- return 0;
+-}
+
+ static atomic_t late_cpus_in;
+ static atomic_t late_cpus_out;
+@@ -387,6 +370,35 @@ static int microcode_reload_late(void)
+ return ret;
+ }
+
++/*
++ * Ensure that all required CPUs which are present and have been booted
++ * once are online.
++ *
++ * To pass this check, all primary threads must be online.
++ *
++ * If the microcode load is not safe against NMI then all SMT threads
++ * must be online as well because they still react to NMIs when they are
++ * soft-offlined and parked in one of the play_dead() variants. So if a
++ * NMI hits while the primary thread updates the microcode the resulting
++ * behaviour is undefined. The default play_dead() implementation on
++ * modern CPUs uses MWAIT, which is also not guaranteed to be safe
++ * against a microcode update which affects MWAIT.
++ */
++static bool ensure_cpus_are_online(void)
++{
++ unsigned int cpu;
++
++ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
++ if (!cpu_online(cpu)) {
++ if (topology_is_primary_thread(cpu) || !microcode_ops->nmi_safe) {
++ pr_err("CPU %u not online\n", cpu);
++ return false;
++ }
++ }
++ }
++ return true;
++}
++
+ static ssize_t reload_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+@@ -402,9 +414,10 @@ static ssize_t reload_store(struct devic
+
+ cpus_read_lock();
+
+- ret = check_online_cpus();
+- if (ret)
++ if (!ensure_cpus_are_online()) {
++ ret = -EBUSY;
+ goto put;
++ }
+
+ tmp_ret = microcode_ops->request_microcode_fw(bsp, µcode_pdev->dev);
+ if (tmp_ret != UCODE_NEW)
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -20,18 +20,17 @@ enum ucode_state {
+
+ struct microcode_ops {
+ enum ucode_state (*request_microcode_fw)(int cpu, struct device *dev);
+-
+ void (*microcode_fini_cpu)(int cpu);
+
+ /*
+- * The generic 'microcode_core' part guarantees that
+- * the callbacks below run on a target cpu when they
+- * are being called.
++ * The generic 'microcode_core' part guarantees that the callbacks
++ * below run on a target CPU when they are being called.
+ * See also the "Synchronization" section in microcode_core.c.
+ */
+- enum ucode_state (*apply_microcode)(int cpu);
+- int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
+- void (*finalize_late_load)(int result);
++ enum ucode_state (*apply_microcode)(int cpu);
++ int (*collect_cpu_info)(int cpu, struct cpu_signature *csig);
++ void (*finalize_late_load)(int result);
++ unsigned int nmi_safe : 1;
+ };
+
+ extern struct ucode_cpu_info ucode_cpu_info[];
--- /dev/null
+From 55d40b5d38571a06c143786742b425d2e083c67c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:08 +0200
+Subject: x86/microcode: Handle "offline" CPUs correctly
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 8f849ff63bcbc77670da03cb8f2b78b06257f455 upstream
+
+Offline CPUs need to be parked in a safe loop when microcode update is
+in progress on the primary CPU. Currently, offline CPUs are parked in
+mwait_play_dead(), and for Intel CPUs, its not a safe instruction,
+because the MWAIT instruction can be patched in the new microcode update
+that can cause instability.
+
+ - Add a new microcode state 'UCODE_OFFLINE' to report status on per-CPU
+ basis.
+ - Force NMI on the offline CPUs.
+
+Wake up offline CPUs while the update is in progress and then return
+them back to mwait_play_dead() after microcode update is complete.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.660850472@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/microcode.h | 1
+ arch/x86/kernel/cpu/microcode/core.c | 112 +++++++++++++++++++++++++++++--
+ arch/x86/kernel/cpu/microcode/internal.h | 1
+ arch/x86/kernel/nmi.c | 5 +
+ 4 files changed, 113 insertions(+), 6 deletions(-)
+
+--- a/arch/x86/include/asm/microcode.h
++++ b/arch/x86/include/asm/microcode.h
+@@ -71,6 +71,7 @@ static inline u32 intel_get_microcode_re
+ #endif /* !CONFIG_CPU_SUP_INTEL */
+
+ bool microcode_nmi_handler(void);
++void microcode_offline_nmi_handler(void);
+
+ #ifdef CONFIG_MICROCODE_LATE_LOADING
+ DECLARE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -272,8 +272,9 @@ struct microcode_ctrl {
+
+ DEFINE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+ static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
++static atomic_t late_cpus_in, offline_in_nmi;
+ static unsigned int loops_per_usec;
+-static atomic_t late_cpus_in;
++static cpumask_t cpu_offline_mask;
+
+ static noinstr bool wait_for_cpus(atomic_t *cnt)
+ {
+@@ -381,7 +382,7 @@ static noinstr void load_secondary(unsig
+ instrumentation_end();
+ }
+
+-static void load_primary(unsigned int cpu)
++static void __load_primary(unsigned int cpu)
+ {
+ struct cpumask *secondaries = topology_sibling_cpumask(cpu);
+ enum sibling_ctrl ctrl;
+@@ -416,6 +417,67 @@ static void load_primary(unsigned int cp
+ }
+ }
+
++static bool kick_offline_cpus(unsigned int nr_offl)
++{
++ unsigned int cpu, timeout;
++
++ for_each_cpu(cpu, &cpu_offline_mask) {
++ /* Enable the rendezvous handler and send NMI */
++ per_cpu(ucode_ctrl.nmi_enabled, cpu) = true;
++ apic_send_nmi_to_offline_cpu(cpu);
++ }
++
++ /* Wait for them to arrive */
++ for (timeout = 0; timeout < (USEC_PER_SEC / 2); timeout++) {
++ if (atomic_read(&offline_in_nmi) == nr_offl)
++ return true;
++ udelay(1);
++ }
++ /* Let the others time out */
++ return false;
++}
++
++static void release_offline_cpus(void)
++{
++ unsigned int cpu;
++
++ for_each_cpu(cpu, &cpu_offline_mask)
++ per_cpu(ucode_ctrl.ctrl, cpu) = SCTRL_DONE;
++}
++
++static void load_primary(unsigned int cpu)
++{
++ unsigned int nr_offl = cpumask_weight(&cpu_offline_mask);
++ bool proceed = true;
++
++ /* Kick soft-offlined SMT siblings if required */
++ if (!cpu && nr_offl)
++ proceed = kick_offline_cpus(nr_offl);
++
++ /* If the soft-offlined CPUs did not respond, abort */
++ if (proceed)
++ __load_primary(cpu);
++
++ /* Unconditionally release soft-offlined SMT siblings if required */
++ if (!cpu && nr_offl)
++ release_offline_cpus();
++}
++
++/*
++ * Minimal stub rendezvous handler for soft-offlined CPUs which participate
++ * in the NMI rendezvous to protect against a concurrent NMI on affected
++ * CPUs.
++ */
++void noinstr microcode_offline_nmi_handler(void)
++{
++ if (!raw_cpu_read(ucode_ctrl.nmi_enabled))
++ return;
++ raw_cpu_write(ucode_ctrl.nmi_enabled, false);
++ raw_cpu_write(ucode_ctrl.result, UCODE_OFFLINE);
++ raw_atomic_inc(&offline_in_nmi);
++ wait_for_ctrl();
++}
++
+ static noinstr bool microcode_update_handler(void)
+ {
+ unsigned int cpu = raw_smp_processor_id();
+@@ -472,6 +534,7 @@ static int load_cpus_stopped(void *unuse
+ static int load_late_stop_cpus(void)
+ {
+ unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
++ unsigned int nr_offl, offline = 0;
+ int old_rev = boot_cpu_data.microcode;
+ struct cpuinfo_x86 prev_info;
+
+@@ -479,6 +542,7 @@ static int load_late_stop_cpus(void)
+ pr_err("You should switch to early loading, if possible.\n");
+
+ atomic_set(&late_cpus_in, num_online_cpus());
++ atomic_set(&offline_in_nmi, 0);
+ loops_per_usec = loops_per_jiffy / (TICK_NSEC / 1000);
+
+ /*
+@@ -501,6 +565,7 @@ static int load_late_stop_cpus(void)
+ case UCODE_UPDATED: updated++; break;
+ case UCODE_TIMEOUT: timedout++; break;
+ case UCODE_OK: siblings++; break;
++ case UCODE_OFFLINE: offline++; break;
+ default: failed++; break;
+ }
+ }
+@@ -512,6 +577,13 @@ static int load_late_stop_cpus(void)
+ /* Nothing changed. */
+ if (!failed && !timedout)
+ return 0;
++
++ nr_offl = cpumask_weight(&cpu_offline_mask);
++ if (offline < nr_offl) {
++ pr_warn("%u offline siblings did not respond.\n",
++ nr_offl - atomic_read(&offline_in_nmi));
++ return -EIO;
++ }
+ pr_err("update failed: %u CPUs failed %u CPUs timed out\n",
+ failed, timedout);
+ return -EIO;
+@@ -545,19 +617,49 @@ static int load_late_stop_cpus(void)
+ * modern CPUs uses MWAIT, which is also not guaranteed to be safe
+ * against a microcode update which affects MWAIT.
+ *
+- * 2) Initialize the per CPU control structure
++ * As soft-offlined CPUs still react on NMIs, the SMT sibling
++ * restriction can be lifted when the vendor driver signals to use NMI
++ * for rendezvous and the APIC provides a mechanism to send an NMI to a
++ * soft-offlined CPU. The soft-offlined CPUs are then able to
++ * participate in the rendezvous in a trivial stub handler.
++ *
++ * 2) Initialize the per CPU control structure and create a cpumask
++ * which contains "offline"; secondary threads, so they can be handled
++ * correctly by a control CPU.
+ */
+ static bool setup_cpus(void)
+ {
+ struct microcode_ctrl ctrl = { .ctrl = SCTRL_WAIT, .result = -1, };
++ bool allow_smt_offline;
+ unsigned int cpu;
+
++ allow_smt_offline = microcode_ops->nmi_safe ||
++ (microcode_ops->use_nmi && apic->nmi_to_offline_cpu);
++
++ cpumask_clear(&cpu_offline_mask);
++
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
++ /*
++ * Offline CPUs sit in one of the play_dead() functions
++ * with interrupts disabled, but they still react on NMIs
++ * and execute arbitrary code. Also MWAIT being updated
++ * while the offline CPU sits there is not necessarily safe
++ * on all CPU variants.
++ *
++ * Mark them in the offline_cpus mask which will be handled
++ * by CPU0 later in the update process.
++ *
++ * Ensure that the primary thread is online so that it is
++ * guaranteed that all cores are updated.
++ */
+ if (!cpu_online(cpu)) {
+- if (topology_is_primary_thread(cpu) || !microcode_ops->nmi_safe) {
+- pr_err("CPU %u not online\n", cpu);
++ if (topology_is_primary_thread(cpu) || !allow_smt_offline) {
++ pr_err("CPU %u not online, loading aborted\n", cpu);
+ return false;
+ }
++ cpumask_set_cpu(cpu, &cpu_offline_mask);
++ per_cpu(ucode_ctrl, cpu) = ctrl;
++ continue;
+ }
+
+ /*
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -17,6 +17,7 @@ enum ucode_state {
+ UCODE_NFOUND,
+ UCODE_ERROR,
+ UCODE_TIMEOUT,
++ UCODE_OFFLINE,
+ };
+
+ struct microcode_ops {
+--- a/arch/x86/kernel/nmi.c
++++ b/arch/x86/kernel/nmi.c
+@@ -502,8 +502,11 @@ DEFINE_IDTENTRY_RAW(exc_nmi)
+ if (IS_ENABLED(CONFIG_NMI_CHECK_CPU))
+ raw_atomic_long_inc(&nsp->idt_calls);
+
+- if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id()))
++ if (IS_ENABLED(CONFIG_SMP) && arch_cpu_is_offline(smp_processor_id())) {
++ if (microcode_nmi_handler_enabled())
++ microcode_offline_nmi_handler();
+ return;
++ }
+
+ if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
+ this_cpu_write(nmi_state, NMI_LATCHED);
--- /dev/null
+From 8d78a5ff8ee83e456d68102d9d7ae8c6766fa7ce Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:41 +0200
+Subject: x86/microcode/intel: Cleanup code further
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 0177669ee61de4dc641f9ad86a3df6f22327cf6c upstream
+
+Sanitize the microcode scan loop, fixup printks and move the loading
+function for builtin microcode next to the place where it is used and mark
+it __init.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.389400871@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 76 ++++++++++++++--------------------
+ 1 file changed, 32 insertions(+), 44 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -36,7 +36,7 @@ static const char ucode_path[] = "kernel
+ static struct microcode_intel *intel_ucode_patch __read_mostly;
+
+ /* last level cache size per core */
+-static int llc_size_per_core __ro_after_init;
++static unsigned int llc_size_per_core __ro_after_init;
+
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+@@ -294,29 +294,6 @@ static struct microcode_intel *scan_micr
+ return patch;
+ }
+
+-static bool load_builtin_intel_microcode(struct cpio_data *cp)
+-{
+- unsigned int eax = 1, ebx, ecx = 0, edx;
+- struct firmware fw;
+- char name[30];
+-
+- if (IS_ENABLED(CONFIG_X86_32))
+- return false;
+-
+- native_cpuid(&eax, &ebx, &ecx, &edx);
+-
+- sprintf(name, "intel-ucode/%02x-%02x-%02x",
+- x86_family(eax), x86_model(eax), x86_stepping(eax));
+-
+- if (firmware_request_builtin(&fw, name)) {
+- cp->size = fw.size;
+- cp->data = (void *)fw.data;
+- return true;
+- }
+-
+- return false;
+-}
+-
+ static int apply_microcode_early(struct ucode_cpu_info *uci)
+ {
+ struct microcode_intel *mc;
+@@ -360,6 +337,28 @@ static int apply_microcode_early(struct
+ return 0;
+ }
+
++static bool load_builtin_intel_microcode(struct cpio_data *cp)
++{
++ unsigned int eax = 1, ebx, ecx = 0, edx;
++ struct firmware fw;
++ char name[30];
++
++ if (IS_ENABLED(CONFIG_X86_32))
++ return false;
++
++ native_cpuid(&eax, &ebx, &ecx, &edx);
++
++ sprintf(name, "intel-ucode/%02x-%02x-%02x",
++ x86_family(eax), x86_model(eax), x86_stepping(eax));
++
++ if (firmware_request_builtin(&fw, name)) {
++ cp->size = fw.size;
++ cp->data = (void *)fw.data;
++ return true;
++ }
++ return false;
++}
++
+ int __init save_microcode_in_initrd_intel(void)
+ {
+ struct ucode_cpu_info uci;
+@@ -432,25 +431,16 @@ void load_ucode_intel_ap(void)
+ apply_microcode_early(&uci);
+ }
+
+-/* Accessor for microcode pointer */
+-static struct microcode_intel *ucode_get_patch(void)
+-{
+- return intel_ucode_patch;
+-}
+-
+ void reload_ucode_intel(void)
+ {
+- struct microcode_intel *p;
+ struct ucode_cpu_info uci;
+
+ intel_cpu_collect_info(&uci);
+
+- p = ucode_get_patch();
+- if (!p)
++ uci.mc = intel_ucode_patch;
++ if (!uci.mc)
+ return;
+
+- uci.mc = p;
+-
+ apply_microcode_early(&uci);
+ }
+
+@@ -488,8 +478,7 @@ static enum ucode_state apply_microcode_
+ if (WARN_ON(raw_smp_processor_id() != cpu))
+ return UCODE_ERROR;
+
+- /* Look for a newer patch in our cache: */
+- mc = ucode_get_patch();
++ mc = intel_ucode_patch;
+ if (!mc) {
+ mc = uci->mc;
+ if (!mc)
+@@ -680,18 +669,17 @@ static enum ucode_state request_microcod
+ }
+
+ static struct microcode_ops microcode_intel_ops = {
+- .request_microcode_fw = request_microcode_fw,
+- .collect_cpu_info = collect_cpu_info,
+- .apply_microcode = apply_microcode_intel,
++ .request_microcode_fw = request_microcode_fw,
++ .collect_cpu_info = collect_cpu_info,
++ .apply_microcode = apply_microcode_intel,
+ };
+
+-static int __init calc_llc_size_per_core(struct cpuinfo_x86 *c)
++static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c)
+ {
+ u64 llc_size = c->x86_cache_size * 1024ULL;
+
+ do_div(llc_size, c->x86_max_cores);
+-
+- return (int)llc_size;
++ llc_size_per_core = (unsigned int)llc_size;
+ }
+
+ struct microcode_ops * __init init_intel_microcode(void)
+@@ -704,7 +692,7 @@ struct microcode_ops * __init init_intel
+ return NULL;
+ }
+
+- llc_size_per_core = calc_llc_size_per_core(c);
++ calc_llc_size_per_core(c);
+
+ return µcode_intel_ops;
+ }
--- /dev/null
+From f602940dde8cafbe9518143dc1cfca3c17c17478 Mon Sep 17 00:00:00 2001
+From: "Chang S. Bae" <chang.seok.bae@intel.com>
+Date: Tue, 1 Oct 2024 09:10:36 -0700
+Subject: x86/microcode/intel: Remove unnecessary cache writeback and invalidation
+
+From: "Chang S. Bae" <chang.seok.bae@intel.com>
+
+commit 9a819753b0209c6edebdea447a1aa53e8c697653 upstream
+
+Currently, an unconditional cache flush is performed during every
+microcode update. Although the original changelog did not mention
+a specific erratum, this measure was primarily intended to address
+a specific microcode bug, the load of which has already been blocked by
+is_blacklisted(). Therefore, this cache flush is no longer necessary.
+
+Additionally, the side effects of doing this have been overlooked. It
+increases CPU rendezvous time during late loading, where the cache flush
+takes between 1x to 3.5x longer than the actual microcode update.
+
+Remove native_wbinvd() and update the erratum name to align with the
+latest errata documentation, document ID 334163 Version 022US.
+
+ [ bp: Zap the flaky documentation URL. ]
+
+Fixes: 91df9fdf5149 ("x86/microcode/intel: Writeback and invalidate caches before updating microcode")
+Reported-by: Yan Hua Wu <yanhua1.wu@intel.com>
+Reported-by: William Xie <william.xie@intel.com>
+Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Ashok Raj <ashok.raj@intel.com>
+Tested-by: Yan Hua Wu <yanhua1.wu@intel.com>
+Link: https://lore.kernel.org/r/20241001161042.465584-2-chang.seok.bae@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -319,12 +319,6 @@ static enum ucode_state __apply_microcod
+ return UCODE_OK;
+ }
+
+- /*
+- * Writeback and invalidate caches before updating microcode to avoid
+- * internal issues depending on what the microcode is updating.
+- */
+- native_wbinvd();
+-
+ /* write microcode via MSR 0x79 */
+ native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
+
+@@ -551,7 +545,7 @@ static bool is_blacklisted(unsigned int
+ /*
+ * Late loading on model 79 with microcode revision less than 0x0b000021
+ * and LLC size per core bigger than 2.5MB may result in a system hang.
+- * This behavior is documented in item BDF90, #334165 (Intel Xeon
++ * This behavior is documented in item BDX90, #334165 (Intel Xeon
+ * Processor E7-8800/4800 v4 Product Family).
+ */
+ if (c->x86 == 6 &&
+@@ -559,7 +553,7 @@ static bool is_blacklisted(unsigned int
+ c->x86_stepping == 0x01 &&
+ llc_size_per_core > 2621440 &&
+ c->microcode < 0x0b000021) {
+- pr_err_once("Erratum BDF90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
++ pr_err_once("Erratum BDX90: late loading with revision < 0x0b000021 (0x%x) disabled.\n", c->microcode);
+ pr_err_once("Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
+ return true;
+ }
--- /dev/null
+From 5aa5d3f9c1e431e15a849caf6f502152901cfff3 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:49 +0200
+Subject: x86/microcode/intel: Reuse intel_cpu_collect_info()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 11f96ac4c21e701650c7d8349b252973185ac6ce upstream
+
+No point for an almost duplicate function.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.741173606@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 16 +---------------
+ 1 file changed, 1 insertion(+), 15 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -435,21 +435,7 @@ void reload_ucode_intel(void)
+
+ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
+ {
+- struct cpuinfo_x86 *c = &cpu_data(cpu_num);
+- unsigned int val[2];
+-
+- memset(csig, 0, sizeof(*csig));
+-
+- csig->sig = cpuid_eax(0x00000001);
+-
+- if ((c->x86_model >= 5) || (c->x86 > 6)) {
+- /* get processor flags from MSR 0x17 */
+- rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+- csig->pf = 1 << ((val[1] >> 18) & 7);
+- }
+-
+- csig->rev = c->microcode;
+-
++ intel_collect_cpu_info(csig);
+ return 0;
+ }
+
--- /dev/null
+From 3959c233b1a962997ecb8854d484882a2025b1c1 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:45 +0200
+Subject: x86/microcode/intel: Rework intel_cpu_collect_info()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 164aa1ca537238c46923ccacd8995b4265aee47b upstream
+
+Nothing needs struct ucode_cpu_info. Make it take struct cpu_signature,
+let it return a boolean and simplify the implementation. Rename it now
+that the silly name clash with collect_cpu_info() is gone.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211722.851573238@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/cpu.h | 4 ++--
+ arch/x86/kernel/cpu/microcode/intel.c | 33 +++++++++------------------------
+ drivers/platform/x86/intel/ifs/load.c | 8 +++-----
+ 3 files changed, 14 insertions(+), 31 deletions(-)
+
+--- a/arch/x86/include/asm/cpu.h
++++ b/arch/x86/include/asm/cpu.h
+@@ -71,9 +71,9 @@ static inline void init_ia32_feat_ctl(st
+
+ extern __noendbr void cet_disable(void);
+
+-struct ucode_cpu_info;
++struct cpu_signature;
+
+-int intel_cpu_collect_info(struct ucode_cpu_info *uci);
++void intel_collect_cpu_info(struct cpu_signature *sig);
+
+ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+ unsigned int s2, unsigned int p2)
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -68,36 +68,21 @@ static inline unsigned int exttable_size
+ return et->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE;
+ }
+
+-int intel_cpu_collect_info(struct ucode_cpu_info *uci)
++void intel_collect_cpu_info(struct cpu_signature *sig)
+ {
+- unsigned int val[2];
+- unsigned int family, model;
+- struct cpu_signature csig = { 0 };
+- unsigned int eax, ebx, ecx, edx;
++ sig->sig = cpuid_eax(1);
++ sig->pf = 0;
++ sig->rev = intel_get_microcode_revision();
+
+- memset(uci, 0, sizeof(*uci));
++ if (x86_model(sig->sig) >= 5 || x86_family(sig->sig) > 6) {
++ unsigned int val[2];
+
+- eax = 0x00000001;
+- ecx = 0;
+- native_cpuid(&eax, &ebx, &ecx, &edx);
+- csig.sig = eax;
+-
+- family = x86_family(eax);
+- model = x86_model(eax);
+-
+- if (model >= 5 || family > 6) {
+ /* get processor flags from MSR 0x17 */
+ native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+- csig.pf = 1 << ((val[1] >> 18) & 7);
++ sig->pf = 1 << ((val[1] >> 18) & 7);
+ }
+-
+- csig.rev = intel_get_microcode_revision();
+-
+- uci->cpu_sig = csig;
+-
+- return 0;
+ }
+-EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
++EXPORT_SYMBOL_GPL(intel_collect_cpu_info);
+
+ /*
+ * Returns 1 if update has been found, 0 otherwise.
+@@ -391,7 +376,7 @@ static __init struct microcode_intel *ge
+ if (!(cp.data && cp.size))
+ return NULL;
+
+- intel_cpu_collect_info(uci);
++ intel_collect_cpu_info(&uci->cpu_sig);
+
+ return scan_microcode(cp.data, cp.size, uci, save);
+ }
+--- a/drivers/platform/x86/intel/ifs/load.c
++++ b/drivers/platform/x86/intel/ifs/load.c
+@@ -227,7 +227,7 @@ out:
+
+ static int image_sanity_check(struct device *dev, const struct microcode_header_intel *data)
+ {
+- struct ucode_cpu_info uci;
++ struct cpu_signature sig;
+
+ /* Provide a specific error message when loading an older/unsupported image */
+ if (data->hdrver != MC_HEADER_TYPE_IFS) {
+@@ -240,11 +240,9 @@ static int image_sanity_check(struct dev
+ return -EINVAL;
+ }
+
+- intel_cpu_collect_info(&uci);
++ intel_collect_cpu_info(&sig);
+
+- if (!intel_find_matching_signature((void *)data,
+- uci.cpu_sig.sig,
+- uci.cpu_sig.pf)) {
++ if (!intel_find_matching_signature((void *)data, sig.sig, sig.pf)) {
+ dev_err(dev, "cpu signature, processor flags not matching\n");
+ return -EINVAL;
+ }
--- /dev/null
+From 19c08250133b454726b8efd5a7c6fd27859af202 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:50 +0200
+Subject: x86/microcode/intel: Rework intel_find_matching_signature()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit b7fcd995b261c9976e05f47554529c98a0f1cbb0 upstream
+
+Take a cpu_signature argument and work from there. Move the match()
+helper next to the callsite as there is no point for having it in
+a header.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.797820205@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/cpu.h | 16 +---------------
+ arch/x86/kernel/cpu/microcode/intel.c | 31 +++++++++++++++++++------------
+ drivers/platform/x86/intel/ifs/load.c | 2 +-
+ 3 files changed, 21 insertions(+), 28 deletions(-)
+
+--- a/arch/x86/include/asm/cpu.h
++++ b/arch/x86/include/asm/cpu.h
+@@ -75,22 +75,8 @@ struct cpu_signature;
+
+ void intel_collect_cpu_info(struct cpu_signature *sig);
+
+-static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
+- unsigned int s2, unsigned int p2)
+-{
+- if (s1 != s2)
+- return false;
+-
+- /* Processor flags are either both 0 ... */
+- if (!p1 && !p2)
+- return true;
+-
+- /* ... or they intersect. */
+- return p1 & p2;
+-}
+-
+ extern u64 x86_read_arch_cap_msr(void);
+-int intel_find_matching_signature(void *mc, unsigned int csig, int cpf);
++bool intel_find_matching_signature(void *mc, struct cpu_signature *sig);
+ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
+
+ extern struct cpumask cpus_stop_mask;
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -84,29 +84,36 @@ void intel_collect_cpu_info(struct cpu_s
+ }
+ EXPORT_SYMBOL_GPL(intel_collect_cpu_info);
+
+-/*
+- * Returns 1 if update has been found, 0 otherwise.
+- */
+-int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
++static inline bool cpu_signatures_match(struct cpu_signature *s1, unsigned int sig2,
++ unsigned int pf2)
++{
++ if (s1->sig != sig2)
++ return false;
++
++ /* Processor flags are either both 0 or they intersect. */
++ return ((!s1->pf && !pf2) || (s1->pf & pf2));
++}
++
++bool intel_find_matching_signature(void *mc, struct cpu_signature *sig)
+ {
+ struct microcode_header_intel *mc_hdr = mc;
+- struct extended_sigtable *ext_hdr;
+ struct extended_signature *ext_sig;
++ struct extended_sigtable *ext_hdr;
+ int i;
+
+- if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+- return 1;
++ if (cpu_signatures_match(sig, mc_hdr->sig, mc_hdr->pf))
++ return true;
+
+ /* Look for ext. headers: */
+ if (get_totalsize(mc_hdr) <= intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE)
+- return 0;
++ return false;
+
+ ext_hdr = mc + intel_microcode_get_datasize(mc_hdr) + MC_HEADER_SIZE;
+ ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
+
+ for (i = 0; i < ext_hdr->count; i++) {
+- if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+- return 1;
++ if (cpu_signatures_match(sig, ext_sig->sig, ext_sig->pf))
++ return true;
+ ext_sig++;
+ }
+ return 0;
+@@ -268,7 +275,7 @@ static __init struct microcode_intel *sc
+ intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)
+ break;
+
+- if (!intel_find_matching_signature(data, uci->cpu_sig.sig, uci->cpu_sig.pf))
++ if (!intel_find_matching_signature(data, &uci->cpu_sig))
+ continue;
+
+ /*
+@@ -512,7 +519,7 @@ static enum ucode_state parse_microcode_
+ if (cur_rev >= mc_header.rev)
+ continue;
+
+- if (!intel_find_matching_signature(mc, uci->cpu_sig.sig, uci->cpu_sig.pf))
++ if (!intel_find_matching_signature(mc, &uci->cpu_sig))
+ continue;
+
+ kvfree(new_mc);
+--- a/drivers/platform/x86/intel/ifs/load.c
++++ b/drivers/platform/x86/intel/ifs/load.c
+@@ -242,7 +242,7 @@ static int image_sanity_check(struct dev
+
+ intel_collect_cpu_info(&sig);
+
+- if (!intel_find_matching_signature((void *)data, sig.sig, sig.pf)) {
++ if (!intel_find_matching_signature((void *)data, &sig)) {
+ dev_err(dev, "cpu signature, processor flags not matching\n");
+ return -EINVAL;
+ }
--- /dev/null
+From 58ea3102876845d0088b8ebe8458cfac8251d4e3 Mon Sep 17 00:00:00 2001
+From: Ashok Raj <ashok.raj@intel.com>
+Date: Tue, 17 Oct 2023 23:23:33 +0200
+Subject: x86/microcode/intel: Rip out mixed stepping support for Intel CPUs
+
+From: Ashok Raj <ashok.raj@intel.com>
+
+commit ae76d951f6537001bdf77894d19cd4a446de337e upstream
+
+Mixed steppings aren't supported on Intel CPUs. Only one microcode patch
+is required for the entire system. The caching of microcode blobs which
+match the family and model is therefore pointless and in fact is
+dysfunctional as CPU hotplug updates use only a single microcode blob,
+i.e. the one where *intel_ucode_patch points to.
+
+Remove the microcode cache and make it an AMD local feature.
+
+ [ tglx:
+ - save only at the end. Otherwise random microcode ends up in the
+ pointer for early loading
+ - free the ucode patch pointer in save_microcode_patch() only
+ after kmemdup() has succeeded, as reported by Andrew Cooper ]
+
+Originally-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ashok Raj <ashok.raj@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211722.404362809@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 10 ++
+ arch/x86/kernel/cpu/microcode/core.c | 2
+ arch/x86/kernel/cpu/microcode/intel.c | 133 +++++--------------------------
+ arch/x86/kernel/cpu/microcode/internal.h | 10 --
+ 4 files changed, 34 insertions(+), 121 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -37,6 +37,16 @@
+
+ #include "internal.h"
+
++struct ucode_patch {
++ struct list_head plist;
++ void *data;
++ unsigned int size;
++ u32 patch_id;
++ u16 equiv_cpu;
++};
++
++static LIST_HEAD(microcode_cache);
++
+ #define UCODE_MAGIC 0x00414d44
+ #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
+ #define UCODE_UCODE_TYPE 0x00000001
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -46,8 +46,6 @@ static bool dis_ucode_ldr = true;
+
+ bool initrd_gone;
+
+-LIST_HEAD(microcode_cache);
+-
+ /*
+ * Synchronization.
+ *
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -33,10 +33,10 @@
+ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
+
+ /* Current microcode patch used in early patching on the APs. */
+-static struct microcode_intel *intel_ucode_patch;
++static struct microcode_intel *intel_ucode_patch __read_mostly;
+
+ /* last level cache size per core */
+-static int llc_size_per_core;
++static int llc_size_per_core __ro_after_init;
+
+ /* microcode format is extended from prescott processors */
+ struct extended_signature {
+@@ -253,74 +253,17 @@ static int has_newer_microcode(void *mc,
+ return intel_find_matching_signature(mc, csig, cpf);
+ }
+
+-static struct ucode_patch *memdup_patch(void *data, unsigned int size)
++static void save_microcode_patch(void *data, unsigned int size)
+ {
+- struct ucode_patch *p;
++ struct microcode_header_intel *p;
+
+- p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
++ p = kmemdup(data, size, GFP_KERNEL);
+ if (!p)
+- return NULL;
+-
+- p->data = kmemdup(data, size, GFP_KERNEL);
+- if (!p->data) {
+- kfree(p);
+- return NULL;
+- }
+-
+- return p;
+-}
+-
+-static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size)
+-{
+- struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
+- struct ucode_patch *iter, *tmp, *p = NULL;
+- bool prev_found = false;
+- unsigned int sig, pf;
+-
+- mc_hdr = (struct microcode_header_intel *)data;
+-
+- list_for_each_entry_safe(iter, tmp, µcode_cache, plist) {
+- mc_saved_hdr = (struct microcode_header_intel *)iter->data;
+- sig = mc_saved_hdr->sig;
+- pf = mc_saved_hdr->pf;
+-
+- if (intel_find_matching_signature(data, sig, pf)) {
+- prev_found = true;
+-
+- if (mc_hdr->rev <= mc_saved_hdr->rev)
+- continue;
+-
+- p = memdup_patch(data, size);
+- if (!p)
+- pr_err("Error allocating buffer %p\n", data);
+- else {
+- list_replace(&iter->plist, &p->plist);
+- kfree(iter->data);
+- kfree(iter);
+- }
+- }
+- }
+-
+- /*
+- * There weren't any previous patches found in the list cache; save the
+- * newly found.
+- */
+- if (!prev_found) {
+- p = memdup_patch(data, size);
+- if (!p)
+- pr_err("Error allocating buffer for %p\n", data);
+- else
+- list_add_tail(&p->plist, µcode_cache);
+- }
+-
+- if (!p)
+- return;
+-
+- if (!intel_find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ return;
+
++ kfree(intel_ucode_patch);
+ /* Save for early loading */
+- intel_ucode_patch = p->data;
++ intel_ucode_patch = (struct microcode_intel *)p;
+ }
+
+ /*
+@@ -332,6 +275,7 @@ scan_microcode(void *data, size_t size,
+ {
+ struct microcode_header_intel *mc_header;
+ struct microcode_intel *patch = NULL;
++ u32 cur_rev = uci->cpu_sig.rev;
+ unsigned int mc_size;
+
+ while (size) {
+@@ -341,8 +285,7 @@ scan_microcode(void *data, size_t size,
+ mc_header = (struct microcode_header_intel *)data;
+
+ mc_size = get_totalsize(mc_header);
+- if (!mc_size ||
+- mc_size > size ||
++ if (!mc_size || mc_size > size ||
+ intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)
+ break;
+
+@@ -354,31 +297,16 @@ scan_microcode(void *data, size_t size,
+ continue;
+ }
+
+- if (save) {
+- save_microcode_patch(uci, data, mc_size);
++ /* BSP scan: Check whether there is newer microcode */
++ if (!save && cur_rev >= mc_header->rev)
+ goto next;
+- }
+-
+
+- if (!patch) {
+- if (!has_newer_microcode(data,
+- uci->cpu_sig.sig,
+- uci->cpu_sig.pf,
+- uci->cpu_sig.rev))
+- goto next;
+-
+- } else {
+- struct microcode_header_intel *phdr = &patch->hdr;
+-
+- if (!has_newer_microcode(data,
+- phdr->sig,
+- phdr->pf,
+- phdr->rev))
+- goto next;
+- }
++ /* Save scan: Check whether there is newer or matching microcode */
++ if (save && cur_rev != mc_header->rev)
++ goto next;
+
+- /* We have a newer patch, save it. */
+ patch = data;
++ cur_rev = mc_header->rev;
+
+ next:
+ data += mc_size;
+@@ -387,6 +315,9 @@ next:
+ if (size)
+ return NULL;
+
++ if (save && patch)
++ save_microcode_patch(patch, mc_size);
++
+ return patch;
+ }
+
+@@ -528,26 +459,10 @@ void load_ucode_intel_ap(void)
+ apply_microcode_early(&uci);
+ }
+
+-static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
++/* Accessor for microcode pointer */
++static struct microcode_intel *ucode_get_patch(void)
+ {
+- struct microcode_header_intel *phdr;
+- struct ucode_patch *iter, *tmp;
+-
+- list_for_each_entry_safe(iter, tmp, µcode_cache, plist) {
+-
+- phdr = (struct microcode_header_intel *)iter->data;
+-
+- if (phdr->rev <= uci->cpu_sig.rev)
+- continue;
+-
+- if (!intel_find_matching_signature(phdr,
+- uci->cpu_sig.sig,
+- uci->cpu_sig.pf))
+- continue;
+-
+- return iter->data;
+- }
+- return NULL;
++ return intel_ucode_patch;
+ }
+
+ void reload_ucode_intel(void)
+@@ -557,7 +472,7 @@ void reload_ucode_intel(void)
+
+ intel_cpu_collect_info(&uci);
+
+- p = find_patch(&uci);
++ p = ucode_get_patch();
+ if (!p)
+ return;
+
+@@ -601,7 +516,7 @@ static enum ucode_state apply_microcode_
+ return UCODE_ERROR;
+
+ /* Look for a newer patch in our cache: */
+- mc = find_patch(uci);
++ mc = ucode_get_patch();
+ if (!mc) {
+ mc = uci->mc;
+ if (!mc)
+@@ -730,7 +645,7 @@ static enum ucode_state generic_load_mic
+ uci->mc = (struct microcode_intel *)new_mc;
+
+ /* Save for CPU hotplug */
+- save_microcode_patch(uci, new_mc, new_mc_size);
++ save_microcode_patch(new_mc, new_mc_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);
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -8,16 +8,6 @@
+ #include <asm/cpu.h>
+ #include <asm/microcode.h>
+
+-struct ucode_patch {
+- struct list_head plist;
+- void *data; /* Intel uses only this one */
+- unsigned int size;
+- u32 patch_id;
+- u16 equiv_cpu;
+-};
+-
+-extern struct list_head microcode_cache;
+-
+ struct device;
+
+ enum ucode_state {
--- /dev/null
+From 9b3fa0e8651fe1988c3103d1bca401cca0341258 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:44 +0200
+Subject: x86/microcode/intel: Save the microcode only after a successful late-load
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 2a1dada3d1cf8f80a27663653a371d99dbf5d540 upstream
+
+There are situations where the late microcode is loaded into memory but
+is not applied:
+
+ 1) The rendezvous fails
+ 2) The microcode is rejected by the CPUs
+
+If any of this happens then the pointer which was updated at firmware
+load time is stale and subsequent CPU hotplug operations either fail to
+update or create inconsistent microcode state.
+
+Save the loaded microcode in a separate pointer before the late load is
+attempted and when successful, update the hotplug pointer accordingly
+via a new microcode_ops callback.
+
+Remove the pointless fallback in the loader to a microcode pointer which
+is never populated.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.505491309@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 4 ++++
+ arch/x86/kernel/cpu/microcode/intel.c | 30 +++++++++++++++---------------
+ arch/x86/kernel/cpu/microcode/internal.h | 1 +
+ 3 files changed, 20 insertions(+), 15 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -403,6 +403,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);
+--- 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
+
+ /* 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_
+ 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_
+ 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_microcod
+ 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)
+--- 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[];
--- /dev/null
+From 9f96838d0ac5ce33575968c2596eba004118f885 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Fri, 1 Dec 2023 14:35:06 +0100
+Subject: x86/microcode/intel: Set new revision only after a successful update
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 9c21ea53e6bd1104c637b80a0688040f184cc761 upstream
+
+This was meant to be done only when early microcode got updated
+successfully. Move it into the if-branch.
+
+Also, make sure the current revision is read unconditionally and only
+once.
+
+Fixes: 080990aa3344 ("x86/microcode: Rework early revisions reporting")
+Reported-by: Ashok Raj <ashok.raj@intel.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Ashok Raj <ashok.raj@intel.com>
+Link: https://lore.kernel.org/r/ZWjVt5dNRjbcvlzR@a4bf019067fa.jf.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -370,14 +370,14 @@ static __init struct microcode_intel *ge
+ {
+ struct cpio_data cp;
+
++ intel_collect_cpu_info(&uci->cpu_sig);
++
+ if (!load_builtin_intel_microcode(&cp))
+ cp = find_microcode_in_initrd(ucode_path);
+
+ if (!(cp.data && cp.size))
+ return NULL;
+
+- intel_collect_cpu_info(&uci->cpu_sig);
+-
+ return scan_microcode(cp.data, cp.size, uci, save);
+ }
+
+@@ -410,13 +410,13 @@ void __init load_ucode_intel_bsp(struct
+ {
+ struct ucode_cpu_info uci;
+
+- ed->old_rev = intel_get_microcode_revision();
+-
+ uci.mc = get_microcode_blob(&uci, false);
+- if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED)
+- ucode_patch_va = UCODE_BSP_LOADED;
++ ed->old_rev = uci.cpu_sig.rev;
+
+- ed->new_rev = uci.cpu_sig.rev;
++ if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED) {
++ ucode_patch_va = UCODE_BSP_LOADED;
++ ed->new_rev = uci.cpu_sig.rev;
++ }
+ }
+
+ void load_ucode_intel_ap(void)
--- /dev/null
+From 439bbf98a0eeb839da26fe91d0dd0fb158957de3 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:40 +0200
+Subject: x86/microcode/intel: Simplify and rename generic_load_microcode()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 6b072022ab2e1e83b7588144ee0080f7197b71da upstream
+
+so it becomes less obfuscated and rename it because there is nothing
+generic about it.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.330295409@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 47 ++++++++++++----------------------
+ 1 file changed, 17 insertions(+), 30 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -240,19 +240,6 @@ int intel_microcode_sanity_check(void *m
+ }
+ EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
+
+-/*
+- * Returns 1 if update has been found, 0 otherwise.
+- */
+-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)
+- return 0;
+-
+- return intel_find_matching_signature(mc, csig, cpf);
+-}
+-
+ static void save_microcode_patch(void *data, unsigned int size)
+ {
+ struct microcode_header_intel *p;
+@@ -559,14 +546,12 @@ out:
+ return ret;
+ }
+
+-static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
++static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
+ {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+ unsigned int curr_mc_size = 0, new_mc_size = 0;
+- enum ucode_state ret = UCODE_OK;
+- int new_rev = uci->cpu_sig.rev;
++ int cur_rev = uci->cpu_sig.rev;
+ u8 *new_mc = NULL, *mc = NULL;
+- unsigned int csig, cpf;
+
+ while (iov_iter_count(iter)) {
+ struct microcode_header_intel mc_header;
+@@ -583,6 +568,7 @@ static enum ucode_state generic_load_mic
+ pr_err("error! Bad data in microcode data file (totalsize too small)\n");
+ break;
+ }
++
+ data_size = mc_size - sizeof(mc_header);
+ if (data_size > iov_iter_count(iter)) {
+ pr_err("error! Bad data in microcode data file (truncated file?)\n");
+@@ -605,16 +591,17 @@ static enum ucode_state generic_load_mic
+ break;
+ }
+
+- csig = uci->cpu_sig.sig;
+- cpf = uci->cpu_sig.pf;
+- if (has_newer_microcode(mc, csig, cpf, new_rev)) {
+- vfree(new_mc);
+- new_rev = mc_header.rev;
+- new_mc = mc;
+- new_mc_size = mc_size;
+- mc = NULL; /* trigger new vmalloc */
+- ret = UCODE_NEW;
+- }
++ if (cur_rev >= mc_header.rev)
++ continue;
++
++ if (!intel_find_matching_signature(mc, uci->cpu_sig.sig, uci->cpu_sig.pf))
++ continue;
++
++ vfree(new_mc);
++ cur_rev = mc_header.rev;
++ new_mc = mc;
++ new_mc_size = mc_size;
++ mc = NULL;
+ }
+
+ vfree(mc);
+@@ -634,9 +621,9 @@ static enum ucode_state generic_load_mic
+ save_microcode_patch(new_mc, new_mc_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);
++ cpu, cur_rev, uci->cpu_sig.rev);
+
+- return ret;
++ return UCODE_NEW;
+ }
+
+ static bool is_blacklisted(unsigned int cpu)
+@@ -685,7 +672,7 @@ static enum ucode_state request_microcod
+ kvec.iov_base = (void *)firmware->data;
+ kvec.iov_len = firmware->size;
+ iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, firmware->size);
+- ret = generic_load_microcode(cpu, &iter);
++ ret = parse_microcode_blobs(cpu, &iter);
+
+ release_firmware(firmware);
+
--- /dev/null
+From 3c4ebaefd467735f9aec389f02264f17fc7e0f3a Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:43 +0200
+Subject: x86/microcode/intel: Simplify early loading
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit dd5e3e3ca6ac011582a9f3f987493bf6741568c0 upstream.
+
+The early loading code is overly complicated:
+
+ - It scans the builtin/initrd for microcode not only on the BSP, but also
+ on all APs during early boot and then later in the boot process it
+ scans again to duplicate and save the microcode before initrd goes
+ away.
+
+ That's a pointless exercise because this can be simply done before
+ bringing up the APs when the memory allocator is up and running.
+
+ - Saving the microcode from within the scan loop is completely
+ non-obvious and a left over of the microcode cache.
+
+ This can be done at the call site now which makes it obvious.
+
+Rework the code so that only the BSP scans the builtin/initrd microcode
+once during early boot and save it away in an early initcall for later
+use.
+
+ [ bp: Test and fold in a fix from tglx ontop which handles the need to
+ distinguish what save_microcode() does depending on when it is
+ called:
+
+ - when on the BSP during early load, it needs to find a newer
+ revision than the one currently loaded on the BSP
+
+ - later, before SMP init, it still runs on the BSP and gets the BSP
+ revision just loaded and uses that revision to know which patch
+ to save for the APs. For that it needs to find the exact one as
+ on the BSP.
+ ]
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211722.629085215@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 6 -
+ arch/x86/kernel/cpu/microcode/intel.c | 163 ++++++++++++++-----------------
+ arch/x86/kernel/cpu/microcode/internal.h | 3
+ 3 files changed, 79 insertions(+), 93 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -42,7 +42,7 @@
+ #define DRIVER_VERSION "2.2"
+
+ static struct microcode_ops *microcode_ops;
+-static bool dis_ucode_ldr = true;
++bool dis_ucode_ldr = true;
+
+ bool initrd_gone;
+
+@@ -191,10 +191,6 @@ static int __init save_microcode_in_init
+ }
+
+ switch (c->x86_vendor) {
+- case X86_VENDOR_INTEL:
+- if (c->x86 >= 6)
+- ret = save_microcode_in_initrd_intel();
+- break;
+ case X86_VENDOR_AMD:
+ if (c->x86 >= 0x10)
+ ret = save_microcode_in_initrd_amd(cpuid_eax(1));
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -32,8 +32,10 @@
+
+ static const char ucode_path[] = "kernel/x86/microcode/GenuineIntel.bin";
+
++#define UCODE_BSP_LOADED ((struct microcode_intel *)0x1UL)
++
+ /* Current microcode patch used in early patching on the APs. */
+-static struct microcode_intel *intel_ucode_patch __read_mostly;
++static struct microcode_intel *ucode_patch_va __read_mostly;
+
+ /* last level cache size per core */
+ static unsigned int llc_size_per_core __ro_after_init;
+@@ -240,22 +242,30 @@ int intel_microcode_sanity_check(void *m
+ }
+ EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
+
+-static void save_microcode_patch(void *data, unsigned int size)
++static void update_ucode_pointer(struct microcode_intel *mc)
+ {
+- struct microcode_header_intel *p;
++ kfree(ucode_patch_va);
++
++ /*
++ * Save the virtual address for early loading and for eventual free
++ * on late loading.
++ */
++ ucode_patch_va = mc;
++}
+
+- p = kmemdup(data, size, GFP_KERNEL);
+- if (!p)
+- return;
++static void save_microcode_patch(struct microcode_intel *patch)
++{
++ struct microcode_intel *mc;
+
+- kfree(intel_ucode_patch);
+- /* Save for early loading */
+- intel_ucode_patch = (struct microcode_intel *)p;
++ mc = kmemdup(patch, get_totalsize(&patch->hdr), GFP_KERNEL);
++ if (mc)
++ update_ucode_pointer(mc);
+ }
+
+-/* Scan CPIO for microcode matching the boot CPU's family, model, stepping */
+-static struct microcode_intel *scan_microcode(void *data, size_t size,
+- struct ucode_cpu_info *uci, bool save)
++/* Scan blob for microcode matching the boot CPUs family, model, stepping */
++static __init struct microcode_intel *scan_microcode(void *data, size_t size,
++ struct ucode_cpu_info *uci,
++ bool save)
+ {
+ struct microcode_header_intel *mc_header;
+ struct microcode_intel *patch = NULL;
+@@ -273,35 +283,35 @@ static struct microcode_intel *scan_micr
+ if (!intel_find_matching_signature(data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ continue;
+
+- /* BSP scan: Check whether there is newer microcode */
+- if (!save && cur_rev >= mc_header->rev)
+- continue;
+-
+- /* Save scan: Check whether there is newer or matching microcode */
+- if (save && cur_rev != mc_header->rev)
++ /*
++ * For saving the early microcode, find the matching revision which
++ * was loaded on the BSP.
++ *
++ * On the BSP during early boot, find a newer revision than
++ * actually loaded in the CPU.
++ */
++ if (save) {
++ if (cur_rev != mc_header->rev)
++ continue;
++ } else if (cur_rev >= mc_header->rev) {
+ continue;
++ }
+
+ patch = data;
+ cur_rev = mc_header->rev;
+ }
+
+- if (size)
+- return NULL;
+-
+- if (save && patch)
+- save_microcode_patch(patch, mc_size);
+-
+- return patch;
++ return size ? NULL : patch;
+ }
+
+-static int apply_microcode_early(struct ucode_cpu_info *uci)
++static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
+ {
+ struct microcode_intel *mc;
+ u32 rev, old_rev, date;
+
+ mc = uci->mc;
+ if (!mc)
+- return 0;
++ return UCODE_NFOUND;
+
+ /*
+ * Save us the MSR write below - which is a particular expensive
+@@ -327,17 +337,17 @@ static int apply_microcode_early(struct
+
+ rev = intel_get_microcode_revision();
+ if (rev != mc->hdr.rev)
+- return -1;
++ return UCODE_ERROR;
+
+ uci->cpu_sig.rev = rev;
+
+ date = mc->hdr.date;
+ pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
+ old_rev, rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
+- return 0;
++ return UCODE_UPDATED;
+ }
+
+-static bool load_builtin_intel_microcode(struct cpio_data *cp)
++static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
+ {
+ unsigned int eax = 1, ebx, ecx = 0, edx;
+ struct firmware fw;
+@@ -359,89 +369,71 @@ static bool load_builtin_intel_microcode
+ return false;
+ }
+
+-int __init save_microcode_in_initrd_intel(void)
++static __init struct microcode_intel *get_microcode_blob(struct ucode_cpu_info *uci, bool save)
+ {
+- struct ucode_cpu_info uci;
+ struct cpio_data cp;
+
+- /*
+- * initrd is going away, clear patch ptr. We will scan the microcode one
+- * last time before jettisoning and save a patch, if found. Then we will
+- * update that pointer too, with a stable patch address to use when
+- * resuming the cores.
+- */
+- intel_ucode_patch = NULL;
+-
+ if (!load_builtin_intel_microcode(&cp))
+ cp = find_microcode_in_initrd(ucode_path);
+
+ if (!(cp.data && cp.size))
+- return 0;
++ return NULL;
+
+- intel_cpu_collect_info(&uci);
++ intel_cpu_collect_info(uci);
+
+- scan_microcode(cp.data, cp.size, &uci, true);
+- return 0;
++ return scan_microcode(cp.data, cp.size, uci, save);
+ }
+
+ /*
+- * @res_patch, output: a pointer to the patch we found.
++ * Invoked from an early init call to save the microcode blob which was
++ * selected during early boot when mm was not usable. The microcode must be
++ * saved because initrd is going away. It's an early init call so the APs
++ * just can use the pointer and do not have to scan initrd/builtin firmware
++ * again.
+ */
+-static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
++static int __init save_builtin_microcode(void)
+ {
+- struct cpio_data cp;
+-
+- /* try built-in microcode first */
+- if (!load_builtin_intel_microcode(&cp))
+- cp = find_microcode_in_initrd(ucode_path);
++ struct ucode_cpu_info uci;
+
+- if (!(cp.data && cp.size))
+- return NULL;
++ if (xchg(&ucode_patch_va, NULL) != UCODE_BSP_LOADED)
++ return 0;
+
+- intel_cpu_collect_info(uci);
++ if (dis_ucode_ldr || boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
++ return 0;
+
+- return scan_microcode(cp.data, cp.size, uci, false);
++ uci.mc = get_microcode_blob(&uci, true);
++ if (uci.mc)
++ save_microcode_patch(uci.mc);
++ return 0;
+ }
++early_initcall(save_builtin_microcode);
+
++/* Load microcode on BSP from initrd or builtin blobs */
+ void __init load_ucode_intel_bsp(void)
+ {
+- struct microcode_intel *patch;
+ struct ucode_cpu_info uci;
+
+- patch = __load_ucode_intel(&uci);
+- if (!patch)
+- return;
+-
+- uci.mc = patch;
+-
+- apply_microcode_early(&uci);
++ uci.mc = get_microcode_blob(&uci, false);
++ if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED)
++ ucode_patch_va = UCODE_BSP_LOADED;
+ }
+
+ void load_ucode_intel_ap(void)
+ {
+ struct ucode_cpu_info uci;
+
+- if (!intel_ucode_patch) {
+- intel_ucode_patch = __load_ucode_intel(&uci);
+- if (!intel_ucode_patch)
+- return;
+- }
+-
+- uci.mc = intel_ucode_patch;
+- apply_microcode_early(&uci);
++ uci.mc = ucode_patch_va;
++ if (uci.mc)
++ apply_microcode_early(&uci);
+ }
+
++/* Reload microcode on resume */
+ void reload_ucode_intel(void)
+ {
+- struct ucode_cpu_info uci;
+-
+- intel_cpu_collect_info(&uci);
+-
+- uci.mc = intel_ucode_patch;
+- if (!uci.mc)
+- return;
++ struct ucode_cpu_info uci = { .mc = ucode_patch_va, };
+
+- apply_microcode_early(&uci);
++ if (uci.mc)
++ apply_microcode_early(&uci);
+ }
+
+ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
+@@ -478,7 +470,7 @@ static enum ucode_state apply_microcode_
+ if (WARN_ON(raw_smp_processor_id() != cpu))
+ return UCODE_ERROR;
+
+- mc = intel_ucode_patch;
++ mc = ucode_patch_va;
+ if (!mc) {
+ mc = uci->mc;
+ if (!mc)
+@@ -538,8 +530,8 @@ out:
+ static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
+ {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+- unsigned int curr_mc_size = 0, new_mc_size = 0;
+ int cur_rev = uci->cpu_sig.rev;
++ unsigned int curr_mc_size = 0;
+ u8 *new_mc = NULL, *mc = NULL;
+
+ while (iov_iter_count(iter)) {
+@@ -589,7 +581,6 @@ static enum ucode_state parse_microcode_
+ vfree(new_mc);
+ cur_rev = mc_header.rev;
+ new_mc = mc;
+- new_mc_size = mc_size;
+ mc = NULL;
+ }
+
+@@ -603,11 +594,11 @@ static enum ucode_state parse_microcode_
+ if (!new_mc)
+ return UCODE_NFOUND;
+
+- vfree(uci->mc);
+- uci->mc = (struct microcode_intel *)new_mc;
+-
+ /* Save for CPU hotplug */
+- save_microcode_patch(new_mc, new_mc_size);
++ 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);
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -84,6 +84,7 @@ static inline unsigned int x86_cpuid_fam
+ return x86_family(eax);
+ }
+
++extern bool dis_ucode_ldr;
+ extern bool initrd_gone;
+
+ #ifdef CONFIG_CPU_SUP_AMD
+@@ -107,13 +108,11 @@ static inline void exit_amd_microcode(vo
+ #ifdef CONFIG_CPU_SUP_INTEL
+ void load_ucode_intel_bsp(void);
+ void load_ucode_intel_ap(void);
+-int save_microcode_in_initrd_intel(void);
+ void reload_ucode_intel(void);
+ struct microcode_ops *init_intel_microcode(void);
+ #else /* CONFIG_CPU_SUP_INTEL */
+ static inline void load_ucode_intel_bsp(void) { }
+ static inline void load_ucode_intel_ap(void) { }
+-static inline int save_microcode_in_initrd_intel(void) { return -EINVAL; }
+ static inline void reload_ucode_intel(void) { }
+ static inline struct microcode_ops *init_intel_microcode(void) { return NULL; }
+ #endif /* !CONFIG_CPU_SUP_INTEL */
--- /dev/null
+From 0487743593c7df7d637db9048c5727bd7c1cea03 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:39 +0200
+Subject: x86/microcode/intel: Simplify scan_microcode()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit b0f0bf5eef5fac6ba30b7cac15ca4cb01f8a6ca9 upstream
+
+Make it readable and comprehensible.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.271940980@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 28 +++++++---------------------
+ 1 file changed, 7 insertions(+), 21 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -266,22 +266,16 @@ static void save_microcode_patch(void *d
+ intel_ucode_patch = (struct microcode_intel *)p;
+ }
+
+-/*
+- * Get microcode matching with BSP's model. Only CPUs with the same model as
+- * BSP can stay in the platform.
+- */
+-static struct microcode_intel *
+-scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
++/* Scan CPIO for microcode matching the boot CPU's family, model, stepping */
++static struct microcode_intel *scan_microcode(void *data, size_t size,
++ struct ucode_cpu_info *uci, bool save)
+ {
+ struct microcode_header_intel *mc_header;
+ struct microcode_intel *patch = NULL;
+ u32 cur_rev = uci->cpu_sig.rev;
+ unsigned int mc_size;
+
+- while (size) {
+- if (size < sizeof(struct microcode_header_intel))
+- break;
+-
++ for (; size >= sizeof(struct microcode_header_intel); size -= mc_size, data += mc_size) {
+ mc_header = (struct microcode_header_intel *)data;
+
+ mc_size = get_totalsize(mc_header);
+@@ -289,27 +283,19 @@ scan_microcode(void *data, size_t size,
+ intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)
+ break;
+
+- size -= mc_size;
+-
+- if (!intel_find_matching_signature(data, uci->cpu_sig.sig,
+- uci->cpu_sig.pf)) {
+- data += mc_size;
++ if (!intel_find_matching_signature(data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ continue;
+- }
+
+ /* BSP scan: Check whether there is newer microcode */
+ if (!save && cur_rev >= mc_header->rev)
+- goto next;
++ continue;
+
+ /* Save scan: Check whether there is newer or matching microcode */
+ if (save && cur_rev != mc_header->rev)
+- goto next;
++ continue;
+
+ patch = data;
+ cur_rev = mc_header->rev;
+-
+-next:
+- data += mc_size;
+ }
+
+ if (size)
--- /dev/null
+From 0937c0624d82085ec90acde324c0bd6d9accfa20 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:45 +0200
+Subject: x86/microcode/intel: Switch to kvmalloc()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit f24f204405f9875bc539c6e88553fd5ac913c867 upstream
+
+Microcode blobs are getting larger and might soon reach the kmalloc()
+limit. Switch over kvmalloc().
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115902.564323243@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 48 +++++++++++++++++-----------------
+ 1 file changed, 25 insertions(+), 23 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -14,7 +14,6 @@
+ #include <linux/earlycpio.h>
+ #include <linux/firmware.h>
+ #include <linux/uaccess.h>
+-#include <linux/vmalloc.h>
+ #include <linux/initrd.h>
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+@@ -245,7 +244,7 @@ EXPORT_SYMBOL_GPL(intel_microcode_sanity
+
+ static void update_ucode_pointer(struct microcode_intel *mc)
+ {
+- kfree(ucode_patch_va);
++ kvfree(ucode_patch_va);
+
+ /*
+ * Save the virtual address for early loading and for eventual free
+@@ -256,11 +255,14 @@ static void update_ucode_pointer(struct
+
+ static void save_microcode_patch(struct microcode_intel *patch)
+ {
++ unsigned int size = get_totalsize(&patch->hdr);
+ struct microcode_intel *mc;
+
+- mc = kmemdup(patch, get_totalsize(&patch->hdr), GFP_KERNEL);
++ mc = kvmemdup(patch, size, GFP_KERNEL);
+ if (mc)
+ update_ucode_pointer(mc);
++ else
++ pr_err("Unable to allocate microcode memory size: %u\n", size);
+ }
+
+ /* Scan blob for microcode matching the boot CPUs family, model, stepping */
+@@ -539,36 +541,34 @@ static enum ucode_state parse_microcode_
+
+ if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
+ pr_err("error! Truncated or inaccessible header in microcode data file\n");
+- break;
++ goto fail;
+ }
+
+ mc_size = get_totalsize(&mc_header);
+ if (mc_size < sizeof(mc_header)) {
+ pr_err("error! Bad data in microcode data file (totalsize too small)\n");
+- break;
++ goto fail;
+ }
+-
+ data_size = mc_size - sizeof(mc_header);
+ if (data_size > iov_iter_count(iter)) {
+ pr_err("error! Bad data in microcode data file (truncated file?)\n");
+- break;
++ goto fail;
+ }
+
+ /* For performance reasons, reuse mc area when possible */
+ if (!mc || mc_size > curr_mc_size) {
+- vfree(mc);
+- mc = vmalloc(mc_size);
++ kvfree(mc);
++ mc = kvmalloc(mc_size, GFP_KERNEL);
+ if (!mc)
+- break;
++ goto fail;
+ curr_mc_size = mc_size;
+ }
+
+ memcpy(mc, &mc_header, sizeof(mc_header));
+ data = mc + sizeof(mc_header);
+ if (!copy_from_iter_full(data, data_size, iter) ||
+- intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) {
+- break;
+- }
++ intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0)
++ goto fail;
+
+ if (cur_rev >= mc_header.rev)
+ continue;
+@@ -576,24 +576,26 @@ static enum ucode_state parse_microcode_
+ if (!intel_find_matching_signature(mc, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ continue;
+
+- vfree(new_mc);
++ kvfree(new_mc);
+ cur_rev = mc_header.rev;
+ new_mc = mc;
+ mc = NULL;
+ }
+
+- vfree(mc);
+-
+- if (iov_iter_count(iter)) {
+- vfree(new_mc);
+- return UCODE_ERROR;
+- }
++ if (iov_iter_count(iter))
++ goto fail;
+
++ kvfree(mc);
+ if (!new_mc)
+ return UCODE_NFOUND;
+
+ ucode_patch_late = (struct microcode_intel *)new_mc;
+ return UCODE_NEW;
++
++fail:
++ kvfree(mc);
++ kvfree(new_mc);
++ return UCODE_ERROR;
+ }
+
+ static bool is_blacklisted(unsigned int cpu)
+@@ -652,9 +654,9 @@ static enum ucode_state request_microcod
+ static void finalize_late_load(int result)
+ {
+ if (!result)
+- save_microcode_patch(ucode_patch_late);
+-
+- vfree(ucode_patch_late);
++ update_ucode_pointer(ucode_patch_late);
++ else
++ kvfree(ucode_patch_late);
+ ucode_patch_late = NULL;
+ }
+
--- /dev/null
+From 661c46050f078216190d6137423d04a49bfe44ae Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:44 +0200
+Subject: x86/microcode/intel: Unify microcode apply() functions
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 3973718cff1e3a5d88ea78ec28ecca2afa60b30b upstream
+
+Deduplicate the early and late apply() functions.
+
+ [ bp: Rename the function which does the actual application to
+ __apply_microcode() to differentiate it from
+ microcode_ops.apply_microcode(). ]
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20231017211722.795508212@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/intel.c | 106 +++++++++++-----------------------
+ 1 file changed, 37 insertions(+), 69 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -307,12 +307,12 @@ static __init struct microcode_intel *sc
+ return size ? NULL : patch;
+ }
+
+-static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
++static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,
++ struct microcode_intel *mc,
++ u32 *cur_rev)
+ {
+- struct microcode_intel *mc;
+- u32 rev, old_rev, date;
++ u32 rev;
+
+- mc = uci->mc;
+ if (!mc)
+ return UCODE_NFOUND;
+
+@@ -321,14 +321,12 @@ static enum ucode_state apply_microcode_
+ * operation - when the other hyperthread has updated the microcode
+ * already.
+ */
+- rev = intel_get_microcode_revision();
+- if (rev >= mc->hdr.rev) {
+- uci->cpu_sig.rev = rev;
++ *cur_rev = intel_get_microcode_revision();
++ if (*cur_rev >= mc->hdr.rev) {
++ uci->cpu_sig.rev = *cur_rev;
+ return UCODE_OK;
+ }
+
+- old_rev = rev;
+-
+ /*
+ * Writeback and invalidate caches before updating microcode to avoid
+ * internal issues depending on what the microcode is updating.
+@@ -343,13 +341,24 @@ static enum ucode_state apply_microcode_
+ return UCODE_ERROR;
+
+ uci->cpu_sig.rev = rev;
+-
+- date = mc->hdr.date;
+- pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
+- old_rev, rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
+ return UCODE_UPDATED;
+ }
+
++static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
++{
++ struct microcode_intel *mc = uci->mc;
++ enum ucode_state ret;
++ u32 cur_rev, date;
++
++ ret = __apply_microcode(uci, mc, &cur_rev);
++ if (ret == UCODE_UPDATED) {
++ date = mc->hdr.date;
++ pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
++ cur_rev, mc->hdr.rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
++ }
++ return ret;
++}
++
+ static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
+ {
+ unsigned int eax = 1, ebx, ecx = 0, edx;
+@@ -459,70 +468,29 @@ static int collect_cpu_info(int cpu_num,
+ return 0;
+ }
+
+-static enum ucode_state apply_microcode_intel(int cpu)
++static enum ucode_state apply_microcode_late(int cpu)
+ {
+ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+- struct cpuinfo_x86 *c = &cpu_data(cpu);
+- bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
+- struct microcode_intel *mc;
++ struct microcode_intel *mc = ucode_patch_late;
+ enum ucode_state ret;
+- static int prev_rev;
+- u32 rev;
+-
+- /* We should bind the task to the CPU */
+- if (WARN_ON(raw_smp_processor_id() != cpu))
+- return UCODE_ERROR;
+-
+- mc = ucode_patch_late;
+- if (!mc)
+- return UCODE_NFOUND;
+-
+- /*
+- * Save us the MSR write below - which is a particular expensive
+- * operation - when the other hyperthread has updated the microcode
+- * already.
+- */
+- rev = intel_get_microcode_revision();
+- if (rev >= mc->hdr.rev) {
+- ret = UCODE_OK;
+- goto out;
+- }
++ u32 cur_rev;
+
+- /*
+- * Writeback and invalidate caches before updating microcode to avoid
+- * internal issues depending on what the microcode is updating.
+- */
+- native_wbinvd();
+-
+- /* write microcode via MSR 0x79 */
+- wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
+-
+- rev = intel_get_microcode_revision();
+-
+- if (rev != mc->hdr.rev) {
+- pr_err("CPU%d update to revision 0x%x failed\n",
+- cpu, mc->hdr.rev);
++ if (WARN_ON_ONCE(smp_processor_id() != cpu))
+ return UCODE_ERROR;
+- }
+
+- if (bsp && rev != prev_rev) {
+- pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
+- rev,
+- mc->hdr.date & 0xffff,
+- mc->hdr.date >> 24,
++ ret = __apply_microcode(uci, mc, &cur_rev);
++ if (ret != UCODE_UPDATED && ret != UCODE_OK)
++ return ret;
++
++ if (!cpu && uci->cpu_sig.rev != cur_rev) {
++ pr_info("Updated to revision 0x%x, date = %04x-%02x-%02x\n",
++ uci->cpu_sig.rev, mc->hdr.date & 0xffff, mc->hdr.date >> 24,
+ (mc->hdr.date >> 16) & 0xff);
+- prev_rev = rev;
+ }
+
+- ret = UCODE_UPDATED;
+-
+-out:
+- uci->cpu_sig.rev = rev;
+- c->microcode = rev;
+-
+- /* Update boot_cpu_data's revision too, if we're on the BSP: */
+- if (bsp)
+- boot_cpu_data.microcode = rev;
++ cpu_data(cpu).microcode = uci->cpu_sig.rev;
++ if (!cpu)
++ boot_cpu_data.microcode = uci->cpu_sig.rev;
+
+ return ret;
+ }
+@@ -663,7 +631,7 @@ static void finalize_late_load(int resul
+ static struct microcode_ops microcode_intel_ops = {
+ .request_microcode_fw = request_microcode_fw,
+ .collect_cpu_info = collect_cpu_info,
+- .apply_microcode = apply_microcode_intel,
++ .apply_microcode = apply_microcode_late,
+ .finalize_late_load = finalize_late_load,
+ };
+
--- /dev/null
+From 3f7517298aa0e62866887bff84df0ae84cec2b96 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:56 +0200
+Subject: x86/microcode: Mop up early loading leftovers
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 8529e8ab6c6fab8ebf06ead98e77d7646b42fc48 upstream
+
+Get rid of the initrd_gone hack which was required to keep
+find_microcode_in_initrd() functional after init.
+
+As find_microcode_in_initrd() is now only used during init, mark it
+accordingly.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211723.298854846@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 17 +----------------
+ arch/x86/kernel/cpu/microcode/internal.h | 1 -
+ 2 files changed, 1 insertion(+), 17 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -44,8 +44,6 @@
+ static struct microcode_ops *microcode_ops;
+ bool dis_ucode_ldr = true;
+
+-bool initrd_gone;
+-
+ /*
+ * Synchronization.
+ *
+@@ -180,15 +178,7 @@ void load_ucode_ap(void)
+ }
+ }
+
+-/* Temporary workaround until find_microcode_in_initrd() is __init */
+-static int __init mark_initrd_gone(void)
+-{
+- initrd_gone = true;
+- return 0;
+-}
+-fs_initcall(mark_initrd_gone);
+-
+-struct cpio_data find_microcode_in_initrd(const char *path)
++struct cpio_data __init find_microcode_in_initrd(const char *path)
+ {
+ #ifdef CONFIG_BLK_DEV_INITRD
+ unsigned long start = 0;
+@@ -216,12 +206,7 @@ struct cpio_data find_microcode_in_initr
+ * has the virtual address of the beginning of the initrd. It also
+ * possibly relocates the ramdisk. In either case, initrd_start contains
+ * the updated address so use that instead.
+- *
+- * initrd_gone is for the hotplug case where we've thrown out initrd
+- * already.
+ */
+- if (initrd_gone)
+- return (struct cpio_data){ NULL, 0, "" };
+ if (initrd_start)
+ start = initrd_start;
+
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -86,7 +86,6 @@ static inline unsigned int x86_cpuid_fam
+ }
+
+ extern bool dis_ucode_ldr;
+-extern bool initrd_gone;
+
+ #ifdef CONFIG_CPU_SUP_AMD
+ void load_ucode_amd_bsp(unsigned int family);
--- /dev/null
+From 1aa144827ab0a7f4c1f30ac972f4ec66f079afb3 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:24:16 +0200
+Subject: x86/microcode: Prepare for minimal revision check
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 9407bda845dd19756e276d4f3abc15a20777ba45 upstream
+
+Applying microcode late can be fatal for the running kernel when the
+update changes functionality which is in use already in a non-compatible
+way, e.g. by removing a CPUID bit.
+
+There is no way for admins which do not have access to the vendors deep
+technical support to decide whether late loading of such a microcode is
+safe or not.
+
+Intel has added a new field to the microcode header which tells the
+minimal microcode revision which is required to be active in the CPU in
+order to be safe.
+
+Provide infrastructure for handling this in the core code and a command
+line switch which allows to enforce it.
+
+If the update is considered safe the kernel is not tainted and the annoying
+warning message not emitted. If it's enforced and the currently loaded
+microcode revision is not safe for late loading then the load is aborted.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231017211724.079611170@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 5 +++++
+ arch/x86/Kconfig | 23 ++++++++++++++++++++++-
+ arch/x86/kernel/cpu/microcode/amd.c | 3 +++
+ arch/x86/kernel/cpu/microcode/core.c | 19 ++++++++++++++-----
+ arch/x86/kernel/cpu/microcode/intel.c | 3 +++
+ arch/x86/kernel/cpu/microcode/internal.h | 2 ++
+ 6 files changed, 49 insertions(+), 6 deletions(-)
+
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3287,6 +3287,11 @@
+
+ mga= [HW,DRM]
+
++ microcode.force_minrev= [X86]
++ Format: <bool>
++ Enable or disable the microcode minimal revision
++ enforcement for the runtime microcode loader.
++
+ min_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory below this
+ physical address is ignored.
+
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1323,7 +1323,28 @@ config MICROCODE_LATE_LOADING
+ is a tricky business and should be avoided if possible. Just the sequence
+ of synchronizing all cores and SMT threads is one fragile dance which does
+ not guarantee that cores might not softlock after the loading. Therefore,
+- use this at your own risk. Late loading taints the kernel too.
++ use this at your own risk. Late loading taints the kernel unless the
++ microcode header indicates that it is safe for late loading via the
++ minimal revision check. This minimal revision check can be enforced on
++ the kernel command line with "microcode.minrev=Y".
++
++config MICROCODE_LATE_FORCE_MINREV
++ bool "Enforce late microcode loading minimal revision check"
++ default n
++ depends on MICROCODE_LATE_LOADING
++ help
++ To prevent that users load microcode late which modifies already
++ in use features, newer microcode patches have a minimum revision field
++ in the microcode header, which tells the kernel which minimum
++ revision must be active in the CPU to safely load that new microcode
++ late into the running system. If disabled the check will not
++ be enforced but the kernel will be tainted when the minimal
++ revision check fails.
++
++ This minimal revision check can also be controlled via the
++ "microcode.minrev" parameter on the kernel command line.
++
++ If unsure say Y.
+
+ config X86_MSR
+ tristate "/dev/cpu/*/msr - Model-specific register support"
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -888,6 +888,9 @@ static enum ucode_state request_microcod
+ enum ucode_state ret = UCODE_NFOUND;
+ const struct firmware *fw;
+
++ if (force_minrev)
++ return UCODE_NFOUND;
++
+ if (c->x86 >= 0x15)
+ snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -46,6 +46,9 @@
+ static struct microcode_ops *microcode_ops;
+ bool dis_ucode_ldr = true;
+
++bool force_minrev = IS_ENABLED(CONFIG_MICROCODE_LATE_FORCE_MINREV);
++module_param(force_minrev, bool, S_IRUSR | S_IWUSR);
++
+ /*
+ * Synchronization.
+ *
+@@ -531,15 +534,17 @@ static int load_cpus_stopped(void *unuse
+ return 0;
+ }
+
+-static int load_late_stop_cpus(void)
++static int load_late_stop_cpus(bool is_safe)
+ {
+ unsigned int cpu, updated = 0, failed = 0, timedout = 0, siblings = 0;
+ unsigned int nr_offl, offline = 0;
+ int old_rev = boot_cpu_data.microcode;
+ struct cpuinfo_x86 prev_info;
+
+- pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
+- pr_err("You should switch to early loading, if possible.\n");
++ if (!is_safe) {
++ pr_err("Late microcode loading without minimal revision check.\n");
++ pr_err("You should switch to early loading, if possible.\n");
++ }
+
+ atomic_set(&late_cpus_in, num_online_cpus());
+ atomic_set(&offline_in_nmi, 0);
+@@ -589,7 +594,9 @@ static int load_late_stop_cpus(void)
+ return -EIO;
+ }
+
+- add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
++ if (!is_safe || failed || timedout)
++ add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
++
+ pr_info("load: updated on %u primary CPUs with %u siblings\n", updated, siblings);
+ if (failed || timedout) {
+ pr_err("load incomplete. %u CPUs timed out or failed\n",
+@@ -679,7 +686,9 @@ static int load_late_locked(void)
+
+ switch (microcode_ops->request_microcode_fw(0, µcode_pdev->dev)) {
+ case UCODE_NEW:
+- return load_late_stop_cpus();
++ return load_late_stop_cpus(false);
++ case UCODE_NEW_SAFE:
++ return load_late_stop_cpus(true);
+ case UCODE_NFOUND:
+ return -ENOENT;
+ default:
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -480,6 +480,9 @@ static enum ucode_state parse_microcode_
+ unsigned int curr_mc_size = 0;
+ u8 *new_mc = NULL, *mc = NULL;
+
++ if (force_minrev)
++ return UCODE_NFOUND;
++
+ while (iov_iter_count(iter)) {
+ struct microcode_header_intel mc_header;
+ unsigned int mc_size, data_size;
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -13,6 +13,7 @@ struct device;
+ enum ucode_state {
+ UCODE_OK = 0,
+ UCODE_NEW,
++ UCODE_NEW_SAFE,
+ UCODE_UPDATED,
+ UCODE_NFOUND,
+ UCODE_ERROR,
+@@ -88,6 +89,7 @@ static inline unsigned int x86_cpuid_fam
+ }
+
+ extern bool dis_ucode_ldr;
++extern bool force_minrev;
+
+ #ifdef CONFIG_CPU_SUP_AMD
+ void load_ucode_amd_bsp(unsigned int family);
--- /dev/null
+From 27c67e37da3074932dc5811ec05c30fdeaab8939 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:06 +0200
+Subject: x86/microcode: Protect against instrumentation
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 1582c0f4a21303792f523fe2839dd8433ee630c0 upstream
+
+The wait for control loop in which the siblings are waiting for the
+microcode update on the primary thread must be protected against
+instrumentation as instrumentation can end up in #INT3, #DB or #PF,
+which then returns with IRET. That IRET reenables NMI which is the
+opposite of what the NMI rendezvous is trying to achieve.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.545969323@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 111 ++++++++++++++++++++++++++---------
+ 1 file changed, 83 insertions(+), 28 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -272,54 +272,65 @@ struct microcode_ctrl {
+
+ DEFINE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+ static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
++static unsigned int loops_per_usec;
+ static atomic_t late_cpus_in;
+
+-static bool wait_for_cpus(atomic_t *cnt)
++static noinstr bool wait_for_cpus(atomic_t *cnt)
+ {
+- unsigned int timeout;
++ unsigned int timeout, loops;
+
+- WARN_ON_ONCE(atomic_dec_return(cnt) < 0);
++ WARN_ON_ONCE(raw_atomic_dec_return(cnt) < 0);
+
+ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
+- if (!atomic_read(cnt))
++ if (!raw_atomic_read(cnt))
+ return true;
+
+- udelay(1);
++ for (loops = 0; loops < loops_per_usec; loops++)
++ cpu_relax();
+
+ /* If invoked directly, tickle the NMI watchdog */
+- if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC))
++ if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {
++ instrumentation_begin();
+ touch_nmi_watchdog();
++ instrumentation_end();
++ }
+ }
+ /* Prevent the late comers from making progress and let them time out */
+- atomic_inc(cnt);
++ raw_atomic_inc(cnt);
+ return false;
+ }
+
+-static bool wait_for_ctrl(void)
++static noinstr bool wait_for_ctrl(void)
+ {
+- unsigned int timeout;
++ unsigned int timeout, loops;
+
+ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
+- if (this_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)
++ if (raw_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)
+ return true;
+- udelay(1);
++
++ for (loops = 0; loops < loops_per_usec; loops++)
++ cpu_relax();
++
+ /* If invoked directly, tickle the NMI watchdog */
+- if (!microcode_ops->use_nmi && !(timeout % 1000))
++ if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC)) {
++ instrumentation_begin();
+ touch_nmi_watchdog();
++ instrumentation_end();
++ }
+ }
+ return false;
+ }
+
+-static void load_secondary(unsigned int cpu)
++/*
++ * Protected against instrumentation up to the point where the primary
++ * thread completed the update. See microcode_nmi_handler() for details.
++ */
++static noinstr bool load_secondary_wait(unsigned int ctrl_cpu)
+ {
+- unsigned int ctrl_cpu = this_cpu_read(ucode_ctrl.ctrl_cpu);
+- enum ucode_state ret;
+-
+ /* Initial rendezvous to ensure that all CPUs have arrived */
+ if (!wait_for_cpus(&late_cpus_in)) {
+- pr_err_once("load: %d CPUs timed out\n", atomic_read(&late_cpus_in) - 1);
+- this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
+- return;
++ raw_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
++ return false;
+ }
+
+ /*
+@@ -329,9 +340,33 @@ static void load_secondary(unsigned int
+ * scheduler, watchdogs etc. There is no way to safely evacuate the
+ * machine.
+ */
+- if (!wait_for_ctrl())
+- panic("Microcode load: Primary CPU %d timed out\n", ctrl_cpu);
++ if (wait_for_ctrl())
++ return true;
++
++ instrumentation_begin();
++ panic("Microcode load: Primary CPU %d timed out\n", ctrl_cpu);
++ instrumentation_end();
++}
+
++/*
++ * Protected against instrumentation up to the point where the primary
++ * thread completed the update. See microcode_nmi_handler() for details.
++ */
++static noinstr void load_secondary(unsigned int cpu)
++{
++ unsigned int ctrl_cpu = raw_cpu_read(ucode_ctrl.ctrl_cpu);
++ enum ucode_state ret;
++
++ if (!load_secondary_wait(ctrl_cpu)) {
++ instrumentation_begin();
++ pr_err_once("load: %d CPUs timed out\n",
++ atomic_read(&late_cpus_in) - 1);
++ instrumentation_end();
++ return;
++ }
++
++ /* Primary thread completed. Allow to invoke instrumentable code */
++ instrumentation_begin();
+ /*
+ * If the primary succeeded then invoke the apply() callback,
+ * otherwise copy the state from the primary thread.
+@@ -343,6 +378,7 @@ static void load_secondary(unsigned int
+
+ this_cpu_write(ucode_ctrl.result, ret);
+ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
++ instrumentation_end();
+ }
+
+ static void load_primary(unsigned int cpu)
+@@ -380,25 +416,43 @@ static void load_primary(unsigned int cp
+ }
+ }
+
+-static bool microcode_update_handler(void)
++static noinstr bool microcode_update_handler(void)
+ {
+- unsigned int cpu = smp_processor_id();
++ unsigned int cpu = raw_smp_processor_id();
+
+- if (this_cpu_read(ucode_ctrl.ctrl_cpu) == cpu)
++ if (raw_cpu_read(ucode_ctrl.ctrl_cpu) == cpu) {
++ instrumentation_begin();
+ load_primary(cpu);
+- else
++ instrumentation_end();
++ } else {
+ load_secondary(cpu);
++ }
+
++ instrumentation_begin();
+ touch_nmi_watchdog();
++ instrumentation_end();
++
+ return true;
+ }
+
+-bool microcode_nmi_handler(void)
++/*
++ * Protection against instrumentation is required for CPUs which are not
++ * safe against an NMI which is delivered to the secondary SMT sibling
++ * while the primary thread updates the microcode. Instrumentation can end
++ * up in #INT3, #DB and #PF. The IRET from those exceptions reenables NMI
++ * which is the opposite of what the NMI rendezvous is trying to achieve.
++ *
++ * The primary thread is safe versus instrumentation as the actual
++ * microcode update handles this correctly. It's only the sibling code
++ * path which must be NMI safe until the primary thread completed the
++ * update.
++ */
++bool noinstr microcode_nmi_handler(void)
+ {
+- if (!this_cpu_read(ucode_ctrl.nmi_enabled))
++ if (!raw_cpu_read(ucode_ctrl.nmi_enabled))
+ return false;
+
+- this_cpu_write(ucode_ctrl.nmi_enabled, false);
++ raw_cpu_write(ucode_ctrl.nmi_enabled, false);
+ return microcode_update_handler();
+ }
+
+@@ -425,6 +479,7 @@ static int load_late_stop_cpus(void)
+ pr_err("You should switch to early loading, if possible.\n");
+
+ atomic_set(&late_cpus_in, num_online_cpus());
++ loops_per_usec = loops_per_jiffy / (TICK_NSEC / 1000);
+
+ /*
+ * Take a snapshot before the microcode update in order to compare and
--- /dev/null
+From 284ad8d909ac86b325f5e3a4798e90df4af30d8c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:02 +0200
+Subject: x86/microcode: Provide new control functions
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 6067788f04b1020b316344fe34746f96d594a042 upstream
+
+The current all in one code is unreadable and really not suited for
+adding future features like uniform loading with package or system
+scope.
+
+Provide a set of new control functions which split the handling of the
+primary and secondary CPUs. These will replace the current rendezvous
+all in one function in the next step. This is intentionally a separate
+change because diff makes an complete unreadable mess otherwise.
+
+So the flow separates the primary and the secondary CPUs into their own
+functions which use the control field in the per CPU ucode_ctrl struct.
+
+ primary() secondary()
+ wait_for_all() wait_for_all()
+ apply_ucode() wait_for_release()
+ release() apply_ucode()
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.377922731@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 84 +++++++++++++++++++++++++++++++++++
+ 1 file changed, 84 insertions(+)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -290,6 +290,90 @@ static bool wait_for_cpus(atomic_t *cnt)
+ return false;
+ }
+
++static bool wait_for_ctrl(void)
++{
++ unsigned int timeout;
++
++ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
++ if (this_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)
++ return true;
++ udelay(1);
++ if (!(timeout % 1000))
++ touch_nmi_watchdog();
++ }
++ return false;
++}
++
++static __maybe_unused void load_secondary(unsigned int cpu)
++{
++ unsigned int ctrl_cpu = this_cpu_read(ucode_ctrl.ctrl_cpu);
++ enum ucode_state ret;
++
++ /* Initial rendezvous to ensure that all CPUs have arrived */
++ if (!wait_for_cpus(&late_cpus_in)) {
++ pr_err_once("load: %d CPUs timed out\n", atomic_read(&late_cpus_in) - 1);
++ this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
++ return;
++ }
++
++ /*
++ * Wait for primary threads to complete. If one of them hangs due
++ * to the update, there is no way out. This is non-recoverable
++ * because the CPU might hold locks or resources and confuse the
++ * scheduler, watchdogs etc. There is no way to safely evacuate the
++ * machine.
++ */
++ if (!wait_for_ctrl())
++ panic("Microcode load: Primary CPU %d timed out\n", ctrl_cpu);
++
++ /*
++ * If the primary succeeded then invoke the apply() callback,
++ * otherwise copy the state from the primary thread.
++ */
++ if (this_cpu_read(ucode_ctrl.ctrl) == SCTRL_APPLY)
++ ret = microcode_ops->apply_microcode(cpu);
++ else
++ ret = per_cpu(ucode_ctrl.result, ctrl_cpu);
++
++ this_cpu_write(ucode_ctrl.result, ret);
++ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
++}
++
++static __maybe_unused void load_primary(unsigned int cpu)
++{
++ struct cpumask *secondaries = topology_sibling_cpumask(cpu);
++ enum sibling_ctrl ctrl;
++ enum ucode_state ret;
++ unsigned int sibling;
++
++ /* Initial rendezvous to ensure that all CPUs have arrived */
++ if (!wait_for_cpus(&late_cpus_in)) {
++ this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
++ pr_err_once("load: %d CPUs timed out\n", atomic_read(&late_cpus_in) - 1);
++ return;
++ }
++
++ ret = microcode_ops->apply_microcode(cpu);
++ this_cpu_write(ucode_ctrl.result, ret);
++ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
++
++ /*
++ * If the update was successful, let the siblings run the apply()
++ * callback. If not, tell them it's done. This also covers the
++ * case where the CPU has uniform loading at package or system
++ * scope implemented but does not advertise it.
++ */
++ if (ret == UCODE_UPDATED || ret == UCODE_OK)
++ ctrl = SCTRL_APPLY;
++ else
++ ctrl = SCTRL_DONE;
++
++ for_each_cpu(sibling, secondaries) {
++ if (sibling != cpu)
++ per_cpu(ucode_ctrl.ctrl, sibling) = ctrl;
++ }
++}
++
+ static int load_cpus_stopped(void *unused)
+ {
+ int cpu = smp_processor_id();
--- /dev/null
+From bcdf3a18c00f084fe58ca11dc7c2e58c7ee1ae49 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 17 Oct 2023 23:23:49 +0200
+Subject: x86/microcode: Remove pointless apply() invocation
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit b48b26f992a3828b4ae274669f99ce68451d4904 upstream
+
+Microcode is applied on the APs during early bringup. There is no point
+in trying to apply the microcode again during the hotplug operations and
+neither at the point where the microcode device is initialized.
+
+Collect CPU info and microcode revision in setup_online_cpu() for now.
+This will move to the CPU hotplug callback later.
+
+ [ bp: Leave the starting notifier for the following scenario:
+
+ - boot, late load, suspend to disk, resume
+
+ without the starting notifier, only the last core manages to update the
+ microcode upon resume:
+
+ # rdmsr -a 0x8b
+ 10000bf
+ 10000bf
+ 10000bf
+ 10000bf
+ 10000bf
+ 10000dc <----
+
+ This is on an AMD F10h machine.
+
+ For the future, one should check whether potential unification of
+ the CPU init path could cover the resume path too so that this can
+ be simplified even more.
+
+ tglx: This is caused by the odd handling of APs which try to find the
+ microcode blob in builtin or initrd instead of caching the microcode
+ blob during early init before the APs are brought up. Will be cleaned
+ up in a later step. ]
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20231017211723.018821624@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 23 ++++++-----------------
+ 1 file changed, 6 insertions(+), 17 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -493,17 +493,6 @@ static void microcode_fini_cpu(int cpu)
+ microcode_ops->microcode_fini_cpu(cpu);
+ }
+
+-static enum ucode_state microcode_init_cpu(int cpu)
+-{
+- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+-
+- memset(uci, 0, sizeof(*uci));
+-
+- microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
+-
+- return microcode_ops->apply_microcode(cpu);
+-}
+-
+ /**
+ * microcode_bsp_resume - Update boot CPU microcode during resume.
+ */
+@@ -558,14 +547,14 @@ static int mc_cpu_down_prep(unsigned int
+ static void setup_online_cpu(struct work_struct *work)
+ {
+ int cpu = smp_processor_id();
+- enum ucode_state err;
++ struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+- err = microcode_init_cpu(cpu);
+- if (err == UCODE_ERROR) {
+- pr_err("Error applying microcode on CPU%d\n", cpu);
+- return;
+- }
++ memset(uci, 0, sizeof(*uci));
+
++ microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
++ cpu_data(cpu).microcode = uci->cpu_sig.rev;
++ if (!cpu)
++ boot_cpu_data.microcode = uci->cpu_sig.rev;
+ mc_cpu_online(cpu);
+ }
+
--- /dev/null
+From 1b3dbb4473d085a7845d6348b8838c4796dde230 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:05 +0200
+Subject: x86/microcode: Rendezvous and load in NMI
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 7eb314a22800457396f541c655697dabd71e44a7 upstream
+
+stop_machine() does not prevent the spin-waiting sibling from handling
+an NMI, which is obviously violating the whole concept of rendezvous.
+
+Implement a static branch right in the beginning of the NMI handler
+which is nopped out except when enabled by the late loading mechanism.
+
+The late loader enables the static branch before stop_machine() is
+invoked. Each CPU has an nmi_enable in its control structure which
+indicates whether the CPU should go into the update routine.
+
+This is required to bridge the gap between enabling the branch and
+actually being at the point where it is required to enter the loader
+wait loop.
+
+Each CPU which arrives in the stopper thread function sets that flag and
+issues a self NMI right after that. If the NMI function sees the flag
+clear, it returns. If it's set it clears the flag and enters the
+rendezvous.
+
+This is safe against a real NMI which hits in between setting the flag
+and sending the NMI to itself. The real NMI will be swallowed by the
+microcode update and the self NMI will then let stuff continue.
+Otherwise this would end up with a spurious NMI.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.489900814@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/microcode.h | 12 ++++++++
+ arch/x86/kernel/cpu/microcode/core.c | 42 ++++++++++++++++++++++++++++---
+ arch/x86/kernel/cpu/microcode/intel.c | 1
+ arch/x86/kernel/cpu/microcode/internal.h | 3 +-
+ arch/x86/kernel/nmi.c | 4 ++
+ 5 files changed, 57 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/include/asm/microcode.h
++++ b/arch/x86/include/asm/microcode.h
+@@ -70,4 +70,16 @@ static inline u32 intel_get_microcode_re
+ }
+ #endif /* !CONFIG_CPU_SUP_INTEL */
+
++bool microcode_nmi_handler(void);
++
++#ifdef CONFIG_MICROCODE_LATE_LOADING
++DECLARE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
++static __always_inline bool microcode_nmi_handler_enabled(void)
++{
++ return static_branch_unlikely(µcode_nmi_handler_enable);
++}
++#else
++static __always_inline bool microcode_nmi_handler_enabled(void) { return false; }
++#endif
++
+ #endif /* _ASM_X86_MICROCODE_H */
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -23,6 +23,7 @@
+ #include <linux/miscdevice.h>
+ #include <linux/capability.h>
+ #include <linux/firmware.h>
++#include <linux/cpumask.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+ #include <linux/mutex.h>
+@@ -31,6 +32,7 @@
+ #include <linux/fs.h>
+ #include <linux/mm.h>
+
++#include <asm/apic.h>
+ #include <asm/cpu_device_id.h>
+ #include <asm/perf_event.h>
+ #include <asm/processor.h>
+@@ -265,8 +267,10 @@ struct microcode_ctrl {
+ enum sibling_ctrl ctrl;
+ enum ucode_state result;
+ unsigned int ctrl_cpu;
++ bool nmi_enabled;
+ };
+
++DEFINE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
+ static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
+ static atomic_t late_cpus_in;
+
+@@ -282,7 +286,8 @@ static bool wait_for_cpus(atomic_t *cnt)
+
+ udelay(1);
+
+- if (!(timeout % USEC_PER_MSEC))
++ /* If invoked directly, tickle the NMI watchdog */
++ if (!microcode_ops->use_nmi && !(timeout % USEC_PER_MSEC))
+ touch_nmi_watchdog();
+ }
+ /* Prevent the late comers from making progress and let them time out */
+@@ -298,7 +303,8 @@ static bool wait_for_ctrl(void)
+ if (this_cpu_read(ucode_ctrl.ctrl) != SCTRL_WAIT)
+ return true;
+ udelay(1);
+- if (!(timeout % 1000))
++ /* If invoked directly, tickle the NMI watchdog */
++ if (!microcode_ops->use_nmi && !(timeout % 1000))
+ touch_nmi_watchdog();
+ }
+ return false;
+@@ -374,7 +380,7 @@ static void load_primary(unsigned int cp
+ }
+ }
+
+-static int load_cpus_stopped(void *unused)
++static bool microcode_update_handler(void)
+ {
+ unsigned int cpu = smp_processor_id();
+
+@@ -383,7 +389,29 @@ static int load_cpus_stopped(void *unuse
+ else
+ load_secondary(cpu);
+
+- /* No point to wait here. The CPUs will all wait in stop_machine(). */
++ touch_nmi_watchdog();
++ return true;
++}
++
++bool microcode_nmi_handler(void)
++{
++ if (!this_cpu_read(ucode_ctrl.nmi_enabled))
++ return false;
++
++ this_cpu_write(ucode_ctrl.nmi_enabled, false);
++ return microcode_update_handler();
++}
++
++static int load_cpus_stopped(void *unused)
++{
++ if (microcode_ops->use_nmi) {
++ /* Enable the NMI handler and raise NMI */
++ this_cpu_write(ucode_ctrl.nmi_enabled, true);
++ apic->send_IPI(smp_processor_id(), NMI_VECTOR);
++ } else {
++ /* Just invoke the handler directly */
++ microcode_update_handler();
++ }
+ return 0;
+ }
+
+@@ -404,8 +432,14 @@ static int load_late_stop_cpus(void)
+ */
+ store_cpu_caps(&prev_info);
+
++ if (microcode_ops->use_nmi)
++ static_branch_enable_cpuslocked(µcode_nmi_handler_enable);
++
+ stop_machine_cpuslocked(load_cpus_stopped, NULL, cpu_online_mask);
+
++ if (microcode_ops->use_nmi)
++ static_branch_disable_cpuslocked(µcode_nmi_handler_enable);
++
+ /* Analyze the results */
+ for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) {
+ switch (per_cpu(ucode_ctrl.result, cpu)) {
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -611,6 +611,7 @@ static struct microcode_ops microcode_in
+ .collect_cpu_info = collect_cpu_info,
+ .apply_microcode = apply_microcode_late,
+ .finalize_late_load = finalize_late_load,
++ .use_nmi = IS_ENABLED(CONFIG_X86_64),
+ };
+
+ static __init void calc_llc_size_per_core(struct cpuinfo_x86 *c)
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -31,7 +31,8 @@ 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);
+- unsigned int nmi_safe : 1;
++ unsigned int nmi_safe : 1,
++ use_nmi : 1;
+ };
+
+ extern struct ucode_cpu_info ucode_cpu_info[];
+--- a/arch/x86/kernel/nmi.c
++++ b/arch/x86/kernel/nmi.c
+@@ -33,6 +33,7 @@
+ #include <asm/reboot.h>
+ #include <asm/cache.h>
+ #include <asm/nospec-branch.h>
++#include <asm/microcode.h>
+ #include <asm/sev.h>
+
+ #define CREATE_TRACE_POINTS
+@@ -343,6 +344,9 @@ static noinstr void default_do_nmi(struc
+
+ instrumentation_begin();
+
++ if (microcode_nmi_handler_enabled() && microcode_nmi_handler())
++ goto out;
++
+ handled = nmi_handle(NMI_LOCAL, regs);
+ __this_cpu_add(nmi_stats.normal, handled);
+ if (handled) {
--- /dev/null
+From 305f7001fdf2d3452a142a0afb726f180e664c95 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 14:00:03 +0200
+Subject: x86/microcode: Replace the all-in-one rendevous handler
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 0bf871651211b58c7b19f40b746b646d5311e2ec upstream
+
+with a new handler which just separates the control flow of primary and
+secondary CPUs.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.433704135@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 51 ++++++-----------------------------
+ 1 file changed, 9 insertions(+), 42 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -268,7 +268,7 @@ struct microcode_ctrl {
+ };
+
+ static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl);
+-static atomic_t late_cpus_in, late_cpus_out;
++static atomic_t late_cpus_in;
+
+ static bool wait_for_cpus(atomic_t *cnt)
+ {
+@@ -304,7 +304,7 @@ static bool wait_for_ctrl(void)
+ return false;
+ }
+
+-static __maybe_unused void load_secondary(unsigned int cpu)
++static void load_secondary(unsigned int cpu)
+ {
+ unsigned int ctrl_cpu = this_cpu_read(ucode_ctrl.ctrl_cpu);
+ enum ucode_state ret;
+@@ -339,7 +339,7 @@ static __maybe_unused void load_secondar
+ this_cpu_write(ucode_ctrl.ctrl, SCTRL_DONE);
+ }
+
+-static __maybe_unused void load_primary(unsigned int cpu)
++static void load_primary(unsigned int cpu)
+ {
+ struct cpumask *secondaries = topology_sibling_cpumask(cpu);
+ enum sibling_ctrl ctrl;
+@@ -376,46 +376,14 @@ static __maybe_unused void load_primary(
+
+ static int load_cpus_stopped(void *unused)
+ {
+- int cpu = smp_processor_id();
+- enum ucode_state ret;
+-
+- /*
+- * Wait for all CPUs to arrive. A load will not be attempted unless all
+- * CPUs show up.
+- * */
+- if (!wait_for_cpus(&late_cpus_in)) {
+- this_cpu_write(ucode_ctrl.result, UCODE_TIMEOUT);
+- return 0;
+- }
+-
+- /*
+- * On an SMT system, it suffices to load the microcode on one sibling of
+- * the core because the microcode engine is shared between the threads.
+- * Synchronization still needs to take place so that no concurrent
+- * loading attempts happen on multiple threads of an SMT core. See
+- * below.
+- */
+- if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
+- goto wait_for_siblings;
++ unsigned int cpu = smp_processor_id();
+
+- ret = microcode_ops->apply_microcode(cpu);
+- this_cpu_write(ucode_ctrl.result, ret);
+-
+-wait_for_siblings:
+- if (!wait_for_cpus(&late_cpus_out))
+- panic("Timeout during microcode update!\n");
+-
+- /*
+- * At least one thread has completed update on each core.
+- * For others, simply call the update to make sure the
+- * per-cpu cpuinfo can be updated with right microcode
+- * revision.
+- */
+- if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
+- return 0;
++ if (this_cpu_read(ucode_ctrl.ctrl_cpu) == cpu)
++ load_primary(cpu);
++ else
++ load_secondary(cpu);
+
+- ret = microcode_ops->apply_microcode(cpu);
+- this_cpu_write(ucode_ctrl.result, ret);
++ /* No point to wait here. The CPUs will all wait in stop_machine(). */
+ return 0;
+ }
+
+@@ -429,7 +397,6 @@ static int load_late_stop_cpus(void)
+ pr_err("You should switch to early loading, if possible.\n");
+
+ atomic_set(&late_cpus_in, num_online_cpus());
+- atomic_set(&late_cpus_out, num_online_cpus());
+
+ /*
+ * Take a snapshot before the microcode update in order to compare and
--- /dev/null
+From 343ac1f3a5241bcaf0e50e741ce06f9be092310f Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Nov 2023 22:02:12 +0100
+Subject: x86/microcode: Rework early revisions reporting
+
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+
+commit 080990aa3344123673f686cda2df0d1b0deee046 upstream
+
+The AMD side of the loader issues the microcode revision for each
+logical thread on the system, which can become really noisy on huge
+machines. And doing that doesn't make a whole lot of sense - the
+microcode revision is already in /proc/cpuinfo.
+
+So in case one is interested in the theoretical support of mixed silicon
+steppings on AMD, one can check there.
+
+What is also missing on the AMD side - something which people have
+requested before - is showing the microcode revision the CPU had
+*before* the early update.
+
+So abstract that up in the main code and have the BSP on each vendor
+provide those revision numbers.
+
+Then, dump them only once on driver init.
+
+On Intel, do not dump the patch date - it is not needed.
+
+Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/CAHk-=wg=%2B8rceshMkB4VnKxmRccVLtBLPBawnewZuuqyx5U=3A@mail.gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/amd.c | 39 ++++++++-----------------------
+ arch/x86/kernel/cpu/microcode/core.c | 11 +++++++-
+ arch/x86/kernel/cpu/microcode/intel.c | 17 +++++--------
+ arch/x86/kernel/cpu/microcode/internal.h | 14 +++++++----
+ 4 files changed, 37 insertions(+), 44 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -104,8 +104,6 @@ struct cont_desc {
+ size_t size;
+ };
+
+-static u32 ucode_new_rev;
+-
+ /*
+ * Microcode patch container file is prepended to the initrd in cpio
+ * format. See Documentation/arch/x86/microcode.rst
+@@ -442,12 +440,11 @@ static int __apply_microcode_amd(struct
+ *
+ * Returns true if container found (sets @desc), false otherwise.
+ */
+-static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size)
++static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size)
+ {
+ struct cont_desc desc = { 0 };
+ struct microcode_amd *mc;
+ bool ret = false;
+- u32 rev, dummy;
+
+ desc.cpuid_1_eax = cpuid_1_eax;
+
+@@ -457,22 +454,15 @@ static bool early_apply_microcode(u32 cp
+ if (!mc)
+ return ret;
+
+- native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+-
+ /*
+ * Allow application of the same revision to pick up SMT-specific
+ * changes even if the revision of the other SMT thread is already
+ * up-to-date.
+ */
+- if (rev > mc->hdr.patch_id)
++ if (old_rev > mc->hdr.patch_id)
+ return ret;
+
+- if (!__apply_microcode_amd(mc)) {
+- ucode_new_rev = mc->hdr.patch_id;
+- ret = true;
+- }
+-
+- return ret;
++ return !__apply_microcode_amd(mc);
+ }
+
+ static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
+@@ -506,9 +496,12 @@ static void __init find_blobs_in_contain
+ *ret = cp;
+ }
+
+-void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax)
++void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax)
+ {
+ struct cpio_data cp = { };
++ u32 dummy;
++
++ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy);
+
+ /* Needed in load_microcode_amd() */
+ ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax;
+@@ -517,7 +510,8 @@ void __init load_ucode_amd_bsp(unsigned
+ if (!(cp.data && cp.size))
+ return;
+
+- early_apply_microcode(cpuid_1_eax, cp.data, cp.size);
++ if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size))
++ native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy);
+ }
+
+ static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
+@@ -625,10 +619,8 @@ void reload_ucode_amd(unsigned int cpu)
+ rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+
+ if (rev < mc->hdr.patch_id) {
+- if (!__apply_microcode_amd(mc)) {
+- ucode_new_rev = mc->hdr.patch_id;
+- pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
+- }
++ if (!__apply_microcode_amd(mc))
++ pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
+ }
+ }
+
+@@ -649,8 +641,6 @@ static int collect_cpu_info_amd(int cpu,
+ if (p && (p->patch_id == csig->rev))
+ uci->mc = p->data;
+
+- pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
+-
+ return 0;
+ }
+
+@@ -691,8 +681,6 @@ static enum ucode_state apply_microcode_
+ rev = mc_amd->hdr.patch_id;
+ ret = UCODE_UPDATED;
+
+- pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
+-
+ out:
+ uci->cpu_sig.rev = rev;
+ c->microcode = rev;
+@@ -935,11 +923,6 @@ struct microcode_ops * __init init_amd_m
+ pr_warn("AMD CPU family 0x%x not supported\n", c->x86);
+ return NULL;
+ }
+-
+- if (ucode_new_rev)
+- pr_info_once("microcode updated early to new patch_level=0x%08x\n",
+- ucode_new_rev);
+-
+ return µcode_amd_ops;
+ }
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -77,6 +77,8 @@ static u32 final_levels[] = {
+ 0, /* T-101 terminator */
+ };
+
++struct early_load_data early_data;
++
+ /*
+ * Check the current patch level on this CPU.
+ *
+@@ -155,9 +157,9 @@ void __init load_ucode_bsp(void)
+ return;
+
+ if (intel)
+- load_ucode_intel_bsp();
++ load_ucode_intel_bsp(&early_data);
+ else
+- load_ucode_amd_bsp(cpuid_1_eax);
++ load_ucode_amd_bsp(&early_data, cpuid_1_eax);
+ }
+
+ void load_ucode_ap(void)
+@@ -828,6 +830,11 @@ static int __init microcode_init(void)
+ if (!microcode_ops)
+ return -ENODEV;
+
++ pr_info_once("Current revision: 0x%08x\n", (early_data.new_rev ?: early_data.old_rev));
++
++ if (early_data.new_rev)
++ pr_info_once("Updated early from: 0x%08x\n", early_data.old_rev);
++
+ microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0);
+ if (IS_ERR(microcode_pdev))
+ return PTR_ERR(microcode_pdev);
+--- a/arch/x86/kernel/cpu/microcode/intel.c
++++ b/arch/x86/kernel/cpu/microcode/intel.c
+@@ -339,16 +339,9 @@ static enum ucode_state __apply_microcod
+ static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
+ {
+ struct microcode_intel *mc = uci->mc;
+- enum ucode_state ret;
+- u32 cur_rev, date;
++ u32 cur_rev;
+
+- ret = __apply_microcode(uci, mc, &cur_rev);
+- if (ret == UCODE_UPDATED) {
+- date = mc->hdr.date;
+- pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
+- cur_rev, mc->hdr.rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
+- }
+- return ret;
++ return __apply_microcode(uci, mc, &cur_rev);
+ }
+
+ static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
+@@ -413,13 +406,17 @@ static int __init save_builtin_microcode
+ early_initcall(save_builtin_microcode);
+
+ /* Load microcode on BSP from initrd or builtin blobs */
+-void __init load_ucode_intel_bsp(void)
++void __init load_ucode_intel_bsp(struct early_load_data *ed)
+ {
+ struct ucode_cpu_info uci;
+
++ ed->old_rev = intel_get_microcode_revision();
++
+ uci.mc = get_microcode_blob(&uci, false);
+ if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED)
+ ucode_patch_va = UCODE_BSP_LOADED;
++
++ ed->new_rev = uci.cpu_sig.rev;
+ }
+
+ void load_ucode_intel_ap(void)
+--- a/arch/x86/kernel/cpu/microcode/internal.h
++++ b/arch/x86/kernel/cpu/microcode/internal.h
+@@ -37,6 +37,12 @@ struct microcode_ops {
+ use_nmi : 1;
+ };
+
++struct early_load_data {
++ u32 old_rev;
++ u32 new_rev;
++};
++
++extern struct early_load_data early_data;
+ extern struct ucode_cpu_info ucode_cpu_info[];
+ struct cpio_data find_microcode_in_initrd(const char *path);
+
+@@ -92,14 +98,14 @@ extern bool dis_ucode_ldr;
+ extern bool force_minrev;
+
+ #ifdef CONFIG_CPU_SUP_AMD
+-void load_ucode_amd_bsp(unsigned int family);
++void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family);
+ void load_ucode_amd_ap(unsigned int family);
+ int save_microcode_in_initrd_amd(unsigned int family);
+ void reload_ucode_amd(unsigned int cpu);
+ struct microcode_ops *init_amd_microcode(void);
+ void exit_amd_microcode(void);
+ #else /* CONFIG_CPU_SUP_AMD */
+-static inline void load_ucode_amd_bsp(unsigned int family) { }
++static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { }
+ static inline void load_ucode_amd_ap(unsigned int family) { }
+ static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
+ static inline void reload_ucode_amd(unsigned int cpu) { }
+@@ -108,12 +114,12 @@ static inline void exit_amd_microcode(vo
+ #endif /* !CONFIG_CPU_SUP_AMD */
+
+ #ifdef CONFIG_CPU_SUP_INTEL
+-void load_ucode_intel_bsp(void);
++void load_ucode_intel_bsp(struct early_load_data *ed);
+ void load_ucode_intel_ap(void);
+ void reload_ucode_intel(void);
+ struct microcode_ops *init_intel_microcode(void);
+ #else /* CONFIG_CPU_SUP_INTEL */
+-static inline void load_ucode_intel_bsp(void) { }
++static inline void load_ucode_intel_bsp(struct early_load_data *ed) { }
+ static inline void load_ucode_intel_ap(void) { }
+ static inline void reload_ucode_intel(void) { }
+ static inline struct microcode_ops *init_intel_microcode(void) { return NULL; }
--- /dev/null
+From 14dd21cf8c2a8ecf32f7c4cd986675eff64de4ed Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Mon, 2 Oct 2023 13:59:59 +0200
+Subject: x86/microcode: Sanitize __wait_for_cpus()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit 0772b9aa1a8f7322dce8588c231cff8b57298a53 upstream
+
+The code is too complicated for no reason:
+
+ - The return value is pointless as this is a strict boolean.
+
+ - It's way simpler to count down from num_online_cpus() and check for
+ zero.
+
+ - The timeout argument is pointless as this is always one second.
+
+ - Touching the NMI watchdog every 100ns does not make any sense, neither
+ does checking every 100ns. This is really not a hotpath operation.
+
+Preload the atomic counter with the number of online CPUs and simplify the
+whole timeout logic. Delay for one microsecond and touch the NMI watchdog
+once per millisecond.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20231002115903.204251527@linutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kernel/cpu/microcode/core.c | 39 +++++++++++++++--------------------
+ 1 file changed, 17 insertions(+), 22 deletions(-)
+
+--- a/arch/x86/kernel/cpu/microcode/core.c
++++ b/arch/x86/kernel/cpu/microcode/core.c
+@@ -252,31 +252,26 @@ static struct platform_device *microcode
+ * requirement can be relaxed in the future. Right now, this is conservative
+ * and good.
+ */
+-#define SPINUNIT 100 /* 100 nsec */
++static atomic_t late_cpus_in, late_cpus_out;
+
+-
+-static atomic_t late_cpus_in;
+-static atomic_t late_cpus_out;
+-
+-static int __wait_for_cpus(atomic_t *t, long long timeout)
++static bool wait_for_cpus(atomic_t *cnt)
+ {
+- int all_cpus = num_online_cpus();
++ unsigned int timeout;
+
+- atomic_inc(t);
++ WARN_ON_ONCE(atomic_dec_return(cnt) < 0);
+
+- while (atomic_read(t) < all_cpus) {
+- if (timeout < SPINUNIT) {
+- pr_err("Timeout while waiting for CPUs rendezvous, remaining: %d\n",
+- all_cpus - atomic_read(t));
+- return 1;
+- }
++ for (timeout = 0; timeout < USEC_PER_SEC; timeout++) {
++ if (!atomic_read(cnt))
++ return true;
+
+- ndelay(SPINUNIT);
+- timeout -= SPINUNIT;
++ udelay(1);
+
+- touch_nmi_watchdog();
++ if (!(timeout % USEC_PER_MSEC))
++ touch_nmi_watchdog();
+ }
+- return 0;
++ /* Prevent the late comers from making progress and let them time out */
++ atomic_inc(cnt);
++ return false;
+ }
+
+ /*
+@@ -294,7 +289,7 @@ static int __reload_late(void *info)
+ * Wait for all CPUs to arrive. A load will not be attempted unless all
+ * CPUs show up.
+ * */
+- if (__wait_for_cpus(&late_cpus_in, NSEC_PER_SEC))
++ if (!wait_for_cpus(&late_cpus_in))
+ return -1;
+
+ /*
+@@ -317,7 +312,7 @@ static int __reload_late(void *info)
+ }
+
+ wait_for_siblings:
+- if (__wait_for_cpus(&late_cpus_out, NSEC_PER_SEC))
++ if (!wait_for_cpus(&late_cpus_out))
+ panic("Timeout during microcode update!\n");
+
+ /*
+@@ -344,8 +339,8 @@ static int microcode_reload_late(void)
+ pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
+ pr_err("You should switch to early loading, if possible.\n");
+
+- atomic_set(&late_cpus_in, 0);
+- atomic_set(&late_cpus_out, 0);
++ atomic_set(&late_cpus_in, num_online_cpus());
++ atomic_set(&late_cpus_out, num_online_cpus());
+
+ /*
+ * Take a snapshot before the microcode update in order to compare and