diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2010-01-13 22:57:31 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2010-01-13 22:57:31 +0000 |
commit | 201b6066fefecd206926b81850efca43b210e3fe (patch) | |
tree | 007dd53bce28f1ceba4a6a35f6dc0760be07e1fc /sys | |
parent | 74d43aa089d22f4280837684804f42508a85c0d6 (diff) |
Crude handler for the Octane NMI button, for kernels compiled with
option DDB.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sgi/conf/files.sgi | 3 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/autoconf.c | 14 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip30.h | 50 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip30_machdep.c | 212 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip30_nmi.S | 99 |
5 files changed, 278 insertions, 100 deletions
diff --git a/sys/arch/sgi/conf/files.sgi b/sys/arch/sgi/conf/files.sgi index f3885c33ebd..b3b9280af18 100644 --- a/sys/arch/sgi/conf/files.sgi +++ b/sys/arch/sgi/conf/files.sgi @@ -1,4 +1,4 @@ -# $OpenBSD: files.sgi,v 1.42 2009/11/21 23:28:14 syuu Exp $ +# $OpenBSD: files.sgi,v 1.43 2010/01/13 22:57:28 miod Exp $ # # maxpartitions must be first item in files.${ARCH} # @@ -16,6 +16,7 @@ file arch/sgi/sgi/disksubr.c disk file arch/sgi/sgi/lock_machdep.c multiprocessor file arch/sgi/sgi/ip27_machdep.c tgt_origin file arch/sgi/sgi/ip30_machdep.c tgt_octane +file arch/sgi/sgi/ip30_nmi.S tgt_octane & ddb file arch/sgi/sgi/ip32_machdep.c tgt_o2 file arch/sgi/sgi/l1.c tgt_origin file arch/sgi/sgi/machdep.c diff --git a/sys/arch/sgi/sgi/autoconf.c b/sys/arch/sgi/sgi/autoconf.c index 493a13db8cd..09266b6c32b 100644 --- a/sys/arch/sgi/sgi/autoconf.c +++ b/sys/arch/sgi/sgi/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.29 2009/11/19 06:06:51 miod Exp $ */ +/* $OpenBSD: autoconf.c,v 1.30 2010/01/13 22:57:29 miod Exp $ */ /* * Copyright (c) 2009 Miodrag Vallat. * @@ -102,6 +102,7 @@ #include <uvm/uvm_extern.h> +#include <sgi/sgi/ip30.h> #include <sgi/xbow/xbow.h> #include <dev/pci/pcivar.h> #include <scsi/scsi_all.h> @@ -182,6 +183,17 @@ memrange_register(uint64_t startpfn, uint64_t endpfn, uint64_t bmask, #endif physmem += endpfn - startpfn; +#ifdef TGT_OCTANE + /* + * On Octane, the second 16KB page is reserved for the NMI handler. + */ + if (sys_config.system_type == SGI_OCTANE && + startpfn < atop(IP30_MEMORY_BASE) + 2) { + startpfn = atop(IP30_MEMORY_BASE) + 2; + if (startpfn >= endpfn) + return 0; + } +#endif /* * Prevent use of memory above 16GB physical, until pmap can support * this. diff --git a/sys/arch/sgi/sgi/ip30.h b/sys/arch/sgi/sgi/ip30.h index 3b31c4ee1af..ad52c6e03f9 100644 --- a/sys/arch/sgi/sgi/ip30.h +++ b/sys/arch/sgi/sgi/ip30.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip30.h,v 1.6 2010/01/05 06:44:58 syuu Exp $ */ +/* $OpenBSD: ip30.h,v 1.7 2010/01/13 22:57:30 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -56,21 +56,39 @@ * Multiprocessor configuration area */ -#define MPCONF_BASE 0x0000000000000600UL -#define MPCONF_LEN 0x80 +#define MPCONF_BASE 0x0000000000000600UL +#define MPCONF_LEN 0x80 -#define MPCONF_MAGIC(i) ((i) * MPCONF_LEN + 0x00) -#define MPCONF_PRID(i) ((i) * MPCONF_LEN + 0x04) -#define MPCONF_PHYSID(i) ((i) * MPCONF_LEN + 0x08) -#define MPCONF_VIRTID(i) ((i) * MPCONF_LEN + 0x0c) -#define MPCONF_SCACHESZ(i) ((i) * MPCONF_LEN + 0x10) -#define MPCONF_FANLOADS(i) ((i) * MPCONF_LEN + 0x14) -#define MPCONF_LAUNCH(i) ((i) * MPCONF_LEN + 0x18) -#define MPCONF_RNDVZ(i) ((i) * MPCONF_LEN + 0x20) -#define MPCONF_STACKADDR(i) ((i) * MPCONF_LEN + 0x40) -#define MPCONF_LPARAM(i) ((i) * MPCONF_LEN + 0x48) -#define MPCONF_RPARAM(i) ((i) * MPCONF_LEN + 0x50) -#define MPCONF_IDLEFLAG(i) ((i) * MPCONF_LEN + 0x58) +#define MPCONF_MAGIC(i) ((i) * MPCONF_LEN + 0x00) +#define MPCONF_PRID(i) ((i) * MPCONF_LEN + 0x04) +#define MPCONF_PHYSID(i) ((i) * MPCONF_LEN + 0x08) +#define MPCONF_VIRTID(i) ((i) * MPCONF_LEN + 0x0c) +#define MPCONF_SCACHESZ(i) ((i) * MPCONF_LEN + 0x10) +#define MPCONF_FANLOADS(i) ((i) * MPCONF_LEN + 0x14) +#define MPCONF_LAUNCH(i) ((i) * MPCONF_LEN + 0x18) +#define MPCONF_RNDVZ(i) ((i) * MPCONF_LEN + 0x20) +#define MPCONF_STACKADDR(i) ((i) * MPCONF_LEN + 0x40) +#define MPCONF_LPARAM(i) ((i) * MPCONF_LEN + 0x48) +#define MPCONF_RPARAM(i) ((i) * MPCONF_LEN + 0x50) +#define MPCONF_IDLEFLAG(i) ((i) * MPCONF_LEN + 0x58) -#define MPCONF_MAGIC_VAL 0xbaddeed2 +#define MPCONF_MAGIC_VAL 0xbaddeed2 +/* + * Global data area + */ + +#define GDA_BASE 0x0000000000000400UL + +#define GDA_MAGIC 0x58464552 /* XFER */ + +#if !defined(_LOCORE) +struct ip30_gda { + uint32_t magic; /* GDA_MAGIC */ + uint32_t promop; + void (*nmi_cb)(void); + uint64_t masterspid; + void *tlb_handlers[3]; + uint64_t nmi_count; +}; +#endif diff --git a/sys/arch/sgi/sgi/ip30_machdep.c b/sys/arch/sgi/sgi/ip30_machdep.c index a5802857308..101160b5354 100644 --- a/sys/arch/sgi/sgi/ip30_machdep.c +++ b/sys/arch/sgi/sgi/ip30_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip30_machdep.c,v 1.31 2010/01/09 23:34:29 miod Exp $ */ +/* $OpenBSD: ip30_machdep.c,v 1.32 2010/01/13 22:57:30 miod Exp $ */ /* * Copyright (c) 2008, 2009 Miodrag Vallat. @@ -23,6 +23,7 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/device.h> +#include <sys/reboot.h> #include <sys/tty.h> #include <mips64/arcbios.h> @@ -69,6 +70,11 @@ paddr_t ip30_widget_map(int16_t, u_int, bus_addr_t *, bus_size_t *); int ip30_widget_id(int16_t, u_int, uint32_t *); static u_long ip30_get_ncpusfound(void); +#ifdef DDB +void ip30_nmi(void); /* ip30_nmi.S */ +void ip30_nmi_handler(void); +#endif + static paddr_t ip30_iocbase; static const paddr_t mpconf = @@ -84,6 +90,9 @@ ip30_setup() uint32_t memcfg; uint64_t start, count, end; u_long cpuspeed; +#ifdef DDB + struct ip30_gda *gda; +#endif /* * Although being r10k/r12k based, the uncached spaces are @@ -180,6 +189,15 @@ ip30_setup() if (comconsrate < 50 || comconsrate > 115200) comconsrate = 9600; +#ifdef DDB + /* + * Setup NMI handler. + */ + gda = (struct ip30_gda *)PHYS_TO_XKPHYS(GDA_BASE, CCA_CACHED); + if (gda->magic == GDA_MAGIC) + gda->nmi_cb = ip30_nmi; +#endif + /* * Octane and Octane2 can be told apart with a GPIO source bit * in the onboard IOC3. @@ -331,9 +349,9 @@ ip30_lights_frob(uint32_t hwpend, struct trap_frame *cf) static int ip30_cpu_exists(int cpuid) { - uint32_t magic = - *(volatile uint32_t *)(mpconf + MPCONF_MAGIC(cpuid)); - return magic == MPCONF_MAGIC_VAL; + uint32_t magic = + *(volatile uint32_t *)(mpconf + MPCONF_MAGIC(cpuid)); + return magic == MPCONF_MAGIC_VAL; } u_long @@ -342,126 +360,156 @@ ip30_get_ncpusfound(void) int i; for (i = 1; i < MAXCPUS; i++) if (!ip30_cpu_exists(i)) - break; + continue; return i; } +#ifdef DDB +void +ip30_nmi_handler() +{ + extern int kdb_trap(int, struct trap_frame *); + extern void stacktrace(struct trap_frame *); + struct trap_frame *fr0, *fr1; + + setsr(getsr() & ~SR_BOOT_EXC_VEC); + printf("NMI\n"); + + fr0 = (struct trap_frame *)PHYS_TO_XKPHYS(IP30_MEMORY_BASE + 0x4000, + CCA_CACHED); + fr1 = (struct trap_frame *)PHYS_TO_XKPHYS(IP30_MEMORY_BASE + 0x6000, + CCA_CACHED); + + printf("cpu #0 traceback\n"); + stacktrace(fr0); + printf("cpu #1 traceback\n"); + stacktrace(fr1); + + kdb_trap(-1, fr0); + + printf("Resetting system...\n"); + boot(RB_USERREQ); +} +#endif + #ifdef MULTIPROCESSOR void hw_cpu_boot_secondary(struct cpu_info *ci) { - int cpuid = ci->ci_cpuid; - vaddr_t kstack; + int cpuid = ci->ci_cpuid; + vaddr_t kstack; #ifdef DEBUG - uint64_t stackaddr = - *(volatile uint64_t *)(mpconf + MPCONF_STACKADDR(cpuid)); - uint64_t lparam = - *(volatile uint64_t *)(mpconf + MPCONF_LPARAM(cpuid)); - uint64_t launch = - *(volatile uint64_t *)(mpconf + MPCONF_LAUNCH(cpuid)); + uint64_t stackaddr = + *(volatile uint64_t *)(mpconf + MPCONF_STACKADDR(cpuid)); + uint64_t lparam = + *(volatile uint64_t *)(mpconf + MPCONF_LPARAM(cpuid)); + uint64_t launch = + *(volatile uint64_t *)(mpconf + MPCONF_LAUNCH(cpuid)); uint32_t magic = - *(volatile uint32_t *)(mpconf + MPCONF_MAGIC(cpuid)); - uint32_t prid = - *(volatile uint32_t *)(mpconf + MPCONF_PRID(cpuid)); - uint32_t physid = - *(volatile uint32_t *)(mpconf + MPCONF_PHYSID(cpuid)); - uint32_t virtid = - *(volatile uint32_t *)(mpconf + MPCONF_VIRTID(cpuid)); - uint32_t scachesz = - *(volatile uint32_t *)(mpconf + MPCONF_SCACHESZ(cpuid)); - uint16_t fanloads = - *(volatile uint16_t *)(mpconf + MPCONF_FANLOADS(cpuid)); - uint64_t rndvz = - *(volatile uint64_t *)(mpconf + MPCONF_RNDVZ(cpuid)); - uint64_t rparam = - *(volatile uint64_t *)(mpconf + MPCONF_RPARAM(cpuid)); - uint32_t idleflag = - *(volatile uint32_t *)(mpconf + MPCONF_IDLEFLAG(cpuid)); - - printf("ci:%p cpuid:%d magic:%x prid:%x physid:%x virtid:%x\n" - "scachesz:%u fanloads:%x launch:%llx rndvz:%llx\n" - "stackaddr:%llx lparam:%llx rparam:%llx idleflag:%x\n", - ci, cpuid, magic, prid, physid, virtid, - scachesz, fanloads, launch, rndvz, - stackaddr, lparam, rparam, idleflag); + *(volatile uint32_t *)(mpconf + MPCONF_MAGIC(cpuid)); + uint32_t prid = + *(volatile uint32_t *)(mpconf + MPCONF_PRID(cpuid)); + uint32_t physid = + *(volatile uint32_t *)(mpconf + MPCONF_PHYSID(cpuid)); + uint32_t virtid = + *(volatile uint32_t *)(mpconf + MPCONF_VIRTID(cpuid)); + uint32_t scachesz = + *(volatile uint32_t *)(mpconf + MPCONF_SCACHESZ(cpuid)); + uint16_t fanloads = + *(volatile uint16_t *)(mpconf + MPCONF_FANLOADS(cpuid)); + uint64_t rndvz = + *(volatile uint64_t *)(mpconf + MPCONF_RNDVZ(cpuid)); + uint64_t rparam = + *(volatile uint64_t *)(mpconf + MPCONF_RPARAM(cpuid)); + uint32_t idleflag = + *(volatile uint32_t *)(mpconf + MPCONF_IDLEFLAG(cpuid)); + + printf("ci:%p cpuid:%d magic:%x prid:%x physid:%x virtid:%x\n" + "scachesz:%u fanloads:%x launch:%llx rndvz:%llx\n" + "stackaddr:%llx lparam:%llx rparam:%llx idleflag:%x\n", + ci, cpuid, magic, prid, physid, virtid, + scachesz, fanloads, launch, rndvz, + stackaddr, lparam, rparam, idleflag); #endif - kstack = smp_malloc(USPACE); - if (kstack == NULL) - panic("unable to allocate idle stack\n"); - bzero((char *)kstack, USPACE); - ci->ci_curprocpaddr = (void *)kstack; - - *(volatile uint64_t *)(mpconf + MPCONF_STACKADDR(cpuid)) = - (uint64_t)(kstack + USPACE); - *(volatile uint64_t *)(mpconf + MPCONF_LPARAM(cpuid)) = - (uint64_t)ci; - *(volatile uint64_t *)(mpconf + MPCONF_LAUNCH(cpuid)) = - (uint64_t)hw_cpu_spinup_trampoline; - - while(!cpuset_isset(&cpus_running, ci)) - ; + kstack = smp_malloc(USPACE); + if (kstack == NULL) + panic("unable to allocate idle stack\n"); + bzero((char *)kstack, USPACE); + ci->ci_curprocpaddr = (void *)kstack; + + *(volatile uint64_t *)(mpconf + MPCONF_STACKADDR(cpuid)) = + (uint64_t)(kstack + USPACE); + *(volatile uint64_t *)(mpconf + MPCONF_LPARAM(cpuid)) = + (uint64_t)ci; + *(volatile uint64_t *)(mpconf + MPCONF_LAUNCH(cpuid)) = + (uint64_t)hw_cpu_spinup_trampoline; + + while (!cpuset_isset(&cpus_running, ci)) + ; } void hw_cpu_hatch(struct cpu_info *ci) { - int s; - - /* - * Make sure we can access the extended address space. - * Note that r10k and later do not allow XUSEG accesses - * from kernel mode unless SR_UX is set. - */ - setsr(getsr() | SR_KX | SR_UX); + int s; - Mips10k_ConfigCache(ci); + /* + * Make sure we can access the extended address space. + * Note that r10k and later do not allow XUSEG accesses + * from kernel mode unless SR_UX is set. + */ + setsr(getsr() | SR_KX | SR_UX); tlb_set_page_mask(TLB_PAGE_MASK); tlb_set_wired(0); tlb_flush(64); tlb_set_wired(UPAGES / 2); - tlb_set_pid(0); + tlb_set_pid(0); - /* - * Turn off bootstrap exception vectors. - */ - setsr(getsr() & ~SR_BOOT_EXC_VEC); + /* + * Turn off bootstrap exception vectors. + */ + setsr(getsr() & ~SR_BOOT_EXC_VEC); - /* - * Clear out the I and D caches. - */ - Mips_SyncCache(ci); + /* + * Clear out the I and D caches. + */ + Mips10k_ConfigCache(ci); + Mips_SyncCache(ci); - cpu_startclock(ci); + cpu_startclock(ci); - ncpus++; - cpuset_add(&cpus_running, ci); + ncpus++; + cpuset_add(&cpus_running, ci); - mips64_ipi_init(); - xheart_setintrmask(0); + mips64_ipi_init(); + xheart_setintrmask(0); - spl0(); - (void)updateimask(0); + spl0(); + (void)updateimask(0); - SCHED_LOCK(s); - cpu_switchto(NULL, sched_chooseproc()); + SCHED_LOCK(s); + cpu_switchto(NULL, sched_chooseproc()); } -int hw_ipi_intr_establish(int (*func)(void *), u_long cpuid) +int +hw_ipi_intr_establish(int (*func)(void *), u_long cpuid) { return xheart_intr_establish(func, (void *)cpuid, HEART_ISR_IPI(cpuid), IPL_IPI, NULL, &curcpu()->ci_ipiih); }; -void hw_ipi_intr_set(u_long cpuid) +void +hw_ipi_intr_set(u_long cpuid) { xheart_intr_set(HEART_ISR_IPI(cpuid)); } -void hw_ipi_intr_clear(u_long cpuid) +void +hw_ipi_intr_clear(u_long cpuid) { xheart_intr_clear(HEART_ISR_IPI(cpuid)); } diff --git a/sys/arch/sgi/sgi/ip30_nmi.S b/sys/arch/sgi/sgi/ip30_nmi.S new file mode 100644 index 00000000000..0454df73acb --- /dev/null +++ b/sys/arch/sgi/sgi/ip30_nmi.S @@ -0,0 +1,99 @@ +/* $OpenBSD: ip30_nmi.S,v 1.1 2010/01/13 22:57:30 miod Exp $ */ + +/* + * Copyright (c) 2010 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. + */ + +#include <machine/asm.h> +#include <machine/cpu.h> +#include <machine/cpustate.h> +#include <machine/regnum.h> + +#include <arch/sgi/sgi/ip30.h> + +#ifndef MULTIPROCESSOR +#define HW_CPU_NUMBER_REG 0x900000000ff50000 /* HEART_PRID */ +#endif + +#include "assym.h" + + .set mips3 + +/* + * The NMI handler routine is shared accross all processors. + * + * When the NMI is triggered, we might be in the middle of an exception + * handler, and relying upon k0 and k1. + * + * Unfortunately, since there is no way to know whether our stack is valid, + * we will need these registers. Therefore NMI are fatal if they occur in + * kernel mode... but we don't even try to resume from them, yet. + */ + .globl ip30_nmi +ip30_nmi: + .set noat + sync + + LOAD_XKPHYS(k0, CCA_CACHED) + LA k1, IP30_MEMORY_BASE + 0x4000 + PTR_ADDU k0, k0, k1 + + /* + * We use part of the low memory as stack and save area. + * This is safe since we reserved this area early. + * We give ourselves 8KB, minus the size of the frame, of stack. + */ + + LA k1, HW_CPU_NUMBER_REG + PTR_L k1, 0(k1) + beqz k1, 1f + nop + + /* CPU #1 */ + PTR_ADDU k0, k0, 0x2000 +1: + /* + * Save state. + * k0 = frame base, k1 = cpu number + */ + + SAVE_CPU(k0, 0) + SAVE_CPU_SREG(k0, 0) + .set at + + PTR_ADDU sp, k0, 0x2000 + LA gp, _gp + + /* + * Interrupts should be disabled. Just in case they aren't, + * enforce this (a1 still contains the value of cop0 SR). + */ + + and a1, a1, ~SR_INT_ENAB + mtc0 a1, COP_0_STATUS_REG + ITLBNOPFIX + + LA k0, HW_CPU_NUMBER_REG + PTR_L k1, 0(k0) + bnez k1, 9f + nop + + jal ip30_nmi_handler /* ip30_machdep.c */ + nop + +9: + sync + b 9b + nop |