diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-09-10 09:32:32 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2023-09-10 09:32:32 +0000 |
commit | 2864e55305c036d5c7b1ba5148993ebf2c55a9ed (patch) | |
tree | 4e03a67cdacb2345e204763809fbc9dfddf40639 | |
parent | a83240a189a59051c21d7201dd62b44f4bc59d72 (diff) |
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@
-rw-r--r-- | sys/arch/amd64/amd64/ucode.c | 14 | ||||
-rw-r--r-- | 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 <fritsch@genua.de> * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se> @@ -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 <fritsch@genua.de> * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se> @@ -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); |