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);