summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-01-13 22:57:31 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-01-13 22:57:31 +0000
commit201b6066fefecd206926b81850efca43b210e3fe (patch)
tree007dd53bce28f1ceba4a6a35f6dc0760be07e1fc /sys
parent74d43aa089d22f4280837684804f42508a85c0d6 (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.sgi3
-rw-r--r--sys/arch/sgi/sgi/autoconf.c14
-rw-r--r--sys/arch/sgi/sgi/ip30.h50
-rw-r--r--sys/arch/sgi/sgi/ip30_machdep.c212
-rw-r--r--sys/arch/sgi/sgi/ip30_nmi.S99
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