From 9280895b488c9151e99f1a5974f50a80afffccf2 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sat, 27 Mar 2010 05:40:50 +0000 Subject: [PATCH] Implement interrupt to CPU binding. Assign interrupts to CPUs in a round-robin fashion, starting with the highest priority interrupt on the highest-numbered CPU and cycling downwards. --- sys/ia64/ia64/autoconf.c | 2 +- sys/ia64/ia64/interrupt.c | 22 ++++++++++++++++++---- sys/ia64/ia64/mp_machdep.c | 6 ++++++ sys/ia64/ia64/nexus.c | 14 ++++++++++++++ sys/ia64/ia64/sapic.c | 21 +++++++++++++++++++++ sys/ia64/include/intr.h | 4 +++- 6 files changed, 63 insertions(+), 6 deletions(-) diff --git a/sys/ia64/ia64/autoconf.c b/sys/ia64/ia64/autoconf.c index acac159df7e1..cf073c835095 100644 --- a/sys/ia64/ia64/autoconf.c +++ b/sys/ia64/ia64/autoconf.c @@ -93,7 +93,7 @@ configure_final(void *dummy) cninit_finish(); - ia64_finalize_intr(); + ia64_enable_intr(); cold = 0; } diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index 82ac35fb43a5..adb16ece9d58 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -122,7 +122,7 @@ ia64_xiv_reserve(u_int xiv, enum ia64_xiv_use what, ia64_ihtype ih) return (EBUSY); ia64_xiv[xiv] = what; ia64_handler[xiv] = (ih == NULL) ? ia64_ih_invalid: ih; - if (1 || bootverbose) + if (bootverbose) printf("XIV %u: use=%u, IH=%p\n", xiv, what, ih); return (0); } @@ -139,7 +139,7 @@ ia64_xiv_alloc(u_int prio, enum ia64_xiv_use what, ia64_ihtype ih) xiv0 = IA64_NXIVS - (hwprio + 1) * 16; - KASSERT(xiv0 > IA64_MIN_XIV, ("%s: min XIV", __func__)); + KASSERT(xiv0 >= IA64_MIN_XIV, ("%s: min XIV", __func__)); KASSERT(xiv0 < IA64_NXIVS, ("%s: max XIV", __func__)); xiv = xiv0; @@ -281,10 +281,24 @@ ia64_teardown_intr(void *cookie) } void -ia64_finalize_intr(void) +ia64_bind_intr(void) { + struct ia64_intr *i; + struct pcpu *pc; + u_int xiv; + int cpu; - ia64_enable_intr(); + cpu = MAXCPU; + for (xiv = IA64_NXIVS - 1; xiv >= IA64_MIN_XIV; xiv--) { + if (ia64_xiv[xiv] != IA64_XIV_IRQ) + continue; + i = ia64_intrs[xiv]; + do { + cpu = (cpu == 0) ? MAXCPU - 1 : cpu - 1; + pc = cpuid_to_pcpu[cpu]; + } while (pc == NULL || !pc->pc_md.awake); + sapic_bind_intr(i->irq, pc); + } } /* diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 60ad43a1b294..600803a74b47 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -382,6 +382,12 @@ cpu_mp_unleash(void *dummy) smp_active = 1; smp_started = 1; + + /* + * Now that all CPUs are up and running, bind interrupts to each of + * them. + */ + ia64_bind_intr(); } /* diff --git a/sys/ia64/ia64/nexus.c b/sys/ia64/ia64/nexus.c index 889c3d622c54..9885b747aa25 100644 --- a/sys/ia64/ia64/nexus.c +++ b/sys/ia64/ia64/nexus.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ static int nexus_set_resource(device_t, device_t, int, int, u_long, u_long); static int nexus_get_resource(device_t, device_t, int, int, u_long *, u_long *); static void nexus_delete_resource(device_t, device_t, int, int); +static int nexus_bind_intr(device_t, device_t, struct resource *, int); static int nexus_config_intr(device_t, int, enum intr_trigger, enum intr_polarity); @@ -129,6 +131,7 @@ static device_method_t nexus_methods[] = { DEVMETHOD(bus_set_resource, nexus_set_resource), DEVMETHOD(bus_get_resource, nexus_get_resource), DEVMETHOD(bus_delete_resource, nexus_delete_resource), + DEVMETHOD(bus_bind_intr, nexus_bind_intr), DEVMETHOD(bus_config_intr, nexus_config_intr), /* Clock interface */ @@ -461,6 +464,17 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, return (sapic_config_intr(irq, trig, pol)); } +static int +nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) +{ + struct pcpu *pc; + + pc = cpuid_to_pcpu[cpu]; + if (pc == NULL) + return (EINVAL); + return (sapic_bind_intr(rman_get_start(irq), pc)); +} + static int nexus_gettime(device_t dev, struct timespec *ts) { diff --git a/sys/ia64/ia64/sapic.c b/sys/ia64/ia64/sapic.c index cb8a1c305eaf..5aa14493e779 100644 --- a/sys/ia64/ia64/sapic.c +++ b/sys/ia64/ia64/sapic.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -171,6 +172,26 @@ sapic_lookup(u_int irq, u_int *vecp) } +int +sapic_bind_intr(u_int irq, struct pcpu *pc) +{ + struct sapic_rte rte; + struct sapic *sa; + + sa = sapic_lookup(irq, NULL); + if (sa == NULL) + return (EINVAL); + + mtx_lock_spin(&sa->sa_mtx); + sapic_read_rte(sa, irq - sa->sa_base, &rte); + rte.rte_destination_id = (pc->pc_md.lid >> 24) & 255; + rte.rte_destination_eid = (pc->pc_md.lid >> 16) & 255; + rte.rte_delivery_mode = SAPIC_DELMODE_FIXED; + sapic_write_rte(sa, irq - sa->sa_base, &rte); + mtx_unlock_spin(&sa->sa_mtx); + return (0); +} + int sapic_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol) { diff --git a/sys/ia64/include/intr.h b/sys/ia64/include/intr.h index 2ea858c345f0..81603cfabfdf 100644 --- a/sys/ia64/include/intr.h +++ b/sys/ia64/include/intr.h @@ -35,6 +35,7 @@ #define IA64_MAX_HWPRIO 14 +struct pcpu; struct sapic; struct thread; struct trapframe; @@ -65,7 +66,7 @@ typedef u_int (ia64_ihtype)(struct thread *, u_int, struct trapframe *); extern struct ia64_pib *ia64_pib; -void ia64_finalize_intr(void); +void ia64_bind_intr(void); void ia64_handle_intr(struct trapframe *); int ia64_setup_intr(const char *, int, driver_filter_t, driver_intr_t, void *, enum intr_type, void **); @@ -76,6 +77,7 @@ u_int ia64_xiv_alloc(u_int, enum ia64_xiv_use, ia64_ihtype); int ia64_xiv_free(u_int, enum ia64_xiv_use); int ia64_xiv_reserve(u_int, enum ia64_xiv_use, ia64_ihtype); +int sapic_bind_intr(u_int, struct pcpu *); int sapic_config_intr(u_int, enum intr_trigger, enum intr_polarity); struct sapic *sapic_create(u_int, u_int, uint64_t); int sapic_enable(struct sapic *, u_int, u_int);