diff options
| author | Gleb Smirnoff <glebius@FreeBSD.org> | 2025-09-18 15:10:59 +0000 |
|---|---|---|
| committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2025-09-18 15:10:59 +0000 |
| commit | 6683dcf61b3d0dfa8639c9e501eefb7709922ddf (patch) | |
| tree | 8e7224739cddbec88a949488b464085e72e7bc2f | |
| parent | 6b841d70960a3a0ec4e43392683053878c403f9c (diff) | |
cpuctl: run amd_ucode_wrmsr only on one CPU and report if it failed
The CPUCTL_UPDATE is supposed to be applied only to the CPU the ioctl(2)
was performed on. This is true for Intel CPUs, but for AMD the SMP
rendezvouz of amd_ucode_wrmsr() effectively executed it on all CPUs.
Also, the update failure was not reported.
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D52466
| -rw-r--r-- | sys/dev/cpuctl/cpuctl.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/sys/dev/cpuctl/cpuctl.c b/sys/dev/cpuctl/cpuctl.c index 9253b17a259d..b0ab3467df69 100644 --- a/sys/dev/cpuctl/cpuctl.c +++ b/sys/dev/cpuctl/cpuctl.c @@ -402,19 +402,20 @@ out: * its workings. */ static void -amd_ucode_wrmsr(void *ucode_ptr) +amd_ucode_wrmsr(void *arg) { + struct ucode_update_data *d = arg; uint32_t tmp[4]; - wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)ucode_ptr); + if (PCPU_GET(cpuid) == d->cpu) + d->ret = wrmsr_safe(MSR_K8_UCODE_UPDATE, (uintptr_t)d->ptr); do_cpuid(0, tmp); } static int update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) { - void *ptr; - int ret; + struct ucode_update_data d = { .cpu = cpu }; if (args->size == 0 || args->data == NULL) { DPRINTF("[cpuctl,%d]: zero-sized firmware image", __LINE__); @@ -430,18 +431,17 @@ update_amd(int cpu, cpuctl_update_args_t *args, struct thread *td) * malloc(9) always returns the pointer aligned at least on * the size of the allocation. */ - ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK); - if (copyin(args->data, ptr, args->size) != 0) { + d.ptr = malloc(args->size + 16, M_CPUCTL, M_ZERO | M_WAITOK); + if (copyin(args->data, d.ptr, args->size) != 0) { DPRINTF("[cpuctl,%d]: copyin %p->%p of %zd bytes failed", __LINE__, args->data, ptr, args->size); - ret = EFAULT; + d.ret = EFAULT; goto fail; } - smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, ptr); - ret = 0; + smp_rendezvous(NULL, amd_ucode_wrmsr, NULL, &d); fail: - free(ptr, M_CPUCTL); - return (ret); + free(d.ptr, M_CPUCTL); + return (d.ret); } static int |
