Skip site navigation (1)Skip section navigation (2)
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>