diff options
author | Borislav Petkov <bp@suse.de> | 2016-06-06 11:10:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-06-08 05:04:19 -0400 |
commit | 4b703305d98bf7350d4b2953ee39a3aa2eeb1778 (patch) | |
tree | a0d54efdf01453b0a262109e517cc6cd69e773f5 | |
parent | 6c5456474e7f0b63be66d44b0595001e2a8b44d5 (diff) |
x86/microcode: Fix suspend to RAM with builtin microcode
Usually, after we have found the proper microcode blob for the current
machine, we stash it away for later use with save_microcode_in_initrd().
However, with builtin microcode which doesn't come from the initrd, we
don't call that function because CONFIG_BLK_DEV_INITRD=n and even if
set, we don't have a valid initrd.
In order to fix this, let's make save_microcode_in_initrd() an
fs_initcall which runs before rootfs_initcall() as this was the time it
was called previously through:
rootfs_initcall(populate_rootfs)
|-> free_initrd()
|-> free_initrd_mem()
|-> save_microcode_in_initrd()
Also, we make it run independently from initrd functionality being
present or not.
And since it is called in the microcode loader only now, we can also
make it static.
Reported-and-tested-by: Jim Bos <jim876@xs4all.nl>
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: <stable@vger.kernel.org> # v4.6
Cc: Andy Lutomirski <luto@amacapital.net>
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: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1465225850-7352-3-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/include/asm/microcode.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 3 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 7 |
3 files changed, 2 insertions, 10 deletions
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index ca2af7ed6cbf..da0d81fa0b54 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -133,13 +133,11 @@ static inline unsigned int x86_cpuid_family(void) | |||
133 | #ifdef CONFIG_MICROCODE | 133 | #ifdef CONFIG_MICROCODE |
134 | extern void __init load_ucode_bsp(void); | 134 | extern void __init load_ucode_bsp(void); |
135 | extern void load_ucode_ap(void); | 135 | extern void load_ucode_ap(void); |
136 | extern int __init save_microcode_in_initrd(void); | ||
137 | void reload_early_microcode(void); | 136 | void reload_early_microcode(void); |
138 | extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); | 137 | extern bool get_builtin_firmware(struct cpio_data *cd, const char *name); |
139 | #else | 138 | #else |
140 | static inline void __init load_ucode_bsp(void) { } | 139 | static inline void __init load_ucode_bsp(void) { } |
141 | static inline void load_ucode_ap(void) { } | 140 | static inline void load_ucode_ap(void) { } |
142 | static inline int __init save_microcode_in_initrd(void) { return 0; } | ||
143 | static inline void reload_early_microcode(void) { } | 141 | static inline void reload_early_microcode(void) { } |
144 | static inline bool | 142 | static inline bool |
145 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } | 143 | get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; } |
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index ac360bfbbdb6..12823b6ebd6d 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
@@ -175,7 +175,7 @@ void load_ucode_ap(void) | |||
175 | } | 175 | } |
176 | } | 176 | } |
177 | 177 | ||
178 | int __init save_microcode_in_initrd(void) | 178 | static int __init save_microcode_in_initrd(void) |
179 | { | 179 | { |
180 | struct cpuinfo_x86 *c = &boot_cpu_data; | 180 | struct cpuinfo_x86 *c = &boot_cpu_data; |
181 | 181 | ||
@@ -691,4 +691,5 @@ int __init microcode_init(void) | |||
691 | return error; | 691 | return error; |
692 | 692 | ||
693 | } | 693 | } |
694 | fs_initcall(save_microcode_in_initrd); | ||
694 | late_initcall(microcode_init); | 695 | late_initcall(microcode_init); |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 372aad2b3291..dffd162db0a4 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -696,13 +696,6 @@ void free_initmem(void) | |||
696 | void __init free_initrd_mem(unsigned long start, unsigned long end) | 696 | void __init free_initrd_mem(unsigned long start, unsigned long end) |
697 | { | 697 | { |
698 | /* | 698 | /* |
699 | * Remember, initrd memory may contain microcode or other useful things. | ||
700 | * Before we lose initrd mem, we need to find a place to hold them | ||
701 | * now that normal virtual memory is enabled. | ||
702 | */ | ||
703 | save_microcode_in_initrd(); | ||
704 | |||
705 | /* | ||
706 | * end could be not aligned, and We can not align that, | 699 | * end could be not aligned, and We can not align that, |
707 | * decompresser could be confused by aligned initrd_end | 700 | * decompresser could be confused by aligned initrd_end |
708 | * We already reserve the end partial page before in | 701 | * We already reserve the end partial page before in |