Skip to content

Commit f24f204

Browse files
KAGA-KOKObp3tk0v
authored andcommitted
x86/microcode/intel: Switch to kvmalloc()
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
1 parent 2a1dada commit f24f204

1 file changed

Lines changed: 25 additions & 23 deletions

File tree

  • arch/x86/kernel/cpu/microcode

arch/x86/kernel/cpu/microcode/intel.c

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/earlycpio.h>
1515
#include <linux/firmware.h>
1616
#include <linux/uaccess.h>
17-
#include <linux/vmalloc.h>
1817
#include <linux/initrd.h>
1918
#include <linux/kernel.h>
2019
#include <linux/slab.h>
@@ -245,7 +244,7 @@ EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
245244

246245
static void update_ucode_pointer(struct microcode_intel *mc)
247246
{
248-
kfree(ucode_patch_va);
247+
kvfree(ucode_patch_va);
249248

250249
/*
251250
* Save the virtual address for early loading and for eventual free
@@ -256,11 +255,14 @@ static void update_ucode_pointer(struct microcode_intel *mc)
256255

257256
static void save_microcode_patch(struct microcode_intel *patch)
258257
{
258+
unsigned int size = get_totalsize(&patch->hdr);
259259
struct microcode_intel *mc;
260260

261-
mc = kmemdup(patch, get_totalsize(&patch->hdr), GFP_KERNEL);
261+
mc = kvmemdup(patch, size, GFP_KERNEL);
262262
if (mc)
263263
update_ucode_pointer(mc);
264+
else
265+
pr_err("Unable to allocate microcode memory size: %u\n", size);
264266
}
265267

266268
/* Scan blob for microcode matching the boot CPUs family, model, stepping */
@@ -539,61 +541,61 @@ static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
539541

540542
if (!copy_from_iter_full(&mc_header, sizeof(mc_header), iter)) {
541543
pr_err("error! Truncated or inaccessible header in microcode data file\n");
542-
break;
544+
goto fail;
543545
}
544546

545547
mc_size = get_totalsize(&mc_header);
546548
if (mc_size < sizeof(mc_header)) {
547549
pr_err("error! Bad data in microcode data file (totalsize too small)\n");
548-
break;
550+
goto fail;
549551
}
550-
551552
data_size = mc_size - sizeof(mc_header);
552553
if (data_size > iov_iter_count(iter)) {
553554
pr_err("error! Bad data in microcode data file (truncated file?)\n");
554-
break;
555+
goto fail;
555556
}
556557

557558
/* For performance reasons, reuse mc area when possible */
558559
if (!mc || mc_size > curr_mc_size) {
559-
vfree(mc);
560-
mc = vmalloc(mc_size);
560+
kvfree(mc);
561+
mc = kvmalloc(mc_size, GFP_KERNEL);
561562
if (!mc)
562-
break;
563+
goto fail;
563564
curr_mc_size = mc_size;
564565
}
565566

566567
memcpy(mc, &mc_header, sizeof(mc_header));
567568
data = mc + sizeof(mc_header);
568569
if (!copy_from_iter_full(data, data_size, iter) ||
569-
intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) {
570-
break;
571-
}
570+
intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0)
571+
goto fail;
572572

573573
if (cur_rev >= mc_header.rev)
574574
continue;
575575

576576
if (!intel_find_matching_signature(mc, uci->cpu_sig.sig, uci->cpu_sig.pf))
577577
continue;
578578

579-
vfree(new_mc);
579+
kvfree(new_mc);
580580
cur_rev = mc_header.rev;
581581
new_mc = mc;
582582
mc = NULL;
583583
}
584584

585-
vfree(mc);
586-
587-
if (iov_iter_count(iter)) {
588-
vfree(new_mc);
589-
return UCODE_ERROR;
590-
}
585+
if (iov_iter_count(iter))
586+
goto fail;
591587

588+
kvfree(mc);
592589
if (!new_mc)
593590
return UCODE_NFOUND;
594591

595592
ucode_patch_late = (struct microcode_intel *)new_mc;
596593
return UCODE_NEW;
594+
595+
fail:
596+
kvfree(mc);
597+
kvfree(new_mc);
598+
return UCODE_ERROR;
597599
}
598600

599601
static bool is_blacklisted(unsigned int cpu)
@@ -652,9 +654,9 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device)
652654
static void finalize_late_load(int result)
653655
{
654656
if (!result)
655-
save_microcode_patch(ucode_patch_late);
656-
657-
vfree(ucode_patch_late);
657+
update_ucode_pointer(ucode_patch_late);
658+
else
659+
kvfree(ucode_patch_late);
658660
ucode_patch_late = NULL;
659661
}
660662

0 commit comments

Comments
 (0)