/* * Mach Operating System * Copyright (c) 1992,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 * 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 the * rights to redistribute these changes. * * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU) */ #include <sys/cdefs.h> __FBSDID("$FreeBSD: src/sys/ia64/ia64/db_interface.c,v 1.25 2004/07/10 23:47:19 marcel Exp $"); /* * Interface to DDB. */ #include <sys/param.h> #include <sys/systm.h> #include <sys/cons.h> #include <sys/kdb.h> #include <sys/ktr.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/reboot.h> #include <sys/smp.h> #include <vm/vm.h> #include <machine/db_machdep.h> #include <machine/frame.h> #include <machine/mutex.h> #include <machine/setjmp.h> #include <ddb/ddb.h> #include <ddb/db_access.h> #include <ddb/db_sym.h> #include <ddb/db_variables.h> #include <ia64/disasm/disasm.h> #define TMPL_BITS 5 #define TMPL_MASK ((1 << TMPL_BITS) - 1) #define SLOT_BITS 41 #define SLOT_COUNT 3 #define SLOT_MASK ((1ULL << SLOT_BITS) - 1ULL) #define SLOT_SHIFT(i) (TMPL_BITS+((i)<<3)+(i)) static db_varfcn_t db_frame; static db_varfcn_t db_getrse; static db_varfcn_t db_getip; #define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) struct db_variable db_regs[] = { {"ip", NULL, db_getip}, {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame}, {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame}, {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame}, {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame}, {"rp", DB_OFFSET(tf_special.rp), db_frame}, {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame}, {"psr", DB_OFFSET(tf_special.psr), db_frame}, {"cr.isr", DB_OFFSET(tf_special.isr), db_frame}, {"pr", DB_OFFSET(tf_special.pr), db_frame}, {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame}, {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame}, {"ar.unat", DB_OFFSET(tf_special.unat), db_frame}, {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame}, {"gp", DB_OFFSET(tf_special.gp), db_frame}, {"sp", DB_OFFSET(tf_special.sp), db_frame}, {"tp", DB_OFFSET(tf_special.tp), db_frame}, {"b6", DB_OFFSET(tf_scratch.br6), db_frame}, {"b7", DB_OFFSET(tf_scratch.br7), db_frame}, {"r2", DB_OFFSET(tf_scratch.gr2), db_frame}, {"r3", DB_OFFSET(tf_scratch.gr3), db_frame}, {"r8", DB_OFFSET(tf_scratch.gr8), db_frame}, {"r9", DB_OFFSET(tf_scratch.gr9), db_frame}, {"r10", DB_OFFSET(tf_scratch.gr10), db_frame}, {"r11", DB_OFFSET(tf_scratch.gr11), db_frame}, {"r14", DB_OFFSET(tf_scratch.gr14), db_frame}, {"r15", DB_OFFSET(tf_scratch.gr15), db_frame}, {"r16", DB_OFFSET(tf_scratch.gr16), db_frame}, {"r17", DB_OFFSET(tf_scratch.gr17), db_frame}, {"r18", DB_OFFSET(tf_scratch.gr18), db_frame}, {"r19", DB_OFFSET(tf_scratch.gr19), db_frame}, {"r20", DB_OFFSET(tf_scratch.gr20), db_frame}, {"r21", DB_OFFSET(tf_scratch.gr21), db_frame}, {"r22", DB_OFFSET(tf_scratch.gr22), db_frame}, {"r23", DB_OFFSET(tf_scratch.gr23), db_frame}, {"r24", DB_OFFSET(tf_scratch.gr24), db_frame}, {"r25", DB_OFFSET(tf_scratch.gr25), db_frame}, {"r26", DB_OFFSET(tf_scratch.gr26), db_frame}, {"r27", DB_OFFSET(tf_scratch.gr27), db_frame}, {"r28", DB_OFFSET(tf_scratch.gr28), db_frame}, {"r29", DB_OFFSET(tf_scratch.gr29), db_frame}, {"r30", DB_OFFSET(tf_scratch.gr30), db_frame}, {"r31", DB_OFFSET(tf_scratch.gr31), db_frame}, {"r32", (db_expr_t*)0, db_getrse}, {"r33", (db_expr_t*)1, db_getrse}, {"r34", (db_expr_t*)2, db_getrse}, {"r35", (db_expr_t*)3, db_getrse}, {"r36", (db_expr_t*)4, db_getrse}, {"r37", (db_expr_t*)5, db_getrse}, {"r38", (db_expr_t*)6, db_getrse}, {"r39", (db_expr_t*)7, db_getrse}, {"r40", (db_expr_t*)8, db_getrse}, {"r41", (db_expr_t*)9, db_getrse}, {"r42", (db_expr_t*)10, db_getrse}, {"r43", (db_expr_t*)11, db_getrse}, {"r44", (db_expr_t*)12, db_getrse}, {"r45", (db_expr_t*)13, db_getrse}, {"r46", (db_expr_t*)14, db_getrse}, {"r47", (db_expr_t*)15, db_getrse}, {"r48", (db_expr_t*)16, db_getrse}, {"r49", (db_expr_t*)17, db_getrse}, {"r50", (db_expr_t*)18, db_getrse}, {"r51", (db_expr_t*)19, db_getrse}, {"r52", (db_expr_t*)20, db_getrse}, {"r53", (db_expr_t*)21, db_getrse}, {"r54", (db_expr_t*)22, db_getrse}, {"r55", (db_expr_t*)23, db_getrse}, {"r56", (db_expr_t*)24, db_getrse}, {"r57", (db_expr_t*)25, db_getrse}, {"r58", (db_expr_t*)26, db_getrse}, {"r59", (db_expr_t*)27, db_getrse}, {"r60", (db_expr_t*)28, db_getrse}, {"r61", (db_expr_t*)29, db_getrse}, {"r62", (db_expr_t*)30, db_getrse}, {"r63", (db_expr_t*)31, db_getrse}, {"r64", (db_expr_t*)32, db_getrse}, {"r65", (db_expr_t*)33, db_getrse}, {"r66", (db_expr_t*)34, db_getrse}, {"r67", (db_expr_t*)35, db_getrse}, {"r68", (db_expr_t*)36, db_getrse}, {"r69", (db_expr_t*)37, db_getrse}, {"r70", (db_expr_t*)38, db_getrse}, {"r71", (db_expr_t*)39, db_getrse}, {"r72", (db_expr_t*)40, db_getrse}, {"r73", (db_expr_t*)41, db_getrse}, {"r74", (db_expr_t*)42, db_getrse}, {"r75", (db_expr_t*)43, db_getrse}, {"r76", (db_expr_t*)44, db_getrse}, {"r77", (db_expr_t*)45, db_getrse}, {"r78", (db_expr_t*)46, db_getrse}, {"r79", (db_expr_t*)47, db_getrse}, {"r80", (db_expr_t*)48, db_getrse}, {"r81", (db_expr_t*)49, db_getrse}, {"r82", (db_expr_t*)50, db_getrse}, {"r83", (db_expr_t*)51, db_getrse}, {"r84", (db_expr_t*)52, db_getrse}, {"r85", (db_expr_t*)53, db_getrse}, {"r86", (db_expr_t*)54, db_getrse}, {"r87", (db_expr_t*)55, db_getrse}, {"r88", (db_expr_t*)56, db_getrse}, {"r89", (db_expr_t*)57, db_getrse}, {"r90", (db_expr_t*)58, db_getrse}, {"r91", (db_expr_t*)59, db_getrse}, {"r92", (db_expr_t*)60, db_getrse}, {"r93", (db_expr_t*)61, db_getrse}, {"r94", (db_expr_t*)62, db_getrse}, {"r95", (db_expr_t*)63, db_getrse}, {"r96", (db_expr_t*)64, db_getrse}, {"r97", (db_expr_t*)65, db_getrse}, {"r98", (db_expr_t*)66, db_getrse}, {"r99", (db_expr_t*)67, db_getrse}, {"r100", (db_expr_t*)68, db_getrse}, {"r101", (db_expr_t*)69, db_getrse}, {"r102", (db_expr_t*)70, db_getrse}, {"r103", (db_expr_t*)71, db_getrse}, {"r104", (db_expr_t*)72, db_getrse}, {"r105", (db_expr_t*)73, db_getrse}, {"r106", (db_expr_t*)74, db_getrse}, {"r107", (db_expr_t*)75, db_getrse}, {"r108", (db_expr_t*)76, db_getrse}, {"r109", (db_expr_t*)77, db_getrse}, {"r110", (db_expr_t*)78, db_getrse}, {"r111", (db_expr_t*)79, db_getrse}, {"r112", (db_expr_t*)80, db_getrse}, {"r113", (db_expr_t*)81, db_getrse}, {"r114", (db_expr_t*)82, db_getrse}, {"r115", (db_expr_t*)83, db_getrse}, {"r116", (db_expr_t*)84, db_getrse}, {"r117", (db_expr_t*)85, db_getrse}, {"r118", (db_expr_t*)86, db_getrse}, {"r119", (db_expr_t*)87, db_getrse}, {"r120", (db_expr_t*)88, db_getrse}, {"r121", (db_expr_t*)89, db_getrse}, {"r122", (db_expr_t*)90, db_getrse}, {"r123", (db_expr_t*)91, db_getrse}, {"r124", (db_expr_t*)92, db_getrse}, {"r125", (db_expr_t*)93, db_getrse}, {"r126", (db_expr_t*)94, db_getrse}, {"r127", (db_expr_t*)95, db_getrse}, }; struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); static int db_frame(struct db_variable *vp, db_expr_t *valuep, int op) { uint64_t *reg; if (kdb_frame == NULL) return (0); reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); if (op == DB_VAR_GET) *valuep = *reg; else *reg = *valuep; return (1); } static int db_getrse(struct db_variable *vp, db_expr_t *valuep, int op) { u_int64_t *reg; uint64_t bsp; int nats, regno, sof; if (kdb_frame == NULL) return (0); regno = (int)(intptr_t)valuep; bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty; sof = (int)(kdb_frame->tf_special.cfm & 0x7f); if (regno >= sof) return (0); nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; reg = (void*)(bsp - ((sof - regno + nats) << 3)); if (op == DB_VAR_GET) *valuep = *reg; else *reg = *valuep; return (1); } static int db_getip(struct db_variable *vp, db_expr_t *valuep, int op) { u_long iip, slot; if (kdb_frame == NULL) return (0); if (op == DB_VAR_GET) { iip = kdb_frame->tf_special.iip; slot = (kdb_frame->tf_special.psr >> 41) & 3; *valuep = iip + slot; } else { iip = *valuep & ~0xf; slot = *valuep & 0xf; if (slot > 2) return (0); kdb_frame->tf_special.iip = iip; kdb_frame->tf_special.psr &= ~IA64_PSR_RI; kdb_frame->tf_special.psr |= slot << 41; } return (1); } /* * Read bytes from kernel address space for debugger. */ int db_read_bytes(vm_offset_t addr, size_t size, char *data) { jmp_buf jb; void *prev_jb; char *src; int ret; prev_jb = kdb_jmpbuf(jb); ret = setjmp(jb); if (ret == 0) { src = (char *)addr; while (size-- > 0) *data++ = *src++; } (void)kdb_jmpbuf(prev_jb); return (ret); } /* * Write bytes to kernel address space for debugger. */ int db_write_bytes(vm_offset_t addr, size_t size, char *data) { jmp_buf jb; void *prev_jb; char *dst; int ret; prev_jb = kdb_jmpbuf(jb); ret = setjmp(jb); if (ret == 0) { dst = (char *)addr; while (size-- > 0) *dst++ = *data++; } (void)kdb_jmpbuf(prev_jb); return (ret); } void db_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage) { BKPT_INST_TYPE tmp; db_addr_t loc; int slot; slot = addr & 0xfUL; if (slot >= SLOT_COUNT) return; loc = (addr & ~0xfUL) + (slot << 2); db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK; tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); tmp |= (0x84000 << 6) << SLOT_SHIFT(slot); db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); } void db_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage) { BKPT_INST_TYPE tmp; db_addr_t loc; int slot; slot = addr & 0xfUL; if (slot >= SLOT_COUNT) return; loc = (addr & ~0xfUL) + (slot << 2); db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); tmp |= *storage << SLOT_SHIFT(slot); db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); } void db_bkpt_skip(void) { if (kdb_frame == NULL) return; kdb_frame->tf_special.psr += IA64_PSR_RI_1; if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { kdb_frame->tf_special.psr &= ~IA64_PSR_RI; kdb_frame->tf_special.iip += 16; } } db_addr_t db_disasm(db_addr_t loc, boolean_t altfmt) { char buf[32]; struct asm_bundle bundle; const struct asm_inst *i; const char *tmpl; int n, slot; slot = loc & 0xf; loc &= ~0xful; db_read_bytes(loc, 16, buf); if (asm_decode((uintptr_t)buf, &bundle)) { i = bundle.b_inst + slot; tmpl = bundle.b_templ + slot; if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';')) tmpl++; if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) { db_printf("\n"); goto out; } /* Unit + slot. */ db_printf("[%c%d] ", *tmpl, slot); /* Predicate. */ if (i->i_oper[0].o_value != 0) { asm_operand(i->i_oper+0, buf, loc); db_printf("(%s) ", buf); } else db_printf(" "); /* Mnemonic & completers. */ asm_mnemonic(i->i_op, buf); db_printf(buf); n = 0; while (n < i->i_ncmpltrs) { asm_completer(i->i_cmpltr + n, buf); db_printf(buf); n++; } db_printf(" "); /* Operands. */ n = 1; while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) { if (n > 1) { if (n == i->i_srcidx) db_printf("="); else db_printf(","); } asm_operand(i->i_oper + n, buf, loc); db_printf(buf); n++; } } else { tmpl = NULL; slot = 2; } db_printf("\n"); out: slot++; if (slot == 1 && tmpl[1] == 'L') slot++; if (slot > 2) slot = 16; return (loc + slot); } void db_show_mdpcpu(struct pcpu *pc) { }