DDB for mips.

Add DDB interface to /sys/arch/mips/mips..
  Rework heuristic stack traceback to work with DDB.
  Add hooks  to print exception log from DDB.
  Add hooks from pmax console drivers:   call Debugger()
  after break from serial console, or 'DO' key from LK-xxx.
This commit is contained in:
jonathan 1997-07-07 03:54:24 +00:00
parent d65e85e261
commit d1ec048977
15 changed files with 1279 additions and 104 deletions

View File

@ -0,0 +1,71 @@
/* $NetBSD */
#ifndef _MIPS_DB_MACHDEP_H_
#define _MIPS_DB_MACHDEP_H_
#include <vm/vm_param.h> /* XXX boolean_t */
#include <mips/trap.h> /* T_BREAK */
#include <mips/reg.h> /* register names */
#include <mips/proc.h> /* register state */
typedef vm_offset_t db_addr_t; /* address - unsigned */
typedef long db_expr_t; /* expression - signed */
typedef struct frame db_regs_t;
db_regs_t ddb_regs; /* register state */
#define DDB_REGS (&ddb_regs)
#define PC_REGS(regs) ((db_addr_t)(regs)->f_regs[PC])
#define BKPT_INST 0x0001000D /* XXX endianness? */
#define BKPT_SIZE (4) /* size of breakpoint inst */
#define BKPT_SET(inst) (BKPT_INST)
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAK)
#define IS_WATCHPOINT_TRAP(type, code) (0) /* XXX mips3 watchpoint */
#define inst_trap_return(ins) ((ins)&0)
#define inst_return(ins) ((ins)&0)
#define inst_load(ins) 0
#define inst_store(ins) 0
/*
* Interface to disassembly (shared with mdb)
*/
db_addr_t db_disasm_insn __P((int insn, db_addr_t loc, boolean_t altfmt));
/*
* Entrypoints to DDB for kernel, keyboard drivers, init hook
*/
void kdb_kbd_trap __P((db_regs_t *));
int kdb_trap __P((int type, db_regs_t *));
void db_machine_init __P((void));
/*
* We use ELF symbols in DDB.
*
*/
/* #define DB_ELF_SYMBOLS */
#define DB_AOUT_SYMBOLS */
/*
* MIPS cpus have no hardware single-step.
*/
#define SOFTWARE_SSTEP
boolean_t inst_branch __P((int inst));
boolean_t inst_call __P((int inst));
boolean_t inst_unconditional_flow_transfer __P((int inst));
db_addr_t branch_taken __P((int inst, db_addr_t pc, db_regs_t *regs));
db_addr_t next_instr_address __P((db_addr_t pc, boolean_t bd));
/*
* We have machine-dependent commands.
*/
#define DB_MACHINE_COMMANDS
#endif /* _MIPS_DB_MACHDEP_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: mips_param.h,v 1.4 1997/06/16 03:52:08 jonathan Exp $ */ /* $NetBSD: mips_param.h,v 1.5 1997/07/07 03:54:30 jonathan Exp $ */
/* /*
* Architecture name. * Architecture name.
@ -6,6 +6,19 @@
#define _MACHINE_ARCH mips #define _MACHINE_ARCH mips
#define MACHINE_ARCH "mips" #define MACHINE_ARCH "mips"
/*
* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE.
* On mips, UPAGES is fixed by sys/arch/mips/mips/locore code
* to be the number of per-process-wired kernel-stack pages/PTES.
*/
#define UPAGES 2 /* pages of u-area */
#define UADDR 0xffffc000 /* address of u */
#define USPACE (UPAGES*NBPG) /* size of u-area in bytes */
#define UVPN (UADDR>>PGSHIFT)/* virtual page number of u */
#define KERNELSTACK (UADDR+UPAGES*NBPG) /* top of kernel stack */
/* /*
* Round p (pointer or byte index) up to a correctly-aligned value for all * Round p (pointer or byte index) up to a correctly-aligned value for all
* data types (int, long, ...). The result is u_int and must be cast to * data types (int, long, ...). The result is u_int and must be cast to

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.7 1997/06/15 17:36:25 mhitch Exp $ */ /* $NetBSD: proc.h,v 1.8 1997/07/07 03:54:29 jonathan Exp $ */
/* /*
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
@ -38,6 +38,8 @@
* @(#)proc.h 8.1 (Berkeley) 6/10/93 * @(#)proc.h 8.1 (Berkeley) 6/10/93
*/ */
#ifndef _MIPS_PROC_H_
#define _MIPS_PROC_H_
/* /*
* Machine-dependent part of the proc structure for MIPS * Machine-dependent part of the proc structure for MIPS
*/ */
@ -63,3 +65,5 @@ struct frame {
/* kernel single-step emulation */ /* kernel single-step emulation */
extern int mips_singlestep __P((struct proc *p)); extern int mips_singlestep __P((struct proc *p));
#endif /* _KERNEL */ #endif /* _KERNEL */
#endif /* _MIPS_PROC_H_ */

View File

@ -0,0 +1,427 @@
/* $NetBSD: db_disasm.c,v 1.1 1997/07/07 03:54:37 jonathan Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
*/
#include <sys/types.h>
#include <sys/systm.h>
#include <machine/reg.h>
#include <machine/cpu.h>
#include <mips/mips_opcode.h>
#include <machine/param.h>
#include <mips/db_machdep.h>
#include <ddb/db_interface.h>
#include <ddb/db_output.h>
static char *op_name[64] = {
/* 0 */ "spec", "bcond","j", "jal", "beq", "bne", "blez", "bgtz",
/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
};
static char *spec_name[64] = {
/* 0 */ "sll", "spec01","srl", "sra", "sllv", "spec05","srlv","srav",
/* 8 */ "jr", "jalr", "spec12","spec13","syscall","break","spec16","sync",
/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
};
static char *bcond_name[32] = {
/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
/*24 */ "?", "?", "?", "?", "?", "?", "?", "?",
};
static char *cop1_name[64] = {
/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
"fcmp.ole","fcmp.ule",
/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
"fcmp.le","fcmp.ngt"
};
static char *fmt_name[16] = {
"s", "d", "e", "fmt3",
"w", "fmt5", "fmt6", "fmt7",
"fmt8", "fmt9", "fmta", "fmtb",
"fmtc", "fmtd", "fmte", "fmtf"
};
static char *reg_name[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
};
static char *c0_opname[64] = {
"c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
"tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
"rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
"eret","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
};
static char *c0_reg[32] = {
"index","random","tlblo0","tlblo1","context","tlbmask","wired","c0r7",
"badvaddr","count","tlbhi","c0r11","sr","cause","epc", "prid",
"config","lladr","watchlo","watchhi","xcontext","c0r21","c0r22","c0r23",
"c0r24","c0r25","ecc","cacheerr","taglo","taghi","errepc","c0r31"
};
/*
* Disassemble instruction at 'loc'. 'altfmt' specifies an
* (optional) alternate format (altfmt for vax: don't assume
* that each external label is a procedure entry mask).
* Return address of start of next instruction.
* Since this function is used by 'examine' and by 'step'
* "next instruction" does NOT mean the next instruction to
* be executed but the 'linear' next instruction.
*/
db_addr_t
db_disasm(loc, altfmt)
db_addr_t loc;
boolean_t altfmt;
{
return (db_disasm_insn(*(int*)loc, loc, altfmt));
}
/*
* Disassemble instruction 'insn' nominally at 'loc'.
* 'loc' may in fact contain a breakpoint instruction.
*/
db_addr_t
db_disasm_insn(insn, loc, altfmt)
int insn;
db_addr_t loc;
boolean_t altfmt;
{
InstFmt i;
i.word = insn;
switch (i.JType.op) {
case OP_SPECIAL:
if (i.word == 0) {
db_printf("nop");
break;
}
if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
db_printf("move\t%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs]);
break;
}
db_printf("%s", spec_name[i.RType.func]);
switch (i.RType.func) {
case OP_SLL:
case OP_SRL:
case OP_SRA:
case OP_DSLL:
case OP_DSRL:
case OP_DSRA:
case OP_DSLL32:
case OP_DSRL32:
case OP_DSRA32:
db_printf("\t%s,%s,%d",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
i.RType.shamt);
break;
case OP_SLLV:
case OP_SRLV:
case OP_SRAV:
case OP_DSLLV:
case OP_DSRLV:
case OP_DSRAV:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rt],
reg_name[i.RType.rs]);
break;
case OP_MFHI:
case OP_MFLO:
db_printf("\t%s", reg_name[i.RType.rd]);
break;
case OP_JR:
case OP_JALR:
/* FALLTHROUGH */
case OP_MTLO:
case OP_MTHI:
db_printf("\t%s", reg_name[i.RType.rs]);
break;
case OP_MULT:
case OP_MULTU:
case OP_DMULT:
case OP_DMULTU:
case OP_DIV:
case OP_DIVU:
case OP_DDIV:
case OP_DDIVU:
db_printf("\t%s,%s",
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
break;
case OP_SYSCALL:
case OP_SYNC:
break;
case OP_BREAK:
db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
break;
default:
db_printf("\t%s,%s,%s",
reg_name[i.RType.rd],
reg_name[i.RType.rs],
reg_name[i.RType.rt]);
};
break;
case OP_BCOND:
db_printf("%s\t%s,", bcond_name[i.IType.rt],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BLEZ:
case OP_BLEZL:
case OP_BGTZ:
case OP_BGTZL:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rs]);
goto pr_displ;
case OP_BEQ:
case OP_BEQL:
if (i.IType.rs == 0 && i.IType.rt == 0) {
db_printf("b\t");
goto pr_displ;
}
/* FALLTHROUGH */
case OP_BNE:
case OP_BNEL:
db_printf("%s\t%s,%s,", op_name[i.IType.op],
reg_name[i.IType.rs],
reg_name[i.IType.rt]);
pr_displ:
db_printf("0x%08lx", loc + 4 + ((short)i.IType.imm << 2));
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc0%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMT:
db_printf("dmtc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_MF:
db_printf("mfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
case OP_DMF:
db_printf("dmfc0\t%s,%s",
reg_name[i.RType.rt],
c0_reg[i.RType.rd]);
break;
default:
db_printf("%s", c0_opname[i.FRType.func]);
};
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
db_printf("bc1%c\t",
"ft"[i.RType.rt & COPz_BC_TF_MASK]);
goto pr_displ;
case OP_MT:
db_printf("mtc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_MF:
db_printf("mfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CT:
db_printf("ctc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
case OP_CF:
db_printf("cfc1\t%s,f%d",
reg_name[i.RType.rt],
i.RType.rd);
break;
default:
db_printf("%s.%s\tf%d,f%d,f%d",
cop1_name[i.FRType.func],
fmt_name[i.FRType.fmt],
i.FRType.fd, i.FRType.fs, i.FRType.ft);
};
break;
case OP_J:
case OP_JAL:
db_printf("%s\t", op_name[i.JType.op]);
db_printf("0x%8lx",(loc & 0xF0000000) | (i.JType.target << 2));
break;
case OP_LWC1:
case OP_SWC1:
db_printf("%s\tf%d,", op_name[i.IType.op],
i.IType.rt);
goto loadstore;
case OP_LB:
case OP_LH:
case OP_LW:
case OP_LD:
case OP_LBU:
case OP_LHU:
case OP_LWU:
case OP_SB:
case OP_SH:
case OP_SW:
case OP_SD:
db_printf("%s\t%s,", op_name[i.IType.op],
reg_name[i.IType.rt]);
loadstore:
db_printf("%d(%s)", (short)i.IType.imm,
reg_name[i.IType.rs]);
break;
case OP_ORI:
case OP_XORI:
if (i.IType.rs == 0) {
db_printf("li\t%s,0x%x",
reg_name[i.IType.rt],
i.IType.imm);
break;
}
/* FALLTHROUGH */
case OP_ANDI:
db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
i.IType.imm);
break;
case OP_LUI:
db_printf("%s\t%s,0x%x", op_name[i.IType.op],
reg_name[i.IType.rt],
i.IType.imm);
break;
case OP_ADDI:
case OP_DADDI:
case OP_ADDIU:
case OP_DADDIU:
if (i.IType.rs == 0) {
db_printf("li\t%s,%d",
reg_name[i.IType.rt],
(short)i.IType.imm);
break;
}
/* FALLTHROUGH */
default:
db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
reg_name[i.IType.rt],
reg_name[i.IType.rs],
(short)i.IType.imm);
}
return (loc + 4);
}

