Skip to content

Commit c809b0d

Browse files
committed
x86/microcode/AMD: Flush patch buffer mapping after application
Due to specific requirements while applying microcode patches on Zen1 and 2, the patch buffer mapping needs to be flushed from the TLB after application. Do so. If not, unnecessary and unnatural delays happen in the boot process. Reported-by: Thomas De Schampheleire <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Tested-by: Thomas De Schampheleire <[email protected]> Cc: <[email protected]> # f1d84b5 ("x86/mm: Carve out INVLPG inline asm for use by others") Link: https://lore.kernel.org/r/ZyulbYuvrkshfsd2@antipodes
1 parent f1d84b5 commit c809b0d

File tree

1 file changed

+20
-5
lines changed
  • arch/x86/kernel/cpu/microcode

1 file changed

+20
-5
lines changed

arch/x86/kernel/cpu/microcode/amd.c

+20-5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <asm/setup.h>
3535
#include <asm/cpu.h>
3636
#include <asm/msr.h>
37+
#include <asm/tlb.h>
3738

3839
#include "internal.h"
3940

@@ -483,11 +484,25 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
483484
}
484485
}
485486

486-
static int __apply_microcode_amd(struct microcode_amd *mc)
487+
static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
487488
{
489+
unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
488490
u32 rev, dummy;
489491

490-
native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc->hdr.data_code);
492+
native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
493+
494+
if (x86_family(bsp_cpuid_1_eax) == 0x17) {
495+
unsigned long p_addr_end = p_addr + psize - 1;
496+
497+
invlpg(p_addr);
498+
499+
/*
500+
* Flush next page too if patch image is crossing a page
501+
* boundary.
502+
*/
503+
if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT)
504+
invlpg(p_addr_end);
505+
}
491506

492507
/* verify patch application was successful */
493508
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
@@ -529,7 +544,7 @@ static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
529544
if (old_rev > mc->hdr.patch_id)
530545
return ret;
531546

532-
return !__apply_microcode_amd(mc);
547+
return !__apply_microcode_amd(mc, desc.psize);
533548
}
534549

535550
static bool get_builtin_microcode(struct cpio_data *cp)
@@ -745,7 +760,7 @@ void reload_ucode_amd(unsigned int cpu)
745760
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
746761

747762
if (rev < mc->hdr.patch_id) {
748-
if (!__apply_microcode_amd(mc))
763+
if (!__apply_microcode_amd(mc, p->size))
749764
pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
750765
}
751766
}
@@ -798,7 +813,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
798813
goto out;
799814
}
800815

801-
if (__apply_microcode_amd(mc_amd)) {
816+
if (__apply_microcode_amd(mc_amd, p->size)) {
802817
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
803818
cpu, mc_amd->hdr.patch_id);
804819
return UCODE_ERROR;

0 commit comments

Comments
 (0)