diff options
Diffstat (limited to 'arch/x86/kernel/cpu/microcode/amd_early.c')
| -rw-r--r-- | arch/x86/kernel/cpu/microcode/amd_early.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/microcode/amd_early.c b/arch/x86/kernel/cpu/microcode/amd_early.c index 7aa1acc79789..06674473b0e6 100644 --- a/arch/x86/kernel/cpu/microcode/amd_early.c +++ b/arch/x86/kernel/cpu/microcode/amd_early.c | |||
| @@ -108,12 +108,13 @@ static size_t compute_container_size(u8 *data, u32 total_size) | |||
| 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in | 108 | * load_microcode_amd() to save equivalent cpu table and microcode patches in |
| 109 | * kernel heap memory. | 109 | * kernel heap memory. |
| 110 | */ | 110 | */ |
| 111 | static void apply_ucode_in_initrd(void *ucode, size_t size) | 111 | static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch) |
| 112 | { | 112 | { |
| 113 | struct equiv_cpu_entry *eq; | 113 | struct equiv_cpu_entry *eq; |
| 114 | size_t *cont_sz; | 114 | size_t *cont_sz; |
| 115 | u32 *header; | 115 | u32 *header; |
| 116 | u8 *data, **cont; | 116 | u8 *data, **cont; |
| 117 | u8 (*patch)[PATCH_MAX_SIZE]; | ||
| 117 | u16 eq_id = 0; | 118 | u16 eq_id = 0; |
| 118 | int offset, left; | 119 | int offset, left; |
| 119 | u32 rev, eax, ebx, ecx, edx; | 120 | u32 rev, eax, ebx, ecx, edx; |
| @@ -123,10 +124,12 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
| 123 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); | 124 | new_rev = (u32 *)__pa_nodebug(&ucode_new_rev); |
| 124 | cont_sz = (size_t *)__pa_nodebug(&container_size); | 125 | cont_sz = (size_t *)__pa_nodebug(&container_size); |
| 125 | cont = (u8 **)__pa_nodebug(&container); | 126 | cont = (u8 **)__pa_nodebug(&container); |
| 127 | patch = (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch); | ||
| 126 | #else | 128 | #else |
| 127 | new_rev = &ucode_new_rev; | 129 | new_rev = &ucode_new_rev; |
| 128 | cont_sz = &container_size; | 130 | cont_sz = &container_size; |
| 129 | cont = &container; | 131 | cont = &container; |
| 132 | patch = &amd_ucode_patch; | ||
| 130 | #endif | 133 | #endif |
| 131 | 134 | ||
| 132 | data = ucode; | 135 | data = ucode; |
| @@ -213,9 +216,9 @@ static void apply_ucode_in_initrd(void *ucode, size_t size) | |||
| 213 | rev = mc->hdr.patch_id; | 216 | rev = mc->hdr.patch_id; |
| 214 | *new_rev = rev; | 217 | *new_rev = rev; |
| 215 | 218 | ||
| 216 | /* save ucode patch */ | 219 | if (save_patch) |
| 217 | memcpy(amd_ucode_patch, mc, | 220 | memcpy(patch, mc, |
| 218 | min_t(u32, header[1], PATCH_MAX_SIZE)); | 221 | min_t(u32, header[1], PATCH_MAX_SIZE)); |
| 219 | } | 222 | } |
| 220 | } | 223 | } |
| 221 | 224 | ||
| @@ -246,7 +249,7 @@ void __init load_ucode_amd_bsp(void) | |||
| 246 | *data = cp.data; | 249 | *data = cp.data; |
| 247 | *size = cp.size; | 250 | *size = cp.size; |
| 248 | 251 | ||
| 249 | apply_ucode_in_initrd(cp.data, cp.size); | 252 | apply_ucode_in_initrd(cp.data, cp.size, true); |
| 250 | } | 253 | } |
| 251 | 254 | ||
| 252 | #ifdef CONFIG_X86_32 | 255 | #ifdef CONFIG_X86_32 |
| @@ -263,7 +266,7 @@ void load_ucode_amd_ap(void) | |||
| 263 | size_t *usize; | 266 | size_t *usize; |
| 264 | void **ucode; | 267 | void **ucode; |
| 265 | 268 | ||
| 266 | mc = (struct microcode_amd *)__pa(amd_ucode_patch); | 269 | mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch); |
| 267 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { | 270 | if (mc->hdr.patch_id && mc->hdr.processor_rev_id) { |
| 268 | __apply_microcode_amd(mc); | 271 | __apply_microcode_amd(mc); |
| 269 | return; | 272 | return; |
| @@ -275,7 +278,7 @@ void load_ucode_amd_ap(void) | |||
| 275 | if (!*ucode || !*usize) | 278 | if (!*ucode || !*usize) |
| 276 | return; | 279 | return; |
| 277 | 280 | ||
| 278 | apply_ucode_in_initrd(*ucode, *usize); | 281 | apply_ucode_in_initrd(*ucode, *usize, false); |
| 279 | } | 282 | } |
| 280 | 283 | ||
| 281 | static void __init collect_cpu_sig_on_bsp(void *arg) | 284 | static void __init collect_cpu_sig_on_bsp(void *arg) |
| @@ -339,7 +342,7 @@ void load_ucode_amd_ap(void) | |||
| 339 | * AP has a different equivalence ID than BSP, looks like | 342 | * AP has a different equivalence ID than BSP, looks like |
| 340 | * mixed-steppings silicon so go through the ucode blob anew. | 343 | * mixed-steppings silicon so go through the ucode blob anew. |
| 341 | */ | 344 | */ |
| 342 | apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size); | 345 | apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false); |
| 343 | } | 346 | } |
| 344 | } | 347 | } |
| 345 | #endif | 348 | #endif |
| @@ -347,7 +350,9 @@ void load_ucode_amd_ap(void) | |||
| 347 | int __init save_microcode_in_initrd_amd(void) | 350 | int __init save_microcode_in_initrd_amd(void) |
| 348 | { | 351 | { |
| 349 | unsigned long cont; | 352 | unsigned long cont; |
| 353 | int retval = 0; | ||
| 350 | enum ucode_state ret; | 354 | enum ucode_state ret; |
| 355 | u8 *cont_va; | ||
| 351 | u32 eax; | 356 | u32 eax; |
| 352 | 357 | ||
| 353 | if (!container) | 358 | if (!container) |
| @@ -355,13 +360,15 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 355 | 360 | ||
| 356 | #ifdef CONFIG_X86_32 | 361 | #ifdef CONFIG_X86_32 |
| 357 | get_bsp_sig(); | 362 | get_bsp_sig(); |
| 358 | cont = (unsigned long)container; | 363 | cont = (unsigned long)container; |
| 364 | cont_va = __va(container); | ||
| 359 | #else | 365 | #else |
| 360 | /* | 366 | /* |
| 361 | * We need the physical address of the container for both bitness since | 367 | * We need the physical address of the container for both bitness since |
| 362 | * boot_params.hdr.ramdisk_image is a physical address. | 368 | * boot_params.hdr.ramdisk_image is a physical address. |
| 363 | */ | 369 | */ |
| 364 | cont = __pa(container); | 370 | cont = __pa(container); |
| 371 | cont_va = container; | ||
| 365 | #endif | 372 | #endif |
| 366 | 373 | ||
| 367 | /* | 374 | /* |
| @@ -372,6 +379,8 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 372 | if (relocated_ramdisk) | 379 | if (relocated_ramdisk) |
| 373 | container = (u8 *)(__va(relocated_ramdisk) + | 380 | container = (u8 *)(__va(relocated_ramdisk) + |
| 374 | (cont - boot_params.hdr.ramdisk_image)); | 381 | (cont - boot_params.hdr.ramdisk_image)); |
| 382 | else | ||
| 383 | container = cont_va; | ||
| 375 | 384 | ||
| 376 | if (ucode_new_rev) | 385 | if (ucode_new_rev) |
| 377 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | 386 | pr_info("microcode: updated early to new patch_level=0x%08x\n", |
| @@ -382,7 +391,7 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 382 | 391 | ||
| 383 | ret = load_microcode_amd(eax, container, container_size); | 392 | ret = load_microcode_amd(eax, container, container_size); |
| 384 | if (ret != UCODE_OK) | 393 | if (ret != UCODE_OK) |
| 385 | return -EINVAL; | 394 | retval = -EINVAL; |
| 386 | 395 | ||
| 387 | /* | 396 | /* |
| 388 | * This will be freed any msec now, stash patches for the current | 397 | * This will be freed any msec now, stash patches for the current |
| @@ -391,5 +400,5 @@ int __init save_microcode_in_initrd_amd(void) | |||
| 391 | container = NULL; | 400 | container = NULL; |
| 392 | container_size = 0; | 401 | container_size = 0; |
| 393 | 402 | ||
| 394 | return 0; | 403 | return retval; |
| 395 | } | 404 | } |
