From 1f6c261b917e82523c659d6ded8d4ad3e742e070 Mon Sep 17 00:00:00 2001 From: jsg Date: Sun, 10 Sep 2023 09:32:31 +0000 Subject: [PATCH] load amd patch into a malloc'd region to make it page aligned avoids a General-Protection Exception on patch loader wrmsr with A10-5700, TN-A1 00610f01 15-10-01 the alignment requirement is not present on at least Ryzen 5 2600X, PiR-B2 00800f82 17-08-02 problem reported and fix tested by espie@ --- sys/arch/amd64/amd64/ucode.c | 14 ++++++++++++-- sys/arch/i386/i386/ucode.c | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sys/arch/amd64/amd64/ucode.c b/sys/arch/amd64/amd64/ucode.c index c2badbcfd9c..7111cc8dda3 100644 --- a/sys/arch/amd64/amd64/ucode.c +++ b/sys/arch/amd64/amd64/ucode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ucode.c,v 1.7 2023/08/09 02:59:41 jsg Exp $ */ +/* $OpenBSD: ucode.c,v 1.8 2023/09/10 09:32:31 jsg Exp $ */ /* * Copyright (c) 2018 Stefan Fritsch * Copyright (c) 2018 Patrick Wildt @@ -141,6 +141,7 @@ cpu_ucode_amd_apply(struct cpu_info *ci) uint16_t eid = 0; uint32_t sig, ebx, ecx, edx; uint64_t start = 0; + uint32_t patch_len = 0; if (cpu_ucode_data == NULL || cpu_ucode_size == 0) { DPRINTF(("%s: no microcode provided\n", __func__)); @@ -187,8 +188,10 @@ cpu_ucode_amd_apply(struct cpu_info *ci) goto out; } memcpy(&ap, &cpu_ucode_data[i], sizeof(ap)); - if (ap.type == 1 && ap.eid == eid && ap.level > level) + if (ap.type == 1 && ap.eid == eid && ap.level > level) { start = (uint64_t)&cpu_ucode_data[i + 8]; + patch_len = ap.len; + } if (i + ap.len + 8 > cpu_ucode_size) { DPRINTF(("%s: truncated patch\n", __func__)); goto out; @@ -197,9 +200,16 @@ cpu_ucode_amd_apply(struct cpu_info *ci) } if (start != 0) { + /* alignment required on fam 15h */ + uint8_t *p = malloc(patch_len, M_TEMP, M_NOWAIT); + if (p == NULL) + goto out; + memcpy(p, (uint8_t *)start, patch_len); + start = (uint64_t)p; wrmsr(MSR_PATCH_LOADER, start); level = rdmsr(MSR_PATCH_LEVEL); DPRINTF(("%s: new patch level 0x%llx\n", __func__, level)); + free(p, M_TEMP, patch_len); } out: mtx_leave(&cpu_ucode_mtx); diff --git a/sys/arch/i386/i386/ucode.c b/sys/arch/i386/i386/ucode.c index ec73218f11a..dde72a116b7 100644 --- a/sys/arch/i386/i386/ucode.c +++ b/sys/arch/i386/i386/ucode.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ucode.c,v 1.5 2023/08/09 02:59:41 jsg Exp $ */ +/* $OpenBSD: ucode.c,v 1.6 2023/09/10 09:32:31 jsg Exp $ */ /* * Copyright (c) 2018 Stefan Fritsch * Copyright (c) 2018 Patrick Wildt @@ -164,6 +164,7 @@ cpu_ucode_amd_apply(struct cpu_info *ci) uint16_t eid = 0; uint32_t sig, ebx, ecx, edx; uint64_t start = 0; + uint32_t patch_len = 0; if (cpu_ucode_data == NULL || cpu_ucode_size == 0) { DPRINTF(("%s: no microcode provided\n", __func__)); @@ -210,8 +211,10 @@ cpu_ucode_amd_apply(struct cpu_info *ci) goto out; } memcpy(&ap, &cpu_ucode_data[i], sizeof(ap)); - if (ap.type == 1 && ap.eid == eid && ap.level > level) + if (ap.type == 1 && ap.eid == eid && ap.level > level) { start = (uint64_t)&cpu_ucode_data[i + 8]; + patch_len = ap.len; + } if (i + ap.len + 8 > cpu_ucode_size) { DPRINTF(("%s: truncated patch\n", __func__)); goto out; @@ -220,9 +223,16 @@ cpu_ucode_amd_apply(struct cpu_info *ci) } if (start != 0) { + /* alignment required on fam 15h */ + uint8_t *p = malloc(patch_len, M_TEMP, M_NOWAIT); + if (p == NULL) + goto out; + memcpy(p, (uint8_t *)start, patch_len); + start = (uint64_t)p; wrmsr(MSR_PATCH_LOADER, start); level = rdmsr(MSR_PATCH_LEVEL); DPRINTF(("%s: new patch level 0x%llx\n", __func__, level)); + free(p, M_TEMP, patch_len); } out: mtx_leave(&cpu_ucode_mtx); -- 2.20.1