Date: Mon, 21 Aug 2006 14:08:27 GMT From: Paolo Pisati <piso@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 104687 for review Message-ID: <200608211408.k7LE8RX2096468@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=104687 Change 104687 by piso@piso_newluxor on 2006/08/21 14:07:35 Fill the missing MD bits for stray detection: the low level ie_enable() and ie_pending() are still missing for archs !i386 and !amd64, but someone with knowlegde of the different interrupt controllers could write them very quickly. Looks like arm doesn't have any mutex to protect the global interrupt event table... Affected files ... .. //depot/projects/soc2006/intr_filter/amd64/amd64/intr_machdep.c#7 edit .. //depot/projects/soc2006/intr_filter/arm/arm/intr.c#6 edit .. //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#13 edit .. //depot/projects/soc2006/intr_filter/ia64/ia64/interrupt.c#7 edit .. //depot/projects/soc2006/intr_filter/powerpc/powerpc/intr_machdep.c#8 edit .. //depot/projects/soc2006/intr_filter/sparc64/sparc64/intr_machdep.c#8 edit Differences ... ==== //depot/projects/soc2006/intr_filter/amd64/amd64/intr_machdep.c#7 (text+ko) ==== @@ -63,6 +63,8 @@ static struct intsrc *interrupt_sources[NUM_IO_INTS]; static struct mtx intr_table_lock; +extern struct callout stray_callout_handle; + #ifdef SMP static int assign_cpu; @@ -168,6 +170,22 @@ return (isrc->is_pic->pic_config_intr(isrc, trig, pol)); } +/* Stray detection MD code */ +static struct intr_event * +walk_intr_src(void) { + struct intsrc *isrc; + static int i = 0; + + for (; i<NUM_IO_INTS; ) { + int j = i++; + isrc = interrupt_sources[j]; + if (isrc != NULL && isrc->is_event != NULL) + return (isrc->is_event); + } + i = 0; + return (NULL); +} + void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame) { @@ -235,6 +253,15 @@ isrc->is_pic->pic_disable_source(isrc, PIC_EOI); critical_exit(); + /* Interrupt storm logic */ + if (thread & FILTER_STRAY) { + printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", ie->ie_name); + ie->ie_count = INT_MAX; + mtx_lock_spin(&intr_table_lock); + callout_reset(&stray_callout_handle, hz, &stray_detection, &walk_intr_src); + mtx_unlock_spin(&intr_table_lock); + } + /* Schedule the ithread if needed. */ if (thread & FILTER_SCHEDULE_THREAD) { error = intr_event_schedule_thread(ie); @@ -319,6 +346,7 @@ intrcnt_setname("???", 0); intrcnt_index = 1; mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); + callout_init_mtx(&stray_callout_handle, &intr_table_lock, 0); } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL) ==== //depot/projects/soc2006/intr_filter/arm/arm/intr.c#6 (text+ko) ==== @@ -55,6 +55,8 @@ static int intrcnt_index = 0; static int last_printed = 0; +extern struct callout stray_callout_handle; + void arm_handler_execute(struct trapframe *, int); void @@ -98,6 +100,22 @@ { } +/* Stray detection MD code */ +static struct intr_event * +walk_intr_events(void) { + struct intr_event *ie; + static int i = 0; + + for (; i<NIRQ; ) { + int j = i++; + ie = intr_events[j]; + if (ie != NULL) + return (ie); + } + i = 0; + return (NULL); +} + void arm_handler_execute(struct trapframe *frame, int irqnb __unused) { @@ -116,6 +134,19 @@ /* Execute fast handlers. */ thread = intr_filter_loop(event, frame); + /* Interrupt storm logic */ + if (thread & FILTER_STRAY) { + if (event->ie_enable == NULL || event->ie_pending == NULL) + printf("Interrupt stray detection not ready yet: check ie_enable and ie_pending\n"); + else { + printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", event->ie_name); + event->ie_count = INT_MAX; + // XXX missing callout_init_mtx(&stray_callout_handle, ...); + callout_reset(&stray_callout_handle, hz, + &stray_detection, &walk_intr_events); + } + } + // XXX eoi & mask intr not verified. /* Schedule thread if needed. */ if (thread & FILTER_SCHEDULE_THREAD) ==== //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#13 (text+ko) ==== @@ -186,7 +186,7 @@ for (; i<NUM_IO_INTS; ) { int j = i++; isrc = interrupt_sources[j]; - if (isrc != NULL) + if (isrc != NULL && isrc->is_event != NULL) return (isrc->is_event); } i = 0; ==== //depot/projects/soc2006/intr_filter/ia64/ia64/interrupt.c#7 (text+ko) ==== @@ -255,8 +255,11 @@ volatile long *cntp; /* interrupt counter */ }; +#define IA64_NUMI 256 static struct mtx ia64_intrs_lock; -static struct ia64_intr *ia64_intrs[256]; +static struct ia64_intr *ia64_intrs[IA64_NUMI]; + +extern struct callout stray_callout_handle; extern struct sapic *ia64_sapics[]; extern int ia64_sapic_count; @@ -266,6 +269,7 @@ { mtx_init(&ia64_intrs_lock, "intr table", NULL, MTX_SPIN); + callout_init_mtx(&stray_callout_handle, &ia64_intrs_lock, 0); } SYSINIT(ithds_init, SI_SUB_INTR, SI_ORDER_SECOND, ithds_init, NULL); @@ -347,6 +351,22 @@ return (intr_event_remove_handler(cookie)); } +/* Stray detection MD code */ +static struct intr_event * +walk_intr_ia64(void) { + struct ia64_intr *ia64_i; + static int i = 0; + + for (; i<IA64_NUMI; ) { + int j = i++; + ia64_i = ia64_intrs[j]; + if (ia64_i != NULL && ia64_i->event != NULL) + return (ia64_i->event); + } + i = 0; + return (NULL); +} + void ia64_dispatch_intr(void *frame __unused, unsigned long vector) { @@ -383,6 +403,20 @@ thread = intr_filter_loop(ie, NULL); critical_exit(); + /* Interrupt storm logic */ + if (thread & FILTER_STRAY) { + if (ie->ie_enable == NULL || ie->ie_pending == NULL) + printf("Interrupt stray detection not ready yet: check ie_enable and ie_pending\n"); + else { + printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", ie->ie_name); + ie->ie_count = INT_MAX; + mtx_lock_spin(&ia64_intrs_lock); + callout_reset(&stray_callout_handle, hz, + &stray_detection, &walk_intr_ia64); + mtx_unlock_spin(&ia64_intrs_lock); + } + } + // XXX eoi & mask intr not verified. if (thread & FILTER_SCHEDULE_THREAD) { error = intr_event_schedule_thread(ie); ==== //depot/projects/soc2006/intr_filter/powerpc/powerpc/intr_machdep.c#8 (text+ko) ==== @@ -88,6 +88,8 @@ static struct mtx intr_table_lock; +extern struct callout stray_callout_handle; + extern int extint, extsize; extern u_long extint_call; @@ -165,6 +167,7 @@ irq_disable = irq_d; mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); + callout_init_mtx(&stray_callout_handle, &intr_table_lock, 0); } int @@ -223,6 +226,22 @@ return(intr_event_remove_handler(cookie)); } +/* Stray detection MD code */ +static struct intr_event * +walk_intr_ppc(void) { + struct ppc_intr_handler *ppc; + static int i = 0; + + for (; i<intr_nirq; ) { + int j = i++; + ppc = intr_handlers[j]; + if (ppc != NULL && ppc->ih_event != NULL) + return (ppc->ih_event); + } + i = 0; + return (NULL); +} + void intr_handle(u_int irq) { @@ -243,6 +262,20 @@ thread = intr_filter_loop(ie, NULL); critical_exit(); + /* Interrupt storm logic */ + if (thread & FILTER_STRAY) { + if (ie->ie_enable == NULL || ie->ie_pending == NULL) + printf("Interrupt stray detection not ready yet: check ie_enable and ie_pending\n"); + else { + printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", ie->ie_name); + ie->ie_count = INT_MAX; + mtx_lock_spin(&intr_table_lock); + callout_reset(&stray_callout_handle, hz, + &stray_detection, &walk_intr_ppc); + mtx_unlock_spin(&intr_table_lock); + } + } + // XXX eoi & mask intr not verified. /* Schedule a heavyweight interrupt process. */ if (thread & FILTER_SCHEDULE_THREAD) ==== //depot/projects/soc2006/intr_filter/sparc64/sparc64/intr_machdep.c#8 (text+ko) ==== @@ -103,6 +103,8 @@ /* protect the intr_vectors table */ static struct mtx intr_table_lock; +extern struct callout stray_callout_handle; + static void intr_execute_handlers(void *); static void intr_stray_level(struct trapframe *); static void intr_stray_vector(void *); @@ -228,8 +230,25 @@ { mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN); + callout_init_mtx(&stray_callout_handle, &intr_table_lock, 0); } +/* Stray detection MD code */ +static struct intr_event * +walk_intr_sparc64(void) { + struct intr_vector *iv; + static int i = 0; + + for (; i<IV_MAX; ) { + int j = i++; + iv = intr_vectors[j]; + if (iv != NULL && iv->iv_event != NULL) + return (iv->iv_event); + } + i = 0; + return (NULL); +} + static void intr_execute_handlers(void *cookie) { @@ -247,6 +266,20 @@ /* Execute fast interrupt handlers directly. */ thread = intr_filter_loop(ie, NULL); + /* Interrupt storm logic */ + if (thread & FILTER_STRAY) { + if (ie->ie_enable == NULL || ie->ie_pending == NULL) + printf("Interrupt stray detection not ready yet: check ie_enable and ie_pending\n"); + else { + printf("Interrupt stray detected on \"%s\"; throttling interrupt source\n", ie->ie_name); + ie->ie_count = INT_MAX; + mtx_lock_spin(&intr_table_lock); + callout_reset(&stray_callout_handle, hz, + &stray_detection, &walk_intr_sparc64); + mtx_unlock_spin(&intr_table_lock); + } + } + // XXX eoi & mask intr not verified. /* Schedule a heavyweight interrupt process. */ if (thread & FILTER_SCHEDULE_THREAD)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608211408.k7LE8RX2096468>