Page MenuHomeFreeBSD

D55045.diff
No OneTemporary

D55045.diff

diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -172,6 +172,7 @@
/*
* Where and which execution mode
*/
+#define MSR_OP_SAFE 0x08000000
#define MSR_OP_LOCAL 0x10000000
#define MSR_OP_SCHED_ALL 0x20000000
#define MSR_OP_SCHED_ONE 0x30000000
@@ -179,7 +180,7 @@
#define MSR_OP_RENDEZVOUS_ONE 0x50000000
#define MSR_OP_CPUID(id) ((id) << 8)
-void x86_msr_op(u_int msr, u_int op, uint64_t arg1, uint64_t *res);
+int x86_msr_op(u_int msr, u_int op, uint64_t arg1, uint64_t *res);
#if defined(__i386__) && defined(INVARIANTS)
void trap_check_kstack(void);
diff --git a/sys/x86/x86/cpu_machdep.c b/sys/x86/x86/cpu_machdep.c
--- a/sys/x86/x86/cpu_machdep.c
+++ b/sys/x86/x86/cpu_machdep.c
@@ -118,15 +118,47 @@
int op;
uint64_t arg1;
uint64_t *res;
+ bool safe;
};
-static void
-x86_msr_op_one(void *argp)
+static int
+x86_msr_op_one_safe(struct msr_op_arg *a)
+{
+ uint64_t v;
+ int error;
+
+ error = 0;
+ switch (a->op) {
+ case MSR_OP_ANDNOT:
+ error = rdmsr_safe(a->msr, &v);
+ if (error != 0)
+ break;
+ v &= ~a->arg1;
+ error = wrmsr_safe(a->msr, v);
+ break;
+ case MSR_OP_OR:
+ error = rdmsr_safe(a->msr, &v);
+ if (error != 0)
+ break;
+ v |= a->arg1;
+ error = wrmsr_safe(a->msr, v);
+ case MSR_OP_WRITE:
+ error = wrmsr_safe(a->msr, a->arg1);
+ break;
+ case MSR_OP_READ:
+ error = rdmsr_safe(a->msr, &v);
+ if (error == 0)
+ *a->res = v;
+ break;
+ }
+ return (error);
+}
+
+static void
+x86_msr_op_one_unsafe(struct msr_op_arg *a)
{
- struct msr_op_arg *a;
uint64_t v;
- a = argp;
switch (a->op) {
case MSR_OP_ANDNOT:
v = rdmsr(a->msr);
@@ -148,20 +180,37 @@
}
}
+static void
+x86_msr_op_one_unsafe_void(void *arg)
+{
+ x86_msr_op_one_unsafe(arg);
+}
+
+static int
+x86_msr_op_one(struct msr_op_arg *a)
+{
+ if (a->safe)
+ return (x86_msr_op_one_safe(a));
+ x86_msr_op_one_unsafe(a);
+ return (0);
+}
+
#define MSR_OP_EXMODE_MASK 0xf0000000
#define MSR_OP_OP_MASK 0x000000ff
#define MSR_OP_GET_CPUID(x) (((x) & ~MSR_OP_EXMODE_MASK) >> 8)
-void
+int
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;
u_int exmode;
- int bound_cpu, cpu, i, is_bound;
+ int bound_cpu, cpu, error, i, is_bound;
+ bool safe;
a.op = op & MSR_OP_OP_MASK;
+ safe = op & MSR_OP_SAFE;
MPASS(a.op == MSR_OP_ANDNOT || a.op == MSR_OP_OR ||
a.op == MSR_OP_WRITE || a.op == MSR_OP_READ);
exmode = op & MSR_OP_EXMODE_MASK;
@@ -169,21 +218,31 @@
exmode == MSR_OP_SCHED_ONE || exmode == MSR_OP_RENDEZVOUS_ALL ||
exmode == MSR_OP_RENDEZVOUS_ONE);
a.msr = msr;
+ a.safe = safe;
a.arg1 = arg1;
a.res = res;
+ error = 0;
+ /*
+ * MSR_OP_RENDEZVOUS and MSR_OP_LOCAL variants cannot be safe,
+ * and cannot return an error.
+ */
+
switch (exmode) {
case MSR_OP_LOCAL:
- x86_msr_op_one(&a);
+ MPASS(!safe);
+ x86_msr_op_one_unsafe(&a);
break;
case MSR_OP_SCHED_ALL:
td = curthread;
thread_lock(td);
is_bound = sched_is_bound(td);
bound_cpu = td->td_oncpu;
+ thread_unlock(td);
CPU_FOREACH(i) {
sched_bind(td, i);
- x86_msr_op_one(&a);
+ error = x86_msr_op_one(&a);
}
+ thread_lock(td);
if (is_bound)
sched_bind(td, bound_cpu);
else
@@ -198,7 +257,9 @@
bound_cpu = td->td_oncpu;
if (!is_bound || bound_cpu != cpu)
sched_bind(td, cpu);
- x86_msr_op_one(&a);
+ thread_unlock(td);
+ error = x86_msr_op_one(&a);
+ thread_lock(td);
if (is_bound) {
if (bound_cpu != cpu)
sched_bind(td, bound_cpu);
@@ -208,16 +269,19 @@
thread_unlock(td);
break;
case MSR_OP_RENDEZVOUS_ALL:
- smp_rendezvous(smp_no_rendezvous_barrier, x86_msr_op_one,
- smp_no_rendezvous_barrier, &a);
+ MPASS(!safe);
+ smp_rendezvous(smp_no_rendezvous_barrier,
+ x86_msr_op_one_unsafe_void, smp_no_rendezvous_barrier, &a);
break;
case MSR_OP_RENDEZVOUS_ONE:
+ MPASS(!safe);
cpu = MSR_OP_GET_CPUID(op);
CPU_SETOF(cpu, &set);
smp_rendezvous_cpus(set, smp_no_rendezvous_barrier,
- x86_msr_op_one, smp_no_rendezvous_barrier, &a);
+ x86_msr_op_one_unsafe_void, smp_no_rendezvous_barrier, &a);
break;
}
+ return (error);
}
/*

File Metadata

Mime Type
text/plain
Expires
Wed, Feb 4, 10:48 PM (2 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28419272
Default Alt Text
D55045.diff (4 KB)

Event Timeline