diff options
author | Takuya ASADA <syuu@cvs.openbsd.org> | 2010-11-23 18:46:30 +0000 |
---|---|---|
committer | Takuya ASADA <syuu@cvs.openbsd.org> | 2010-11-23 18:46:30 +0000 |
commit | 3d03c809ed4b5bc94de1b69bbca15cf4c06a5322 (patch) | |
tree | 07731707210c6d546a63a9fe4df1d8a196c553e3 /sys/arch | |
parent | 35949d32559e07705cfb1ed0e69add34eb9e0453 (diff) |
Correct interrupt handling
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/octeon/dev/obio.c | 63 | ||||
-rw-r--r-- | sys/arch/octeon/dev/obiovar.h | 3 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octeon_pcibus.c | 12 | ||||
-rw-r--r-- | sys/arch/octeon/dev/octeonreg.h | 14 | ||||
-rw-r--r-- | sys/arch/octeon/include/cpu.h | 3 | ||||
-rw-r--r-- | sys/arch/octeon/octeon/machdep.c | 68 |
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 |