summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2023-09-10 09:32:32 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2023-09-10 09:32:32 +0000
commit2864e55305c036d5c7b1ba5148993ebf2c55a9ed (patch)
tree4e03a67cdacb2345e204763809fbc9dfddf40639 /sys/arch/i386
parenta83240a189a59051c21d7201dd62b44f4bc59d72 (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@
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/i386/ucode.c14
1 files changed, 12 insertions, 2 deletions
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);