From 78afae27e57f3f98f73e13b048a381e0036db329 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Mon, 6 Aug 2007 05:11:01 +0000 Subject: [PATCH] Keep interrupts disabled while handling external interrupts. There's no advantage in allowing nested external interrupts. In fact, it leads to a potential stack overrun. While here, put the interrupt vector in the trapframe, so as to compensate for the 36 cycle latency of reading cr.ivr. Further simplify assembly code by dealing with ASTs from C. Approved by: re (blanket) --- sys/ia64/ia64/exception.S | 67 +++++++++++++------------------------- sys/ia64/ia64/interrupt.c | 68 +++++++++++++++++++++++---------------- sys/ia64/include/md_var.h | 2 +- 3 files changed, 64 insertions(+), 73 deletions(-) diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S index d1864525d56..aa96357e19c 100644 --- a/sys/ia64/ia64/exception.S +++ b/sys/ia64/ia64/exception.S @@ -636,22 +636,22 @@ END(exception_restore) { .mib ; \ mov r17=_ifa_ ; \ mov r16=ip ; \ - br.sptk exception_save ; \ + br.sptk exception_save ;; \ } ; \ { .mmi ; \ -(p11) ssm psr.i ;; \ - alloc r15=ar.pfs,0,0,2,0 ; \ + alloc r15=ar.pfs,0,0,2,0 ;; \ +(p11) ssm psr.i ; \ mov out0=_n_ ;; \ } ; \ -{ .mfb ; \ +{ .mib ; \ +(p11) srlz.d ; \ add out1=16,sp ; \ - nop 0 ; \ - br.call.sptk rp=_func_ ; \ + br.call.sptk rp=_func_ ;; \ } ; \ { .mfb ; \ nop 0 ; \ nop 0 ; \ - br.sptk exception_restore ; \ + br.sptk exception_restore ;; \ } #define IVT_ENTRY(name, offset) \ @@ -1233,13 +1233,19 @@ IVT_ENTRY(Break_Instruction, 0x2c00) { .mmi alloc r15=ar.pfs,0,0,2,0 ;; - flushrs +(p11) ssm psr.i mov out0=11 ;; } -{ .mib -(p11) ssm psr.i +{ .mmi + flushrs + ;; +(p11) srlz.d add out1=16,sp +} +{ .mfb + nop 0 + nop 0 br.call.sptk rp=trap ;; } @@ -1253,50 +1259,21 @@ IVT_END(Break_Instruction) IVT_ENTRY(External_Interrupt, 0x3000) { .mib - mov r17=cr.lid // cr.iim and cr.ifa are undefined. + mov r17=cr.ivr // Put the vector in the trap frame. mov r16=ip br.sptk exception_save ;; } - alloc r14=ar.pfs,0,0,2,0 - cmp4.eq p14,p0=0,r0 - ;; -1: -{ .mii - mov out0=cr.ivr // Get interrupt vector - add out1=16,sp - ;; - cmp.eq p15,p0=15,out0 // check for spurious vector number -} -{ .mbb - ssm psr.i // re-enable interrupts -(p15) br.dpnt.few 2f // if spurious, we are done - br.call.sptk.many rp=interrupt // call high-level handler - ;; -} -{ .mmi - rsm psr.i // disable interrupts - ;; - srlz.d +{ .mfb + alloc r15=ar.pfs,0,0,1,0 nop 0 -} -{ .mmi - mov cr.eoi=r0 // ack the interrupt - ;; - srlz.d nop 0 + ;; } { .mfb - cmp4.eq p14,p0=0,r8 // Return to kernel mode? - nop 0 - br.sptk 1b // loop for more - ;; -} -2: -{ .mbb add out0=16,sp -(p14) br.sptk exception_restore - br.call.sptk rp=do_ast + nop 0 + br.call.sptk rp=interrupt ;; } { .mfb diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c index 2290bd779a8..5460c59428b 100644 --- a/sys/ia64/ia64/interrupt.c +++ b/sys/ia64/ia64/interrupt.c @@ -127,34 +127,44 @@ static int adjust_ticks = 0; SYSCTL_INT(_debug_clock, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks, 0, "Total number of ITC interrupts with adjustment"); -int -interrupt(u_int vector, struct trapframe *tf) +void +interrupt(struct trapframe *tf) { struct thread *td; volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK; uint64_t adj, clk, itc; int64_t delta; + u_int vector; int count; - + uint8_t inta; ia64_set_fpsr(IA64_FPSR_DEFAULT); td = curthread; atomic_add_int(&td->td_intr_nesting_level, 1); + vector = tf->tf_special.ifa; + + next: /* * Handle ExtINT interrupts by generating an INTA cycle to * read the vector. */ if (vector == 0) { - vector = ib->ib_inta; - printf("ExtINT interrupt: vector=%u\n", vector); - if (vector == 15) + inta = ib->ib_inta; + printf("ExtINT interrupt: vector=%u\n", (int)inta); + if (inta == 15) { + __asm __volatile("mov cr.eoi = r0;; srlz.d"); goto stray; - } + } + vector = (int)inta; + } else if (vector == 15) + goto stray; if (vector == CLOCK_VECTOR) {/* clock interrupt */ /* CTR0(KTR_INTR, "clock interrupt"); */ + itc = ia64_get_itc(); + PCPU_INC(cnt.v_intr); #ifdef EVCNT_COUNTERS clock_intr_evcnt.ev_count++; @@ -166,8 +176,6 @@ interrupt(u_int vector, struct trapframe *tf) critical_enter(); adj = PCPU_GET(clockadj); - itc = ia64_get_itc(); - ia64_set_itm(itc + ia64_clock_reload - adj); clk = PCPU_GET(clock); delta = itc - clk; count = 0; @@ -186,6 +194,7 @@ interrupt(u_int vector, struct trapframe *tf) adjust_ticks++; count++; } + ia64_set_itm(itc + ia64_clock_reload - adj); if (count > 0) { adjust_lost += count - 1; if (delta > (ia64_clock_reload >> 3)) { @@ -200,8 +209,8 @@ interrupt(u_int vector, struct trapframe *tf) } PCPU_SET(clock, clk); PCPU_SET(clockadj, adj); - critical_exit(); + ia64_srlz_d(); #ifdef SMP } else if (vector == ipi_vector[IPI_AST]) { @@ -221,17 +230,14 @@ interrupt(u_int vector, struct trapframe *tf) CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid)); smp_rendezvous_action(); } else if (vector == ipi_vector[IPI_STOP]) { - register_t intr; cpumask_t mybit = PCPU_GET(cpumask); - intr = intr_disable(); savectx(PCPU_PTR(pcb)); atomic_set_int(&stopped_cpus, mybit); while ((started_cpus & mybit) == 0) - /* spin */; + cpu_spinwait(); atomic_clear_int(&started_cpus, mybit); atomic_clear_int(&stopped_cpus, mybit); - intr_restore(intr); } else if (vector == ipi_vector[IPI_TEST]) { CTR1(KTR_SMP, "IPI_TEST, cpuid=%d", PCPU_GET(cpuid)); mp_ipi_test++; @@ -241,9 +247,20 @@ interrupt(u_int vector, struct trapframe *tf) ia64_dispatch_intr(tf, vector); } + __asm __volatile("mov cr.eoi = r0;; srlz.d"); + vector = ia64_get_ivr(); + if (vector != 15) + goto next; + stray: atomic_subtract_int(&td->td_intr_nesting_level, 1); - return (TRAPF_USERMODE(tf)); + + if (TRAPF_USERMODE(tf)) { + enable_intr(); + userret(td, tf); + mtx_assert(&Giant, MA_NOTOWNED); + do_ast(tf); + } } /* @@ -271,22 +288,21 @@ ia64_intr_eoi(void *arg) sapic_eoi(i->sapic, vector); } -#ifdef INTR_FILTER static void -ia64_intr_disable(void *arg) +ia64_intr_mask(void *arg) { u_int vector = (uintptr_t)arg; struct ia64_intr *i; i = ia64_intrs[vector]; if (i != NULL) { - sapic_eoi(i->sapic, vector); sapic_mask(i->sapic, i->irq); + sapic_eoi(i->sapic, vector); } } static void -ia64_intr_enable(void *arg) +ia64_intr_unmask(void *arg) { u_int vector = (uintptr_t)arg; struct ia64_intr *i; @@ -295,7 +311,6 @@ ia64_intr_enable(void *arg) if (i != NULL) sapic_unmask(i->sapic, i->irq); } -#endif int ia64_setup_intr(const char *name, int irq, driver_filter_t filter, @@ -324,14 +339,12 @@ ia64_setup_intr(const char *name, int irq, driver_filter_t filter, if (i == NULL) return (ENOMEM); + error = intr_event_create(&i->event, (void *)(uintptr_t)vector, + 0, ia64_intr_unmask, #ifdef INTR_FILTER - error = intr_event_create(&i->event, (void *)(uintptr_t)vector, - 0, ia64_intr_enable, ia64_intr_eoi, ia64_intr_disable, - "irq%u:", irq); -#else - error = intr_event_create(&i->event, (void *)(uintptr_t)vector, - 0, ia64_intr_eoi, "irq%u:", irq); + ia64_intr_eoi, ia64_intr_mask, #endif + "irq%u:", irq); if (error) { free(i, M_DEVBUF); return (error); @@ -393,7 +406,7 @@ ia64_dispatch_intr(void *frame, u_int vector) #ifdef INTR_FILTER if (intr_event_handle(ie, frame) != 0) { - ia64_intr_disable((void *)(uintptr_t)vector); + ia64_intr_mask((void *)(uintptr_t)vector); log(LOG_ERR, "stray irq%u\n", i->irq); } #else @@ -431,6 +444,7 @@ ia64_dispatch_intr(void *frame, u_int vector) critical_exit(); if (thread) { + ia64_intr_mask((void *)(uintptr_t)vector); error = intr_event_schedule_thread(ie); KASSERT(error == 0, ("%s: impossible stray", __func__)); } else diff --git a/sys/ia64/include/md_var.h b/sys/ia64/include/md_var.h index e54ac9e6faf..738fefa08d9 100644 --- a/sys/ia64/include/md_var.h +++ b/sys/ia64/include/md_var.h @@ -84,7 +84,7 @@ int ia64_highfp_drop(struct thread *); int ia64_highfp_save(struct thread *); void ia64_init(void); void ia64_probe_sapics(void); -int interrupt(u_int, struct trapframe *); +void interrupt(struct trapframe *); void map_gateway_page(void); void map_pal_code(void); void map_vhpt(uintptr_t);