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:
parent
d65e85e261
commit
d1ec048977
|
@ -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_ */
|
|
@ -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
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
/* $NetBSD: db_machdep.h,v 1.1 1997/07/07 03:54:24 jonathan Exp $ */
|
||||||
|
|
||||||
|
#include <mips/db_machdep.h>
|
|
@ -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.
|
||||||
|
|
|
@ -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--;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue