Skip to content

Commit dec7ad7

Browse files
committed
x86/microcode/hygon: Fix microcode loading issue for Hygon processors
The commit ecc031c ("x86/microcode/AMD: Load only SHA256-checksummed patches") and commit efdb189 ("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: efdb189 ("x86/microcode/AMD: Use the family,model,stepping encoded in the patch ID") Signed-off-by: Liao Xuan <liaoxuan@hygon.cn>
1 parent 770e4a6 commit dec7ad7

2 files changed

Lines changed: 37 additions & 15 deletions

File tree

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

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,10 @@ static bool verify_sha256_digest(u32 patch_id, u32 cur_rev, const u8 *data, unsi
216216
struct sha256_state s;
217217
int i;
218218

219-
if (x86_family(bsp_cpuid_1_eax) < 0x17 ||
220-
x86_family(bsp_cpuid_1_eax) > 0x19)
219+
if ((x86_cpuid_vendor() == X86_VENDOR_AMD &&
220+
(x86_family(bsp_cpuid_1_eax) < 0x17 ||
221+
x86_family(bsp_cpuid_1_eax) > 0x19)) ||
222+
x86_cpuid_vendor() == X86_VENDOR_HYGON)
221223
return true;
222224

223225
if (!need_sha_check(cur_rev))
@@ -280,7 +282,8 @@ static u16 find_equiv_id(struct equiv_cpu_table *et, u32 sig)
280282
unsigned int i;
281283

282284
/* Zen and newer do not need an equivalence table. */
283-
if (x86_family(bsp_cpuid_1_eax) >= 0x17)
285+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
286+
x86_family(bsp_cpuid_1_eax) >= 0x17)
284287
return 0;
285288

286289
if (!et || !et->num_entries)
@@ -330,7 +333,8 @@ static bool verify_equivalence_table(const u8 *buf, size_t buf_size)
330333
return false;
331334

332335
/* Zen and newer do not need an equivalence table. */
333-
if (x86_family(bsp_cpuid_1_eax) >= 0x17)
336+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
337+
x86_family(bsp_cpuid_1_eax) >= 0x17)
334338
return true;
335339

