Skip to content

Commit

Permalink
x86/microcode/AMD: Flush patch buffer mapping after application
Browse files Browse the repository at this point in the history
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 <thomas.de_schampheleire@nokia.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
Cc: <stable@kernel.org> # f1d84b5 ("x86/mm: Carve out INVLPG inline asm for use by others")
Link: https://lore.kernel.org/r/ZyulbYuvrkshfsd2@antipodes
  • Loading branch information
Borislav Petkov (AMD) committed Nov 25, 2024
1 parent f1d84b5 commit c809b0d
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions arch/x86/kernel/cpu/microcode/amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <asm/setup.h>
#include <asm/cpu.h>
#include <asm/msr.h>
#include <asm/tlb.h>

#include "internal.h"

Expand Down Expand Up @@ -483,11 +484,25 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
}
}

static int __apply_microcode_amd(struct microcode_amd *mc)
static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
{
unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
u32 rev, dummy;

native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc->hdr.data_code);
native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);

if (x86_family(bsp_cpuid_1_eax) == 0x17) {
unsigned long p_addr_end = p_addr + psize - 1;

invlpg(p_addr);

/*
* Flush next page too if patch image is crossing a page
* boundary.
*/
if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT)
invlpg(p_addr_end);
}

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

return !__apply_microcode_amd(mc);
return !__apply_microcode_amd(mc, desc.psize);
}

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

if (rev < mc->hdr.patch_id) {
if (!__apply_microcode_amd(mc))
if (!__apply_microcode_amd(mc, p->size))
pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
}
}
Expand Down Expand Up @@ -798,7 +813,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
goto out;
}

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

0 comments on commit c809b0d

Please sign in to comment.