aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2008-03-14 19:41:48 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2008-03-14 19:41:48 +0000
commiteaf86d1678b7caea39710ed2b2086bb4e131eeda (patch)
treec7c725651b1ad4c07a8fe93c253676ef3d6d5279 /sys/amd64
parent9e3bdede0f3df75b406a354c65350cb976a3f1df (diff)
Notes
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/intr_machdep.c61
-rw-r--r--sys/amd64/include/intr_machdep.h3
2 files changed, 55 insertions, 9 deletions
diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c
index 7efc7ace54ce..23d9278456cc 100644
--- a/sys/amd64/amd64/intr_machdep.c
+++ b/sys/amd64/amd64/intr_machdep.c
@@ -89,6 +89,7 @@ static int assign_cpu;
static void intr_assign_next_cpu(struct intsrc *isrc);
#endif
+static int intr_assign_cpu(void *arg, u_char cpu);
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
@@ -146,10 +147,12 @@ intr_register_source(struct intsrc *isrc)
#ifdef INTR_FILTER
error = intr_event_create(&isrc->is_event, isrc, 0,
(mask_fn)isrc->is_pic->pic_enable_source,
- intr_eoi_src, intr_disab_eoi_src, "irq%d:", vector);
+ intr_eoi_src, intr_disab_eoi_src, intr_assign_cpu, "irq%d:",
+ vector);
#else
error = intr_event_create(&isrc->is_event, isrc, 0,
- (mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
+ (mask_fn)isrc->is_pic->pic_enable_source, intr_assign_cpu, "irq%d:",
+ vector);
#endif
if (error)
return (error);
@@ -431,6 +434,28 @@ intr_suspend(void)
sx_xunlock(&intr_table_lock);
}
+static int
+intr_assign_cpu(void *arg, u_char cpu)
+{
+#ifdef SMP
+ struct intsrc *isrc;
+
+ /*
+ * Don't do anything during early boot. We will pick up the
+ * assignment once the APs are started.
+ */
+ if (assign_cpu && cpu != NOCPU) {
+ isrc = arg;
+ sx_xlock(&intr_table_lock);
+ isrc->is_pic->pic_assign_cpu(isrc, cpu_apic_ids[cpu]);
+ sx_xunlock(&intr_table_lock);
+ }
+ return (0);
+#else
+ return (EOPNOTSUPP);
+#endif
+}
+
static void
intrcnt_setname(const char *name, int index)
{
@@ -542,15 +567,11 @@ static int current_cpu;
static void
intr_assign_next_cpu(struct intsrc *isrc)
{
- struct pic *pic;
- u_int apic_id;
/*
* Assign this source to a local APIC in a round-robin fashion.
*/
- pic = isrc->is_pic;
- apic_id = cpu_apic_ids[current_cpu];
- pic->pic_assign_cpu(isrc, apic_id);
+ isrc->is_pic->pic_assign_cpu(isrc, cpu_apic_ids[current_cpu]);
do {
current_cpu++;
if (current_cpu > mp_maxid)
@@ -558,6 +579,18 @@ intr_assign_next_cpu(struct intsrc *isrc)
} while (!(intr_cpus & (1 << current_cpu)));
}
+/* Attempt to bind the specified IRQ to the specified CPU. */
+int
+intr_bind(u_int vector, u_char cpu)
+{
+ struct intsrc *isrc;
+
+ isrc = intr_lookup_source(vector);
+ if (isrc == NULL)
+ return (EINVAL);
+ return (intr_event_bind(isrc->is_event, cpu));
+}
+
/*
* Add a CPU to our mask of valid CPUs that can be destinations of
* interrupts.
@@ -594,8 +627,18 @@ intr_shuffle_irqs(void *arg __unused)
assign_cpu = 1;
for (i = 0; i < NUM_IO_INTS; i++) {
isrc = interrupt_sources[i];
- if (isrc != NULL && isrc->is_handlers > 0)
- intr_assign_next_cpu(isrc);
+ if (isrc != NULL && isrc->is_handlers > 0) {
+ /*
+ * If this event is already bound to a CPU,
+ * then assign the source to that CPU instead
+ * of picking one via round-robin.
+ */
+ if (isrc->is_event->ie_cpu != NOCPU)
+ isrc->is_pic->pic_assign_cpu(isrc,
+ cpu_apic_ids[isrc->is_event->ie_cpu]);
+ else
+ intr_assign_next_cpu(isrc);
+ }
}
sx_xunlock(&intr_table_lock);
}
diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h
index 8b16c5e2fabc..7e1c43f65b90 100644
--- a/sys/amd64/include/intr_machdep.h
+++ b/sys/amd64/include/intr_machdep.h
@@ -137,6 +137,9 @@ void intr_add_cpu(u_int cpu);
int intr_add_handler(const char *name, int vector, driver_filter_t filter,
driver_intr_t handler, void *arg, enum intr_type flags,
void **cookiep);
+#ifdef SMP
+int intr_bind(u_int vector, u_char cpu);
+#endif
int intr_config_intr(int vector, enum intr_trigger trig,
enum intr_polarity pol);
void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);