336340
cont_type = hdr[1];
@@ -486,7 +490,8 @@ static int verify_patch(const u8 *buf, size_t buf_size, u32 *patch_size)
486490
static bool mc_patch_matches(struct microcode_amd *mc, u16 eq_id)
487491
{
488492
/* Zen and newer do not need an equivalence table. */
489-
if (x86_family(bsp_cpuid_1_eax) >= 0x17)
493+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
494+
x86_family(bsp_cpuid_1_eax) >= 0x17)
490495
return ucode_rev_to_cpuid(mc->hdr.patch_id).full == bsp_cpuid_1_eax;
491496
else
492497
return eq_id == mc->hdr.processor_rev_id;
@@ -607,7 +612,9 @@ static bool __apply_microcode_amd(struct microcode_amd *mc, u32 *cur_rev,
607612

608613
native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
609614

610-
if (x86_family(bsp_cpuid_1_eax) == 0x17) {
615+
if ((x86_cpuid_vendor() == X86_VENDOR_AMD &&
616+
x86_family(bsp_cpuid_1_eax) == 0x17) ||
617+
x86_cpuid_vendor() == X86_VENDOR_HYGON) {
611618
unsigned long p_addr_end = p_addr + psize - 1;
612619

613620
invlpg(p_addr);
@@ -658,9 +665,15 @@ static bool __init find_blobs_in_containers(struct cpio_data *ret)
658665
{
659666
struct cpio_data cp;
660667
bool found;
668+
const char *path;
669+
670+
if (x86_cpuid_vendor() == X86_VENDOR_HYGON)
671+
path = "kernel/x86/microcode/HygonGenuine.bin";
672+
else
673+
path = ucode_path;
661674

662675
if (!get_builtin_microcode(&cp))
663-
cp = find_microcode_in_initrd(ucode_path);
676+
cp = find_microcode_in_initrd(path);
664677

665678
found = cp.data && cp.size;
666679
if (found)
@@ -728,7 +741,8 @@ static inline bool patch_cpus_equivalent(struct ucode_patch *p,
728741
bool ignore_stepping)
729742
{
730743
/* Zen and newer hardcode the f/m/s in the patch ID */
731-
if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
744+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
745+
x86_family(bsp_cpuid_1_eax) >= 0x17) {
732746
union cpuid_1_eax p_cid = ucode_rev_to_cpuid(p->patch_id);
733747
union cpuid_1_eax n_cid = ucode_rev_to_cpuid(n->patch_id);
734748

@@ -754,7 +768,8 @@ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equi
754768
n.equiv_cpu = equiv_cpu;
755769
n.patch_id = uci->cpu_sig.rev;
756770

757-
WARN_ON_ONCE(!n.patch_id);
771+
if (x86_cpuid_vendor() != X86_VENDOR_HYGON)
772+
WARN_ON_ONCE(!n.patch_id);
758773

759774
list_for_each_entry(p, &microcode_cache, plist)
760775
if (patch_cpus_equivalent(p, &n, false))
@@ -766,7 +781,8 @@ static struct ucode_patch *cache_find_patch(struct ucode_cpu_info *uci, u16 equi
766781
static inline int patch_newer(struct ucode_patch *p, struct ucode_patch *n)
767782
{
768783
/* Zen and newer hardcode the f/m/s in the patch ID */
769-
if (x86_family(bsp_cpuid_1_eax) >= 0x17) {
784+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
785+
x86_family(bsp_cpuid_1_eax) >= 0x17) {
770786
union zen_patch_rev zp, zn;
771787

772788
zp.ucode_rev = p->patch_id;
@@ -826,7 +842,9 @@ static struct ucode_patch *find_patch(unsigned int cpu)
826842

827843
uci->cpu_sig.rev = get_patch_level();
828844

829-
if (x86_family(bsp_cpuid_1_eax) < 0x17) {
845+
if ((x86_cpuid_vendor() == X86_VENDOR_AMD &&
846+
x86_family(bsp_cpuid_1_eax) < 0x17) ||
847+
x86_cpuid_vendor() == X86_VENDOR_HYGON) {
830848
equiv_id = find_equiv_id(&equiv_table, uci->cpu_sig.sig);
831849
if (!equiv_id)
832850
return NULL;
@@ -941,7 +959,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size)
941959
equiv_tbl_len = hdr[2];
942960

943961
/* Zen and newer do not need an equivalence table. */
944-
if (x86_family(bsp_cpuid_1_eax) >= 0x17)
962+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
963+
x86_family(bsp_cpuid_1_eax) >= 0x17)
945964
goto out;
946965

947966
equiv_table.entry = vmalloc(equiv_tbl_len);
@@ -960,7 +979,8 @@ static size_t install_equiv_cpu_table(const u8 *buf, size_t buf_size)
960979

961980
static void free_equiv_cpu_table(void)
962981
{
963-
if (x86_family(bsp_cpuid_1_eax) >= 0x17)
982+
if (x86_cpuid_vendor() == X86_VENDOR_AMD &&
983+
x86_family(bsp_cpuid_1_eax) >= 0x17)
964984
return;
965985

966986
vfree(equiv_table.entry);
@@ -1106,7 +1126,9 @@ static int __init save_microcode_in_initrd(void)
11061126
enum ucode_state ret;
11071127
struct cpio_data cp;
11081128

1109-
if (dis_ucode_ldr || (c->x86_vendor != X86_VENDOR_AMD && c->x86_vendor != X86_VENDOR_HYGON) || c->x86 < 0x10)
1129+
if (dis_ucode_ldr ||
1130+
(c->x86_vendor != X86_VENDOR_AMD && c->x86_vendor != X86_VENDOR_HYGON) ||
1131+
(c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x10))
11101132
return 0;
11111133

11121134
if (!find_blobs_in_containers(&cp))

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ void load_ucode_ap(void)
190190
load_ucode_amd_ap(cpuid_1_eax);
191191
break;
192192
case X86_VENDOR_HYGON:
193-
load_ucode_amd_bsp(&early_data, cpuid_1_eax);
193+
load_ucode_amd_ap(cpuid_1_eax);
194194
break;
195195
default:
196196
break;

0 commit comments

Comments
 (0)