From owner-freebsd-smp Sun Nov 3 01:54:06 1996 Return-Path: owner-smp Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id BAA11406 for smp-outgoing; Sun, 3 Nov 1996 01:54:06 -0800 (PST) Received: from godzilla.zeta.org.au (godzilla.zeta.org.au [203.2.228.19]) by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id BAA11395; Sun, 3 Nov 1996 01:53:53 -0800 (PST) Received: (from bde@localhost) by godzilla.zeta.org.au (8.7.6/8.6.9) id UAA28658; Sun, 3 Nov 1996 20:47:03 +1100 Date: Sun, 3 Nov 1996 20:47:03 +1100 From: Bruce Evans Message-Id: <199611030947.UAA28658@godzilla.zeta.org.au> To: dg@Root.COM, smp@csn.net Subject: Re: ed0 timeouts Cc: bde@zeta.org.au, hackers@freefall.freebsd.org, smp@freefall.freebsd.org Sender: owner-smp@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >bummer... > >Intel says: > >It is strongly recommended that first 82489 (ie APIC) should be unmasked >and then the device interrupt should be enabled. By this sequence software >can ensure that always an edge will occur at the APIC input only after >the interrupt is unmasked. My version of -current does lazy 8259-masking so that the 8259 doesn't have to be masked unless the device interrupt repeats. It would probably work to never mask it for edge triggered interrupts, but I'm worried about noise, and level sensitive interrupts need to be handled somehow. Is the APIC also braindamaged for interrupts masked at the CPU level? Bruce Warning: these diffs contain unrelated things (mostly undefined macros) that won't compile. diff -c2 icu.s~ icu.s *** icu.s~ Thu Oct 31 22:48:25 1996 --- icu.s Thu Oct 31 22:48:27 1996 *************** *** 106,109 **** --- 106,110 ---- jne doreti_unpend doreti_exit: + CPL_CHANGE_3(%eax) movl %eax,_cpl decb _intr_nesting_level *************** *** 154,157 **** --- 155,159 ---- jae doreti_swi cli + CPL_CHANGE_3(%eax) movl %eax,_cpl MEXITCOUNT *************** *** 171,175 **** --- 173,179 ---- */ orl imasks(,%ecx,4),%eax + CPL_CHANGE_4(%eax) movl %eax,_cpl + CPL_CHANGE_4_DONE call %edx popl %eax *************** *** 256,263 **** --- 260,271 ---- pushl %eax orl imasks(,%ecx,4),%eax + CPL_CHANGE_4(%eax) movl %eax,_cpl + CPL_CHANGE_4_DONE call %edx popl %eax + CPL_CHANGE_4(%eax) movl %eax,_cpl + CPL_CHANGE_4_DONE jmp splz_next *************** *** 276,279 **** --- 284,291 ---- pushl %eax cli + #define irq_num 0 + andb $~IRQ_BIT(irq_num),iactive + IRQ_BYTE(irq_num) + incl inotactive_counts + (irq_num) * 4 + #undef irq_num MEXITCOUNT jmp _Xintr0 /* XXX might need _Xfastintr0 */ *************** *** 287,290 **** --- 299,306 ---- pushl %eax cli + #define irq_num 8 + andb $~IRQ_BIT(irq_num),iactive + IRQ_BYTE(irq_num) + incl inotactive_counts + (irq_num) * 4 + #undef irq_num MEXITCOUNT jmp _Xintr8 /* XXX might need _Xfastintr8 */ *************** *** 294,299 **** --- 310,327 ---- ALIGN_TEXT ; \ __CONCAT(vec,irq_num): ; \ + popl %eax ; \ + pushfl ; \ + pushl $KCSEL ; \ + pushl %eax ; \ + cli ; \ + andb $~IRQ_BIT(irq_num),iactive + IRQ_BYTE(irq_num) ; \ + incl inotactive_counts + (irq_num) * 4 ; \ + MEXITCOUNT ; \ + jmp __CONCAT(_Xintr,irq_num) + + #if 0 int $ICU_OFFSET + (irq_num) ; \ ret + #endif BUILD_VEC(1) diff -c2 vector.s~ vector.s *** vector.s~ Thu Oct 31 22:44:16 1996 --- vector.s Thu Oct 31 22:45:20 1996 *************** *** 128,131 **** --- 128,132 ---- pushl _intr_unit + (irq_num) * 4 ; \ call *_intr_handler + (irq_num) * 4 ; /* do the work ASAP */ \ + INTR_ARG_ADJUST ; \ enable_icus ; /* (re)enable ASAP (helps edge trigger?) */ \ addl $4,%esp ; \ *************** *** 136,140 **** notl %eax ; \ andl _ipending,%eax ; \ ! jne 1f ; /* yes, handle them */ \ MEXITCOUNT ; \ MAYBE_POPL_ES ; \ --- 137,142 ---- notl %eax ; \ andl _ipending,%eax ; \ ! jne 3f ; /* yes, maybe handle them */ \ ! 2: ; \ MEXITCOUNT ; \ MAYBE_POPL_ES ; \ *************** *** 145,152 **** --- 147,162 ---- iret ; \ ; \ + 3: ; \ + cmpb $3,_intr_nesting_level ; /* is there enough stack? */ \ + jb 1f ; /* yes, handle unmasked interrupts */ \ + jmp 2b ; /* no, return */ \ + ; \ ALIGN_TEXT ; \ 1: ; \ + CPL_CHANGE($HWI_MASK|SWI_MASK) ; \ movl _cpl,%eax ; \ + /* XXX next line is probably unnecessary now. */ \ movl $HWI_MASK|SWI_MASK,_cpl ; /* limit nesting ... */ \ + incb _intr_nesting_level ; /* ... really limit it ... */ \ sti ; /* ... to do this as early as possible */ \ MAYBE_POPL_ES ; /* discard most of thin frame ... */ \ *************** *** 164,168 **** pushl %eax ; \ subl $4,%esp ; /* junk for unit number */ \ - incb _intr_nesting_level ; \ MEXITCOUNT ; \ jmp _doreti --- 174,177 ---- *************** *** 180,189 **** movl %ax,%ds ; /* ... early for obsolete reasons */ \ movl %ax,%es ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ orb $IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ enable_icus ; \ - incl _cnt+V_INTR ; /* tally interrupts */ \ movl _cpl,%eax ; \ testb $IRQ_BIT(irq_num),%reg ; \ --- 189,215 ---- movl %ax,%ds ; /* ... early for obsolete reasons */ \ movl %ax,%es ; \ + movb iactive + IRQ_BYTE(irq_num),%al ; \ + testb $IRQ_BIT(irq_num),%al ; \ + je 1f ; \ + /* XXX skip mcounting here to avoid double count */ \ movb _imen + IRQ_BYTE(irq_num),%al ; \ orb $IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ + incl imen_counts + (irq_num) * 4 ; \ + enable_icus ; \ + orb $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num) ; \ + popl %es ; \ + popl %ds ; \ + popal ; \ + addl $4+4,%esp ; \ + iret ; \ + ; \ + ALIGN_TEXT ; \ + 1: ; \ + orb $IRQ_BIT(irq_num),%al ; \ + movb %al,iactive + IRQ_BYTE(irq_num) ; \ + incl iactive_counts + (irq_num) * 4 ; \ enable_icus ; \ movl _cpl,%eax ; \ testb $IRQ_BIT(irq_num),%reg ; \ *************** *** 192,195 **** --- 218,222 ---- __CONCAT(Xresume,irq_num): ; \ FAKE_MCOUNT(12*4(%esp)) ; /* XXX late to avoid double count */ \ + incl _cnt+V_INTR ; /* tally interrupts */ \ movl _intr_countp + (irq_num) * 4,%eax ; \ incl (%eax) ; \ *************** *** 198,209 **** pushl _intr_unit + (irq_num) * 4 ; \ orl _intr_mask + (irq_num) * 4,%eax ; \ movl %eax,_cpl ; \ sti ; \ call *_intr_handler + (irq_num) * 4 ; \ ! cli ; /* must unmask _imen and icu atomically */ \ movb _imen + IRQ_BYTE(irq_num),%al ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ sti ; /* XXX _doreti repeats the cli/sti */ \ MEXITCOUNT ; \ --- 225,244 ---- pushl _intr_unit + (irq_num) * 4 ; \ orl _intr_mask + (irq_num) * 4,%eax ; \ + CPL_CHANGE_1(%eax, irq_num) ; \ movl %eax,_cpl ; \ sti ; \ call *_intr_handler + (irq_num) * 4 ; \ ! INTR_ARG_ADJUST ; \ ! cli ; /* unmask iactive, _imen and icu atomically */ \ ! andb $~IRQ_BIT(irq_num),iactive + IRQ_BYTE(irq_num) ; \ ! incl inotactive_counts + (irq_num) * 4 ; \ movb _imen + IRQ_BYTE(irq_num),%al ; \ + testb $IRQ_BIT(irq_num),%al ; \ + je 3f ; \ andb $~IRQ_BIT(irq_num),%al ; \ movb %al,_imen + IRQ_BYTE(irq_num) ; \ outb %al,$icu+ICU_IMR_OFFSET ; \ + incl inotmen_counts + (irq_num) * 4 ; \ + 3: ; \ sti ; /* XXX _doreti repeats the cli/sti */ \ MEXITCOUNT ; \ *************** *** 258,261 **** --- 293,306 ---- .data + iactive: + .long 0 + iactive_counts: + .space NHWI*4 + inotactive_counts: + .space NHWI*4 + imen_counts: + .space NHWI*4 + inotmen_counts: + .space NHWI*4 ihandlers: /* addresses of interrupt handlers */ /* actually resumption addresses for HWI's */