From nobody Thu Apr 2 18:29:57 2026 Received: from out28-106.mail.aliyun.com (out28-106.mail.aliyun.com [115.124.28.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA3953C2798 for ; Fri, 27 Mar 2026 08:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.106 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774599027; cv=none; b=fw4ZuLH9egnbwgzK7at79My1dr5Wi7aEs58GZYgJwdFgSmqTkerXxwvhKt2kOxX3bnYNv86KEJfIjruLRTDhh32+pdwZRr1JL5T+C4QyGhRvEj6J7sDzDPdZKd3HnJ4wMM9a35h6yOqz6WvpcdqCtDquq9A0T8m3rl8rOZax2CU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774599027; c=relaxed/simple; bh=Sb3qrMkICVL2Yuh5+GEgMaKTrVJ6Z6EYyoo5cAcIiyw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ambk/18N3sX76COuTe6bXDhl0rCR4DrmBCsp2ZRmfmhuoqdMlJ7z7Woh08kjF0ZKLHtrYJ918dRLo608LLSpUamHAQJoSUEP38CsLpWzERvvuj6lIOGeHdftKUtl5bWpeOJfJVPJ/XM9WS+1Ri/kyypoA1NaoMjQT/XvommDNFU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net; spf=pass smtp.mailfrom=open-hieco.net; arc=none smtp.client-ip=115.124.28.106 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=open-hieco.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=open-hieco.net X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=blue;DM=|OVERLOAD|false|;DS=CONTINUE|ham_alarm|0.00359679-0.00150827-0.994895;FP=13686271970075284603|4|1|1|0|-1|-1|-1;HT=maildocker-contentspam033037022039;MF=fuhao@open-hieco.net;NM=1;PH=DS;RN=8;RT=8;SR=0;TI=SMTPD_---.h.LaP6h_1774599011; Received: from higon..(mailfrom:fuhao@open-hieco.net fp:SMTPD_---.h.LaP6h_1774599011 cluster:ay29) by smtp.aliyun-inc.com; Fri, 27 Mar 2026 16:10:18 +0800 From: Fu Hao To: tglx@kernel.org, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com Cc: linux-kernel@vger.kernel.org, Fu Hao Subject: [PATCH 5/8] x86/microcode/hygon: Add microcode loading support for Hygon processors Date: Fri, 27 Mar 2026 16:10:09 +0800 Message-Id: <944d5379c699bbb0ef5122d5860ad1ca01188885.1774595153.git.fuhao@open-hieco.net> X-Mailer: git-send-email 2.34.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for loading Hygon microcode, which is compatible with AMD one. Signed-off-by: Fu Hao --- arch/x86/Kconfig | 2 +- arch/x86/kernel/cpu/microcode/amd.c | 63 ++++++++++++++++++------ arch/x86/kernel/cpu/microcode/core.c | 11 +++++ arch/x86/kernel/cpu/microcode/internal.h | 12 +++++ 4 files changed, 73 insertions(+), 15 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e2df1b147..b94f3dbf1 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1330,7 +1330,7 @@ config X86_REBOOTFIXUPS =20 config MICROCODE def_bool y - depends on CPU_SUP_AMD || CPU_SUP_INTEL + depends on CPU_SUP_AMD || CPU_SUP_INTEL || CPU_SUP_HYGON select CRYPTO_LIB_SHA256 if CPU_SUP_AMD =20 config MICROCODE_INITRD32 diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/micr= ocode/amd.c index e53388128..0f2d4829c 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -347,7 +347,8 @@ static u16 find_equiv_id(struct equiv_cpu_table *et, u3= 2 sig) unsigned int i; =20 /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >=3D 0x17) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) return 0; =20 if (!et || !et->num_entries) @@ -397,7 +398,8 @@ static bool verify_equivalence_table(const u8 *buf, siz= e_t buf_size) return false; =20 /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >=3D 0x17) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) return true; =20 cont_type =3D hdr[1]; @@ -577,7 +579,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) >=3D 0x17) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) return ucode_rev_to_cpuid(mc->hdr.patch_id).full =3D=3D bsp_cpuid_1_eax; else return eq_id =3D=3D mc->hdr.processor_rev_id; @@ -701,7 +704,9 @@ static bool __apply_microcode_amd(struct microcode_amd = *mc, u32 *cur_rev, =20 native_wrmsrq(MSR_AMD64_PATCH_LOADER, p_addr); =20 - if (x86_family(bsp_cpuid_1_eax) =3D=3D 0x17) { + if ((x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) =3D=3D 0x17) || + x86_cpuid_vendor() =3D=3D X86_VENDOR_HYGON) { unsigned long p_addr_end =3D p_addr + psize - 1; =20 invlpg(p_addr); @@ -730,16 +735,19 @@ static bool __apply_microcode_amd(struct microcode_am= d *mc, u32 *cur_rev, =20 static bool get_builtin_microcode(struct cpio_data *cp) { - char fw_name[36] =3D "amd-ucode/microcode_amd.bin"; + char fw_name[40] =3D "amd-ucode/microcode_amd.bin"; u8 family =3D x86_family(bsp_cpuid_1_eax); struct firmware fw; =20 if (IS_ENABLED(CONFIG_X86_32)) return false; =20 - if (family >=3D 0x15) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && family >=3D 0x15) snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%02hhxh.bin", family); + else if (x86_cpuid_vendor() =3D=3D X86_VENDOR_HYGON) + snprintf(fw_name, sizeof(fw_name), + "hygon-ucode/microcode_hygon_fam%.2xh.bin", family); =20 if (firmware_request_builtin(&fw, fw_name)) { cp->size =3D fw.size; @@ -824,7 +832,8 @@ static inline bool patch_cpus_equivalent(struct ucode_p= atch *p, bool ignore_stepping) { /* Zen and newer hardcode the f/m/s in the patch ID */ - if (x86_family(bsp_cpuid_1_eax) >=3D 0x17) { + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) { union cpuid_1_eax p_cid =3D ucode_rev_to_cpuid(p->patch_id); union cpuid_1_eax n_cid =3D ucode_rev_to_cpuid(n->patch_id); =20 @@ -860,7 +869,8 @@ static struct ucode_patch *cache_find_patch(struct ucod= e_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) >=3D 0x17) { + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) { union zen_patch_rev zp, zn; =20 zp.ucode_rev =3D p->patch_id; @@ -920,7 +930,9 @@ static struct ucode_patch *find_patch(unsigned int cpu) =20 uci->cpu_sig.rev =3D get_patch_level(); =20 - if (x86_family(bsp_cpuid_1_eax) < 0x17) { + if ((x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) < 0x17) || + x86_cpuid_vendor() =3D=3D X86_VENDOR_HYGON) { equiv_id =3D find_equiv_id(&equiv_table, uci->cpu_sig.sig); if (!equiv_id) return NULL; @@ -1035,7 +1047,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, = size_t buf_size) equiv_tbl_len =3D hdr[2]; =20 /* Zen and newer do not need an equivalence table. */ - if (x86_family(bsp_cpuid_1_eax) >=3D 0x17) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) goto out; =20 equiv_table.entry =3D vmalloc(equiv_tbl_len); @@ -1054,7 +1067,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, = size_t buf_size) =20 static void free_equiv_cpu_table(void) { - if (x86_family(bsp_cpuid_1_eax) >=3D 0x17) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && + x86_family(bsp_cpuid_1_eax) >=3D 0x17) return; =20 vfree(equiv_table.entry); @@ -1200,7 +1214,9 @@ static int __init save_microcode_in_initrd(void) enum ucode_state ret; struct cpio_data cp; =20 - if (microcode_loader_disabled() || c->x86_vendor !=3D X86_VENDOR_AMD || c= ->x86 < 0x10) + if (microcode_loader_disabled() || + ((c->x86_vendor !=3D X86_VENDOR_AMD || c->x86 < 0x10) && + (c->x86_vendor !=3D X86_VENDOR_HYGON))) return 0; =20 cpuid_1_eax =3D native_cpuid_eax(1); @@ -1238,7 +1254,7 @@ early_initcall(save_microcode_in_initrd); */ static enum ucode_state request_microcode_amd(int cpu, struct device *devi= ce) { - char fw_name[36] =3D "amd-ucode/microcode_amd.bin"; + char fw_name[40] =3D "amd-ucode/microcode_amd.bin"; struct cpuinfo_x86 *c =3D &cpu_data(cpu); enum ucode_state ret =3D UCODE_NFOUND; const struct firmware *fw; @@ -1246,8 +1262,11 @@ static enum ucode_state request_microcode_amd(int cp= u, struct device *device) if (force_minrev) return UCODE_NFOUND; =20 - if (c->x86 >=3D 0x15) + if (x86_cpuid_vendor() =3D=3D X86_VENDOR_AMD && c->x86 >=3D 0x15) snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin= ", c->x86); + else if (x86_cpuid_vendor() =3D=3D X86_VENDOR_HYGON) + snprintf(fw_name, sizeof(fw_name), + "hygon-ucode/microcode_hygon_fam%.2xh.bin", c->x86); =20 if (request_firmware_direct(&fw, (const char *)fw_name, device)) { ucode_dbg("failed to load file %s\n", fw_name); @@ -1297,8 +1316,24 @@ struct microcode_ops * __init init_amd_microcode(voi= d) pr_warn("AMD CPU family 0x%x not supported\n", c->x86); return NULL; } + + return µcode_amd_ops; +} + +#ifdef CONFIG_CPU_SUP_HYGON +struct microcode_ops * __init init_hygon_microcode(void) +{ + struct cpuinfo_x86 *c =3D &boot_cpu_data; + + if (c->x86_vendor !=3D X86_VENDOR_HYGON) + return NULL; + + strscpy((char *)ucode_path, "kernel/x86/microcode/HygonGenuine.bin", + sizeof(ucode_path)); + return µcode_amd_ops; } +#endif =20 void __exit exit_amd_microcode(void) { diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/mic= rocode/core.c index 651202e6f..813c5c157 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -195,6 +195,9 @@ void __init load_ucode_bsp(void) return; intel =3D false; break; + case X86_VENDOR_HYGON: + intel =3D false; + break; =20 default: return; @@ -229,6 +232,9 @@ void load_ucode_ap(void) if (x86_family(cpuid_1_eax) >=3D 0x10) load_ucode_amd_ap(cpuid_1_eax); break; + case X86_VENDOR_HYGON: + load_ucode_amd_ap(cpuid_1_eax); + break; default: break; } @@ -288,6 +294,9 @@ static void reload_early_microcode(unsigned int cpu) if (family >=3D 0x10) reload_ucode_amd(cpu); break; + case X86_VENDOR_HYGON: + reload_ucode_amd(cpu); + break; default: break; } @@ -895,6 +904,8 @@ static int __init microcode_init(void) microcode_ops =3D init_intel_microcode(); else if (c->x86_vendor =3D=3D X86_VENDOR_AMD) microcode_ops =3D init_amd_microcode(); + else if (c->x86_vendor =3D=3D X86_VENDOR_HYGON) + microcode_ops =3D init_hygon_microcode(); else pr_err("no support for this CPU vendor\n"); =20 diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu= /microcode/internal.h index 3b93c0676..75591afae 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -61,6 +61,9 @@ struct cpio_data find_microcode_in_initrd(const char *pat= h); #define CPUID_AMD1 QCHAR('A', 'u', 't', 'h') #define CPUID_AMD2 QCHAR('e', 'n', 't', 'i') #define CPUID_AMD3 QCHAR('c', 'A', 'M', 'D') +#define CPUID_HYGON1 QCHAR('H', 'y', 'g', 'o') +#define CPUID_HYGON2 QCHAR('n', 'G', 'e', 'n') +#define CPUID_HYGON3 QCHAR('u', 'i', 'n', 'e') =20 #define CPUID_IS(a, b, c, ebx, ecx, edx) \ (!(((ebx) ^ (a)) | ((edx) ^ (b)) | ((ecx) ^ (c)))) @@ -87,6 +90,9 @@ static inline int x86_cpuid_vendor(void) if (CPUID_IS(CPUID_AMD1, CPUID_AMD2, CPUID_AMD3, ebx, ecx, edx)) return X86_VENDOR_AMD; =20 + if (CPUID_IS(CPUID_HYGON1, CPUID_HYGON2, CPUID_HYGON3, ebx, ecx, edx)) + return X86_VENDOR_HYGON; + return X86_VENDOR_UNKNOWN; } =20 @@ -128,6 +134,12 @@ static inline void reload_ucode_intel(void) { } static inline struct microcode_ops *init_intel_microcode(void) { return NU= LL; } #endif /* !CONFIG_CPU_SUP_INTEL */ =20 +#ifdef CONFIG_CPU_SUP_HYGON +struct microcode_ops *init_hygon_microcode(void); +#else /* CONFIG_CPU_SUP_HYGON */ +static inline struct microcode_ops *init_hygon_microcode(void) { return NU= LL; } +#endif /* !CONFIG_CPU_SUP_HYGON */ + #define ucode_dbg(fmt, ...) \ ({ \ if (IS_ENABLED(CONFIG_MICROCODE_DBG)) \ --=20 2.34.1