View File

@ -0,0 +1,439 @@
/* $NetBSD: db_interface.c,v 1.1 1997/07/07 03:54:37 jonathan 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.Distribution@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/types.h>
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/reboot.h>
#include <mips/cpu.h>
#include <mips/cpuregs.h>
#include <mips/locore.h>
#include <mips/mips_opcode.h>
#include <mips/db_machdep.h>
#include <ddb/db_access.h>
#include <ddb/db_command.h>
#include <ddb/db_output.h>
#include <ddb/db_sym.h>
#include <ddb/db_extern.h>
#include <dev/cons.h>
/*
* forward declarations
*/
int db_active = 0;
void db_halt_cmd __P((db_expr_t addr, int have_addr, db_expr_t count,
char *modif));
void db_trapdump_cmd __P((db_expr_t addr, int have_addr, db_expr_t count,
char *modif));
void db_tlbdump_cmd __P((db_expr_t addr, int have_addr, db_expr_t count,
char *modif));
extern int kdbpeek __P((vm_offset_t addr));
extern void kdbpoke __P((vm_offset_t addr, int newval));
extern unsigned MachEmulateBranch __P((unsigned *regsPtr,
unsigned instPC, unsigned fpcCSR, int allowNonBranch));
extern void mips1_dump_tlb __P((int, int));
extern void mips3_dump_tlb __P((int, int));
/*
* kdbpoke -- write a value to a kernel virtual address.
* XXX should handle KSEG2 addresses and check for unmapped pages.
* XXX user-space addresess?
* Really belongs wherever kdbpeek() is defined.
*/
void
kdbpoke(vm_offset_t addr, int newval)
{
*(int*) addr = newval;
wbflush();
if (CPUISMIPS3) {
#ifdef MIPS3
mips3_FlushICache((vm_offset_t) addr, sizeof(int));
#endif
} else {
#ifdef MIPS1
mips1_FlushICache(MIPS_KSEG0_TO_PHYS(addr), sizeof(int));
#endif
}
}
/*
* Received keyboard interrupt sequence.
*/
void
kdb_kbd_trap(tf)
db_regs_t *tf;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
kdb_trap(-1, tf);
}
}
/*
* kdb_trap - field a TRACE or BPT trap
*/
int
kdb_trap(type, tf)
int type;
register db_regs_t *tf;
{
/* fb_unblank(); */
switch (type) {
case T_BREAK: /* breakpoint */
case -1: /* keyboard interrupt */
break;
default:
#ifdef notyet
printf("kernel: %s trap", trap_type[type & 0xff]);
if (db_recover != 0) {
db_error("Faulted in DDB; continuing...\n");
/*NOTREACHED*/
}
#endif
break;
}
/* Should switch to kdb`s own stack here. */
/* XXX copy trapframe to ddb_regs */
ddb_regs = *tf;
db_active++;
cnpollc(1);
db_trap(type, 0 /*code*/);
cnpollc(0);
db_active--;
/* write ddb_regs back to trapframe */
*tf = ddb_regs;
return (1);
}
void
Debugger()
{
asm("break ");
}
/*
* Read bytes from kernel address space for debugger.
*/
void
db_read_bytes(addr, size, data)
register vm_offset_t addr;
register size_t size;
register char *data;
{
while (size >= 4)
*((int*)data)++ = kdbpeek(addr), addr += 4, size -= 4;
if (size) {
unsigned tmp;
register char *dst = (char*)data;
tmp = kdbpeek(addr);
while (size--) {
#if BYTE_ORDER == BIG_ENDIAN
int shift = 24;
/* want highest -> lowest byte */
*dst++ = (tmp >> shift) & 0xFF;
shift -= 8;
#else /* BYTE_ORDER == LITTLE_ENDIAN */
*dst++ = tmp & 0xFF;
tmp >>= 8;
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
}
}
}
/*
* Write bytes to kernel address space for debugger.
*/
void
db_write_bytes(addr, size, data)
register vm_offset_t addr;
register size_t size;
register char *data;
{
/*XXX*/ printf("db_write_bytes(%lx, %d, %p, val %x)\n", addr, size, data,
(addr &3 ) == 0? *(u_int*)addr: -1);
while (size >= 4)
kdbpoke(addr++, *(int*)data), addr += 4, size -= 4;
if (size) {
unsigned tmp = kdbpeek(addr), tmp1 = 0;
register char *src = (char*)data;
tmp >>= (size << 3);
tmp <<= (size << 3);
while (size--) {
tmp1 <<= 8;
tmp1 |= src[size] & 0xff;
}
kdbpoke(addr, tmp|tmp1);
}
}
void
db_halt_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
/*
* Force a halt. Don't sync disks in case we panicked
* trying to do just that.
*/
cpu_reboot(RB_HALT|RB_NOSYNC, 0);
}
void
db_tlbdump_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
if (CPUISMIPS3) {
#ifdef MIPS3
mips3_dump_tlb(0, 23);
(void)cngetc();
mips3_dump_tlb(24, 47);
#endif
} else {
#ifdef MIPS1
mips1_dump_tlb(0, 22);
(void)cngetc();
mips1_dump_tlb(23, 45);
(void)cngetc();
mips1_dump_tlb(46, 63);
#endif
}
}
void
db_trapdump_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
#ifdef DEBUG
extern void trapDump __P((char*));
trapDump("CPU exception log:");
#else
db_printf("trap log only available with options DEBUG.\n");
#endif
}
struct db_command mips_db_command_table[] = {
{ "halt", db_halt_cmd, 0, 0 },
{ "trapdump", db_trapdump_cmd, 0, 0 },
{ "tlb", db_tlbdump_cmd, 0, 0 },
{ (char *)0, }
};
void
db_machine_init()
{
db_machine_commands_install(mips_db_command_table);
}
/*
* MD functions for software single-step.
* see db_ for a description.
*/
/*
* inst_branch()
* returns TRUE iff the instruction might branch.
*/
boolean_t
inst_branch(int inst)
{
InstFmt i;
int delay;
i.word = inst;
delay = 0;
switch (i.JType.op) {
case OP_BCOND:
case OP_BLEZ:
case OP_BLEZL:
case OP_BGTZ:
case OP_BGTZL:
case OP_BEQ:
case OP_BEQL:
case OP_BNE:
case OP_BNEL:
delay = 1;
break;
case OP_COP0:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
delay = 1;
}
break;
case OP_COP1:
switch (i.RType.rs) {
case OP_BCx:
case OP_BCy:
delay = 1;
break;
default:
break;
};
break;
case OP_J:
case OP_JAL:
delay = 1;
break;
}
#ifdef DEBUG_DDB
printf(" inst_branch(0x%x) returns %d\n",
inst, delay);
#endif
return delay;
}
/*
*
*/
boolean_t
inst_call(inst)
int inst;
{
register int rv = 0;
InstFmt i;
i.word = inst;
if (i.JType.op == OP_SPECIAL)
if (i.RType.func == OP_JR || i.RType.func == OP_JAL)
rv = 1;
else if (i.JType.op == OP_JAL)
rv = 1;
#ifdef DEBUG_DDB
printf(" inst_call(0x%x) returns 0x%d\n",
inst, rv);
#endif
return rv;
}
/*
* inst_unctiondional_flow_transfer()
* return TRUE if the instruction is an unconditional
* transter of flow (i.e. unconditional branch)
*/
boolean_t
inst_unconditional_flow_transfer(int inst)
{
InstFmt i;
int rv = 0;
if (i.JType.op == OP_J) rv = 1;
#ifdef DEBUG_DDB
printf(" insn_unconditional_flow_transfer(0x%x) returns %d\n",
inst, rv);
#endif
return rv;
}
/*
*
*/
db_addr_t
branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
{
vm_offset_t ra;
ra = (vm_offset_t)MachEmulateBranch(regs->f_regs, pc,
(curproc) ? curproc->p_addr->u_pcb.pcb_fpregs.r_regs[32]: 0, 0);
#ifdef DEBUG_DDB
printf(" branch_taken(0x%lx) returns 0x%lx\n", pc, ra);
#endif
return (ra);
}
/*
* Returns the address of the first instruction following the
* one at "pc", which is either in the taken path of the branch
* (bd == TRUE) or not. This is for machines (e.g. mips) with
* branch delays.
*
* XXX (jrs) The above comment makes no sense. Maybe Jason is thinking
* of mips3 squashed branches?
* In any case, the kernel support can already find the address of the
* next instruction. We could just return that and put a single breakpoint
* at that address. All the cruft above can go.
*/
db_addr_t
next_instr_address(db_addr_t pc, boolean_t bd)
{
vm_offset_t ra;
ra = (vm_offset_t)MachEmulateBranch(ddb_regs.f_regs, pc,
(curproc)? curproc->p_addr->u_pcb.pcb_fpregs.r_regs[32]: 0, 1);
#ifdef DEBUG_DDB
printf(" next_instr_addr(0x%lx, %d) returns 0x%lx\n", pc, bd, ra);
#endif
return ((db_addr_t) ra);
}

