Add rudimentary multiprocessor support for DDB.

This commit is contained in:
ragge 2001-06-04 21:37:11 +00:00
parent cae5d5a796
commit f81f19e7b3
5 changed files with 167 additions and 65 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.h,v 1.59 2001/06/04 15:34:15 ragge Exp $ */
/* $NetBSD: cpu.h,v 1.60 2001/06/04 21:37:12 ragge Exp $ */
/*
* Copyright (c) 1994 Ludd, University of Lule}, Sweden
@ -94,6 +94,7 @@ struct cpu_mp_dep {
#define IPI_SEND_CNCHAR 2 /* Write char to console, kernel printf */
#define IPI_RUNNING 3 /* This CPU just started to run */
#define IPI_TBIA 4 /* Flush the TLB */
#define IPI_DDB 5 /* Jump into the DDB loop */
#define IPI_DEST_MASTER -1 /* Destination is mastercpu */
#define IPI_DEST_ALL -2 /* Broadcast */
@ -133,10 +134,12 @@ struct cpu_info {
vaddr_t ci_istack; /* Interrupt stack location */
int ci_flags; /* See below */
long ci_ipimsgs; /* Sent IPI bits */
struct trapframe *ci_ddb_regs; /* Used by DDB */
#endif
};
#define CI_MASTERCPU 1 /* Set if master CPU */
#define CI_RUNNING 2 /* Set when a slave CPU is running */
#define CI_STOPPED 4 /* Stopped (in debugger) */
#if defined(MULTIPROCESSOR)
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_machdep.h,v 1.9 2001/05/02 15:59:38 matt Exp $ */
/* $NetBSD: db_machdep.h,v 1.10 2001/06/04 21:37:12 ragge Exp $ */
/*
* Mach Operating System
@ -71,6 +71,8 @@ db_regs_t ddb_regs; /* register state */
#define inst_load(ins) 0
#define inst_store(ins) 0
#define DB_MACHINE_COMMANDS
/* Prototypes */
void kdb_trap __P((struct trapframe *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: lock.h,v 1.7 2001/06/04 15:37:05 ragge Exp $ */
/* $NetBSD: lock.h,v 1.8 2001/06/04 21:37:12 ragge Exp $ */
/*
* Copyright (c) 2000 Ludd, University of Lule}, Sweden.
@ -70,6 +70,7 @@ __cpu_simple_lock_try(__cpu_simple_lock_t *alp)
return ret;
}
#define VAX_LOCK_CHECKS ((1 << IPI_SEND_CNCHAR) | (1 << IPI_DDB))
#define __cpu_simple_lock(alp) \
{ \
struct cpu_info *__ci = curcpu(); \
@ -77,7 +78,7 @@ __cpu_simple_lock_try(__cpu_simple_lock_t *alp)
while (__cpu_simple_lock_try(alp) == 0) { \
int __s; \
\
if (__ci->ci_ipimsgs & (1 << IPI_SEND_CNCHAR)) { \
if (__ci->ci_ipimsgs & VAX_LOCK_CHECKS) { \
__s = splipi(); \
cpu_handle_ipi(); \
splx(__s); \

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_machdep.c,v 1.28 2001/04/29 22:17:24 matt Exp $ */
/* $NetBSD: db_machdep.c,v 1.29 2001/06/04 21:37:11 ragge Exp $ */
/*
* :set tabs=4
@ -38,6 +38,7 @@
* Taken from i386 port and modified for vax.
*/
#include "opt_ddb.h"
#include "opt_multiprocessor.h"
#include <sys/param.h>
#include <sys/proc.h>
@ -49,11 +50,11 @@
#include <dev/cons.h>
#include <machine/cpu.h>
#include <machine/db_machdep.h>
#include <machine/trap.h>
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <vax/vax/gencons.h>
@ -65,15 +66,57 @@
#include <ddb/db_interface.h>
#include <ddb/db_variables.h>
extern label_t *db_recover;
#include "ioconf.h"
void kdbprinttrap __P((int, int));
extern label_t *db_recover;
void kdbprinttrap(int, int);
int db_active = 0;
extern int qdpolling;
static int splsave; /* IPL before entering debugger */
#ifdef MULTIPROCESSOR
static struct cpu_info *stopcpu;
/*
* Only the master CPU is allowed to enter DDB, but the correct frames
* must still be there. Keep the state-machine here.
*/
static int
pause_cpus(void)
{
volatile struct cpu_info *ci = curcpu();
if (stopcpu == NULL) {
stopcpu = curcpu();
cpu_send_ipi(IPI_DEST_ALL, IPI_DDB);
}
if ((ci->ci_flags & CI_MASTERCPU) == 0) {
ci->ci_flags |= CI_STOPPED;
while (ci->ci_flags & CI_STOPPED)
;
return 1;
} else
return 0;
}
static void
resume_cpus(void)
{
struct cpu_mp_softc *sc;
struct cpu_info *ci;
int i;
stopcpu = NULL;
for (i = 0; i < cpu_cd.cd_ndevs; i++) {
if ((sc = cpu_cd.cd_devs[i]) == NULL)
continue;
ci = &sc->sc_ci;
ci->ci_flags &= ~CI_STOPPED;
}
}
#endif
/*
* VAX Call frame on the stack, this from
* "Computer Programming and Architecture, The VAX-11"
@ -81,16 +124,16 @@ static int splsave; /* IPL before entering debugger */
* ISBN 0-932376-07-X
*/
typedef struct __vax_frame {
u_int vax_cond; /* condition handler */
u_int vax_psw:16; /* 16 bit processor status word */
u_int vax_regs:12; /* Register save mask. */
u_int vax_zero:1; /* Always zero */
u_int vax_cond; /* condition handler */
u_int vax_psw:16; /* 16 bit processor status word */
u_int vax_regs:12; /* Register save mask. */
u_int vax_zero:1; /* Always zero */
u_int vax_calls:1; /* True if CALLS, false if CALLG */
u_int vax_spa:2; /* Stack pointer alignment */
u_int *vax_ap; /* argument pointer */
u_int vax_spa:2; /* Stack pointer alignment */
u_int *vax_ap; /* argument pointer */
struct __vax_frame *vax_fp; /* frame pointer of previous frame */
u_int vax_pc; /* program counter */
u_int vax_args[1]; /* 0 or more arguments */
u_int vax_pc; /* program counter */
u_int vax_args[1]; /* 0 or more arguments */
} VAX_CALLFRAME;
/*
@ -100,23 +143,26 @@ typedef struct __vax_frame {
* contain the registers when panic was called. (easy to debug).
*/
void
kdb_trap(frame)
struct trapframe *frame;
kdb_trap(struct trapframe *frame)
{
int s;
#ifdef MULTIPROCESSOR
struct cpu_info *ci = curcpu();
#endif
switch (frame->trap) {
case T_BPTFLT: /* breakpoint */
case T_TRCTRAP: /* single_step */
case T_TRCTRAP: /* single_step */
break;
/* XXX todo: should be migrated to use VAX_CALLFRAME at some point */
case T_KDBTRAP:
#ifndef MULTIPROCESSOR /* No fancy panic stack conversion here */
if (panicstr) {
struct callsframe *pf, *df;
df = (void *)frame->fp; /* start of debug's calls */
pf = (void *)df->ca_fp; /* start of panic's calls */
pf = (void *)df->ca_fp; /* start of panic's calls */
bcopy(&pf->ca_argno, &ddb_regs.r0, sizeof(int) * 12);
ddb_regs.fp = pf->ca_fp;
ddb_regs.pc = pf->ca_pc;
@ -126,6 +172,7 @@ kdb_trap(frame)
ddb_regs.psl |= pf->ca_maskpsw & 0xffe0;
ddb_regs.psl |= (splsave << 16);
}
#endif
break;
default:
@ -139,8 +186,18 @@ kdb_trap(frame)
}
}
#ifdef MULTIPROCESSOR
ci->ci_ddb_regs = frame;
if (pause_cpus())
return;
#endif
#ifndef MULTIPROCESSOR
if (!panicstr)
bcopy(frame, &ddb_regs, sizeof(struct trapframe));
#else
bcopy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe));
printf("stopped on cpu %d\n", stopcpu->ci_cpuid);
#endif
/* XXX Should switch to interrupt stack here, if needed. */
@ -152,11 +209,16 @@ kdb_trap(frame)
db_active--;
splx(s);
#ifndef MULTIPROCESSOR
if (!panicstr)
bcopy(&ddb_regs, frame, sizeof(struct trapframe));
#else
bcopy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe));
#endif
frame->sp = mfpr(PR_USP);
return;
#ifdef MULTIPROCESSOR
resume_cpus();
#endif
}
extern char *traptypes[];
@ -182,8 +244,8 @@ kdbprinttrap(type, code)
*/
void
db_read_bytes(addr, size, data)
vaddr_t addr;
register size_t size;
vaddr_t addr;
register size_t size;
register char *data;
{
@ -195,8 +257,8 @@ db_read_bytes(addr, size, data)
*/
void
db_write_bytes(addr, size, data)
vaddr_t addr;
register size_t size;
vaddr_t addr;
register size_t size;
register char *data;
{
@ -225,13 +287,13 @@ const struct db_variable db_regs[] = {
{"r7", &ddb_regs.r7, FCN_NULL},
{"r8", &ddb_regs.r8, FCN_NULL},
{"r9", &ddb_regs.r9, FCN_NULL},
{"r10", &ddb_regs.r10, FCN_NULL},
{"r11", &ddb_regs.r11, FCN_NULL},
{"r10", &ddb_regs.r10, FCN_NULL},
{"r11", &ddb_regs.r11, FCN_NULL},
{"ap", &ddb_regs.ap, FCN_NULL},
{"fp", &ddb_regs.fp, FCN_NULL},
{"sp", &ddb_regs.sp, FCN_NULL},
{"pc", &ddb_regs.pc, FCN_NULL},
{"psl", &ddb_regs.psl, FCN_NULL},
{"psl", &ddb_regs.psl, FCN_NULL},
};
const struct db_variable * const db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
@ -254,7 +316,7 @@ db_dump_stack(VAX_CALLFRAME *fp, u_int stackbase,
(*pr)("Stack traceback : \n");
if (IN_USERLAND(fp)) {
(*pr)(" Process is executing in user space.\n");
(*pr)(" Process is executing in user space.\n");
return;
}
@ -330,20 +392,20 @@ db_dump_stack(VAX_CALLFRAME *fp, u_int stackbase,
/*
* Implement the trace command which has the form:
*
* trace <-- Trace panic (same as before)
* trace 0x88888 <-- Trace process whose address is 888888
* trace/t <-- Trace current process (0 if no current proc)
* trace/t 0tnn <-- Trace process nn (0t for decimal)
* trace <-- Trace panic (same as before)
* trace 0x88888 <-- Trace frame whose address is 888888
* trace/t <-- Trace current process (0 if no current proc)
* trace/t 0tnn <-- Trace process nn (0t for decimal)
*/
void
db_stack_trace_print(addr, have_addr, count, modif, pr)
db_expr_t addr; /* Address parameter */
boolean_t have_addr; /* True if addr is valid */
db_expr_t count; /* Optional count */
char *modif; /* pointer to flag modifier 't' */
void (*pr) __P((const char *, ...)); /* Print function */
db_expr_t addr; /* Address parameter */
boolean_t have_addr; /* True if addr is valid */
db_expr_t count; /* Optional count */
char *modif; /* pointer to flag modifier 't' */
void (*pr) __P((const char *, ...)); /* Print function */
{
extern vaddr_t proc0paddr;
extern vaddr_t proc0paddr;
struct proc *p = curproc;
struct user *uarea;
int trace_proc;
@ -366,7 +428,11 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
}
(*pr)("panic: %s\n", panicstr);
/* xxx ? where did we panic and whose stack are we using? */
#ifdef MULTIPROCESSOR
db_dump_stack((VAX_CALLFRAME *)(ddb_regs.fp), ddb_regs.ap, pr);
#else
db_dump_stack((VAX_CALLFRAME *)(ddb_regs.sp), ddb_regs.ap, pr);
#endif
return;
}
@ -385,7 +451,7 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
while (foo != 0) {
int digit = (foo >> 28) & 0xf;
if (digit > 9) {
(*pr)(" No such process.\n");
(*pr)(" No such process.\n");
return;
}
tpid = tpid * 10 + digit;
@ -393,16 +459,13 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
}
p = pfind(tpid);
if (p == NULL) {
(*pr)(" No such process.\n");
(*pr)(" No such process.\n");
return;
}
}
} else {
p = (struct proc *)(addr);
if (pfind(p->p_pid) != p) {
(*pr)(" This address does not point to a valid process.\n");
return;
}
db_dump_stack((VAX_CALLFRAME *)addr, 0, pr);
return;
}
} else {
if (trace_proc) {
@ -426,28 +489,28 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
curpid = p->p_pid;
}
(*pr)("Process %d\n", curpid);
(*pr)(" PCB contents:\n");
(*pr)(" KSP = 0x%x\n", (unsigned int)(uarea->u_pcb.KSP));
(*pr)(" ESP = 0x%x\n", (unsigned int)(uarea->u_pcb.ESP));
(*pr)(" SSP = 0x%x\n", (unsigned int)(uarea->u_pcb.SSP));
(*pr)(" USP = 0x%x\n", (unsigned int)(uarea->u_pcb.USP));
(*pr)(" R[00] = 0x%08x R[06] = 0x%08x\n",
(*pr)(" PCB contents:\n");
(*pr)(" KSP = 0x%x\n", (unsigned int)(uarea->u_pcb.KSP));
(*pr)(" ESP = 0x%x\n", (unsigned int)(uarea->u_pcb.ESP));
(*pr)(" SSP = 0x%x\n", (unsigned int)(uarea->u_pcb.SSP));
(*pr)(" USP = 0x%x\n", (unsigned int)(uarea->u_pcb.USP));
(*pr)(" R[00] = 0x%08x R[06] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[0]), (unsigned int)(uarea->u_pcb.R[6]));
(*pr)(" R[01] = 0x%08x R[07] = 0x%08x\n",
(*pr)(" R[01] = 0x%08x R[07] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[1]), (unsigned int)(uarea->u_pcb.R[7]));
(*pr)(" R[02] = 0x%08x R[08] = 0x%08x\n",
(*pr)(" R[02] = 0x%08x R[08] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[2]), (unsigned int)(uarea->u_pcb.R[8]));
(*pr)(" R[03] = 0x%08x R[09] = 0x%08x\n",
(*pr)(" R[03] = 0x%08x R[09] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[3]), (unsigned int)(uarea->u_pcb.R[9]));
(*pr)(" R[04] = 0x%08x R[10] = 0x%08x\n",
(*pr)(" R[04] = 0x%08x R[10] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[4]), (unsigned int)(uarea->u_pcb.R[10]));
(*pr)(" R[05] = 0x%08x R[11] = 0x%08x\n",
(*pr)(" R[05] = 0x%08x R[11] = 0x%08x\n",
(unsigned int)(uarea->u_pcb.R[5]), (unsigned int)(uarea->u_pcb.R[11]));
(*pr)(" AP = 0x%x\n", (unsigned int)(uarea->u_pcb.AP));
(*pr)(" FP = 0x%x\n", (unsigned int)(uarea->u_pcb.FP));
(*pr)(" PC = 0x%x\n", (unsigned int)(uarea->u_pcb.PC));
(*pr)(" PSL = 0x%x\n", (unsigned int)(uarea->u_pcb.PSL));
(*pr)(" Trap frame pointer: 0x%x\n",
(*pr)(" AP = 0x%x\n", (unsigned int)(uarea->u_pcb.AP));
(*pr)(" FP = 0x%x\n", (unsigned int)(uarea->u_pcb.FP));
(*pr)(" PC = 0x%x\n", (unsigned int)(uarea->u_pcb.PC));
(*pr)(" PSL = 0x%x\n", (unsigned int)(uarea->u_pcb.PSL));
(*pr)(" Trap frame pointer: 0x%x\n",
(unsigned int)(uarea->u_pcb.framep));
db_dump_stack((VAX_CALLFRAME *)(uarea->u_pcb.FP),
(u_int) uarea->u_pcb.KSP, pr);
@ -522,7 +585,7 @@ db_stack_trace_print(addr, have_addr, count, modif, pr)
paddr = proc0paddr;
stackbase = (ddb_regs.psl & PSL_IS ? istack : paddr);
}
}
#endif
}
@ -553,3 +616,31 @@ kdbrint(tkn)
return 0;
}
#ifdef MULTIPROCESSOR
static void
db_mach_cpu(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
struct cpu_mp_softc *sc;
struct cpu_info *ci;
if ((addr < 0) || (addr >= cpu_cd.cd_ndevs))
return db_printf("%ld: cpu out of range\n", addr);
if ((sc = cpu_cd.cd_devs[addr]) == NULL)
return db_printf("%ld: cpu not configured\n", addr);
ci = &sc->sc_ci;
if ((ci != curcpu()) && ((ci->ci_flags & CI_STOPPED) == 0))
return db_printf("cpu %ld not stopped???\n", addr);
bcopy(&ddb_regs, stopcpu->ci_ddb_regs, sizeof(struct trapframe));
stopcpu = ci;
bcopy(stopcpu->ci_ddb_regs, &ddb_regs, sizeof(struct trapframe));
db_printf("using cpu %ld", addr);
}
const struct db_command db_machine_command_table[] = {
{ "cpu", db_mach_cpu, 0, 0 },
{ (char *)0, },
};
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: multicpu.c,v 1.8 2001/06/04 15:34:16 ragge Exp $ */
/* $NetBSD: multicpu.c,v 1.9 2001/06/04 21:37:11 ragge Exp $ */
/*
* Copyright (c) 2000 Ludd, University of Lule}, Sweden. All rights reserved.
@ -221,6 +221,11 @@ cpu_handle_ipi()
case IPI_TBIA:
mtpr(0, PR_TBIA);
break;
case IPI_DDB:
Debugger();
break;
default:
panic("cpu_handle_ipi: bad bit %x\n", bitno);
}
}
}