summaryrefslogtreecommitdiff
path: root/sys/arch/mvme88k
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mvme88k')
-rw-r--r--sys/arch/mvme88k/dev/bussw.c47
-rw-r--r--sys/arch/mvme88k/dev/busswreg.h22
-rw-r--r--sys/arch/mvme88k/include/mvme197.h6
-rw-r--r--sys/arch/mvme88k/mvme88k/m197_machdep.c260
-rw-r--r--sys/arch/mvme88k/mvme88k/m1x7_machdep.c22
-rw-r--r--sys/arch/mvme88k/mvme88k/m88110.c37
6 files changed, 301 insertions, 93 deletions
diff --git a/sys/arch/mvme88k/dev/bussw.c b/sys/arch/mvme88k/dev/bussw.c
index 2b283a6c544..4e0a52249c3 100644
--- a/sys/arch/mvme88k/dev/bussw.c
+++ b/sys/arch/mvme88k/dev/bussw.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bussw.c,v 1.18 2007/12/04 05:40:14 miod Exp $ */
+/* $OpenBSD: bussw.c,v 1.19 2007/12/04 23:45:52 miod Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
*
@@ -36,7 +36,6 @@
struct bussw_softc {
struct device sc_dev;
- struct intrhand sc_abih; /* `abort' switch */
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
};
@@ -54,8 +53,6 @@ struct cfdriver bussw_cd = {
int bussw_print(void *, const char *);
int bussw_scan(struct device *, void *, void *);
-int busswabort(void *);
-int busswintr_establish(int, struct intrhand *, const char *);
int
bussw_match(parent, vcf, args)
@@ -107,18 +104,12 @@ bussw_attach(parent, self, args)
bus_space_write_1(sc->sc_iot, ioh, BS_VBASE,
bus_space_read_1(sc->sc_iot, ioh, BS_VBASE) | BS_VECBASE);
+
+ /* enable external interrupts */
bus_space_write_2(sc->sc_iot, ioh, BS_GCSR,
bus_space_read_2(sc->sc_iot, ioh, BS_GCSR) | BS_GCSR_XIPL);
- /*
- * pseudo driver, abort interrupt handler
- */
- sc->sc_abih.ih_fn = busswabort;
- sc->sc_abih.ih_arg = 0;
- sc->sc_abih.ih_wantframe = 1;
- sc->sc_abih.ih_ipl = IPL_NMI;
-
- busswintr_establish(BS_ABORTIRQ, &sc->sc_abih, "abort");
+ /* enable abort switch */
bus_space_write_1(sc->sc_iot, ioh, BS_ABORT,
bus_space_read_1(sc->sc_iot, ioh, BS_ABORT) | BS_ABORT_IEN);
@@ -167,33 +158,3 @@ bussw_scan(parent, child, args)
config_attach(parent, cf, &oca, bussw_print);
return (1);
}
-
-int
-busswintr_establish(int vec, struct intrhand *ih, const char *name)
-{
-#ifdef DIAGNOSTIC
- if (vec < 0 || vec >= BS_NVEC)
- panic("busswintr_establish: illegal vector 0x%x", vec);
-#endif
-
- return intr_establish(BS_VECBASE + vec, ih, name);
-}
-
-int
-busswabort(eframe)
- void *eframe;
-{
- struct frame *frame = eframe;
-
- struct bussw_softc *sc = (struct bussw_softc *)bussw_cd.cd_devs[0];
- u_int8_t abort;
-
- abort = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BS_ABORT);
- if (abort & BS_ABORT_INT) {
- bus_space_write_1(sc->sc_iot, sc->sc_ioh, BS_ABORT,
- abort | BS_ABORT_ICLR);
- nmihand(frame);
- return 1;
- }
- return 0;
-}
diff --git a/sys/arch/mvme88k/dev/busswreg.h b/sys/arch/mvme88k/dev/busswreg.h
index 15a31df42ca..f17e49c5f01 100644
--- a/sys/arch/mvme88k/dev/busswreg.h
+++ b/sys/arch/mvme88k/dev/busswreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: busswreg.h,v 1.8 2007/11/22 05:53:57 miod Exp $ */
+/* $OpenBSD: busswreg.h,v 1.9 2007/12/04 23:45:52 miod Exp $ */
/*
* Memory map for BusSwitch chip found in mvme197 boards.
@@ -191,16 +191,18 @@
#define BS_VBASE_SRC_EXT 0x4 /* external interrupt */
#define BS_VBASE_SRC_SPUR 0x7 /* spurious interrupt */
-/* We lock off BusSwitch vectors at 0x40 */
-#define BS_VECBASE 0x40
-#define BS_NVEC 0x10
+/*
+ * BusSwitch wired interrupt vectors
+ */
-/* Bottom 4 bits of the vector returned during IACK cycle */
-#define BS_TMR1IRQ 0x01 /* lowest */
-#define BS_TMR2IRQ 0x02
-#define BS_ABORTIRQ 0x03
+#define BS_VECBASE 0x40 /* vector base */
+#define BS_NVEC 0x10
-/* Define the Abort vector */
-#define BS_ABORTVEC (BS_VECBASE | BS_ABORTIRQ)
+#define BS_TMR1IRQ 0x00 /* timer1 */
+#define BS_TMR2IRQ 0x01 /* timer2 */
+#define BS_WPEIRQ 0x02 /* write post error */
+#define BS_PALIRQ 0x03 /* processor address log interrupt */
+#define BS_EXTIRQ 0x04 /* external interrupt */
+#define BS_SPURIRQ 0x07 /* spurious interrupt */
#endif /* BUSSWREG_H */
diff --git a/sys/arch/mvme88k/include/mvme197.h b/sys/arch/mvme88k/include/mvme197.h
index 9f137ad3451..84eab739bd5 100644
--- a/sys/arch/mvme88k/include/mvme197.h
+++ b/sys/arch/mvme88k/include/mvme197.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mvme197.h,v 1.7 2006/04/27 20:21:19 miod Exp $ */
+/* $OpenBSD: mvme197.h,v 1.8 2007/12/04 23:45:52 miod Exp $ */
/*
* Copyright (c) 1996 Nivas Madhur
* Copyright (c) 1999 Steve Murphree, Jr.
@@ -58,4 +58,8 @@
#define M197_ISRC 0xfff0006f /* interrupt SRC */
#define M197_IACK 0xfff00100 /* interrupt ACK base */
+#ifdef _KERNEL
+void m197_send_complex_ipi(int, cpuid_t, u_int32_t, u_int32_t);
+#endif
+
#endif /* __MACHINE_MVME197_H__ */
diff --git a/sys/arch/mvme88k/mvme88k/m197_machdep.c b/sys/arch/mvme88k/mvme88k/m197_machdep.c
index f73107ffc05..3f1ca1c6323 100644
--- a/sys/arch/mvme88k/mvme88k/m197_machdep.c
+++ b/sys/arch/mvme88k/mvme88k/m197_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m197_machdep.c,v 1.19 2007/12/02 21:32:10 miod Exp $ */
+/* $OpenBSD: m197_machdep.c,v 1.20 2007/12/04 23:45:53 miod Exp $ */
/*
* Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr.
* Copyright (c) 1996 Nivas Madhur
@@ -62,11 +62,18 @@
#include <mvme88k/dev/busswreg.h>
#include <mvme88k/mvme88k/clockvar.h>
+#ifdef MULTIPROCESSOR
+#include <machine/db_machdep.h>
+#endif
+
void m197_bootstrap(void);
+void m197_clock_ipi_handler(struct trapframe *);
void m197_ext_int(u_int, struct trapframe *);
u_int m197_getipl(void);
+void m197_ipi_handler(struct trapframe *);
vaddr_t m197_memsize(void);
u_int m197_raiseipl(u_int);
+void m197_send_ipi(int, cpuid_t);
u_int m197_setipl(u_int);
void m197_startup(void);
@@ -154,23 +161,17 @@ m197_startup()
void
m197_ext_int(u_int v, struct trapframe *eframe)
{
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci = curcpu();
+#endif
+ u_int32_t psr;
int level;
struct intrhand *intr;
intrhand_t *list;
int ret;
vaddr_t ivec;
u_int8_t vec;
-
- if (v == T_NON_MASK) {
- /* This is the abort switch */
- level = IPL_NMI;
- vec = BS_ABORTVEC;
- } 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;
- }
+ u_int8_t abort;
#ifdef MULTIPROCESSOR
if (eframe->tf_mask < IPL_SCHED)
@@ -179,27 +180,63 @@ m197_ext_int(u_int v, struct trapframe *eframe)
uvmexp.intrs++;
- if (v != T_NON_MASK || cold == 0) {
+ 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.
+ */
+#ifdef MULTIPROCESSOR
+ if ((*(volatile u_int8_t *)(BS_BASE + BS_CPINT)) & BS_CPI_INT)
+ m197_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_ICLR;
+ nmihand(eframe);
+ }
+
+#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);
+ }
+#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);
- flush_pipeline();
- set_psr(get_psr() & ~PSR_IND);
- }
+ psr = get_psr();
+ set_psr(psr & ~PSR_IND);
- list = &intr_handlers[vec];
- if (SLIST_EMPTY(list)) {
- printf("Spurious interrupt (level %x and vec %x)\n",
- level, vec);
- } else {
-#ifdef DEBUG
- intr = SLIST_FIRST(list);
- if (intr->ih_ipl != level) {
- panic("Handler ipl %x not the same as level %x. "
- "vec = 0x%x",
- intr->ih_ipl, 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))
+ m197_clock_ipi_handler(eframe);
#endif
+ list = &intr_handlers[vec];
+ if (SLIST_EMPTY(list))
+ printf("Spurious interrupt (level %x and vec %x)\n",
+ level, vec);
+
/*
* Walk through all interrupt handlers in the chain for the
* given vector, calling each handler in turn, till some handler
@@ -222,14 +259,12 @@ m197_ext_int(u_int v, struct trapframe *eframe)
printf("Unclaimed interrupt (level %x and vec %x)\n",
level, vec);
}
- }
- if (v != T_NON_MASK || cold == 0) {
/*
* Disable interrupts before returning to assembler,
* the spl will be restored later.
*/
- set_psr(get_psr() | PSR_IND);
+ set_psr(psr | PSR_IND);
}
#ifdef MULTIPROCESSOR
@@ -297,10 +332,8 @@ m197_bootstrap()
* set the correct value in the other one, since we set
* all the active bits.
*/
- cpu = *(volatile u_int16_t *)(BS_BASE + BS_GCSR) &
- BS_GCSR_CPUID;
- *(volatile u_int8_t *)(BS_BASE + (cpu ? BS_ISEL1 : BS_ISEL0)) =
- 0xfe;
+ cpu = *(u_int16_t *)(BS_BASE + BS_GCSR) & BS_GCSR_CPUID;
+ *(u_int8_t *)(BS_BASE + (cpu ? BS_ISEL1 : BS_ISEL0)) = 0xfe;
} else
cmmu = &cmmu88110; /* 197LE */
@@ -309,4 +342,161 @@ m197_bootstrap()
md_setipl = m197_setipl;
md_raiseipl = m197_raiseipl;
md_init_clocks = m1x7_init_clocks;
+#ifdef MULTIPROCESSOR
+ md_send_ipi = m197_send_ipi;
+#endif
+}
+
+#ifdef MULTIPROCESSOR
+
+void
+m197_send_ipi(int ipi, cpuid_t cpu)
+{
+ struct cpu_info *ci = &m88k_cpus[cpu];
+
+ if (ci->ci_ipi & ipi)
+ return;
+
+ if (ci->ci_ddb_state == CI_DDB_PAUSE)
+ return; /* XXX skirting deadlock */
+
+ atomic_setbits_int(&ci->ci_ipi, ipi);
+
+ /*
+ * If the other processor doesn't have an IPI pending, send one,
+ * keeping IPIs enabled for us.
+ */
+ if ((*(volatile u_int8_t *)(BS_BASE + BS_CPINT) & BS_CPI_STAT) == 0)
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) =
+ BS_CPI_SCPI | BS_CPI_IEN;
}
+
+void
+m197_send_complex_ipi(int ipi, cpuid_t cpu, u_int32_t arg1, u_int32_t arg2)
+{
+ struct cpu_info *ci = &m88k_cpus[cpu];
+ int wait = 0;
+
+ if ((ci->ci_flags & CIF_ALIVE) == 0)
+ return; /* XXX not ready yet */
+
+ if (ci->ci_ddb_state == CI_DDB_PAUSE)
+ return; /* XXX skirting deadlock */
+
+ /*
+ * Wait for the other processor to be ready to accept an IPI.
+ */
+ for (wait = 10000000; wait != 0; wait--) {
+ if (!ISSET(*(volatile u_int8_t *)(BS_BASE + BS_CPINT),
+ BS_CPI_STAT))
+ break;
+ }
+ if (wait == 0)
+ panic("couldn't send complex ipi %x to cpu %d", ipi, cpu);
+
+ /*
+ * In addition to the ipi bit itself, we need to set up ipi arguments.
+ * Note that we do not need to protect against another processor
+ * trying to send another complex IPI, since we know there are only
+ * two processors on the board.
+ */
+ ci->ci_ipi_arg1 = arg1;
+ 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;
+}
+
+void
+m197_ipi_handler(struct trapframe *eframe)
+{
+ struct cpu_info *ci = curcpu();
+ int ipi = ci->ci_ipi & ~(CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK);
+ u_int32_t arg1, arg2;
+
+ if (ipi != 0)
+ atomic_clearbits_int(&ci->ci_ipi, ipi);
+
+ /*
+ * Complex IPIs (with extra arguments). There can only be one
+ * pending at the same time, sending processor will wait for us
+ * to have processed the current one before sending a new one.
+ */
+ if (ipi &
+ (CI_IPI_TLB_FLUSH | CI_IPI_CACHE_FLUSH | CI_IPI_ICACHE_FLUSH)) {
+ arg1 = ci->ci_ipi_arg1;
+ arg2 = ci->ci_ipi_arg2;
+ if (ipi & CI_IPI_TLB_FLUSH) {
+ cmmu_flush_tlb(ci->ci_cpuid, arg1, arg2, 0);
+ }
+ else if (ipi & CI_IPI_CACHE_FLUSH) {
+ cmmu_flush_cache(ci->ci_cpuid, arg1, arg2);
+ }
+ else if (ipi & CI_IPI_ICACHE_FLUSH) {
+ cmmu_flush_inst_cache(ci->ci_cpuid, arg1, arg2);
+ }
+ }
+
+ /*
+ * Regular, simple, IPIs. We can have as many bits set as possible.
+ */
+ if (ipi & CI_IPI_DDB) {
+#ifdef DDB
+ /*
+ * Another processor has entered DDB. Spin on the ddb lock
+ * until it is done.
+ */
+ extern struct __mp_lock ddb_mp_lock;
+
+ ci->ci_ddb_state = CI_DDB_PAUSE;
+
+ __mp_lock(&ddb_mp_lock);
+ __mp_unlock(&ddb_mp_lock);
+
+ ci->ci_ddb_state = CI_DDB_RUNNING;
+
+ /*
+ * If ddb is hoping to us, it's our turn to enter ddb now.
+ */
+ if (ci->ci_cpuid == ddb_mp_nextcpu)
+ Debugger();
+#endif
+ }
+ if (ipi & CI_IPI_NOTIFY) {
+ /* nothing to do */
+ }
+
+ /*
+ * Acknowledge IPIs.
+ */
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = BS_CPI_ICLR | BS_CPI_IEN;
+}
+
+/*
+ * 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.
+ */
+void
+m197_clock_ipi_handler(struct trapframe *eframe)
+{
+ struct cpu_info *ci = curcpu();
+ int ipi = ci->ci_ipi & (CI_IPI_HARDCLOCK | CI_IPI_STATCLOCK);
+ int s;
+
+ atomic_clearbits_int(&ci->ci_ipi, ipi);
+
+ s = splclock();
+ if (ipi & CI_IPI_HARDCLOCK)
+ hardclock((struct clockframe *)eframe);
+ if (ipi & CI_IPI_STATCLOCK)
+ statclock((struct clockframe *)eframe);
+ splx(s);
+}
+
+#endif
diff --git a/sys/arch/mvme88k/mvme88k/m1x7_machdep.c b/sys/arch/mvme88k/mvme88k/m1x7_machdep.c
index 344e1d55d42..60185b55a24 100644
--- a/sys/arch/mvme88k/mvme88k/m1x7_machdep.c
+++ b/sys/arch/mvme88k/mvme88k/m1x7_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m1x7_machdep.c,v 1.5 2007/05/14 16:57:43 miod Exp $ */
+/* $OpenBSD: m1x7_machdep.c,v 1.6 2007/12/04 23:45:53 miod Exp $ */
/*
* Copyright (c) 1999 Steve Murphree, Jr.
* Copyright (c) 1995 Theo de Raadt
@@ -159,6 +159,14 @@ m1x7_clockintr(void *eframe)
hardclock(eframe);
+#ifdef MULTIPROCESSOR
+ /*
+ * Send an IPI to all other processors, so they can get their
+ * own ticks.
+ */
+ m88k_broadcast_ipi(CI_IPI_HARDCLOCK);
+#endif
+
return (1);
}
@@ -169,8 +177,6 @@ m1x7_statintr(void *eframe)
*(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T2ICR) = STAT_RESET;
- statclock((struct clockframe *)eframe);
-
/*
* Compute new randomized interval. The intervals are uniformly
* distributed on [statint - statvar / 2, statint + statvar / 2],
@@ -189,5 +195,15 @@ m1x7_statintr(void *eframe)
*(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T2ICR) = STAT_RESET;
*(volatile u_int8_t *)(PCC2_BASE + PCCTWO_T2CTL) =
PCC2_TCTL_CEN | PCC2_TCTL_COC;
+
+ statclock((struct clockframe *)eframe);
+
+#ifdef MULTIPROCESSOR
+ /*
+ * Send an IPI to all other processors as well.
+ */
+ m88k_broadcast_ipi(CI_IPI_STATCLOCK);
+#endif
+
return (1);
}
diff --git a/sys/arch/mvme88k/mvme88k/m88110.c b/sys/arch/mvme88k/mvme88k/m88110.c
index 0cec6f53e37..4c79f141fc8 100644
--- a/sys/arch/mvme88k/mvme88k/m88110.c
+++ b/sys/arch/mvme88k/mvme88k/m88110.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: m88110.c,v 1.47 2007/12/04 05:41:48 miod Exp $ */
+/* $OpenBSD: m88110.c,v 1.48 2007/12/04 23:45:53 miod Exp $ */
/*
* Copyright (c) 1998 Steve Murphree, Jr.
* All rights reserved.
@@ -70,6 +70,9 @@
#include <machine/psl.h>
#include <mvme88k/dev/busswreg.h>
+#ifdef MULTIPROCESSOR
+#include <machine/mvme197.h>
+#endif
cpuid_t m88110_init(void);
cpuid_t m88410_init(void);
@@ -233,6 +236,14 @@ m88410_init(void)
dctl |= CMMU_DCTL_SEN;
set_dctl(dctl);
mc88410_inval(); /* clear external data cache */
+
+#ifdef MULTIPROCESSOR
+ /*
+ * Mark us as allowing IPIs now.
+ */
+ *(volatile u_int8_t *)(BS_BASE + BS_CPINT) = BS_CPI_ICLR | BS_CPI_IEN;
+#endif
+
return (cpu);
}
@@ -364,6 +375,14 @@ void
m88110_flush_tlb(cpuid_t cpu, u_int kernel, vaddr_t vaddr, u_int count)
{
u_int32_t psr;
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci = curcpu();
+
+ if (cpu != ci->ci_cpuid) {
+ m197_send_complex_ipi(CI_IPI_TLB_FLUSH, cpu, kernel, vaddr);
+ return;
+ }
+#endif
psr = get_psr();
set_psr(psr | PSR_IND);
@@ -420,6 +439,14 @@ void
m88410_flush_cache(cpuid_t cpu, paddr_t pa, psize_t size)
{
u_int32_t psr;
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci = curcpu();
+
+ if (cpu != ci->ci_cpuid) {
+ m197_send_complex_ipi(CI_IPI_CACHE_FLUSH, cpu, pa, size);
+ return;
+ }
+#endif
psr = get_psr();
set_psr(psr | PSR_IND);
@@ -449,6 +476,14 @@ void
m88410_flush_inst_cache(cpuid_t cpu, paddr_t pa, psize_t size)
{
u_int32_t psr;
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci = curcpu();
+
+ if (cpu != ci->ci_cpuid) {
+ m197_send_complex_ipi(CI_IPI_ICACHE_FLUSH, cpu, pa, size);
+ return;
+ }
+#endif
psr = get_psr();
set_psr(psr | PSR_IND);