Make ddb's "mach cpu" command do the right thing: run ddb on the requested

cpu. There is a tiny bit of cheating involved, but I assume we won't run
parallel + recursive ddb scripts to play towers of hanoi.

This fixes the wrong prompt, and (more importantly) makes things like
"mach dtlb" display the registers of the right MMU.
This commit is contained in:
martin 2008-03-02 22:01:38 +00:00
parent 1b00238d8c
commit 54c5277e8e
3 changed files with 81 additions and 67 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.20 2008/01/15 10:35:33 martin Exp $ */
/* $NetBSD: intr.h,v 1.21 2008/03/02 22:01:38 martin Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -60,6 +60,7 @@ void save_and_clear_fpstate(struct lwp *);
void sparc64_ipi_init (void);
int sparc64_ipi_halt_thiscpu (void *);
int sparc64_ipi_pause_thiscpu (void *);
void sparc64_do_pause(void);
void sparc64_ipi_drop_fpstate (void *);
void sparc64_ipi_save_fpstate (void *);
void sparc64_ipi_nop (void *);
@ -67,6 +68,7 @@ void mp_halt_cpus (void);
void mp_pause_cpus (void);
void mp_resume_cpus (void);
int mp_cpu_is_paused (sparc64_cpuset_t);
void mp_resume_cpu(int);
#endif
#endif /* _SPARC64_INTR_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_interface.c,v 1.108 2008/02/29 20:27:07 martin Exp $ */
/* $NetBSD: db_interface.c,v 1.109 2008/03/02 22:01:38 martin Exp $ */
/*
* Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.108 2008/02/29 20:27:07 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.109 2008/03/02 22:01:38 martin Exp $");
#include "opt_ddb.h"
@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.108 2008/02/29 20:27:07 martin Ex
#include <sys/user.h>
#include <sys/reboot.h>
#include <sys/systm.h>
#include <sys/atomic.h>
#include <uvm/uvm_extern.h>
@ -89,8 +90,9 @@ static uint64_t nil;
#define pmap_ctx(PM) ((PM)->pm_ctx)
#endif
static void fill_ddb_regs_from_tf(struct trapframe64 *tf);
static void ddb_restore_state(void);
void fill_ddb_regs_from_tf(struct trapframe64 *tf);
void ddb_restore_state(void);
bool ddb_running_on_this_cpu(void);
static int
db_sparc_charop(const struct db_variable *vp, db_expr_t *val, int opcode)
@ -303,42 +305,40 @@ static void db_print_trace_entry(struct traptrace *, int);
#define NOCPU -1
static int db_suspend_others(void);
static void db_resume_others(void);
static void ddb_suspend(struct trapframe64 *);
void db_resume_others(void);
__cpu_simple_lock_t db_lock;
int ddb_cpu = NOCPU;
bool
ddb_running_on_this_cpu(void)
{
return ddb_cpu == cpu_number();
}
static int
db_suspend_others(void)
{
int cpu_me = cpu_number();
int win;
bool win;
if (cpus == NULL)
return 1;
__cpu_simple_lock(&db_lock);
if (ddb_cpu == NOCPU)
ddb_cpu = cpu_me;
win = (ddb_cpu == cpu_me);
__cpu_simple_unlock(&db_lock);
win = atomic_cas_32(&ddb_cpu, NOCPU, cpu_me) == (uint32_t)NOCPU;
if (win)
mp_pause_cpus();
return win;
}
static void
void
db_resume_others(void)
{
int cpu_me = cpu_number();
mp_resume_cpus();
__cpu_simple_lock(&db_lock);
ddb_cpu = NOCPU;
__cpu_simple_unlock(&db_lock);
if (atomic_cas_32(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
mp_resume_cpus();
}
static void
@ -361,7 +361,7 @@ kdb_kbd_trap(struct trapframe64 *tf)
}
}
static void
void
fill_ddb_regs_from_tf(struct trapframe64 *tf)
{
extern int savetstate(struct trapstate *);
@ -416,7 +416,7 @@ fill_ddb_regs_from_tf(struct trapframe64 *tf)
DDB_REGS->db_tl = savetstate(&DDB_REGS->db_ts[0]);
}
static void
void
ddb_restore_state()
{
extern void restoretstate(int, struct trapstate *);
@ -445,8 +445,6 @@ kdb_trap(int type, struct trapframe64 *tf)
#endif
switch (type) {
case T_BREAKPOINT: /* breakpoint */
printf("cpu%d: kdb breakpoint at %llx\n", cpu_number(),
(unsigned long long)tf->tf_pc);
break;
case -1: /* keyboard interrupt */
printf("kdb tf=%p\n", tf);
@ -1154,10 +1152,6 @@ db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
return;
}
#ifdef MULTIPROCESSOR
if ((addr < 0) || (addr >= sparc_ncpus)) {
db_printf("%ld: CPU out of range\n", addr);
return;
}
for (ci = cpus; ci != NULL; ci = ci->ci_next)
if (ci->ci_index == addr)
break;
@ -1170,12 +1164,11 @@ db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
db_printf("CPU %ld not paused\n", addr);
return;
}
/* no locking needed - all other cpus are paused */
ddb_cpu = ci->ci_index;
mp_resume_cpu(ddb_cpu);
sparc64_do_pause();
}
if (ci->ci_ddb_regs == NULL) {
db_printf("CPU %ld has no saved regs\n", addr);
return;
}
db_printf("using CPU %ld", addr);
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipifuncs.c,v 1.13 2008/02/22 10:55:00 martin Exp $ */
/* $NetBSD: ipifuncs.c,v 1.14 2008/03/02 22:01:38 martin Exp $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.13 2008/02/22 10:55:00 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.14 2008/03/02 22:01:38 martin Exp $");
#include "opt_ddb.h"
@ -55,7 +55,10 @@ __KERNEL_RCSID(0, "$NetBSD: ipifuncs.c,v 1.13 2008/02/22 10:55:00 martin Exp $")
#define sparc64_ipi_sleep() delay(1000)
#if defined(DDB) || defined(KGDB)
extern int db_active;
#ifdef DDB
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#endif
#endif
/* CPU sets containing halted, paused and resumed cpus */
@ -91,47 +94,56 @@ sparc64_ipi_halt_thiscpu(void *arg)
return(1);
}
void
sparc64_do_pause(void)
{
#if defined(DDB)
extern bool ddb_running_on_this_cpu(void);
extern void db_resume_others(void);
#endif
CPUSET_ADD(cpus_paused, cpu_number());
do {
membar_sync();
} while(CPUSET_HAS(cpus_paused, cpu_number()));
membar_sync();
CPUSET_ADD(cpus_resumed, cpu_number());
#if defined(DDB)
if (ddb_running_on_this_cpu()) {
db_command_loop();
db_resume_others();
}
#endif
}
/*
* Pause cpu. This is called from locore.s after setting up a trapframe.
*/
int
sparc64_ipi_pause_thiscpu(void *arg)
{
cpuid_t cpuid;
int s;
#if defined(DDB)
struct trapframe64 *tf = arg;
volatile db_regs_t dbregs;
extern void fill_ddb_regs_from_tf(struct trapframe64 *tf);
extern void ddb_restore_state(void);
if (arg)
fill_ddb_regs_from_tf(arg);
#endif
if (tf) {
/* Initialise local dbregs storage from trap frame */
dbregs.db_tf = *tf;
dbregs.db_fr = *(struct frame64 *)(u_long)tf->tf_out[6];
s = intr_disable();
sparc64_do_pause();
curcpu()->ci_ddb_regs = &dbregs;
#if defined(DDB)
if (arg) {
ddb_restore_state();
curcpu()->ci_ddb_regs = NULL;
}
#endif
cpuid = cpu_number();
printf("cpu%ld paused.\n", cpuid);
s = intr_disable();
CPUSET_ADD(cpus_paused, cpuid);
do {
membar_sync();
} while(CPUSET_HAS(cpus_paused, cpuid));
membar_sync();
CPUSET_ADD(cpus_resumed, cpuid);
#if defined(DDB)
if (tf)
curcpu()->ci_ddb_regs = NULL;
#endif
intr_restore(s);
printf("cpu%ld resumed.\n", cpuid);
return (1);
}
@ -218,12 +230,9 @@ sparc64_send_ipi(int upaid, ipifunc_t func, uint64_t arg1)
return;
}
if (!db_active && panicstr == NULL)
if (panicstr == NULL)
panic("cpu%d: ipi_send: couldn't send ipi to UPAID %u",
cpu_number(), upaid);
else
printf("\noops, can't send IPI from cpu%d to UPAID %u\n",
cpu_number(), upaid);
}
/*
@ -283,6 +292,16 @@ mp_pause_cpus()
sparc64_ipi_error("pause", cpus_paused, cpuset);
}
/*
* Resume a single cpu
*/
void
mp_resume_cpu(int cno)
{
CPUSET_DEL(cpus_paused, cno);
membar_sync();
}
/*
* Resume all paused cpus.
*/