DragonFly kernel List (threaded) for 2008-01
DragonFly BSD
DragonFly kernel List (threaded) for 2008-01
[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]

Re: Interrupt recursion smashes kernel memory


From: Matthew Dillon <dillon@xxxxxxxxxxxxxxxxxxxx>
Date: Sun, 13 Jan 2008 16:41:20 -0800 (PST)

    Ok, it is definitely able to recurse.  Critical sections prevent
    interrupt recursion but also prevent thread preemption, so its a
    chicken and egg problem... I want to prevent interrupt recursion but
    ALLOW thread preemption when scheduling an interrupt thread from
    inside a slow interrupt.

    The slow interrupt code is STI'ing and calling sched_ithd() without
    a critical section held in order to allow it to preempt.  If it does
    preempt, however, the interrupt thread can run, unmask the interrupt,
    and recurse because interrupts are enabled prior to actually getting
    through the doreti.

    I can't use critical sections because those will disable the desired
    thread preemption along with preventing interrupt recursion.

    I can't use gd->intr_nesting_level because the trap code uses doreti
    and isn't expecting intr_nesting_level to be non-zero in most cases.

    I can't leave us CLI'd because, well, its just a bad idea to do that.

    I think the solution is to use TD_NEST_COUNT (curthread->td_nest_count)
    to prevent recursive interrupts from blowing up the stack.

    Please try this patch.

						-Matt

Index: platform/pc32/apic/apic_vector.s
===================================================================
RCS file: /cvs/src/sys/platform/pc32/apic/apic_vector.s,v
retrieving revision 1.36
diff -u -p -r1.36 apic_vector.s
--- platform/pc32/apic/apic_vector.s	22 Jan 2007 19:37:04 -0000	1.36
+++ platform/pc32/apic/apic_vector.s	14 Jan 2008 00:37:34 -0000
@@ -154,6 +154,8 @@ 	movl	$0, lapic_eoi ;						\
 	movl	PCPU(curthread),%ebx ;					\
 	movl	$0,%eax ;	/* CURRENT CPL IN FRAME (REMOVED) */	\
 	pushl	%eax ;							\
+	testl	$-1,TD_NEST_COUNT(%ebx) ;				\
+	jne	1f ;							\
 	cmpl	$TDPRI_CRIT,TD_PRI(%ebx) ;				\
 	jl	2f ;							\
 1: ;									\
@@ -208,6 +210,8 @@ 	movl	$0, lapic_eoi ;						\
 	movl	PCPU(curthread),%ebx ;					\
 	movl	$0,%eax ;	/* CURRENT CPL IN FRAME (REMOVED) */	\
 	pushl	%eax ;		/* cpl do restore */			\
+	testl	$-1,TD_NEST_COUNT(%ebx) ;				\
+	jne	1f ;							\
 	cmpl	$TDPRI_CRIT,TD_PRI(%ebx) ;				\
 	jl	2f ;							\
 1: ;									\
@@ -218,10 +222,13 @@ 	jmp	5f ;							\
 2: ;									\
 	/* set running bit, clear pending bit, run handler */		\
 	andl	$~IRQ_LBIT(irq_num), PCPU(ipending) ;			\
+	incl	TD_NEST_COUNT(%ebx) ;					\
 	sti ;								\
 	pushl	$irq_num ;						\
 	call	sched_ithd ;						\
 	addl	$4,%esp ;						\
+	cli ;								\
+	decl	TD_NEST_COUNT(%ebx) ;					\
 5: ;									\
 	MEXITCOUNT ;							\
 	jmp	doreti ;						\
Index: platform/pc32/icu/icu_vector.s
===================================================================
RCS file: /cvs/src/sys/platform/pc32/icu/icu_vector.s,v
retrieving revision 1.30
diff -u -p -r1.30 icu_vector.s
--- platform/pc32/icu/icu_vector.s	22 Jan 2007 19:37:04 -0000	1.30
+++ platform/pc32/icu/icu_vector.s	14 Jan 2008 00:38:37 -0000
@@ -144,6 +144,8 @@ 	MASK_IRQ(icu, irq_num) ;					\
 	enable_icus ;							\
 	movl	PCPU(curthread),%ebx ;					\
 	pushl	$0 ;			/* DUMMY CPL FOR DORETI */	\
+	testl	$-1,TD_NEST_COUNT(%ebx) ;				\
+	jne	1f ;							\
 	cmpl	$TDPRI_CRIT,TD_PRI(%ebx) ;				\
 	jl	2f ;							\
 1: ;									\
@@ -198,6 +200,8 @@ 	incl    PCPU(cnt) + V_INTR ;           
 	enable_icus ;							\
 	movl	PCPU(curthread),%ebx ;					\
 	pushl	$0 ;			/* DUMMY CPL FOR DORETI */	\
+	testl	$-1,TD_NEST_COUNT(%ebx) ;				\
+	jne	1f ;							\
 	cmpl	$TDPRI_CRIT,TD_PRI(%ebx) ;				\
 	jl	2f ;							\
 1: ;									\
@@ -208,10 +212,13 @@ 	jmp	5f ;							\
 2: ;									\
 	/* set running bit, clear pending bit, run handler */		\
 	andl	$~IRQ_LBIT(irq_num), PCPU(ipending) ;			\
+	incl	TD_NEST_COUNT(%ebx) ;					\
 	sti ;								\
 	pushl	$irq_num ;						\
 	call	sched_ithd ;						\
 	addl	$4,%esp ;						\
+	cli ;								\
+	decl	TD_NEST_COUNT(%ebx) ;					\
 5: ;									\
 	MEXITCOUNT ;							\
 	jmp	doreti ;						\



[Date Prev][Date Next]  [Thread Prev][Thread Next]  [Date Index][Thread Index]