Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144050514
D55045.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D55045.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D55045: x86: add a safe variant of MSR_OP_SCHED* operations
Attached
Detach File
Event Timeline
Log In to Comment