Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86/microcode/AMD: Split load_microcode_amd()

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

+18 -9
+18 -9
arch/x86/kernel/cpu/microcode/amd.c
··· 584 584 native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); 585 585 } 586 586 587 - static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); 587 + static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size); 588 588 589 589 static int __init save_microcode_in_initrd(void) 590 590 { ··· 605 605 if (!desc.mc) 606 606 return -EINVAL; 607 607 608 - ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); 608 + ret = _load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size); 609 609 if (ret > UCODE_UPDATED) 610 610 return -EINVAL; 611 611 ··· 954 954 return UCODE_OK; 955 955 } 956 956 957 + static enum ucode_state _load_microcode_amd(u8 family, const u8 *data, size_t size) 958 + { 959 + enum ucode_state ret; 960 + 961 + /* free old equiv table */ 962 + free_equiv_cpu_table(); 963 + 964 + ret = __load_microcode_amd(family, data, size); 965 + if (ret != UCODE_OK) 966 + cleanup(); 967 + 968 + return ret; 969 + } 970 + 957 971 static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size) 958 972 { 959 973 struct cpuinfo_x86 *c; ··· 975 961 struct ucode_patch *p; 976 962 enum ucode_state ret; 977 963 978 - /* free old equiv table */ 979 - free_equiv_cpu_table(); 980 - 981 - ret = __load_microcode_amd(family, data, size); 982 - if (ret != UCODE_OK) { 983 - cleanup(); 964 + ret = _load_microcode_amd(family, data, size); 965 + if (ret != UCODE_OK) 984 966 return ret; 985 - } 986 967 987 968 for_each_node(nid) { 988 969 cpu = cpumask_first(cpumask_of_node(nid));