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 software.distribut...@cs.cmu.edu + * 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 */