Module Name: src
Committed By: skrll
Date: Tue Sep 27 08:18:21 UTC 2022
Modified Files:
src/sys/arch/riscv/conf: GENERIC files.riscv
src/sys/arch/riscv/include: db_machdep.h
src/sys/arch/riscv/riscv: db_machdep.c db_trace.c locore.S trap.c
Added Files:
src/sys/arch/riscv/riscv: db_interface.c
Log Message:
Basic ddb and backtrace support.
[ 1.0000000] panic: kernel diagnostic assertion "msgbufaddr != 0" failed:
file "/home/nick/netbsd/nbcvs/src/sys/arch/riscv/riscv/riscv_machdep.c", line
564
[ 1.0000000] cpu0: Begin traceback...
[ 1.0000000] trace fp ffffffc000801dd0
[ 1.0000000] fp ffffffc000801e10 ?() at ffffffc0001eee98
[ 1.0000000] fp ffffffc000801e30 ?() at ffffffc0002ad984
[ 1.0000000] fp ffffffc000801ee0 ?() at ffffffc000005430
[ 1.0000000] cpu0: End traceback...
[ 1.0000000] Trapframe @ 0xffffffc000801cb0 (cause=3 (breakpoint),
status=0x100, pc=0xffffffc0000007e4, va=0):
[ 1.0000000] ra =0xffffffc0001eee9c, sp =0xffffffc000801dd0, gp
=0xffffffc0006a8f40, tp = 0
[ 1.0000000] s0 =0xffffffc000600ac0, s1 = 0x1000, s2
=0xffffffc000438df0, s3 =0xffffffc000801d80
[ 1.0000000] s4 =0xffffffc0001eed78, s5 =0xffffffc0006d55f8, s6
=0xffffffc000801d88, s7 =0xffffffc0006dfdb8
[ 1.0000000] s8 =0xffffffc000428c18, s9 =0xffffffc000801dd0,
s10=0xffffffc0000a3822, s11=0xffffffc0006d55f8
[ 1.0000000] a0 = 0x17, a1 = 0xa, a2 =
0, a3 =0xffffffc00041f658
[ 1.0000000] a4 = 0, a5 = 0x1, a5 =
0, a7 = 0x1
[ 1.0000000] t0 =0xffffffc0006dfe30, t1 =0xffffffc000801bb8, t2
=0xffffffc000803000, t3 = 0x75
[ 1.0000000] t4 = 0, t5 = 0x63, t6 =
0x1
[ 1.0000000] kernel: breakpoint
Stopped in pid 0.0 (system) at ffffffc0000007e4: c.ebreak
db>
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/riscv/conf/GENERIC
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/riscv/conf/files.riscv
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/riscv/include/db_machdep.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/riscv/riscv/db_interface.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/riscv/riscv/db_machdep.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/riscv/riscv/db_trace.c
cvs rdiff -u -r1.25 -r1.26 src/sys/arch/riscv/riscv/locore.S
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/riscv/riscv/trap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/riscv/conf/GENERIC
diff -u src/sys/arch/riscv/conf/GENERIC:1.14 src/sys/arch/riscv/conf/GENERIC:1.15
--- src/sys/arch/riscv/conf/GENERIC:1.14 Sun Sep 11 15:31:11 2022
+++ src/sys/arch/riscv/conf/GENERIC Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.14 2022/09/11 15:31:11 skrll Exp $
+# $NetBSD: GENERIC,v 1.15 2022/09/27 08:18:21 skrll Exp $
#
# GENERIC machine description file
#
@@ -22,7 +22,7 @@ include "arch/riscv/conf/std.riscv64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
-#ident "GENERIC-$Revision: 1.14 $"
+#ident "GENERIC-$Revision: 1.15 $"
maxusers 64 # estimated number of users
@@ -74,7 +74,7 @@ options DIAGNOSTIC # inexpensive kernel
# Because gcc omits the frame pointer for any -O level, the line below
# is needed to make backtraces in DDB work.
#
-#makeoptions COPTS="-O2 -fno-omit-frame-pointer"
+makeoptions COPTS="-O2 -fno-omit-frame-pointer"
makeoptions COPY_SYMTAB=1
options DDB # in-kernel debugger
#options DDB_COMMANDONENTER="bt" # execute command when ddb is entered
Index: src/sys/arch/riscv/conf/files.riscv
diff -u src/sys/arch/riscv/conf/files.riscv:1.9 src/sys/arch/riscv/conf/files.riscv:1.10
--- src/sys/arch/riscv/conf/files.riscv:1.9 Mon Sep 19 09:15:01 2022
+++ src/sys/arch/riscv/conf/files.riscv Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-# $NetBSD: files.riscv,v 1.9 2022/09/19 09:15:01 skrll Exp $
+# $NetBSD: files.riscv,v 1.10 2022/09/27 08:18:21 skrll Exp $
#
maxpartitions 16
@@ -21,6 +21,7 @@ file arch/riscv/riscv/bus_space_notimpl.
file arch/riscv/riscv/clock_machdep.c
file arch/riscv/riscv/core_machdep.c coredump
file arch/riscv/riscv/cpu_subr.c
+file arch/riscv/riscv/db_interface.c ddb
file arch/riscv/riscv/db_disasm.c ddb
file arch/riscv/riscv/db_machdep.c ddb | kgdb
file arch/riscv/riscv/db_trace.c ddb
Index: src/sys/arch/riscv/include/db_machdep.h
diff -u src/sys/arch/riscv/include/db_machdep.h:1.5 src/sys/arch/riscv/include/db_machdep.h:1.6
--- src/sys/arch/riscv/include/db_machdep.h:1.5 Tue May 18 06:42:11 2021
+++ src/sys/arch/riscv/include/db_machdep.h Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.h,v 1.5 2021/05/18 06:42:11 skrll Exp $ */
+/* $NetBSD: db_machdep.h,v 1.6 2022/09/27 08:18:21 skrll Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -43,7 +43,8 @@ typedef long db_expr_t; /* expression -
typedef struct trapframe db_regs_t;
extern const uint32_t __cpu_Debugger_insn[1];
-#define DDB_REGS (curcpu()->ci_ddb_regs)
+extern db_regs_t ddb_regs;
+#define DDB_REGS (&ddb_regs)
#define PC_REGS(tf) ((tf)->tf_pc)
@@ -87,7 +88,7 @@ db_addr_t db_disasm_insn(uint32_t, db_ad
* Entrypoints to DDB for kernel, keyboard drivers, init hook
*/
void kdb_kbd_trap(db_regs_t *);
-int kdb_trap(int, struct trapframe *);
+int kdb_trap(int, db_regs_t *);
static inline void
db_set_ddb_regs(int type, struct trapframe *tf)
@@ -130,4 +131,6 @@ void db_resume_others(void);
#define DB_MACHINE_COMMANDS
#endif
+void dump_trapframe(const struct trapframe *, void (*)(const char *, ...) __printflike(1, 2));
+
#endif /* _RISCV_DB_MACHDEP_H_ */
Index: src/sys/arch/riscv/riscv/db_machdep.c
diff -u src/sys/arch/riscv/riscv/db_machdep.c:1.8 src/sys/arch/riscv/riscv/db_machdep.c:1.9
--- src/sys/arch/riscv/riscv/db_machdep.c:1.8 Sun May 23 23:22:55 2021
+++ src/sys/arch/riscv/riscv/db_machdep.c Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $ */
+/* $NetBSD: db_machdep.c,v 1.9 2022/09/27 08:18:21 skrll Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
-__RCSID("$NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $");
+__RCSID("$NetBSD: db_machdep.c,v 1.9 2022/09/27 08:18:21 skrll Exp $");
#include <sys/param.h>
@@ -44,8 +44,6 @@ __RCSID("$NetBSD: db_machdep.c,v 1.8 202
#include <ddb/db_variables.h>
#include <ddb/db_output.h>
-int db_active = 0;
-
static int db_rw_ddbreg(const struct db_variable *, db_expr_t *, int);
const struct db_variable db_regs[] = {
Index: src/sys/arch/riscv/riscv/db_trace.c
diff -u src/sys/arch/riscv/riscv/db_trace.c:1.2 src/sys/arch/riscv/riscv/db_trace.c:1.3
--- src/sys/arch/riscv/riscv/db_trace.c:1.2 Wed Nov 4 07:09:46 2020
+++ src/sys/arch/riscv/riscv/db_trace.c Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: db_trace.c,v 1.2 2020/11/04 07:09:46 skrll Exp $ */
+/* $NetBSD: db_trace.c,v 1.3 2022/09/27 08:18:21 skrll Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,17 +31,224 @@
#include <sys/cdefs.h>
-__RCSID("$NetBSD: db_trace.c,v 1.2 2020/11/04 07:09:46 skrll Exp $");
+__RCSID("$NetBSD: db_trace.c,v 1.3 2022/09/27 08:18:21 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <riscv/db_machdep.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_command.h>
+#include <ddb/db_output.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_proc.h>
+#include <ddb/db_lwp.h>
+#include <ddb/db_extern.h>
#include <ddb/db_interface.h>
+#define MAXBACKTRACE 128 /* against infinite loop */
+#define TRACEFLAG_LOOKUPLWP 0x00000001
+
+__CTASSERT(VM_MIN_ADDRESS == 0);
+#define IN_USER_VM_ADDRESS(addr) \
+ ((addr) < VM_MAX_ADDRESS)
+#define IN_KERNEL_VM_ADDRESS(addr) \
+ ((VM_MIN_KERNEL_ADDRESS <= (addr)) && ((addr) < VM_MAX_KERNEL_ADDRESS))
+
+static bool __unused
+is_lwp(void *p)
+{
+ lwp_t *lwp;
+
+ for (lwp = db_lwp_first(); lwp != NULL; lwp = db_lwp_next(lwp)) {
+ if (lwp == p)
+ return true;
+ }
+ return false;
+}
+
+static const char *
+getlwpnamebysp(uint64_t sp)
+{
+#if defined(_KERNEL)
+ lwp_t *lwp;
+
+ for (lwp = db_lwp_first(); lwp != NULL; lwp = db_lwp_next(lwp)) {
+ uint64_t uarea = uvm_lwp_getuarea(lwp);
+ if ((uarea <= sp) && (sp < (uarea + USPACE))) {
+ return lwp->l_name;
+ }
+ }
+#endif
+ return "unknown";
+}
+
+static void
+pr_traceaddr(const char *prefix, uint64_t frame, uint64_t pc, int flags,
+ void (*pr)(const char *, ...) __printflike(1, 2))
+{
+ db_expr_t offset;
+ db_sym_t sym;
+ const char *name;
+
+ sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
+ if (sym != DB_SYM_NULL) {
+ db_symbol_values(sym, &name, NULL);
+
+ if (flags & TRACEFLAG_LOOKUPLWP) {
+ (*pr)("%s %016" PRIx64 " %s %s() at %016" PRIx64,
+ prefix, frame, getlwpnamebysp(frame), name, pc);
+ } else {
+ (*pr)("%s %016" PRIx64 " %s() at %016" PRIx64 " ",
+ prefix, frame, name, pc);
+ }
+ db_printsym(pc, DB_STGY_PROC, pr);
+ (*pr)("\n");
+ } else {
+ if (flags & TRACEFLAG_LOOKUPLWP) {
+ (*pr)("%s %016" PRIx64 " %s ?() at %016" PRIx64 "\n",
+ prefix, frame, getlwpnamebysp(frame), pc);
+ } else {
+ (*pr)("%s %016" PRIx64 " ?() at %016" PRIx64 "\n", prefix, frame, pc);
+ }
+ }
+}
+
void
db_stack_trace_print(db_expr_t addr, bool have_addr, db_expr_t count,
- const char *modif, void (*pr)(const char *, ...))
+ const char *modif, void (*pr)(const char *, ...) __printflike(1, 2))
{
- /* TBD!! */
+ register_t ra, fp, lastra, lastfp;
+ struct trapframe *tf = NULL;
+ int flags = 0;
+ bool trace_user = false;
+ bool trace_thread = false;
+ bool trace_lwp = false;
+
+ for (; *modif != '\0'; modif++) {
+ switch (*modif) {
+ case 'a':
+ trace_lwp = true;
+ trace_thread = false;
+ break;
+ case 'l':
+ break;
+ case 't':
+ trace_thread = true;
+ trace_lwp = false;
+ break;
+ case 'u':
+ trace_user = true;
+ break;
+ case 'x':
+ flags |= TRACEFLAG_LOOKUPLWP;
+ break;
+ default:
+ pr("usage: bt[/ulx] [frame-address][,count]\n");
+ pr(" bt/t[ulx] [pid][,count]\n");
+ pr(" bt/a[ulx] [lwpaddr][,count]\n");
+ pr("\n");
+ pr(" /x reverse lookup lwp name from sp\n");
+ return;
+ }
+ }
+
+#if defined(_KERNEL)
+ if (!have_addr) {
+ if (trace_lwp) {
+ addr = (db_expr_t)curlwp;
+ } else if (trace_thread) {
+ addr = curlwp->l_proc->p_pid;
+ } else {
+ tf = DDB_REGS;
+ }
+ }
+#endif
+
+ if (trace_thread) {
+ proc_t *pp, p;
+
+ if ((pp = db_proc_find((pid_t)addr)) == 0) {
+ (*pr)("trace: pid %d: not found\n", (int)addr);
+ return;
+ }
+ db_read_bytes((db_addr_t)pp, sizeof(p), (char *)&p);
+ addr = (db_addr_t)p.p_lwps.lh_first;
+ trace_thread = false;
+ trace_lwp = true;
+ }
+
+#if 0
+ /* "/a" is abbreviated? */
+ if (!trace_lwp && is_lwp(addr))
+ trace_lwp = true;
+#endif
+
+ if (trace_lwp) {
+ proc_t p;
+ struct lwp l;
+
+ db_read_bytes(addr, sizeof(l), (char *)&l);
+ db_read_bytes((db_addr_t)l.l_proc, sizeof(p), (char *)&p);
+
+#if defined(_KERNEL)
+ if (addr == (db_expr_t)curlwp) {
+ fp = (register_t)&DDB_REGS->tf_s0; /* s0 = fp */
+ tf = DDB_REGS;
+ (*pr)("trace: pid %d lid %d (curlwp) at tf %p\n",
+ p.p_pid, l.l_lid, tf);
+ } else
+#endif
+ {
+ tf = l.l_md.md_ktf;
+ db_read_bytes((db_addr_t)&tf->tf_s0, sizeof(fp), (char *)&fp);
+ (*pr)("trace: pid %d lid %d at tf %p\n",
+ p.p_pid, l.l_lid, tf);
+ }
+ } else if (tf == NULL) {
+ fp = addr;
+ pr("trace fp %016" PRIxREGISTER "\n", fp);
+ } else {
+ pr("trace tf %p\n", tf);
+ }
+
+ if (count > MAXBACKTRACE)
+ count = MAXBACKTRACE;
+
+ if (tf != NULL) {
+#if defined(_KERNEL)
+ (*pr)("---- trapframe %p (%zu bytes) ----\n",
+ tf, sizeof(*tf));
+ dump_trapframe(tf, pr);
+ (*pr)("------------------------"
+ "------------------------\n");
+
+#endif
+ lastfp = lastra = ra = fp = 0;
+ db_read_bytes((db_addr_t)&tf->tf_ra, sizeof(ra), (char *)&ra);
+ db_read_bytes((db_addr_t)&tf->tf_s0, sizeof(fp), (char *)&fp);
+
+ pr_traceaddr("fp", fp, ra - 4, flags, pr);
+ }
+ for (; (count > 0) && (fp != 0); count--) {
+
+ lastfp = fp;
+ fp = ra = 0;
+ /*
+ * normal stack frame
+ * fp[-1] saved fp(s0) value
+ * fp[-2] saved ra value
+ */
+ db_read_bytes(lastfp - 1 * sizeof(register_t), sizeof(ra), (char *)&ra);
+ db_read_bytes(lastfp - 2 * sizeof(register_t), sizeof(fp), (char *)&fp);
+
+ if (!trace_user && (IN_USER_VM_ADDRESS(ra) || IN_USER_VM_ADDRESS(fp)))
+ break;
+
+ pr_traceaddr("fp", fp, ra - 4, flags, pr);
+ }
}
Index: src/sys/arch/riscv/riscv/locore.S
diff -u src/sys/arch/riscv/riscv/locore.S:1.25 src/sys/arch/riscv/riscv/locore.S:1.26
--- src/sys/arch/riscv/riscv/locore.S:1.25 Tue Sep 20 07:18:23 2022
+++ src/sys/arch/riscv/riscv/locore.S Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.S,v 1.25 2022/09/20 07:18:23 skrll Exp $ */
+/* $NetBSD: locore.S,v 1.26 2022/09/27 08:18:21 skrll Exp $ */
/*-
* Copyright (c) 2014, 2022 The NetBSD Foundation, Inc.
@@ -363,6 +363,8 @@ vstart:
mv a0, s0 // hartid
mv a1, t0 // vdtb
//mv a1, s1 // dtb (physical)
+
+ li s0, 0 // zero frame pointer
call _C_LABEL(init_riscv) // do MD startup
tail _C_LABEL(main) // and transfer to main
/* No return from main */
Index: src/sys/arch/riscv/riscv/trap.c
diff -u src/sys/arch/riscv/riscv/trap.c:1.17 src/sys/arch/riscv/riscv/trap.c:1.18
--- src/sys/arch/riscv/riscv/trap.c:1.17 Wed Sep 21 07:07:34 2022
+++ src/sys/arch/riscv/riscv/trap.c Tue Sep 27 08:18:21 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.17 2022/09/21 07:07:34 skrll Exp $ */
+/* $NetBSD: trap.c,v 1.18 2022/09/27 08:18:21 skrll Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
#define __PMAP_PRIVATE
#define __UFETCHSTORE_PRIVATE
-__RCSID("$NetBSD: trap.c,v 1.17 2022/09/21 07:07:34 skrll Exp $");
+__RCSID("$NetBSD: trap.c,v 1.18 2022/09/27 08:18:21 skrll Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -46,7 +46,8 @@ __RCSID("$NetBSD: trap.c,v 1.17 2022/09/
#include <uvm/uvm.h>
-#include <riscv/locore.h>
+#include <machine/locore.h>
+#include <machine/db_machdep.h>
#define MACHINE_ECALL_TRAP_MASK (__BIT(CAUSE_MACHINE_ECALL))
@@ -177,7 +178,7 @@ copyoutstr(const void *kaddr, void *uadd
return error;
}
-static void
+void
dump_trapframe(const struct trapframe *tf, void (*pr)(const char *, ...))
{
const char *causestr = "?";
@@ -425,9 +426,15 @@ cpu_trap(struct trapframe *tf, register_
} else if (fault_mask & MISALIGNED_TRAP_MASK) {
ok = trap_misalignment(tf, epc, status, cause, addr,
usertrap_p, &ksi);
- } else {
- dump_trapframe(tf, printf);
- panic("%s: unknown kernel trap", __func__);
+ } else if (fault_mask & BREAKPOINT_TRAP_MASK) {
+ if (!usertrap_p) {
+ dump_trapframe(tf, printf);
+#if defined(DDB)
+ kdb_trap(cause, tf);
+ return; /* KERN */
+#endif
+ panic("%s: unknown kernel trap", __func__);
+ }
}
if (usertrap_p) {
Added files:
Index: src/sys/arch/riscv/riscv/db_interface.c
diff -u /dev/null src/sys/arch/riscv/riscv/db_interface.c:1.1
--- /dev/null Tue Sep 27 08:18:21 2022
+++ src/sys/arch/riscv/riscv/db_interface.c Tue Sep 27 08:18:21 2022
@@ -0,0 +1,248 @@
+/* $NetBSD: db_interface.c,v 1.1 2022/09/27 08:18:21 skrll Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or [email protected]
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.1 2022/09/27 08:18:21 skrll Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_multiprocessor.h"
+#include "opt_ddb.h"
+#include "opt_kgdb.h"
+#endif
+
+#define __PMAP_PRIVATE
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <sys/atomic.h>
+#include <sys/cpu.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/cons.h>
+
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_user.h>
+#ifndef KGDB
+#include <ddb/db_command.h>
+#include <ddb/db_output.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_extern.h>
+#include <ddb/db_interface.h>
+#include <ddb/db_lex.h>
+#include <ddb/db_run.h> /* for db_continue_cmd() proto */
+#endif
+
+#define NOCPU ~0
+volatile u_int ddb_cpu = NOCPU;
+
+int db_active = 0;
+
+#ifdef _KERNEL
+db_regs_t ddb_regs;
+#endif
+
+#ifdef MULTIPROCESSOR
+static void db_mach_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
+#endif
+
+void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *);
+void db_kvtophys_cmd(db_expr_t, bool, db_expr_t, const char *);
+
+paddr_t kvtophys(vaddr_t);
+
+#ifdef _KERNEL
+
+#ifndef KGDB
+int
+kdb_trap(int type, db_regs_t *regs)
+{
+ int s;
+
+ switch (type) {
+ case CAUSE_BREAKPOINT: /* breakpoint */
+ printf("kernel: breakpoint\n");
+ break;
+ case -1: /* keyboard interrupt */
+ printf("kernel: kdbint trap\n");
+ break;
+ default:
+ printf("kernel: cause %d\n", type);
+ if (db_recover != 0) {
+ db_error("Faulted in DDB; continuing...\n");
+ /*NOTREACHED*/
+ }
+ break;
+ }
+
+ s = splhigh();
+
+#if defined(MULTIPROCESSOR)
+ bool first_in_ddb = false;
+ const u_int cpu_me = cpu_number();
+ const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me);
+ if (old_ddb_cpu == NOCPU) {
+ first_in_ddb = true;
+ cpu_pause_others();
+ } else {
+ if (old_ddb_cpu != cpu_me) {
+ KASSERT(cpu_is_paused(cpu_me));
+ cpu_pause(regs);
+ splx(s);
+ return 1;
+ }
+ }
+ KASSERT(! cpu_is_paused(cpu_me));
+#endif
+
+ ddb_regs = *regs;
+ db_active++;
+ cnpollc(1);
+ db_trap(type, 0 /*code*/);
+ cnpollc(0);
+ db_active--;
+ *regs = ddb_regs;
+
+#if defined(MULTIPROCESSOR)
+ if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
+ cpu_resume_others();
+ } else {
+ cpu_resume(ddb_cpu);
+ if (first_in_ddb)
+ cpu_pause(regs);
+ }
+#endif
+
+ splx(s);
+ return 1;
+}
+#endif /* !KGDB */
+
+
+#ifndef KGDB
+void
+db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
+ const char *modif)
+{
+}
+
+void
+db_kvtophys_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
+ const char *modif)
+{
+
+ if (!have_addr)
+ return;
+}
+
+
+static void
+db_mach_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
+ const char *modif)
+{
+}
+
+
+const struct db_command db_machine_command_table[] = {
+#ifdef MULTIPROCESSOR
+ { DDB_ADD_CMD("cpu", db_mach_cpu_cmd, 0,
+ "switch to another cpu", "cpu#", NULL) },
+#endif
+ { DDB_ADD_CMD("kvtop", db_kvtophys_cmd, 0,
+ "Print the physical address for a given kernel virtual address",
+ "address",
+ " address:\tvirtual address to look up") },
+ { DDB_ADD_CMD("reset", db_mach_reset_cmd, CS_NOREPEAT,
+ "Initiate hardware reset",
+ NULL, NULL) },
+ { DDB_ADD_CMD("tlb", db_tlbdump_cmd, 0,
+ "Print out TLB entries. (only works with options DEBUG)",
+ NULL, NULL) },
+ { DDB_END_CMD },
+};
+#endif /* !KGDB */
+
+#ifdef MULTIPROCESSOR
+
+bool
+ddb_running_on_this_cpu_p(void)
+{
+ return ddb_cpu == cpu_number();
+}
+
+bool
+ddb_running_on_any_cpu_p(void)
+{
+ return ddb_cpu != NOCPU;
+}
+
+void
+db_resume_others(void)
+{
+ u_int cpu_me = cpu_number();
+
+ if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
+ cpu_resume_others();
+}
+
+static void
+db_mach_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+ if (!have_addr) {
+ cpu_debug_dump();
+ return;
+ }
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (cpu_index(ci) == addr)
+ break;
+ }
+ if (ci == NULL) {
+ db_printf("CPU %ld not configured\n", (long)addr);
+ return;
+ }
+ if (ci != curcpu()) {
+ if (!cpu_is_paused(cpu_index(ci))) {
+ db_printf("CPU %ld not paused\n", (long)addr);
+ return;
+ }
+ (void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci));
+ db_continue_cmd(0, false, 0, "");
+ }
+}
+#endif /* MULTIPROCESSOR */
+
+#endif /* _KERNEL */