aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Certner <olce@FreeBSD.org>2026-01-23 20:52:46 +0000
committerOlivier Certner <olce@FreeBSD.org>2026-07-23 09:58:59 +0000
commit3f511fa41b3bc846f1af7a6e7a3a5dd0b2dbf0ae (patch)
tree122a119cc79fd795b630c4873a93349f2244d091
parent3e6bdd3acecb0ff414421dadfc1e3e0e00278d85 (diff)
x86: x86_msr_op(): MSR_OP_LOCAL: Disable interrupts on atomic ops
On MSR_OP_LOCAL and non-naturally-atomic operations (MSR_OP_ANDNOT and MSR_OP_OR), there is no guarantee that we are not interrupted between reading and writing the MSR, and that interruption could actually perform some operation on that MSR, which would be lost. Prevent that problem by temporarily disabling interrupts around MSR manipulation. Reviewed by: kib Discussed with: markj MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D54996 (cherry picked from commit e5f8cbb86d58f25b5ff168506b78d09dca266fb6)
-rw-r--r--sys/x86/include/x86_var.h2
-rw-r--r--sys/x86/x86/cpu_machdep.c3
2 files changed, 5 insertions, 0 deletions
diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
index 0ff336c9c1f0..bd246623ec07 100644
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -169,6 +169,8 @@ uint64_t rdtsc_ordered(void);
/*
* Where and which execution mode
+ *
+ * All modes cause execution on the target CPU(s) with interrupts disabled.
*/
#define MSR_OP_LOCAL 0x10000000
#define MSR_OP_SCHED_ALL 0x20000000
diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c
index ca975560fd1c..1c10af10e79d 100644
--- a/sys/x86/x86/cpu_machdep.c
+++ b/sys/x86/x86/cpu_machdep.c
@@ -161,6 +161,7 @@ x86_msr_op(u_int msr, u_int op, uint64_t arg1, uint64_t *res)
struct thread *td;
struct msr_op_arg a;
cpuset_t set;
+ register_t flags;
u_int exmode;
int bound_cpu, cpu, i, is_bound;
@@ -172,7 +173,9 @@ x86_msr_op(u_int msr, u_int op, uint64_t arg1, uint64_t *res)
switch (exmode) {
case MSR_OP_LOCAL:
+ flags = intr_disable();
x86_msr_op_one(&a);
+ intr_restore(flags);
break;
case MSR_OP_SCHED_ALL:
td = curthread;