[PATCH v7 106/120] x86/microcode: Allocate cpuinfo_x86 snapshots on the heap
"Ahmed S. Darwish" <[email protected]> Thu, 28 May 2026 17:39:08 +0200
| Newsgroups | dev.linux.lists.x86-cpuid,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
load_late_stop_cpus() snapshots CPU capabilities before a late microcode update, while microcode_check() snapshots the capabilities again after the update. Both functions allocate their struct cpuinfo_x86 snapshots on the stack. Meanwhile, cpuinfo_x86 contains the parsed CPUID tables where more leaves will be added; resulting in "stack frame length exceeded" warnings. Allocate the before/after cpuinfo_x86 snapshots on the heap. For load_late_stop_cpus(), do the memory allocation before the microcode staging step. This leaves no leaked or stale microcode state in -ENOMEM failure modes. Signed-off-by: Ahmed S. Darwish <[email protected]> --- arch/x86/kernel/cpu/common.c | 11 ++++++++--- arch/x86/kernel/cpu/microcode/core.c | 9 ++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index d78063e4e665..f5e3aaed67ef 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2551,15 +2551,20 @@ void store_cpu_caps(struct cpuinfo_x86 *curr_info) */ void microcode_check(struct cpuinfo_x86 *prev_info) { - struct cpuinfo_x86 curr_info; + struct cpuinfo_x86 *curr_info __free(kfree) = kmalloc_obj(*curr_info); perf_check_microcode(); amd_check_microcode(); - store_cpu_caps(&curr_info); + if (!curr_info) { + pr_warn("x86/CPU: Microcode update CPU capability changes check was skipped (ENOMEM)\n"); + return; + } + + store_cpu_caps(curr_info); - if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability, + if (!memcmp(&prev_info->x86_capability, &curr_info->x86_capability, sizeof(prev_info->x86_capability))) return; diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 56d791aeac4e..7a00671540bc 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -588,16 +588,19 @@ static int load_cpus_stopped(void *unused) static int load_late_stop_cpus(bool is_safe) { + struct cpuinfo_x86 *prev_info __free(kfree) = kmalloc_obj(*prev_info); 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; if (!is_safe) { pr_err("Late microcode loading without minimal revision check.\n"); pr_err("You should switch to early loading, if possible.\n"); } + if (!prev_info) + return -ENOMEM; + /* * Pre-load the microcode image into a staging device. This * process is preemptible and does not require stopping CPUs. @@ -617,7 +620,7 @@ static int load_late_stop_cpus(bool is_safe) * Take a snapshot before the microcode update in order to compare and * check whether any bits changed after an update. */ - store_cpu_caps(&prev_info); + store_cpu_caps(prev_info); if (microcode_ops->use_nmi) static_branch_enable_cpuslocked(µcode_nmi_handler_enable); @@ -666,7 +669,7 @@ static int load_late_stop_cpus(bool is_safe) num_online_cpus() - (updated + siblings)); } pr_info("revision: 0x%x -> 0x%x\n", old_rev, boot_cpu_data.microcode); - microcode_check(&prev_info); + microcode_check(prev_info); return updated + siblings == num_online_cpus() ? 0 : -EIO; } -- 2.54.0