diff options
author | Borislav Petkov <bp@suse.de> | 2015-10-12 05:22:41 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-10-12 10:15:48 -0400 |
commit | 2eff73c0a11f19ff082a566e3429fbaaca7b8e7b (patch) | |
tree | 10555b4a753a5c353a505803946db2c5ac071104 | |
parent | fa20a2ed6fff717839ec03b6574ea0affcb58841 (diff) |
x86/microcode/amd: Extract current patch level read to a function
Pave the way for checking the current patch level of the
microcode in a core. We want to be able to do stuff depending on
the patch level - in this case decide whether to update or not.
But that will be added in a later patch.
Drop unused local var uci assignment, while at it.
Integrate a fix for 32-bit and CONFIG_PARAVIRT from Takashi Iwai:
Use native_rdmsr() in check_current_patch_level() because with
CONFIG_PARAVIRT enabled and on 32-bit, where we run before
paging has been enabled, we cannot deref pv_info yet. Or we
could, but we'd need to access its physical address. This way of
fixing it is simpler. See:
https://bugzilla.suse.com/show_bug.cgi?id=943179 for the background.
Signed-off-by: Borislav Petkov <bp@suse.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Takashi Iwai <tiwai@suse.com>:
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Link: http://lkml.kernel.org/r/1444641762-9437-6-git-send-email-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/include/asm/microcode_amd.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 24 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 17 |
3 files changed, 30 insertions, 12 deletions
diff --git a/arch/x86/include/asm/microcode_amd.h b/arch/x86/include/asm/microcode_amd.h index ac6d328977a6..9b214e10d499 100644 --- a/arch/x86/include/asm/microcode_amd.h +++ b/arch/x86/include/asm/microcode_amd.h | |||
@@ -76,4 +76,5 @@ static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; } | |||
76 | void reload_ucode_amd(void) {} | 76 | void reload_ucode_amd(void) {} |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | extern bool check_current_patch_level(u32 *rev); | ||
79 | #endif /* _ASM_X86_MICROCODE_AMD_H */ | 80 | #endif /* _ASM_X86_MICROCODE_AMD_H */ |
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 12829c3ced3c..2d630138bf3e 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
@@ -177,6 +177,25 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size, | |||
177 | return patch_size; | 177 | return patch_size; |
178 | } | 178 | } |
179 | 179 | ||
180 | /* | ||
181 | * Check the current patch level on this CPU. | ||
182 | * | ||
183 | * @rev: Use it to return the patch level. It is set to 0 in the case of | ||
184 | * error. | ||
185 | * | ||
186 | * Returns: | ||
187 | * - true: if update should stop | ||
188 | * - false: otherwise | ||
189 | */ | ||
190 | bool check_current_patch_level(u32 *rev) | ||
191 | { | ||
192 | u32 dummy; | ||
193 | |||
194 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, *rev, dummy); | ||
195 | |||
196 | return false; | ||
197 | } | ||
198 | |||
180 | int __apply_microcode_amd(struct microcode_amd *mc_amd) | 199 | int __apply_microcode_amd(struct microcode_amd *mc_amd) |
181 | { | 200 | { |
182 | u32 rev, dummy; | 201 | u32 rev, dummy; |
@@ -197,7 +216,7 @@ int apply_microcode_amd(int cpu) | |||
197 | struct microcode_amd *mc_amd; | 216 | struct microcode_amd *mc_amd; |
198 | struct ucode_cpu_info *uci; | 217 | struct ucode_cpu_info *uci; |
199 | struct ucode_patch *p; | 218 | struct ucode_patch *p; |
200 | u32 rev, dummy; | 219 | u32 rev; |
201 | 220 | ||
202 | BUG_ON(raw_smp_processor_id() != cpu); | 221 | BUG_ON(raw_smp_processor_id() != cpu); |
203 | 222 | ||
@@ -210,7 +229,8 @@ int apply_microcode_amd(int cpu) | |||
210 | mc_amd = p->data; | 229 | mc_amd = p->data; |
211 | uci->mc = p->data; | 230 | uci->mc = p->data; |
212 | 231 | ||
213 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | 232 | if (check_current_patch_level(&rev)) |
233 | return -1; | ||
214 | 234 | ||
215 | /* need to apply patch? */ | 235 | /* need to apply patch? */ |
216 | if (rev >= mc_amd->hdr.patch_id) { | 236 | if (rev >= mc_amd->hdr.patch_id) { |
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index e8a215a9a345..abb90097582f 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
@@ -196,9 +196,8 @@ static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) | |||
196 | return; | 196 | return; |
197 | } | 197 | } |
198 | 198 | ||
199 | /* find ucode and update if needed */ | 199 | if (check_current_patch_level(&rev)) |
200 | 200 | return; | |
201 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | ||
202 | 201 | ||
203 | while (left > 0) { | 202 | while (left > 0) { |
204 | struct microcode_amd *mc; | 203 | struct microcode_amd *mc; |
@@ -319,7 +318,6 @@ static void __init get_bsp_sig(void) | |||
319 | void load_ucode_amd_ap(void) | 318 | void load_ucode_amd_ap(void) |
320 | { | 319 | { |
321 | unsigned int cpu = smp_processor_id(); | 320 | unsigned int cpu = smp_processor_id(); |
322 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | ||
323 | struct equiv_cpu_entry *eq; | 321 | struct equiv_cpu_entry *eq; |
324 | struct microcode_amd *mc; | 322 | struct microcode_amd *mc; |
325 | u32 rev, eax; | 323 | u32 rev, eax; |
@@ -332,10 +330,8 @@ void load_ucode_amd_ap(void) | |||
332 | if (!container) | 330 | if (!container) |
333 | return; | 331 | return; |
334 | 332 | ||
335 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | 333 | if (check_current_patch_level(&rev)) |
336 | 334 | return; | |
337 | uci->cpu_sig.rev = rev; | ||
338 | uci->cpu_sig.sig = eax; | ||
339 | 335 | ||
340 | eax = cpuid_eax(0x00000001); | 336 | eax = cpuid_eax(0x00000001); |
341 | eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ); | 337 | eq = (struct equiv_cpu_entry *)(container + CONTAINER_HDR_SZ); |
@@ -424,9 +420,10 @@ int __init save_microcode_in_initrd_amd(void) | |||
424 | void reload_ucode_amd(void) | 420 | void reload_ucode_amd(void) |
425 | { | 421 | { |
426 | struct microcode_amd *mc; | 422 | struct microcode_amd *mc; |
427 | u32 rev, eax; | 423 | u32 rev; |
428 | 424 | ||
429 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax); | 425 | if (check_current_patch_level(&rev)) |
426 | return; | ||
430 | 427 | ||
431 | mc = (struct microcode_amd *)amd_ucode_patch; | 428 | mc = (struct microcode_amd *)amd_ucode_patch; |
432 | 429 | ||