summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-12-14 17:10:45 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-12-14 17:10:45 +0000
commit8e95379f5d8db5b6cb8fe97be8a889303b02cf58 (patch)
treef6e521eeb82a991c5fadcd895a448da0f3c323d2 /sys
parent4519db9a1178840ee2bb09eee527ec3a26d8fe80 (diff)
Implement a "machine xir" ddb command, making it possible to send an
External Initiated Reset (XIR) to processors. A XIR is non-maskable and will drop us at the PROM ok prompt. This makes it possible to diagnose problems where a CPU is spinning with interrupts disabled. For now, this is only supported on machines with bbc(4).
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/dev/bbc.c44
-rw-r--r--sys/arch/sparc64/include/db_machdep.h5
-rw-r--r--sys/arch/sparc64/sparc64/db_interface.c45
3 files changed, 90 insertions, 4 deletions
diff --git a/sys/arch/sparc64/dev/bbc.c b/sys/arch/sparc64/dev/bbc.c
index 353a759ccac..7b51b288335 100644
--- a/sys/arch/sparc64/dev/bbc.c
+++ b/sys/arch/sparc64/dev/bbc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bbc.c,v 1.2 2007/08/21 19:01:38 kettenis Exp $ */
+/* $OpenBSD: bbc.c,v 1.3 2008/12/14 17:10:44 kettenis Exp $ */
/*
* Copyright (c) 2007 Mark Kettenis
@@ -25,19 +25,31 @@
#include <machine/bus.h>
#include <machine/autoconf.h>
+#ifdef DDB
+#include <machine/db_machdep.h>
+#endif
+
#include <sparc64/dev/ebusreg.h>
#include <sparc64/dev/ebusvar.h>
+/* Agent ID */
+#define BBC_AID 0x00000
+
/* Watchdog Action */
#define BBC_WATCHDOG_ACTION 0x00004
/* Perform system reset when watchdog timer expires. */
#define BBC_WATCHDOG_RESET 0x01
+/* Soft_XIR_GEN */
+#define BBC_SOFT_XIR_GEN 0x00007
+
struct bbc_softc {
struct device sc_dv;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
+
+ int sc_aid;
};
int bbc_match(struct device *, void *, void *);
@@ -51,6 +63,10 @@ struct cfdriver bbc_cd = {
NULL, "bbc", DV_DULL
};
+#ifdef DDB
+void bbc_xir(void *, int);
+#endif
+
int
bbc_match(struct device *parent, void *cf, void *aux)
{
@@ -88,7 +104,8 @@ bbc_attach(struct device *parent, struct device *self, void *aux)
return;
}
- printf("\n");
+ sc->sc_aid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, BBC_AID);
+ printf(": AID 0x%02x\n", sc->sc_aid);
/*
* Make sure we actually reset the system when the watchdog
@@ -96,4 +113,27 @@ bbc_attach(struct device *parent, struct device *self, void *aux)
*/
bus_space_write_1(sc->sc_iot, sc->sc_ioh,
BBC_WATCHDOG_ACTION, BBC_WATCHDOG_RESET);
+
+#ifdef DDB
+ db_register_xir(bbc_xir, sc);
+#endif
+}
+
+#ifdef DDB
+void
+bbc_xir(void *arg, int cpu)
+{
+ struct bbc_softc *sc = arg;
+
+ /* Redirect a request to reset all processors to Processor 0. */
+ if (cpu == -1)
+ cpu = 0;
+
+ /* Check whether we're handling the requested processor. */
+ if ((cpu & ~0x7) != sc->sc_aid)
+ return;
+
+ bus_space_write_1(sc->sc_iot, sc->sc_ioh,
+ BBC_SOFT_XIR_GEN, 1 << (cpu & 0x7));
}
+#endif
diff --git a/sys/arch/sparc64/include/db_machdep.h b/sys/arch/sparc64/include/db_machdep.h
index 9bc6d9c21bf..8691ce60e81 100644
--- a/sys/arch/sparc64/include/db_machdep.h
+++ b/sys/arch/sparc64/include/db_machdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_machdep.h,v 1.10 2008/03/17 23:10:21 kettenis Exp $ */
+/* $OpenBSD: db_machdep.h,v 1.11 2008/12/14 17:10:44 kettenis Exp $ */
/* $NetBSD: db_machdep.h,v 1.12 2001/07/07 15:16:13 eeh Exp $ */
/*
@@ -144,4 +144,7 @@ int kdb_trap(int, struct trapframe64 *);
#define DB_ELF_SYMBOLS
#define DB_ELFSIZE 64
+/* Register device-specific method for triggering XIRs. */
+void db_register_xir(void (*)(void *, int), void *);
+
#endif /* _SPARC_DB_MACHDEP_H_ */
diff --git a/sys/arch/sparc64/sparc64/db_interface.c b/sys/arch/sparc64/sparc64/db_interface.c
index 97cb75aeaf7..a5f3d190a79 100644
--- a/sys/arch/sparc64/sparc64/db_interface.c
+++ b/sys/arch/sparc64/sparc64/db_interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_interface.c,v 1.26 2008/03/13 23:29:46 kettenis Exp $ */
+/* $OpenBSD: db_interface.c,v 1.27 2008/12/14 17:10:44 kettenis Exp $ */
/* $NetBSD: db_interface.c,v 1.61 2001/07/31 06:55:47 eeh Exp $ */
/*
@@ -34,6 +34,7 @@
#include <sys/user.h>
#include <sys/reboot.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <uvm/uvm_extern.h>
@@ -227,6 +228,7 @@ void db_traptrace(db_expr_t, int, db_expr_t, char *);
void db_dump_buf(db_expr_t, int, db_expr_t, char *);
void db_dump_espcmd(db_expr_t, int, db_expr_t, char *);
void db_watch(db_expr_t, int, db_expr_t, char *);
+void db_xir(db_expr_t, int, db_expr_t, char *);
static void db_dump_pmap(struct pmap*);
static void db_print_trace_entry(struct traptrace *, int);
@@ -1028,6 +1030,46 @@ db_watch(addr, have_addr, count, modif)
}
}
+/*
+ * Provide a way to trigger an External Initiated Reset (XIR). Some
+ * systems can target individual processors, others can only target
+ * all processors at once.
+ */
+
+struct xirhand {
+ void (*xh_fun)(void *, int);
+ void *xh_arg;
+ SIMPLEQ_ENTRY(xirhand) xh_list;
+};
+
+SIMPLEQ_HEAD(, xirhand) db_xh = SIMPLEQ_HEAD_INITIALIZER(db_xh);
+
+void
+db_xir(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
+{
+ struct xirhand *xh;
+
+ if (!have_addr)
+ addr = -1;
+
+ SIMPLEQ_FOREACH(xh, &db_xh, xh_list) {
+ xh->xh_fun(xh->xh_arg, addr);
+ }
+}
+
+void
+db_register_xir(void (*fun)(void *, int), void *arg)
+{
+ struct xirhand *xh;
+
+ xh = malloc(sizeof(*xh), M_DEVBUF, M_NOWAIT);
+ if (xh == NULL)
+ panic("db_register_xir");
+ xh->xh_fun = fun;
+ xh->xh_arg = arg;
+ SIMPLEQ_INSERT_TAIL(&db_xh, xh, xh_list);
+}
+
#include <uvm/uvm.h>
@@ -1080,6 +1122,7 @@ struct db_command db_machine_command_table[] = {
#endif
{ "watch", db_watch, 0, 0 },
{ "window", db_dump_window, 0, 0 },
+ { "xir", db_xir, 0, 0 },
{ (char *)0, }
};