diff options
-rw-r--r-- | sys/sun4v/sun4v/interrupt.S | 30 | ||||
-rw-r--r-- | sys/sun4v/sun4v/intr_machdep.c | 83 |
2 files changed, 75 insertions, 38 deletions
diff --git a/sys/sun4v/sun4v/interrupt.S b/sys/sun4v/sun4v/interrupt.S index 9fc67f1..0470e16 100644 --- a/sys/sun4v/sun4v/interrupt.S +++ b/sys/sun4v/sun4v/interrupt.S @@ -86,9 +86,6 @@ ENTRY(intr_fast) call %o0 mov %o1, %o0 - lduw [%l0 + IR_VEC], %o0 - call hvio_intr_setstate - mov HV_INTR_IDLE_STATE, %o1 ba,a %xcc, 1b nop END(intr_fast) @@ -386,7 +383,7 @@ ENTRY(tl_invlctx) ta FAST_TRAP brz,pt %o0, 1f nop - ba panic_bad_hcall + ba interrupt_panic_bad_hcall mov MMU_DEMAP_CTX, %o1 1: mov %g2, %o0 @@ -411,7 +408,7 @@ ENTRY(tl_invltlb) ta FAST_TRAP brz,pt %o0, 1f nop - ba panic_bad_hcall + ba interrupt_panic_bad_hcall mov MMU_DEMAP_ALL, %o1 1: mov %g1, %o0 @@ -433,7 +430,7 @@ ENTRY(tl_invlpg) ta MMU_UNMAP_ADDR brz,pt %o0, 1f nop - ba panic_bad_hcall + ba interrupt_panic_bad_hcall mov MMU_UNMAP_ADDR, %o1 1: mov %g5, %o0 @@ -475,3 +472,24 @@ ENTRY(set_ackmask) lda [%g3]%asi, %g1 retry END(set_ackmask) + + /* + * interrupt_panic_bad_hcall is called when a hcall returns + * unexpected error + * %o0 error number + * %o1 hcall number + */ + + .text +interrupt_bad_hcall_error: + .asciz "hypervisor call 0x%x returned an unexpected error %d" + + + ENTRY(interrupt_panic_bad_hcall) + mov %o0, %o2 + sethi %hi(interrupt_bad_hcall_error), %o0 + or %o0, %lo(interrupt_bad_hcall_error), %o0 + mov %o7, %o3 + call panic + mov %o3, %o7 + SET_SIZE(interrupt_panic_bad_hcall) diff --git a/sys/sun4v/sun4v/intr_machdep.c b/sys/sun4v/sun4v/intr_machdep.c index 8ce3989..cd650e5 100644 --- a/sys/sun4v/sun4v/intr_machdep.c +++ b/sys/sun4v/sun4v/intr_machdep.c @@ -99,6 +99,12 @@ struct intr_vector intr_vectors[IV_MAX]; uint16_t intr_countp[IV_MAX]; static u_long intr_stray_count[IV_MAX]; +struct ithread_vector_handler { + iv_func_t *ivh_handler; + void *ivh_arg; + u_int ivh_vec; +}; + static char *pil_names[] = { "stray", "low", /* PIL_LOW */ @@ -203,23 +209,17 @@ intr_setup(int pri, ih_func_t *ihf, int vec, iv_func_t *ivf, void *iva) char pilname[MAXCOMLEN + 1]; u_long ps; - ps = intr_disable(); + ps = intr_disable_all(); if (vec != -1) { - if ((char *)intr_vectors[vec].iv_func == (char *)intr_stray_level) { - intr_vectors[vec].iv_func = ivf; - intr_vectors[vec].iv_arg = iva; - } else { - intr_vectors[vec].iv_func = intr_execute_handlers; - intr_vectors[vec].iv_arg = &intr_vectors[vec]; - } - if (pri > intr_vectors[vec].iv_pri) - intr_vectors[vec].iv_pri = pri; + intr_vectors[vec].iv_func = ivf; + intr_vectors[vec].iv_arg = iva; + intr_vectors[vec].iv_pri = pri; intr_vectors[vec].iv_vec = vec; } snprintf(pilname, MAXCOMLEN + 1, "pil%d: %s", pri, pil_names[pri]); intrcnt_updatename(pri, pilname, 1); intr_handlers[pri] = ihf; - intr_restore(ps); + intr_restore_all(ps); } static void @@ -288,7 +288,6 @@ intr_execute_handlers(void *cookie) return; } - /* Execute fast interrupt handlers directly. */ thread = 0; TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { if (!(ih->ih_flags & IH_FAST)) { @@ -301,17 +300,26 @@ intr_execute_handlers(void *cookie) ih->ih_handler(ih->ih_argument); } - hvio_intr_setstate(iv->iv_vec, HV_INTR_IDLE_STATE); - /* Schedule a heavyweight interrupt process. */ - if (thread) + if (thread) { error = intr_event_schedule_thread(ie); - else if (TAILQ_EMPTY(&ie->ie_handlers)) - error = EINVAL; - else - error = 0; - if (error == EINVAL) - intr_stray_vector(iv); + } else { + if (TAILQ_EMPTY(&ie->ie_handlers)) + intr_stray_vector(iv); + else + hvio_intr_setstate(iv->iv_vec, HV_INTR_IDLE_STATE); + } +} + +static void +ithread_wrapper(void *arg) +{ + struct ithread_vector_handler *ivh = (struct ithread_vector_handler *)arg; + + ivh->ivh_handler(ivh->ivh_arg); + /* re-enable interrupt */ + hvio_intr_setstate(ivh->ivh_vec, HV_INTR_IDLE_STATE); + } int @@ -321,9 +329,9 @@ inthand_add(const char *name, int vec, void (*handler)(void *), void *arg, struct intr_vector *iv; struct intr_event *ie; /* descriptor for the IRQ */ struct intr_event *orphan; + struct ithread_vector_handler *ivh; int errcode, pil; - iv_func_t *ivf; - void *iva; + /* * Work around a race where more than one CPU may be registering * handlers on the same IRQ at the same time. @@ -349,16 +357,29 @@ inthand_add(const char *name, int vec, void (*handler)(void *), void *arg, } } - errcode = intr_event_add_handler(ie, name, handler, arg, - intr_priority(flags), flags, cookiep); - if (errcode) + if (!(flags & INTR_FAST)) { + ivh = (struct ithread_vector_handler *) + malloc(sizeof(struct ithread_vector_handler), M_DEVBUF, M_WAITOK); + ivh->ivh_handler = handler; + ivh->ivh_arg = arg; + ivh->ivh_vec = vec; + errcode = intr_event_add_handler(ie, name, ithread_wrapper, ivh, + intr_priority(flags), flags, cookiep); + } else { + ivh = NULL; + errcode = intr_event_add_handler(ie, name, handler, arg, + intr_priority(flags), flags, + cookiep); + } + + if (errcode) { + if (ivh) + free(ivh, M_DEVBUF); return (errcode); - + } pil = (flags & INTR_FAST) ? PIL_FAST : PIL_ITHREAD; - ivf = (flags & INTR_FAST) ? handler : intr_execute_handlers; - iva = (flags & INTR_FAST) ? arg : iv; - intr_setup(pil, intr_fast, vec, ivf, iva); + intr_setup(pil, intr_fast, vec, intr_execute_handlers, iv); intr_stray_count[vec] = 0; @@ -400,8 +421,6 @@ static void cpu_intrq_alloc(void) { - - mondo_data_array = malloc(INTR_REPORT_SIZE*MAXCPU, M_DEVBUF, M_WAITOK | M_ZERO); PANIC_IF(mondo_data_array == NULL); |