summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorTakuya ASADA <syuu@cvs.openbsd.org>2010-11-23 18:46:30 +0000
committerTakuya ASADA <syuu@cvs.openbsd.org>2010-11-23 18:46:30 +0000
commit3d03c809ed4b5bc94de1b69bbca15cf4c06a5322 (patch)
tree07731707210c6d546a63a9fe4df1d8a196c553e3 /sys/arch
parent35949d32559e07705cfb1ed0e69add34eb9e0453 (diff)
Correct interrupt handling
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/octeon/dev/obio.c63
-rw-r--r--sys/arch/octeon/dev/obiovar.h3
-rw-r--r--sys/arch/octeon/dev/octeon_pcibus.c12
-rw-r--r--sys/arch/octeon/dev/octeonreg.h14
-rw-r--r--sys/arch/octeon/include/cpu.h3
-rw-r--r--sys/arch/octeon/octeon/machdep.c68
6 files changed, 97 insertions, 66 deletions
diff --git a/sys/arch/octeon/dev/obio.c b/sys/arch/octeon/dev/obio.c
index d6a478c99e6..a5d9a627213 100644
--- a/sys/arch/octeon/dev/obio.c
+++ b/sys/arch/octeon/dev/obio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: obio.c,v 1.5 2010/10/28 22:52:10 syuu Exp $ */
+/* $OpenBSD: obio.c,v 1.6 2010/11/23 18:46:29 syuu Exp $ */
/*
* Copyright (c) 2000-2004 Opsycon AB (www.opsycon.se)
@@ -145,15 +145,9 @@ struct machine_bus_dma_tag obio_bus_dma_tag = {
0
};
-struct obio_intrhand {
- struct intrhand ih;
-};
-struct obio_intrhand *obio_intrhand[OBIO_NINTS];
+struct intrhand *obio_intrhand[OBIO_NINTS];
#define INTPRI_CIU_0 (INTPRI_CLOCK + 1)
-#define INTPRI_CIU_1 (INTPRI_CIU_0 + 1)
-#define INTPRI_CIU_2 (INTPRI_CIU_1 + 1)
-#define INTPRI_CIU_3 (INTPRI_CIU_2 + 1)
uint64_t obio_intem[MAXCPUS];
uint64_t obio_imask[MAXCPUS][NIPLS];
@@ -226,25 +220,9 @@ obioattach(struct device *parent, struct device *self, void *aux)
printf("\n");
- bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT1_EN0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT2_EN0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT3_EN0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT32_EN0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT1_EN1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT2_EN1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT3_EN1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT32_EN1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN4_0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT1_EN4_0, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT0_EN4_1, 0);
- bus_space_write_8(&obio_tag, obio_h, CIU_INT1_EN4_1, 0);
+ obio_intr_init();
set_intr(INTPRI_CIU_0, CR_INT_0, obio_iointr);
- set_intr(INTPRI_CIU_1, CR_INT_1, obio_iointr);
- set_intr(INTPRI_CIU_2, CR_INT_2, obio_iointr);
- set_intr(INTPRI_CIU_3, CR_INT_3, obio_iointr);
register_splx_handler(obio_splx);
/*
@@ -433,6 +411,16 @@ obio_device_to_pa(bus_addr_t addr)
* Obio interrupt handler driver.
*/
+void
+obio_intr_init(void)
+{
+ int cpuid = cpu_number();
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP2_EN0(cpuid), 0);
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP3_EN0(cpuid), 0);
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP2_EN1(cpuid), 0);
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP3_EN1(cpuid), 0);
+}
+
/*
* Establish an interrupt handler called from the dispatcher.
* The interrupt function established should return zero if there was nothing
@@ -447,7 +435,7 @@ obio_intr_establish(int irq, int level,
int (*ih_fun)(void *), void *ih_arg, const char *ih_what)
{
int cpuid = cpu_number();
- struct obio_intrhand **p, *q, *ih;
+ struct intrhand **p, *q, *ih;
int s;
#ifdef DIAGNOSTIC
@@ -459,12 +447,12 @@ obio_intr_establish(int irq, int level,
if (ih == NULL)
return NULL;
- ih->ih.ih_next = NULL;
- ih->ih.ih_fun = ih_fun;
- ih->ih.ih_arg = ih_arg;
- ih->ih.ih_level = level;
- ih->ih.ih_irq = irq;
- evcount_attach(&ih->ih.ih_count, ih_what, (void *)&ih->ih.ih_irq);
+ ih->ih_next = NULL;
+ ih->ih_fun = ih_fun;
+ ih->ih_arg = ih_arg;
+ ih->ih_level = level;
+ ih->ih_irq = irq;
+ evcount_attach(&ih->ih_count, ih_what, (void *)&ih->ih_irq);
s = splhigh();
@@ -474,7 +462,7 @@ obio_intr_establish(int irq, int level,
* generally small.
*/
for (p = &obio_intrhand[irq]; (q = *p) != NULL;
- p = (struct obio_intrhand **)&q->ih.ih_next)
+ p = (struct intrhand **)&q->ih_next)
;
*p = ih;
@@ -575,8 +563,8 @@ obio_iointr(uint32_t hwpend, struct trap_frame *frame)
int bit;
struct intrhand *ih;
int rc;
- uint64_t sum0 = CIU_INT_SUM0(cpuid * 2);
- uint64_t en0 = CIU_INT_EN0(cpuid * 2);
+ uint64_t sum0 = CIU_IP2_SUM0(cpuid);
+ uint64_t en0 = CIU_IP2_EN0(cpuid);
isr = bus_space_read_8(&obio_tag, obio_h, sum0);
imr = bus_space_read_8(&obio_tag, obio_h, en0);
@@ -674,8 +662,7 @@ void
obio_setintrmask(int level)
{
int cpuid = cpu_number();
- uint64_t en0 = CIU_INT_EN0(cpuid * 2);
- *(volatile uint64_t *)(PHYS_TO_XKPHYS(OCTEON_CIU_BASE, CCA_NC) +
- en0) = obio_intem[cpuid] & ~obio_imask[cpuid][level];
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP2_EN0(cpuid),
+ obio_intem[cpuid] & ~obio_imask[cpuid][level]);
}
diff --git a/sys/arch/octeon/dev/obiovar.h b/sys/arch/octeon/dev/obiovar.h
index 3557b2d8464..1fae691e4ac 100644
--- a/sys/arch/octeon/dev/obiovar.h
+++ b/sys/arch/octeon/dev/obiovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: obiovar.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */
+/* $OpenBSD: obiovar.h,v 1.2 2010/11/23 18:46:29 syuu Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -48,5 +48,6 @@ void obio_setintrmask(int);
void *obio_intr_establish(int, int, int (*)(void *),
void *, const char *);
void obio_intr_disestablish(void *);
+void obio_intr_init(void);
#endif /* _OBIOVAR_H_ */
diff --git a/sys/arch/octeon/dev/octeon_pcibus.c b/sys/arch/octeon/dev/octeon_pcibus.c
index 9240f16a758..73fe805a9d3 100644
--- a/sys/arch/octeon/dev/octeon_pcibus.c
+++ b/sys/arch/octeon/dev/octeon_pcibus.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: octeon_pcibus.c,v 1.1 2010/10/28 22:52:10 syuu Exp $ */
-/* $OpenBSD: octeon_pcibus.c,v 1.1 2010/10/28 22:52:10 syuu Exp $ */
+/* $OpenBSD: octeon_pcibus.c,v 1.2 2010/11/23 18:46:29 syuu Exp $ */
+/* $OpenBSD: octeon_pcibus.c,v 1.2 2010/11/23 18:46:29 syuu Exp $ */
/* $NetBSD: bonito_mainbus.c,v 1.11 2008/04/28 20:23:10 martin Exp $ */
/* $NetBSD: bonito_pci.c,v 1.5 2008/04/28 20:23:28 martin Exp $ */
@@ -454,13 +454,7 @@ void *
octeon_pcibus_pci_intr_establish(void *cookie, pci_intr_handle_t ih, int level,
int (*cb)(void *), void *cbarg, char *name)
{
- struct octeon_pcibus_softc *sc;
- struct obio_attach_args *oba;
-
- sc = (struct octeon_pcibus_softc *)cookie;
- oba = sc->sc_oba;
-
- return obio_intr_establish(oba->oba_intr, level, cb, cbarg, name);
+ return obio_intr_establish(ih, level, cb, cbarg, name);
}
void
diff --git a/sys/arch/octeon/dev/octeonreg.h b/sys/arch/octeon/dev/octeonreg.h
index 1ff9f10180c..1f0aad9f79e 100644
--- a/sys/arch/octeon/dev/octeonreg.h
+++ b/sys/arch/octeon/dev/octeonreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: octeonreg.h,v 1.3 2010/10/26 00:02:01 syuu Exp $ */
+/* $OpenBSD: octeonreg.h,v 1.4 2010/11/23 18:46:29 syuu Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.com).
@@ -110,20 +110,24 @@
#define CIU_INT1_SUM0 0x00000008
#define CIU_INT2_SUM0 0x00000010
#define CIU_INT3_SUM0 0x00000018
-#define CIU_INT_SUM0(x) (CIU_INT0_SUM0+((x)*8))
+#define CIU_IP2_SUM0(x) (CIU_INT0_SUM0+(0x10 * (x)))
+#define CIU_IP3_SUM0(x) (CIU_INT1_SUM0+(0x10 * (x)))
#define CIU_INT32_SUM0 0x00000100
#define CIU_INT32_SUM1 0x00000108
#define CIU_INT0_EN0 0x00000200
#define CIU_INT1_EN0 0x00000210
#define CIU_INT2_EN0 0x00000220
#define CIU_INT3_EN0 0x00000230
-#define CIU_INT_EN0(x) (CIU_INT0_EN0+((x)*8))
+#define CIU_IP2_EN0(x) (CIU_INT0_EN0+(0x20 * (x)))
+#define CIU_IP3_EN0(x) (CIU_INT1_EN0+(0x20 * (x)))
#define CIU_INT32_EN0 0x00000400
#define CIU_INT0_EN1 0x00000208
#define CIU_INT1_EN1 0x00000218
#define CIU_INT2_EN1 0x00000228
#define CIU_INT3_EN1 0x00000238
#define CIU_INT32_EN1 0x00000408
+#define CIU_IP2_EN1(x) (CIU_INT0_EN1+(0x20 * (x)))
+#define CIU_IP3_EN1(x) (CIU_INT1_EN1+(0x20 * (x)))
#define CIU_TIM0 0x00000480
#define CIU_TIM1 0x00000488
#define CIU_TIM2 0x00000490
@@ -134,10 +138,10 @@
#define CIU_PP_POKE1 0x00000588
#define CIU_MBOX_SET0 0x00000600
#define CIU_MBOX_SET1 0x00000608
-#define CIU_MBOX_SET(x) (CIU_MBOX_SET0+((x)*8))
+#define CIU_MBOX_SET(x) (CIU_MBOX_SET0+(0x08 * (x)))
#define CIU_MBOX_CLR0 0x00000680
#define CIU_MBOX_CLR1 0x00000688
-#define CIU_MBOX_CLR(x) (CIU_MBOX_CLR0+((x)*8))
+#define CIU_MBOX_CLR(x) (CIU_MBOX_CLR0+(0x08 * (x)))
#define CIU_PP_RST 0x00000700
#define CIU_PP_DBG 0x00000708
#define CIU_GSTOP 0x00000710
diff --git a/sys/arch/octeon/include/cpu.h b/sys/arch/octeon/include/cpu.h
index f2d44ab50c0..2f7ed1cd5c3 100644
--- a/sys/arch/octeon/include/cpu.h
+++ b/sys/arch/octeon/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.1 2010/09/20 06:32:30 syuu Exp $ */
+/* $OpenBSD: cpu.h,v 1.2 2010/11/23 18:46:29 syuu Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
@@ -55,6 +55,7 @@ void hw_cpu_spinup_trampoline(struct cpu_info *);
int hw_ipi_intr_establish(int (*)(void *), u_long);
void hw_ipi_intr_set(u_long);
void hw_ipi_intr_clear(u_long);
+void hw_cpu_init_secondary(struct cpu_info *);
#endif /* MULTIPROCESSOR && !_LOCORE */
#define Mips_SyncCache(ci) \
diff --git a/sys/arch/octeon/octeon/machdep.c b/sys/arch/octeon/octeon/machdep.c
index 820a763046f..0adb89d0208 100644
--- a/sys/arch/octeon/octeon/machdep.c
+++ b/sys/arch/octeon/octeon/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.4 2010/10/24 15:40:03 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.5 2010/11/23 18:46:29 syuu Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
@@ -77,8 +77,6 @@
#include <mips64/archtype.h>
-#include <machine/octeon_pcmap_regs.h>
-
#include <octeon/dev/obiovar.h>
#include <octeon/dev/octeonreg.h>
@@ -666,6 +664,13 @@ is_memory_range(paddr_t pa, psize_t len, psize_t limit)
#ifdef MULTIPROCESSOR
unsigned octeon_ap_boot = ~0;
struct cpu_info *cpu_info_boot_secondary = NULL;
+static int (*ipi_handler)(void *);
+
+uint32_t ipi_intr(uint32_t, struct trap_frame *);
+
+extern bus_space_t obio_tag;
+extern bus_space_handle_t obio_h;
+
void
hw_cpu_boot_secondary(struct cpu_info *ci)
{
@@ -675,9 +680,7 @@ hw_cpu_boot_secondary(struct cpu_info *ci)
if (kstack == NULL)
panic("unable to allocate idle stack\n");
ci->ci_curprocpaddr = (void *)kstack;
-
cpu_info_boot_secondary = ci;
-
octeon_ap_boot = ci->ci_cpuid;
while (!cpuset_isset(&cpus_running, ci))
@@ -720,13 +723,11 @@ hw_cpu_hatch(struct cpu_info *ci)
Mips_SyncCache(ci);
cpu_startclock(ci);
-
ncpus++;
cpuset_add(&cpus_running, ci);
-
+ obio_intr_init();
mips64_ipi_init();
obio_setintrmask(0);
-
spl0();
(void)updateimask(0);
@@ -734,24 +735,67 @@ hw_cpu_hatch(struct cpu_info *ci)
cpu_switchto(NULL, sched_chooseproc());
}
+/*
+ * IPI dispatcher.
+ */
+uint32_t
+ipi_intr(uint32_t hwpend, struct trap_frame *frame)
+{
+ u_long cpuid = cpu_number();
+
+ /*
+ * Mask all pending interrupts.
+ */
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP3_EN0(cpuid), 0);
+
+ ipi_handler((void *)cpuid);
+
+ /*
+ * Reenable interrupts which have been serviced.
+ */
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP3_EN0(cpuid),
+ (1ULL << CIU_INT_MBOX0)|(1ULL << CIU_INT_MBOX1));
+ return hwpend;
+}
+
int
hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
{
- obio_intr_establish(CIU_INT_MBOX(cpuid), IPL_IPI, func,
- (void *)cpuid, NULL);
+ if (cpuid == 0)
+ ipi_handler = func;
+
+ bus_space_write_8(&obio_tag, obio_h, CIU_MBOX_CLR(cpuid),
+ 0xffffffff);
+ bus_space_write_8(&obio_tag, obio_h, CIU_IP3_EN0(cpuid),
+ (1ULL << CIU_INT_MBOX0)|(1ULL << CIU_INT_MBOX1));
+ set_intr(INTPRI_IPI, CR_INT_1, ipi_intr);
+
return 0;
};
void
hw_ipi_intr_set(u_long cpuid)
{
- *(uint64_t *)OCTEON_CIU_MBOX_SETX(cpuid) = 1;
+ bus_space_write_8(&obio_tag, obio_h, CIU_MBOX_SET(cpuid), 1);
}
void
hw_ipi_intr_clear(u_long cpuid)
{
- *(uint64_t *)OCTEON_CIU_MBOX_CLRX(cpuid) = 1;
+ uint64_t clr =
+ bus_space_read_8(&obio_tag, obio_h, CIU_MBOX_CLR(cpuid));
+ bus_space_write_8(&obio_tag, obio_h, CIU_MBOX_CLR(cpuid), clr);
}
+void
+hw_cpu_init_secondary(struct cpu_info *ci)
+{
+ ci->ci_cacheways = 2;
+ ci->ci_l1instcachesize = 32 * 1024;
+ ci->ci_l1instcacheline = 64;
+ ci->ci_l1datacachesize = 32 * 1024;
+ ci->ci_l1datacacheline = 64;
+ ci->ci_l2size = ci->ci_hw.l2size;
+ ci->ci_l3size = 0;
+}
#endif