From 339f39d819538ff808f51a2c28cdb0a2509fda54 Mon Sep 17 00:00:00 2001 From: Liao Xuan Date: Thu, 8 May 2025 23:59:27 -0400 Subject: [PATCH] anolis: x86/microcode/hygon: Fix microcode loading issue for Hygon processors ANBZ: #20923 The commit 0433b8e9f4a2 ("x86/microcode/AMD: Load only SHA256-checksummed patches") and commit bef830144feb ("x86/microcode/AMD: Use the family, model,stepping encoded in the patch ID") carry a SHA256 checksum for microcode loading and abandon equivalence table because the family, model and stepping is part of the microcode patch ID. This results in microcode loading failure on Hygon family 18h processors because Hygon still uses equivalence table to verify microcode. So add equivalence table support for Hygon family 18h processors. Fixes: bef830144feb ("x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID") Signed-off-by: Liao Xuan --- arch/x86/kernel/cpu/microcode/amd.c | 46 +++++++++++++++++++---------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 2da034b27e65..58b37844c430 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -222,7 +222,10 @@ static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsi struct sha256_state s; int i; - if (x86_family(bsp_cpuid_1_eax) < 0x17) + + if ((x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) < 0x17) || + x86_cpuid_vendor() == X86_VENDOR_HYGON) return true; if (!need_sha_check(cur_rev)) @@ -285,7 +288,8 @@ static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig) unsigned int i; /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) return 0; if (!et || !et->num_entries) @@ -335,7 +339,8 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size) return false; /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) return true; cont_type = hdr[1]; @@ -491,7 +496,8 @@ static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size) static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id) { /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax; else return eq_id == mc->hdr.processor_rev_id; @@ -612,7 +618,9 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev, native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr); - if (x86_family(bsp_cpuid_1_eax) == 0x17) { + if ((x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) == 0x17) || + x86_cpuid_vendor() == X86_VENDOR_HYGON) { unsigned long p_addr_end = p_addr + psize - 1; invlpg(p_addr); @@ -667,10 +675,9 @@ static bool __init find_blobs_in_containers(struct cpio_data *ret) const char *path; if (x86_cpuid_vendor() == X86_VENDOR_HYGON) - path = (const char *)__pa_nodebug( - "kernel/x86/microcode/HygonGenuine.bin"); + path = "kernel/x86/microcode/HygonGenuine.bin"; else - path = (const char *)__pa_nodebug(ucode_path); + path = ucode_path; if (!get_builtin_microcode(&cp)) cp = find_microcode_in_initrd(path); @@ -741,7 +748,8 @@ static inline bool patch_cpus_equivalent(struct ucode_patch *p, bool ignore_stepping) { /* Zen and newer hardcode the f/m/s in the patch ID */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) { + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) { union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id); union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id); @@ -767,7 +775,8 @@ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equi n.equiv_cpu = equiv_cpu; n.patch_id = uci->cpu_sig.rev; - WARN_ON_ONCE(!n.patch_id); + if (x86_cpuid_vendor() != X86_VENDOR_HYGON) + WARN_ON_ONCE(!n.patch_id); list_for_each_entry(p, µcode_cache, plist) if (patch_cpus_equivalent(p, &n, false)) @@ -779,7 +788,8 @@ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equi static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n) { /* Zen and newer hardcode the f/m/s in the patch ID */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) { + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) { union zen_patch_rev zp, zn; zp.ucode_rev = p->patch_id; @@ -839,7 +849,9 @@ static struct ucode_patch *find_patch(unsigned int cpu) uci->cpu_sig.rev = get_patch_level(); - if (x86_family(bsp_cpuid_1_eax) < 0x17) { + if ((x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) < 0x17) || + x86_cpuid_vendor() == X86_VENDOR_HYGON) { equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig); if (!equiv_id) return NULL; @@ -954,7 +966,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) equiv_tbl_len = hdr[2]; /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >= 0x17) + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) goto out; equiv_table.entry = vmalloc(equiv_tbl_len); @@ -973,7 +986,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size) static void free_equiv_cpu_table(void) { - if (x86_family(bsp_cpuid_1_eax) >= 0x17) + if (x86_cpuid_vendor() == X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >= 0x17) return; vfree(equiv_table.entry); @@ -1119,7 +1133,9 @@ static int __init save_microcode_in_initrd(void) enum ucode_state ret; struct cpio_data cp; - if (dis_ucode_ldr || c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) + if (dis_ucode_ldr || + (c->x86_vendor != X86_VENDOR_AMD && c->x86_vendor != X86_VENDOR_HYGON) || + (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x10)) return 0; if (!find_blobs_in_containers(&cp)) -- Gitee