summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k/mvme88k/m197_machdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k/mvme88k/m197_machdep.c')
-rw-r--r--sys/arch/mvme88k/mvme88k/m197_machdep.c230
1 files changed, 135 insertions, 95 deletions
diff --git a/sys/arch/mvme88k/mvme88k/m197_machdep.c b/sys/arch/mvme88k/mvme88k/m197_machdep.c
index e9fb4d58207..32d2ecc048f 100644
--- a/sys/arch/mvme88k/mvme88k/m197_machdep.c
+++ b/sys/arch/mvme88k/mvme88k/m197_machdep.c
@@ -1,4 +1,20 @@
-/* $OpenBSD: m197_machdep.c,v 1.30 2009/02/13 23:28:07 miod Exp $ */
+/* $OpenBSD: m197_machdep.c,v 1.31 2009/02/13 23:33:51 miod Exp $ */
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
/*
* Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
* Copyright (c) 1996 Nivas Madhur
@@ -74,6 +90,7 @@ void m197_ext_int(u_int, struct trapframe *);
u_int m197_getipl(void);
void m197_ipi_handler(struct trapframe *);
vaddr_t m197_memsize(void);
+void m197_nmi(struct trapframe *);
u_int m197_raiseipl(u_int);
u_int m197_setipl(u_int);
void m197_startup(void);
@@ -180,7 +197,6 @@ m197_ext_int(u_int v, struct trapframe *eframe)
int ret;
vaddr_t ivec;
u_int8_t vec;
- u_int8_t abort;
#ifdef MULTIPROCESSOR
if (eframe->tf_mask < IPL_SCHED)
@@ -189,98 +205,112 @@ m197_ext_int(u_int v, struct trapframe *eframe)
uvmexp.intrs++;
- if (v == T_NON_MASK) {
- /*
- * Non-maskable interrupts are either the abort switch (on
- * cpu0 only) or IPIs (on any cpu). We check for IPI first.
- */
+ level = *(u_int8_t *)M197_ILEVEL & 0x07;
+ /* generate IACK and get the vector */
+ ivec = M197_IACK + (level << 2) + 0x03;
+ vec = *(volatile u_int8_t *)ivec;
+
+ /* block interrupts at level or lower */
+ m197_setipl(level);
+ psr = get_psr();
+ set_psr(psr & ~PSR_IND);
+
#ifdef MULTIPROCESSOR
- if ((*(volatile u_int8_t *)(BS_BASE + BS_CPINT)) & BS_CPI_INT)
- m197_ipi_handler(eframe);
+ /*
+ * If we have pending hardware IPIs and the current
+ * level allows them to be processed, do them now.
+ */
+ if (eframe->tf_mask < IPL_SCHED &&
+ ISSET(ci->ci_ipi, CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK))
+ m197_clock_ipi_handler(eframe);
#endif
- abort = *(u_int8_t *)(BS_BASE + BS_ABORT);
- if (abort & BS_ABORT_INT) {
- *(u_int8_t *)(BS_BASE + BS_ABORT) =
- (abort & ~BS_ABORT_IEN) | BS_ABORT_ICLR;
- nmihand(eframe);
- *(u_int8_t *)(BS_BASE + BS_ABORT) |= BS_ABORT_IEN;
- }
+ list = &intr_handlers[vec];
+ if (SLIST_EMPTY(list))
+ printf("Spurious interrupt (level %x and vec %x)\n",
+ level, vec);
-#ifdef MULTIPROCESSOR
- /*
- * If we have pending hardware IPIs and the current
- * level allows them to be processed, do them now.
- */
- if (eframe->tf_mask < IPL_SCHED &&
- ISSET(ci->ci_ipi,
- CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK)) {
- psr = get_psr();
- set_psr(psr & ~PSR_IND);
- m197_clock_ipi_handler(eframe);
- set_psr(psr);
+ /*
+ * Walk through all interrupt handlers in the chain for the
+ * given vector, calling each handler in turn, till some handler
+ * returns a value != 0.
+ */
+
+ ret = 0;
+ SLIST_FOREACH(intr, list, ih_link) {
+ if (intr->ih_wantframe != 0)
+ ret = (*intr->ih_fn)((void *)eframe);
+ else
+ ret = (*intr->ih_fn)(intr->ih_arg);
+ if (ret != 0) {
+ intr->ih_count.ec_count++;
+ break;
}
-#endif
- } else {
- level = *(u_int8_t *)M197_ILEVEL & 0x07;
- /* generate IACK and get the vector */
- ivec = M197_IACK + (level << 2) + 0x03;
- vec = *(volatile u_int8_t *)ivec;
+ }
- /* block interrupts at level or lower */
- m197_setipl(level);
- psr = get_psr();
- set_psr(psr & ~PSR_IND);
+ if (ret == 0) {
+ printf("Unclaimed interrupt (level %x and vec %x)\n",
+ level, vec);
+ }
+
+#if 0
+ /*
+ * Disable interrupts before returning to assembler,
+ * the spl will be restored later.
+ */
+ set_psr(psr | PSR_IND);
+#endif
#ifdef MULTIPROCESSOR
- /*
- * If we have pending hardware IPIs and the current
- * level allows them to be processed, do them now.
- */
- if (eframe->tf_mask < IPL_SCHED &&
- ISSET(ci->ci_ipi, CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK))
- m197_clock_ipi_handler(eframe);
+ if (eframe->tf_mask < IPL_SCHED)
+ __mp_unlock(&kernel_lock);
#endif
+}
- list = &intr_handlers[vec];
- if (SLIST_EMPTY(list))
- printf("Spurious interrupt (level %x and vec %x)\n",
- level, vec);
+void
+m197_nmi(struct trapframe *eframe)
+{
+ u_int32_t psr;
+ u_int8_t abort;
- /*
- * Walk through all interrupt handlers in the chain for the
- * given vector, calling each handler in turn, till some handler
- * returns a value != 0.
- */
+ /* block all hardware interrupts */
+ m197_setipl(IPL_HIGH); /* IPL_IPI? */
+ psr = get_psr();
+ set_psr(psr & ~PSR_IND);
- ret = 0;
- SLIST_FOREACH(intr, list, ih_link) {
- if (intr->ih_wantframe != 0)
- ret = (*intr->ih_fn)((void *)eframe);
- else
- ret = (*intr->ih_fn)(intr->ih_arg);
- if (ret != 0) {
- intr->ih_count.ec_count++;
- break;
- }
- }
+ /*
+ * Non-maskable interrupts are either the abort switch (on
+ * cpu0 only) or IPIs (on any cpu). We check for IPI first.
+ */
+#ifdef MULTIPROCESSOR
+ if ((*(volatile u_int8_t *)(BS_BASE + BS_CPINT)) & BS_CPI_INT) {
+ /* disable further NMI for now */
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = 0;
+ m197_ipi_handler(eframe);
+ /* acknowledge and reenable IPIs */
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) =
+ BS_CPI_ICLR | BS_CPI_IEN;
+ }
+#endif
- if (ret == 0) {
- printf("Unclaimed interrupt (level %x and vec %x)\n",
- level, vec);
+ if (CPU_IS_PRIMARY(curcpu())) {
+ abort = *(u_int8_t *)(BS_BASE + BS_ABORT);
+ if (abort & BS_ABORT_INT) {
+ *(u_int8_t *)(BS_BASE + BS_ABORT) =
+ (abort & ~BS_ABORT_IEN) | BS_ABORT_ICLR;
+ nmihand(eframe);
+ *(u_int8_t *)(BS_BASE + BS_ABORT) |= BS_ABORT_IEN;
}
-
- /*
- * Disable interrupts before returning to assembler,
- * the spl will be restored later.
- */
- set_psr(psr | PSR_IND);
}
-#ifdef MULTIPROCESSOR
- if (eframe->tf_mask < IPL_SCHED)
- __mp_unlock(&kernel_lock);
+#if 0
+ /*
+ * Disable interrupts before returning to assembler,
+ * the spl will be restored later.
+ */
+ set_psr(psr | PSR_IND);
#endif
+
}
u_int
@@ -387,6 +417,7 @@ m197_bootstrap()
*(volatile u_int8_t *)(BS_BASE + BS_BTIMER) = btimer | pbt;
md_interrupt_func_ptr = m197_ext_int;
+ md_nmi_func_ptr = m197_nmi;
md_getipl = m197_getipl;
md_setipl = m197_setipl;
md_raiseipl = m197_raiseipl;
@@ -409,12 +440,15 @@ m197_send_ipi(int ipi, cpuid_t cpu)
if (ci->ci_ipi & ipi)
return;
+ if ((ci->ci_flags & CIF_ALIVE) == 0)
+ return; /* XXX not ready yet */
+
if (ci->ci_ddb_state == CI_DDB_PAUSE)
return; /* XXX skirting deadlock */
atomic_setbits_int(&ci->ci_ipi, ipi);
- *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = BS_CPI_SCPI | BS_CPI_IEN;
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) |= BS_CPI_SCPI;
}
void
@@ -450,21 +484,23 @@ m197_send_complex_ipi(int ipi, cpuid_t cpu, u_int32_t arg1, u_int32_t arg2)
ci->ci_ipi_arg2 = arg2;
atomic_setbits_int(&ci->ci_ipi, ipi);
- /*
- * Send an IPI, keeping our IPIs enabled.
- */
- *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = BS_CPI_SCPI | BS_CPI_IEN;
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) |= BS_CPI_SCPI;
}
void
m197_ipi_handler(struct trapframe *eframe)
{
struct cpu_info *ci = curcpu();
- int ipi = ci->ci_ipi & ~(CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK);
+ int ipi = ci->ci_ipi;
u_int32_t arg1, arg2;
+#ifdef DDB
+ int need_ddb = 0;
+#endif
- if (ipi != 0)
- atomic_clearbits_int(&ci->ci_ipi, ipi);
+ if (ipi != 0) {
+ atomic_clearbits_int(&ci->ci_ipi,
+ ipi & ~(CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK));
+ }
/*
* Complex IPIs (with extra arguments). There can only be one
@@ -512,25 +548,29 @@ m197_ipi_handler(struct trapframe *eframe)
* If ddb is hoping to us, it's our turn to enter ddb now.
*/
if (ci->ci_cpuid == ddb_mp_nextcpu)
- Debugger();
+ need_ddb = 1;
#endif
}
- if (ipi & CI_IPI_NOTIFY) {
- /* nothing to do */
+ if (ipi & (CI_IPI_NOTIFY | CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK)) {
+ /* force an AST */
+ aston(ci->ci_curproc);
}
- /*
- * Acknowledge IPIs.
- */
- *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = BS_CPI_ICLR | BS_CPI_IEN;
+#ifdef DDB
+ if (need_ddb)
+ Debugger();
+#endif
}
/*
* Maskable IPIs.
*
- * These IPIs are received as non maskable, but are only processed if
- * the current spl permits it; so they are checked again on return from
- * regular interrupts to process them as soon as possible.
+ * These IPIs are received as non maskable, but are not processed in
+ * the NMI handler; instead, they are checked again when changing
+ * spl level on return from regular interrupts to process them as soon
+ * as possible.
+ *
+ * XXX This is grossly suboptimal.
*/
void
m197_clock_ipi_handler(struct trapframe *eframe)