aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/arch/x86/kernel/cpu/microcode/core.c
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2016-10-25 11:55:21 +0200
committerIngo Molnar <mingo@kernel.org>2016-10-25 12:28:59 +0200
commit06b8534cb72837379b3a4781ab252df3d37c2669 (patch)
tree3a7daa56b48067c21556850750b77ed546621916 /arch/x86/kernel/cpu/microcode/core.c
parentx86/microcode/intel: Remove intel_lib.c (diff)
downloadwireguard-linux-06b8534cb72837379b3a4781ab252df3d37c2669.tar.xz
wireguard-linux-06b8534cb72837379b3a4781ab252df3d37c2669.zip
x86/microcode: Rework microcode loading
Yeah, I know, I know, this is a huuge patch and reviewing it is hard. Sorry but this is the only way I could think of in which I can rewrite the microcode patches loading procedure without breaking (knowingly) the driver. So maybe this patch is easier to review if one looks at the files after the patch has been applied instead at the diff. Because then it becomes pretty obvious: * The BSP-loading path - load_ucode_bsp() is working independently from the AP path now and it doesn't save any pointers or patches anymore - it solely parses the builtin or initrd microcode and applies the patch. That's it. This fixes the CONFIG_RANDOMIZE_MEMORY offset fun more solidly. * The AP-loading path - load_ucode_ap() then goes and scans builtin/initrd *again* for the microcode patches but it caches them this time so that we don't have to do that scan on each AP but only once. This simplifies the code considerably. Then, when we save the microcode from the initrd/builtin, we go and add the relevant patches to our own cache. The AMD side did do that and now the Intel side does it too. So no more pointer copying and blabla, we save the microcode patches ourselves and are independent from initrd/builtin. This whole conversion gives us other benefits like unifying the initrd parsing into a single function: find_microcode_in_initrd() is used by both. The diffstat speaks for itself: 456 insertions(+), 695 deletions(-) Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20161025095522.11964-12-bp@alien8.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/cpu/microcode/core.c')
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c63
1 files changed, 56 insertions, 7 deletions
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index f737039d59b2..dd3d64f07364 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -39,6 +39,7 @@
#include <asm/microcode.h>
#include <asm/processor.h>
#include <asm/cmdline.h>
+#include <asm/setup.h>
#define MICROCODE_VERSION "2.01"
@@ -196,6 +197,58 @@ static int __init save_microcode_in_initrd(void)
return -EINVAL;
}
+struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
+{
+#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.
+ */
+ if (size)
+ start = params->hdr.ramdisk_image;
+
+# 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
+
+ /*
+ * Did we relocate the ramdisk?
+ *
+ * So we possibly relocate the ramdisk *after* applying microcode on the
+ * BSP so we rely on use_pa (use physical addresses) - even if it is not
+ * absolutely correct - to determine whether we've done the ramdisk
+ * relocation already.
+ */
+ if (!use_pa && relocated_ramdisk)
+ start = initrd_start;
+
+ return find_cpio_data(path, (void *)start, size, NULL);
+#else /* !CONFIG_BLK_DEV_INITRD */
+ return (struct cpio_data){ NULL, 0, "" };
+#endif
+}
+
void reload_early_microcode(void)
{
int vendor, family;
@@ -455,7 +508,8 @@ static struct attribute_group mc_attr_group = {
static void microcode_fini_cpu(int cpu)
{
- microcode_ops->microcode_fini_cpu(cpu);
+ if (microcode_ops->microcode_fini_cpu)
+ microcode_ops->microcode_fini_cpu(cpu);
}
static enum ucode_state microcode_resume_cpu(int cpu)
@@ -584,12 +638,7 @@ static int mc_cpu_down_prep(unsigned int cpu)
/* Suspend is in progress, only remove the interface */
sysfs_remove_group(&dev->kobj, &mc_attr_group);
pr_debug("CPU%d removed\n", cpu);
- /*
- * When a CPU goes offline, don't free up or invalidate the copy of
- * the microcode in kernel memory, so that we can reuse it when the
- * CPU comes back online without unnecessarily requesting the userspace
- * for it again.
- */
+
return 0;
}