View File

@ -0,0 +1,151 @@
/*
* Mach Operating System
* Copyright (c) 1993-1987 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.Distribution@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/types.h>
#include <vm/vm_param.h> /* XXX boolean_t */
#include <machine/param.h>
#include <mips/db_machdep.h>
#include <ddb/db_interface.h>
#include <ddb/db_output.h>
#include <ddb/db_variables.h>
#include <ddb/db_sym.h>
extern int __start __P((void)); /* lowest kernel code address */
extern vm_offset_t db_maxoff;
extern vm_offset_t getreg_val __P((db_expr_t regno));
#define REG_ARG(i) (4+i)
#define SAVES_RA(x) isa_spill((x),31)
#define KERN_SAVE_REG_IDX(vp) ( \
((vp)->valuep >= (int *)(&((struct mips_saved_state *)0)->s0) && \
(vp)->valuep <= (int *)(&((struct mips_saved_state *)0)->s7))? \
vp->valuep - (int *)(&((struct mips_saved_state *)0)->s0): \
((vp)->valuep >= (int *)(&((struct mips_saved_state *)0)->sp) && \
(vp)->valuep <= (int *)(&((struct mips_saved_state *)0)->ra))? \
((vp)->valuep-(int *)(&((struct mips_saved_state *)0)->sp)) + \
((int *)(&((struct mips_kernel_state *)0)->sp) - (int *)0): \
-1)
extern db_sym_t localsym __P((db_sym_t sym, boolean_t isreg, int *lex_level));
/*
* Machine register set.
*/
struct mips_saved_state *db_cur_exc_frame = 0;
/*
* forward declarations
*/
int print_exception_frame __P((register struct mips_saved_state *fp,
unsigned epc));
/*XXX*/
extern void stacktrace_subr __P((int a0, int a1, int a2, int a3,
u_int pc, u_int sp, u_int fp, u_int ra,
void (*)(const char*, ...)));
/*
* Stack trace helper.
*/
void db_mips_stack_trace __P((int count, vm_offset_t stackp,
vm_offset_t the_pc, vm_offset_t the_ra, int flags, vm_offset_t kstackp));
#define DB_SETF_REGS FCN_NULL
#define DBREGS_REG()
struct db_variable db_regs[] = {
{ "at", (long *)&ddb_regs.f_regs[AST], DB_SETF_REGS },
{ "v0", (long *)&ddb_regs.f_regs[V0], DB_SETF_REGS },
{ "v1", (long *)&ddb_regs.f_regs[V1], DB_SETF_REGS },
{ "a0", (long *)&ddb_regs.f_regs[A0], DB_SETF_REGS },
{ "a1", (long *)&ddb_regs.f_regs[A1], DB_SETF_REGS },
{ "a2", (long *)&ddb_regs.f_regs[A2], DB_SETF_REGS },
{ "a3", (long *)&ddb_regs.f_regs[A3], DB_SETF_REGS },
{ "t0", (long *)&ddb_regs.f_regs[T0], DB_SETF_REGS },
{ "t1", (long *)&ddb_regs.f_regs[T1], DB_SETF_REGS },
{ "t2", (long *)&ddb_regs.f_regs[T2], DB_SETF_REGS },
{ "t3", (long *)&ddb_regs.f_regs[T3], DB_SETF_REGS },
{ "t4", (long *)&ddb_regs.f_regs[T4], DB_SETF_REGS },
{ "t5", (long *)&ddb_regs.f_regs[T5], DB_SETF_REGS },
{ "t6", (long *)&ddb_regs.f_regs[T6], DB_SETF_REGS },
{ "t7", (long *)&ddb_regs.f_regs[T7], DB_SETF_REGS },
{ "s0", (long *)&ddb_regs.f_regs[S0], DB_SETF_REGS },
{ "s1", (long *)&ddb_regs.f_regs[S1], DB_SETF_REGS },
{ "s2", (long *)&ddb_regs.f_regs[S2], DB_SETF_REGS },
{ "s3", (long *)&ddb_regs.f_regs[S3], DB_SETF_REGS },
{ "s4", (long *)&ddb_regs.f_regs[S4], DB_SETF_REGS },
{ "s5", (long *)&ddb_regs.f_regs[S5], DB_SETF_REGS },
{ "s6", (long *)&ddb_regs.f_regs[S6], DB_SETF_REGS },
{ "s7", (long *)&ddb_regs.f_regs[S7], DB_SETF_REGS },
{ "t8", (long *)&ddb_regs.f_regs[T8], DB_SETF_REGS },
{ "t9", (long *)&ddb_regs.f_regs[T9], DB_SETF_REGS },
{ "k0", (long *)&ddb_regs.f_regs[K0], DB_SETF_REGS },
{ "k1", (long *)&ddb_regs.f_regs[K1], DB_SETF_REGS },
{ "gp", (long *)&ddb_regs.f_regs[GP], DB_SETF_REGS },
{ "sp", (long *)&ddb_regs.f_regs[SP], DB_SETF_REGS },
{ "fp", (long *)&ddb_regs.f_regs[S8], DB_SETF_REGS }, /* frame ptr */
{ "ra", (long *)&ddb_regs.f_regs[RA], DB_SETF_REGS },
{ "sr", (long *)&ddb_regs.f_regs[SR], DB_SETF_REGS },
{ "mdlo",(long *)&ddb_regs.f_regs[MULLO], DB_SETF_REGS },
{ "mdhi",(long *)&ddb_regs.f_regs[MULHI], DB_SETF_REGS },
{ "bad", (long *)&ddb_regs.f_regs[BADVADDR], DB_SETF_REGS },
{ "cs", (long *)&ddb_regs.f_regs[CAUSE], DB_SETF_REGS },
{ "pc", (long *)&ddb_regs.f_regs[PC], DB_SETF_REGS },
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
void
db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t addr;
boolean_t have_addr;
db_expr_t count;
char *modif;
{
stacktrace_subr(ddb_regs.f_regs[A0], ddb_regs.f_regs[A1],
ddb_regs.f_regs[A2], ddb_regs.f_regs[A3],
ddb_regs.f_regs[PC],
ddb_regs.f_regs[SP],
ddb_regs.f_regs[S8], /* non-virtual fame pointer */
ddb_regs.f_regs[RA],
db_printf);
}
void
db_mips_stack_trace(count, stackp, the_pc, the_ra, flags, kstackp)
int count;
vm_offset_t stackp, the_pc, the_ra;
int flags;
vm_offset_t kstackp;
{
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore.S,v 1.38 1997/06/30 14:42:32 jonathan Exp $ */ /* $NetBSD: locore.S,v 1.39 1997/07/07 03:54:31 jonathan Exp $ */
/* /*
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
@ -1773,7 +1773,7 @@ END(mdbpanic)
#endif /* MDB */ #endif /* MDB */
#if defined(DEBUG) || defined(MDB) #if defined(DEBUG) || defined(MDB) || defined(DDB)
/* /*
* Stacktrace support hooks which use type punnign to access * Stacktrace support hooks which use type punnign to access
* the caller's registers. * the caller's registers.
@ -1784,42 +1784,62 @@ END(mdbpanic)
* stacktrace() -- print a stack backtrace to the console. * stacktrace() -- print a stack backtrace to the console.
* implicitly accesses caller's a0-a3. * implicitly accesses caller's a0-a3.
*/ */
NON_LEAF(stacktrace, 32, ra) NON_LEAF(stacktrace, STAND_FRAME_SIZE+20, ra)
subu sp,sp,32
subu sp, sp, STAND_FRAME_SIZE+20 # four arg-passing slots
move t0, ra # save caller's PC
addu t1, sp, STAND_FRAME_SIZE+20 # compute caller's SP
move t2, s8 # non-virtual frame pointer
la v0, _C_LABEL(printf) la v0, _C_LABEL(printf)
sw ra,24(sp)
jal stacktrace_subr sw ra, 36(sp) # save return address
sw v0,16(sp)
lw ra,24(sp) /* a0-a3 are still caller's a0-a3, pass in-place as given. */
addu sp,sp,32 sw t0, 16(sp) # push caller's PC
sw t1, 20(sp) # push caller's SP
sw t2, 24(sp) # push caller's FP, in case
sw zero, 28(sp) # caller's RA on stack
jal _C_LABEL(stacktrace_subr)
sw v0, 32(sp) # push printf
lw ra, 36(sp)
addu sp, sp, STAND_FRAME_SIZE+20
j ra j ra
nop
END(stacktrace) END(stacktrace)
/* /*
* logstacktrace() -- log a stack traceback to msgbuf. * logstacktrace() -- log a stack traceback to msgbuf.
* implicitly accesses caller's a0-a3. * implicitly accesses caller's a0-a3.
*/ */
NON_LEAF(logstacktrace, 32, ra) NON_LEAF(logstacktrace, STAND_FRAME_SIZE+20, ra)
subu sp,sp,32
la v0, _C_LABEL(addlog)
sw ra,24(sp)
jal stacktrace_subr subu sp, sp, STAND_FRAME_SIZE+20 # four arg-passing slots
sw v0,16(sp)
lw ra,24(sp) move t0, ra # save caller's PC
addu sp,sp,32 addu t1, sp, STAND_FRAME_SIZE+20 # compute caller's SP
move t2, s8 # non-virtual frame pointer
la v0, _C_LABEL(printf)
sw ra, 36(sp) # save return address
/* a0-a3 are still caller's a0-a3, pass in-place as given. */
sw t0, 16(sp) # push caller's PC
sw t1, 20(sp) # push caller's SP
sw t2, 24(sp) # push caller's FP, in case
sw zero, 28(sp) # RA on stack
jal _C_LABEL(stacktrace_subr)
sw v0, 32(sp) # push printf
lw ra, 36(sp)
addu sp, sp, STAND_FRAME_SIZE+20
j ra j ra
END(stacktrace) nop
END(logstacktrace)
LEAF(cpu_getregs)
sw sp, 0(a0)
sw ra, 4(a0)
j ra
sw s8, 8(a0)
END(cpu_getregs)
#endif /* DEBUG */ #endif /* DEBUG */
@ -1830,6 +1850,10 @@ END(cpu_getregs)
* XXX will need reworking for SMP. * XXX will need reworking for SMP.
*/ */
.data .data
.globl _C_LABEL(esym)
_C_LABEL(esym):
.word 0
.globl _C_LABEL(cpu_id) .globl _C_LABEL(cpu_id)
.globl _C_LABEL(fpu_id) .globl _C_LABEL(fpu_id)
.globl _C_LABEL(cpu_arch) .globl _C_LABEL(cpu_arch)

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore_r2000.S,v 1.37 1997/06/25 05:06:01 mhitch Exp $ */ /* $NetBSD: locore_r2000.S,v 1.38 1997/07/07 03:54:33 jonathan Exp $ */
/* /*
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
@ -222,7 +222,10 @@ NNON_LEAF(mips1_KernGenException, TRAP_FRAME_SIZE, ra)
mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC mfc0 a3, MIPS_COP_0_EXC_PC # 4th arg is PC
sw v1, TRAP_FRAME_OFFSET+(MULHI * 4)(sp) sw v1, TRAP_FRAME_OFFSET+(MULHI * 4)(sp)
sw a3, TRAP_FRAME_OFFSET+(PC * 4)(sp) sw a3, TRAP_FRAME_OFFSET+(PC * 4)(sp)
#ifdef DDB
addu v0, sp, TRAP_FRAME_SIZE # SP at trap for debugging
sw v0, TRAP_FRAME_OFFSET+(SP * 4)(sp)
#endif DDB
jal _C_LABEL(trap) jal _C_LABEL(trap)
sw a3, TRAP_RA_OFFSET(sp) # for debugging sw a3, TRAP_RA_OFFSET(sp) # for debugging
@ -834,6 +837,8 @@ NLEAF(mips1_TLBMissException)
.asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
.text .text
/* Call mips1_dump_tlb(0, 2, printf) to show the bad kstack TLB */
la a2, _C_LABEL(printf)
li a0,0 li a0,0
jal _C_LABEL(mips1_dump_tlb) jal _C_LABEL(mips1_dump_tlb)
li a1,3 # BDslot li a1,3 # BDslot

View File

@ -1,4 +1,4 @@
/* $NetBSD: locore_r4000.S,v 1.38 1997/06/25 05:06:05 mhitch Exp $ */ /* $NetBSD: locore_r4000.S,v 1.39 1997/07/07 03:54:35 jonathan Exp $ */
/* /*
* Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author) * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
@ -306,7 +306,12 @@ NNON_LEAF(mips3_KernGenException, TRAP_FRAME_SIZE, ra)
mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc. mfc0 a3, MIPS_COP_0_EXC_PC # Fourth arg is the pc.
sw a0, TRAP_FRAME_OFFSET + (SR * 4)(sp) sw a0, TRAP_FRAME_OFFSET + (SR * 4)(sp)
#ifdef DDB
addu v0, sp, TRAP_FRAME_SIZE # SP at trap for debugging
sw v0, TRAP_FRAME_OFFSET+(SP * 4)(sp)
#else
nop nop
#endif DDB
sw a3, TRAP_FRAME_OFFSET + (PC * 4)(sp) sw a3, TRAP_FRAME_OFFSET + (PC * 4)(sp)
mtc0 zero,MIPS_COP_0_STATUS_REG # Set kernel no error level mtc0 zero,MIPS_COP_0_STATUS_REG # Set kernel no error level
/* /*
@ -1093,6 +1098,8 @@ sys_stk_chk:
.asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n" .asciiz "ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"
.text .text
/* Call mips3_dump_tlb(0, 2, printf) to show the bad kstack TLB */
la a2, _C_LABEL(printf)
li a0, 0 li a0, 0
jal mips3_dump_tlb jal mips3_dump_tlb
li a1, 2 # BDslot li a1, 2 # BDslot

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.68 1997/06/30 14:42:35 jonathan Exp $ */ /* $NetBSD: trap.c,v 1.69 1997/07/07 03:54:38 jonathan Exp $ */
/* /*
* Copyright (c) 1988 University of Utah. * Copyright (c) 1988 University of Utah.
@ -76,6 +76,10 @@
#include <sys/syslog.h> #include <sys/syslog.h>
#include <miscfs/procfs/procfs.h> #include <miscfs/procfs/procfs.h>
#ifdef DDB
#include <mips/db_machdep.h>
#endif
/* all this to get prototypes for ipintr() and arpintr() */ /* all this to get prototypes for ipintr() and arpintr() */
#include <sys/socket.h> #include <sys/socket.h>
#include <net/if.h> #include <net/if.h>
@ -332,8 +336,8 @@ void trapDump __P((char * msg));
#endif /* DEBUG */ #endif /* DEBUG */
void mips1_dump_tlb __P((int, int)); void mips1_dump_tlb __P((int, int, void (*printfn)(const char*, ...)));
void mips3_dump_tlb __P((int, int)); void mips3_dump_tlb __P((int, int, void (*printfn)(const char*, ...)));
void mips_dump_tlb __P((int, int)); void mips_dump_tlb __P((int, int));
/* /*
@ -366,9 +370,8 @@ extern void ast __P((unsigned pc));
/* /*
* stack trace code, also useful to DDB one day * stack trace code, also useful to DDB one day
*/ */
#if defined(DEBUG) || defined(MDB) #if defined(DEBUG) || defined(MDB) || defined(DDB)
int kdbpeek __P((vm_offset_t addr)); int kdbpeek __P((vm_offset_t addr));
extern void cpu_getregs __P((int *));
extern void stacktrace __P((void)); /*XXX*/ extern void stacktrace __P((void)); /*XXX*/
extern void logstacktrace __P((void)); /*XXX*/ extern void logstacktrace __P((void)); /*XXX*/
@ -666,16 +669,10 @@ trap(status, cause, vaddr, opc, frame)
printf("pid=%d cmd=%s\n", p->p_pid, p->p_comm); printf("pid=%d cmd=%s\n", p->p_pid, p->p_comm);
else else
printf("curproc == NULL\n"); printf("curproc == NULL\n");
#ifdef MDB
frame.f_regs[CAUSE] = cause;
frame.f_regs[BADVADDR] = vaddr;
mdb(type, (struct frame *)&frame.f_regs);
#else
#ifdef DEBUG #ifdef DEBUG
stacktrace(); stacktrace();
trapDump("trap"); trapDump("trap");
#endif /* DEBUG */ #endif /* DEBUG */
#endif /* MDB */
panic("trap"); panic("trap");
/*NOTREACHED*/ /*NOTREACHED*/
case T_TLB_MOD: case T_TLB_MOD:
@ -687,9 +684,6 @@ trap(status, cause, vaddr, opc, frame)
pte = kvtopte(vaddr); pte = kvtopte(vaddr);
entry = pte->pt_entry; entry = pte->pt_entry;
if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) { if (!mips_pg_v(entry) || (entry & mips_pg_m_bit())) {
#ifdef MDB
mdb(type, (struct frame *)&frame.f_regs);
#endif
panic("ktlbmod: invalid pte"); panic("ktlbmod: invalid pte");
} }
/*XXX MIPS3? */ if (entry & mips_pg_ro_bit()) { /*XXX MIPS3? */ if (entry & mips_pg_ro_bit()) {
@ -843,6 +837,14 @@ trap(status, cause, vaddr, opc, frame)
sig = SIGSEGV; sig = SIGSEGV;
ucode = vaddr; ucode = vaddr;
break; /* SIGNAL */ break; /* SIGNAL */
case T_BREAK:
#ifdef DDB
kdb_trap(type, (struct frame *)&frame.f_regs);
return; /* KERN */
#else
goto dopanic;
#endif
case T_BREAK+T_USER: case T_BREAK+T_USER:
{ {
unsigned va, instr; unsigned va, instr;
@ -853,6 +855,9 @@ trap(status, cause, vaddr, opc, frame)
/* read break instruction */ /* read break instruction */
instr = fuiword((caddr_t)va); instr = fuiword((caddr_t)va);
#ifdef DEBUG
/*XXX*/ printf("break insn 0x%x\n", instr);
#endif
if (p->p_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) { if (p->p_md.md_ss_addr != va || instr != MIPS_BREAK_SSTEP) {
sig = SIGTRAP; sig = SIGTRAP;
@ -889,9 +894,10 @@ trap(status, cause, vaddr, opc, frame)
uio.uio_rw = UIO_WRITE; uio.uio_rw = UIO_WRITE;
uio.uio_procp = curproc; uio.uio_procp = curproc;
rv = procfs_domem(p, p, NULL, &uio); rv = procfs_domem(p, p, NULL, &uio);
MachFlushCache();
} }
#endif #endif
MachFlushCache();
if (rv < 0) if (rv < 0)
printf("Warning: can't restore instruction at 0x%x: 0x%x\n", printf("Warning: can't restore instruction at 0x%x: 0x%x\n",
p->p_md.md_ss_addr, p->p_md.md_ss_instr); p->p_md.md_ss_addr, p->p_md.md_ss_instr);
@ -1054,8 +1060,10 @@ trapDump(msg)
trp->vadr, trp->pc, trp->cause, trp->status); trp->vadr, trp->pc, trp->cause, trp->status);
printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code); printf(" RA %x SP %x code %d\n", trp->ra, trp->sp, trp->code);
} }
#ifndef DDB
bzero(trapdebug, sizeof(trapdebug)); bzero(trapdebug, sizeof(trapdebug));
trp = trapdebug; trp = trapdebug;
#endif
splx(s); splx(s);
} }
#endif #endif
@ -1326,13 +1334,15 @@ mips_singlestep(p)
return 0; return 0;
} }
#if defined(DEBUG) || defined(MDB) #if defined(DEBUG) || defined(MDB) || defined(DDB)
int int
kdbpeek(addr) kdbpeek(addr)
vm_offset_t addr; vm_offset_t addr;
{ {
if (addr & 3) { if (addr & 3) {
printf("kdbpeek: unaligned address %lx\n", addr); printf("kdbpeek: unaligned address %lx\n", addr);
/* We might have been called from DDB, so don\'t go there. */
stacktrace();
return (-1); return (-1);
} }
return (*(int *)addr); return (*(int *)addr);
@ -1342,7 +1352,9 @@ kdbpeek(addr)
/* forward */ /* forward */
char *fn_name(unsigned addr); char *fn_name(unsigned addr);
void stacktrace_subr __P((int, int, int, int, void (*)(const char*, ...))); void stacktrace_subr __P((int a0, int a1, int a2, int a3,
u_int pc, u_int sp, u_int fp, u_int ra,
void (*)(const char*, ...)));
/* /*
* Do a stack backtrace. * Do a stack backtrace.
@ -1350,30 +1362,20 @@ void stacktrace_subr __P((int, int, int, int, void (*)(const char*, ...)));
* the console, or both. * the console, or both.
*/ */
void void
stacktrace_subr(a0, a1, a2, a3, printfn) stacktrace_subr(a0, a1, a2, a3, pc, sp, fp, ra, printfn)
int a0, a1, a2, a3; int a0, a1, a2, a3;
u_int pc, sp, fp, ra;
void (*printfn) __P((const char*, ...)); void (*printfn) __P((const char*, ...));
{ {
unsigned pc, sp, fp, ra, va, subr; unsigned va, subr;
unsigned instr, mask; unsigned instr, mask;
InstFmt i; InstFmt i;
int more, stksize; int more, stksize;
int regs[3];
extern char start[], edata[]; extern char start[], edata[];
unsigned int frames = 0; unsigned int frames = 0;
cpu_getregs(regs);
/* get initial values from the exception frame */
sp = regs[0];
pc = regs[1];
ra = 0;
fp = regs[2];
/* Jump here when done with a frame, to start a new one */ /* Jump here when done with a frame, to start a new one */
loop: loop:
ra = 0;
/* Jump here after a nonstandard (interrupt handler) frame */ /* Jump here after a nonstandard (interrupt handler) frame */
specialframe: specialframe:
stksize = 0; stksize = 0;
@ -1706,9 +1708,10 @@ fn_name(unsigned addr)
* called by mips3 locore after in-kernel TLB miss. * called by mips3 locore after in-kernel TLB miss.
*/ */
void void
mips3_dump_tlb(first, last) mips3_dump_tlb(first, last, printfn)
int first; int first;
int last; int last;
void (*printfn) __P((const char*, ...));
{ {
int tlbno; int tlbno;
struct tlb tlb; struct tlb tlb;
@ -1719,20 +1722,20 @@ mips3_dump_tlb(first, last)
while(tlbno <= last) { while(tlbno <= last) {
mips3_TLBRead(tlbno, &tlb); mips3_TLBRead(tlbno, &tlb);
if (mips_pg_v(tlb.tlb_lo0) || mips_pg_v(tlb.tlb_lo1)) { if (mips_pg_v(tlb.tlb_lo0) || mips_pg_v(tlb.tlb_lo1)) {
printf("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi); (*printfn)("TLB %2d vad 0x%08x ", tlbno, tlb.tlb_hi);
} }
else { else {
printf("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi); (*printfn)("TLB*%2d vad 0x%08x ", tlbno, tlb.tlb_hi);
} }
printf("0=0x%08lx ", pfn_to_vad(tlb.tlb_lo0)); (*printfn)("0=0x%08lx ", pfn_to_vad(tlb.tlb_lo0));
printf("%c", tlb.tlb_lo0 & mips_pg_m_bit() ? 'M' : ' '); (*printfn)("%c", tlb.tlb_lo0 & mips_pg_m_bit() ? 'M' : ' ');
printf("%c", tlb.tlb_lo0 & mips_pg_global_bit() ? 'G' : ' '); (*printfn)("%c", tlb.tlb_lo0 & mips_pg_global_bit() ? 'G' : ' ');
printf(" atr %x ", (tlb.tlb_lo0 >> 3) & 7); (*printfn)(" atr %x ", (tlb.tlb_lo0 >> 3) & 7);
printf("1=0x%08lx ", pfn_to_vad(tlb.tlb_lo1)); (*printfn)("1=0x%08lx ", pfn_to_vad(tlb.tlb_lo1));
printf("%c", tlb.tlb_lo1 & mips_pg_m_bit() ? 'M' : ' '); (*printfn)("%c", tlb.tlb_lo1 & mips_pg_m_bit() ? 'M' : ' ');
printf("%c", tlb.tlb_lo1 & mips_pg_global_bit() ? 'G' : ' '); (*printfn)("%c", tlb.tlb_lo1 & mips_pg_global_bit() ? 'G' : ' ');
printf(" atr %x ", (tlb.tlb_lo1 >> 3) & 7); (*printfn)(" atr %x ", (tlb.tlb_lo1 >> 3) & 7);
printf(" sz=%x\n", tlb.tlb_mask); (*printfn)(" sz=%x\n", tlb.tlb_mask);
tlbno++; tlbno++;
} }
@ -1744,9 +1747,10 @@ mips3_dump_tlb(first, last)
* called by mips3 locore after in-kernel TLB miss. * called by mips3 locore after in-kernel TLB miss.
*/ */
void void
mips1_dump_tlb(first, last) mips1_dump_tlb(first, last, printfn)
int first; int first;
int last; int last;
void (*printfn) __P((const char*, ...));
{ {
int tlbno; int tlbno;
extern u_int tlbhi, tlblo; extern u_int tlbhi, tlblo;
@ -1757,21 +1761,24 @@ mips1_dump_tlb(first, last)
while(tlbno <= last) { while(tlbno <= last) {
mips1_TLBRead(tlbno); mips1_TLBRead(tlbno);
if (mips_pg_v(tlblo)) { if (mips_pg_v(tlblo)) {
printf("TLB %2d vad 0x%08x ", tlbno, tlbhi); (*printfn)("TLB %2d vad 0x%08x ", tlbno, tlbhi);
} }
else { else {
printf("TLB*%2d vad 0x%08x ", tlbno, tlbhi); (*printfn)("TLB*%2d vad 0x%08x ", tlbno, tlbhi);
} }
printf("0x%08x ", tlblo & MIPS1_PG_FRAME); (*printfn)("0x%08x ", tlblo & MIPS1_PG_FRAME);
printf("%c", tlblo & mips_pg_m_bit() ? 'M' : ' '); (*printfn)("%c", tlblo & mips_pg_m_bit() ? 'M' : ' ');
printf("%c", tlblo & mips_pg_global_bit() ? 'G' : ' '); (*printfn)("%c", tlblo & mips_pg_global_bit() ? 'G' : ' ');
printf("%c\n", tlblo & MIPS1_PG_N ? 'N' : ' '); (*printfn)("%c\n", tlblo & MIPS1_PG_N ? 'N' : ' ');
tlbno++; tlbno++;
} }
} }
/*
* Dump TLB after panic.
*/
void void
mips_dump_tlb(first, last) mips_dump_tlb(first, last)
int first; int first;
@ -1779,11 +1786,11 @@ mips_dump_tlb(first, last)
{ {
if (CPUISMIPS3) { if (CPUISMIPS3) {
#ifdef MIPS3 #ifdef MIPS3
mips3_dump_tlb(first,last); mips3_dump_tlb(first,last, printf);
#endif #endif
} else { } else {
#ifdef MIPS1 #ifdef MIPS1
mips1_dump_tlb(first,last); mips1_dump_tlb(first,last, printf);
#endif #endif
} }
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: dc.c,v 1.32 1997/06/16 02:53:38 jonathan Exp $ */ /* $NetBSD: dc.c,v 1.33 1997/07/07 03:54:42 jonathan Exp $ */
/*- /*-
* Copyright (c) 1992, 1993 * Copyright (c) 1992, 1993
@ -727,13 +727,14 @@ dcrint(sc)
} }
/* the keyboard requires special translation */ /* the keyboard requires special translation */
if (raster_console() && tp == dc_tty[DCKBD_PORT]) { if (raster_console() && tp == dc_tty[DCKBD_PORT]) {
#ifdef MDB
if (cc == LK_DO) { if (cc == LK_DO) {
#ifdef DDB
spl0(); spl0();
mdbpanic(); Debugger();
return; return;
}
#endif #endif
}
#ifdef DEBUG #ifdef DEBUG
debugChar = cc; debugChar = cc;
#endif #endif

View File

@ -0,0 +1,3 @@
/* $NetBSD: db_machdep.h,v 1.1 1997/07/07 03:54:24 jonathan Exp $ */
#include <mips/db_machdep.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.20 1997/06/15 18:02:20 mhitch Exp $ */ /* $NetBSD: param.h,v 1.21 1997/07/07 03:54:25 jonathan Exp $ */
/* /*
* Copyright (c) 1988 University of Utah. * Copyright (c) 1988 University of Utah.
@ -68,15 +68,13 @@
#define CLSIZE 1 #define CLSIZE 1
#define CLSIZELOG2 0 #define CLSIZELOG2 0
/* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE */ /*
* NOTE: SSIZE, SINCR and UPAGES must be multiples of CLSIZE.
* UPAGES, UADDR, USPACE defined in mips_param.h.
*/
#define SSIZE 1 /* initial stack size/NBPG */ #define SSIZE 1 /* initial stack size/NBPG */
#define SINCR 1 /* increment of stack/NBPG */ #define SINCR 1 /* increment of stack/NBPG */
#define UPAGES 2 /* pages of u-area */
#define UADDR 0xffffc000 /* address of u */
#define USPACE (UPAGES*NBPG) /* size of u-area in bytes */
#define UVPN (UADDR>>PGSHIFT)/* virtual page number of u */
#define KERNELSTACK (UADDR+UPAGES*NBPG) /* top of kernel stack */
/* /*
* Constants related to network buffer management. * Constants related to network buffer management.

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.90 1997/07/01 09:32:23 jonathan Exp $ */ /* $NetBSD: machdep.c,v 1.91 1997/07/07 03:54:27 jonathan Exp $ */
/* /*
* Copyright (c) 1988 University of Utah. * Copyright (c) 1988 University of Utah.
@ -116,6 +116,10 @@
#include "asc.h" #include "asc.h"
extern struct consdev *cn_tab; /* Console I/O table... */
extern struct consdev cd;
#if defined(DS5000_25) || defined(DS5000_100) || defined(DS5000_240) #if defined(DS5000_25) || defined(DS5000_100) || defined(DS5000_240)
/* Will scan from max to min, inclusive */ /* Will scan from max to min, inclusive */
static int tc_max_slot = KN02_TC_MAX; static int tc_max_slot = KN02_TC_MAX;
@ -311,6 +315,9 @@ mach_init(argc, argv, code, cv)
callv = &callvec; callv = &callvec;
} }
/* Use PROM console output until we initialize a console driver. */
cn_tab = &cd;
/* check for direct boot from DS5000 PROM */ /* check for direct boot from DS5000 PROM */
if (argc > 0 && strcmp(argv[0], "boot") == 0) { if (argc > 0 && strcmp(argv[0], "boot") == 0) {
argc--; argc--;

View File

@ -1,4 +1,4 @@
/* $NetBSD: scc.c,v 1.25 1997/06/22 07:42:44 jonathan Exp $ */ /* $NetBSD: scc.c,v 1.26 1997/07/07 03:54:40 jonathan Exp $ */
/* /*
* Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University
@ -1210,13 +1210,14 @@ sccintr(xxxsc)
*/ */
if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) && if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) &&
raster_console()) { raster_console()) {
#ifdef KADB #ifdef DDB
if (cc == LK_DO) { if (cc == LK_DO) {
spl0(); spl0();
kdbpanic(); Debugger();
return -1; return -1;
} }
#endif #endif
#ifdef DEBUG #ifdef DEBUG
debugChar = cc; debugChar = cc;
#endif #endif
@ -1447,27 +1448,44 @@ scc_modem_intr(dev)
if (chan == SCC_CHANNEL_A) if (chan == SCC_CHANNEL_A)
return; return;
s = spltty(); s = spltty();
SCC_READ_REG_ZERO(regs, chan, value);
if (sc->scc_softCAR & (1 << chan)) if (sc->scc_softCAR & (1 << chan))
car = 1; car = 1;
else { else {
SCC_READ_REG_ZERO(regs, chan, value);
car = value & ZSRR0_DCD; car = value & ZSRR0_DCD;
} }
/* Break on serial console drops into the dbeugger */
if ((value & ZSRR0_BREAK) && CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) {
#ifdef DDB
splx(s); /* spl0()? */
Debugger();
return;
#else
/* XXX maybe fall back to PROM? */
#endif
}
/* /*
* The pmax driver follows carrier-detect. The Alpha does not. * The pmax driver follows carrier-detect. The Alpha does not.
* XXX Why doesn't the Alpha driver follow carrier-detect? * XXX Why doesn't the Alpha driver follow carrier-detect?
* (in the Alpha driver, this is an "#ifdef notdef"). * (in the Alpha driver, this is an "#ifdef notdef").
* Is it related to console handling? * Is it related to console handling?
*
* Ignore hups on a console tty.
*/ */
#ifndef alpha #ifndef alpha
if (car) { if (!CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) {
/* carrier present */ if (car) {
if (!(tp->t_state & TS_CARR_ON)) /* carrier present */
(void)(*linesw[tp->t_line].l_modem)(tp, 1); if (!(tp->t_state & TS_CARR_ON))
} else if (tp->t_state & TS_CARR_ON) (void)(*linesw[tp->t_line].l_modem)(tp, 1);
(void)(*linesw[tp->t_line].l_modem)(tp, 0); } else if (tp->t_state & TS_CARR_ON)
#endif /* !alpha */ (void)(*linesw[tp->t_line].l_modem)(tp, 0);
}
#endif
splx(s); splx(s);
} }