summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-07-01 17:20:07 +0000
committerjhb <jhb@FreeBSD.org>2009-07-01 17:20:07 +0000
commit76256698a1223f7daae4d1340f06dfdda9147185 (patch)
treefb5e23052e350ca2b196f1a06067d0f6cf148b56 /sys/kern
parent9f2c78b3f9e8fee455c43e6025959a41def8d05c (diff)
downloadFreeBSD-src-76256698a1223f7daae4d1340f06dfdda9147185.zip
FreeBSD-src-76256698a1223f7daae4d1340f06dfdda9147185.tar.gz
Improve the handling of cpuset with interrupts.
- For x86, change the interrupt source method to assign an interrupt source to a specific CPU to return an error value instead of void, thus allowing it to fail. - If moving an interrupt to a CPU fails due to a lack of IDT vectors in the destination CPU, fail the request with ENOSPC rather than panicing. - For MSI interrupts on x86 (but not MSI-X), only allow cpuset to be used on the first interrupt in a group. Moving the first interrupt in a group moves the entire group. - Use the icu_lock to protect intr_next_cpu() on x86 instead of the intr_table_lock to fix a LOR introduced in the last set of MSI changes. - Add a new privilege PRIV_SCHED_CPUSET_INTR for using cpuset with interrupts. Previously, binding an interrupt to a CPU only performed a privilege check if the interrupt had an interrupt thread. Interrupts without a thread could be bound by non-root users as a result. - If an interrupt event's assign_cpu method fails, then restore the original cpuset mask for the associated interrupt thread. Approved by: re (kib)
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_intr.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
index 56761ba..3eb2c6c 100644
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/random.h>
#include <sys/resourcevar.h>
@@ -304,9 +305,14 @@ intr_event_bind(struct intr_event *ie, u_char cpu)
if (ie->ie_assign_cpu == NULL)
return (EOPNOTSUPP);
+
+ error = priv_check(curthread, PRIV_SCHED_CPUSET_INTR);
+ if (error)
+ return (error);
+
/*
- * If we have any ithreads try to set their mask first since this
- * can fail.
+ * If we have any ithreads try to set their mask first to verify
+ * permissions, etc.
*/
mtx_lock(&ie->ie_lock);
if (ie->ie_thread != NULL) {
@@ -323,8 +329,22 @@ intr_event_bind(struct intr_event *ie, u_char cpu)
} else
mtx_unlock(&ie->ie_lock);
error = ie->ie_assign_cpu(ie->ie_source, cpu);
- if (error)
+ if (error) {
+ mtx_lock(&ie->ie_lock);
+ if (ie->ie_thread != NULL) {
+ CPU_ZERO(&mask);
+ if (ie->ie_cpu == NOCPU)
+ CPU_COPY(cpuset_root, &mask);
+ else
+ CPU_SET(cpu, &mask);
+ id = ie->ie_thread->it_thread->td_tid;
+ mtx_unlock(&ie->ie_lock);
+ (void)cpuset_setthread(id, &mask);
+ } else
+ mtx_unlock(&ie->ie_lock);
return (error);
+ }
+
mtx_lock(&ie->ie_lock);
ie->ie_cpu = cpu;
mtx_unlock(&ie->ie_lock);
OpenPOWER on IntegriCloud