1149926Smarcel/*- 2149926Smarcel * Copyright (c) 2003-2005 Marcel Moolenaar 3149926Smarcel * Copyright (c) 2000-2001 Doug Rabson 4149926Smarcel * All rights reserved. 5149926Smarcel * 6149926Smarcel * Redistribution and use in source and binary forms, with or without 7149926Smarcel * modification, are permitted provided that the following conditions 8149926Smarcel * are met: 9149926Smarcel * 10149926Smarcel * 1. Redistributions of source code must retain the above copyright 11149926Smarcel * notice, this list of conditions and the following disclaimer. 12149926Smarcel * 2. Redistributions in binary form must reproduce the above copyright 13149926Smarcel * notice, this list of conditions and the following disclaimer in the 14149926Smarcel * documentation and/or other materials provided with the distribution. 15149926Smarcel * 16149926Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17149926Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18149926Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19149926Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20149926Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21149926Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22149926Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23149926Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24149926Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25149926Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26149926Smarcel * SUCH DAMAGE. 27149926Smarcel */ 28149926Smarcel 29149926Smarcel#include <sys/cdefs.h> 30149926Smarcel__FBSDID("$FreeBSD$"); 31149926Smarcel 32199502Smarcel#include "opt_xtrace.h" 33171665Smarcel 34149926Smarcel#include <sys/param.h> 35149926Smarcel#include <sys/systm.h> 36149926Smarcel#include <sys/cons.h> 37149926Smarcel#include <sys/kdb.h> 38149926Smarcel#include <sys/ktr.h> 39149926Smarcel#include <sys/kernel.h> 40149926Smarcel#include <sys/proc.h> 41149926Smarcel#include <sys/reboot.h> 42149926Smarcel#include <sys/smp.h> 43149926Smarcel#include <sys/stack.h> 44149926Smarcel 45149926Smarcel#include <vm/vm.h> 46149926Smarcel 47149926Smarcel#include <machine/db_machdep.h> 48149926Smarcel#include <machine/frame.h> 49170474Smarcel#include <machine/kdb.h> 50149926Smarcel#include <machine/md_var.h> 51149926Smarcel#include <machine/pcb.h> 52149926Smarcel#include <machine/setjmp.h> 53149926Smarcel#include <machine/unwind.h> 54149926Smarcel#include <machine/vmparam.h> 55149926Smarcel 56149926Smarcel#include <ddb/ddb.h> 57149926Smarcel#include <ddb/db_access.h> 58149926Smarcel#include <ddb/db_output.h> 59149926Smarcel#include <ddb/db_sym.h> 60149926Smarcel#include <ddb/db_variables.h> 61149926Smarcel 62149926Smarcel#include <ia64/disasm/disasm.h> 63149926Smarcel 64149926Smarcel#define TMPL_BITS 5 65149926Smarcel#define TMPL_MASK ((1 << TMPL_BITS) - 1) 66149926Smarcel#define SLOT_BITS 41 67149926Smarcel#define SLOT_COUNT 3 68149926Smarcel#define SLOT_MASK ((1ULL << SLOT_BITS) - 1ULL) 69149926Smarcel#define SLOT_SHIFT(i) (TMPL_BITS+((i)<<3)+(i)) 70149926Smarcel 71149926Smarceltypedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, 72149926Smarcel db_expr_t, db_expr_t, db_expr_t); 73149926Smarcel 74149926Smarcelregister uint64_t __db_gp __asm__("gp"); 75149926Smarcel 76149926Smarcelstatic db_varfcn_t db_frame; 77149926Smarcelstatic db_varfcn_t db_getip; 78149926Smarcelstatic db_varfcn_t db_getrse; 79149926Smarcel 80149926Smarcel#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 81149926Smarcelstruct db_variable db_regs[] = { 82149926Smarcel {"ip", NULL, db_getip}, 83149926Smarcel {"cr.ifs", DB_OFFSET(tf_special.cfm), db_frame}, 84149926Smarcel {"cr.ifa", DB_OFFSET(tf_special.ifa), db_frame}, 85149926Smarcel {"ar.bspstore", DB_OFFSET(tf_special.bspstore), db_frame}, 86149926Smarcel {"ndirty", DB_OFFSET(tf_special.ndirty), db_frame}, 87149926Smarcel {"rp", DB_OFFSET(tf_special.rp), db_frame}, 88149926Smarcel {"ar.pfs", DB_OFFSET(tf_special.pfs), db_frame}, 89149926Smarcel {"psr", DB_OFFSET(tf_special.psr), db_frame}, 90149926Smarcel {"cr.isr", DB_OFFSET(tf_special.isr), db_frame}, 91149926Smarcel {"pr", DB_OFFSET(tf_special.pr), db_frame}, 92149926Smarcel {"ar.rsc", DB_OFFSET(tf_special.rsc), db_frame}, 93149926Smarcel {"ar.rnat", DB_OFFSET(tf_special.rnat), db_frame}, 94149926Smarcel {"ar.unat", DB_OFFSET(tf_special.unat), db_frame}, 95149926Smarcel {"ar.fpsr", DB_OFFSET(tf_special.fpsr), db_frame}, 96149926Smarcel {"gp", DB_OFFSET(tf_special.gp), db_frame}, 97149926Smarcel {"sp", DB_OFFSET(tf_special.sp), db_frame}, 98149926Smarcel {"tp", DB_OFFSET(tf_special.tp), db_frame}, 99149926Smarcel {"b6", DB_OFFSET(tf_scratch.br6), db_frame}, 100149926Smarcel {"b7", DB_OFFSET(tf_scratch.br7), db_frame}, 101149926Smarcel {"r2", DB_OFFSET(tf_scratch.gr2), db_frame}, 102149926Smarcel {"r3", DB_OFFSET(tf_scratch.gr3), db_frame}, 103149926Smarcel {"r8", DB_OFFSET(tf_scratch.gr8), db_frame}, 104149926Smarcel {"r9", DB_OFFSET(tf_scratch.gr9), db_frame}, 105149926Smarcel {"r10", DB_OFFSET(tf_scratch.gr10), db_frame}, 106149926Smarcel {"r11", DB_OFFSET(tf_scratch.gr11), db_frame}, 107149926Smarcel {"r14", DB_OFFSET(tf_scratch.gr14), db_frame}, 108149926Smarcel {"r15", DB_OFFSET(tf_scratch.gr15), db_frame}, 109149926Smarcel {"r16", DB_OFFSET(tf_scratch.gr16), db_frame}, 110149926Smarcel {"r17", DB_OFFSET(tf_scratch.gr17), db_frame}, 111149926Smarcel {"r18", DB_OFFSET(tf_scratch.gr18), db_frame}, 112149926Smarcel {"r19", DB_OFFSET(tf_scratch.gr19), db_frame}, 113149926Smarcel {"r20", DB_OFFSET(tf_scratch.gr20), db_frame}, 114149926Smarcel {"r21", DB_OFFSET(tf_scratch.gr21), db_frame}, 115149926Smarcel {"r22", DB_OFFSET(tf_scratch.gr22), db_frame}, 116149926Smarcel {"r23", DB_OFFSET(tf_scratch.gr23), db_frame}, 117149926Smarcel {"r24", DB_OFFSET(tf_scratch.gr24), db_frame}, 118149926Smarcel {"r25", DB_OFFSET(tf_scratch.gr25), db_frame}, 119149926Smarcel {"r26", DB_OFFSET(tf_scratch.gr26), db_frame}, 120149926Smarcel {"r27", DB_OFFSET(tf_scratch.gr27), db_frame}, 121149926Smarcel {"r28", DB_OFFSET(tf_scratch.gr28), db_frame}, 122149926Smarcel {"r29", DB_OFFSET(tf_scratch.gr29), db_frame}, 123149926Smarcel {"r30", DB_OFFSET(tf_scratch.gr30), db_frame}, 124149926Smarcel {"r31", DB_OFFSET(tf_scratch.gr31), db_frame}, 125149926Smarcel {"r32", (db_expr_t*)0, db_getrse}, 126149926Smarcel {"r33", (db_expr_t*)1, db_getrse}, 127149926Smarcel {"r34", (db_expr_t*)2, db_getrse}, 128149926Smarcel {"r35", (db_expr_t*)3, db_getrse}, 129149926Smarcel {"r36", (db_expr_t*)4, db_getrse}, 130149926Smarcel {"r37", (db_expr_t*)5, db_getrse}, 131149926Smarcel {"r38", (db_expr_t*)6, db_getrse}, 132149926Smarcel {"r39", (db_expr_t*)7, db_getrse}, 133149926Smarcel {"r40", (db_expr_t*)8, db_getrse}, 134149926Smarcel {"r41", (db_expr_t*)9, db_getrse}, 135149926Smarcel {"r42", (db_expr_t*)10, db_getrse}, 136149926Smarcel {"r43", (db_expr_t*)11, db_getrse}, 137149926Smarcel {"r44", (db_expr_t*)12, db_getrse}, 138149926Smarcel {"r45", (db_expr_t*)13, db_getrse}, 139149926Smarcel {"r46", (db_expr_t*)14, db_getrse}, 140149926Smarcel {"r47", (db_expr_t*)15, db_getrse}, 141149926Smarcel {"r48", (db_expr_t*)16, db_getrse}, 142149926Smarcel {"r49", (db_expr_t*)17, db_getrse}, 143149926Smarcel {"r50", (db_expr_t*)18, db_getrse}, 144149926Smarcel {"r51", (db_expr_t*)19, db_getrse}, 145149926Smarcel {"r52", (db_expr_t*)20, db_getrse}, 146149926Smarcel {"r53", (db_expr_t*)21, db_getrse}, 147149926Smarcel {"r54", (db_expr_t*)22, db_getrse}, 148149926Smarcel {"r55", (db_expr_t*)23, db_getrse}, 149149926Smarcel {"r56", (db_expr_t*)24, db_getrse}, 150149926Smarcel {"r57", (db_expr_t*)25, db_getrse}, 151149926Smarcel {"r58", (db_expr_t*)26, db_getrse}, 152149926Smarcel {"r59", (db_expr_t*)27, db_getrse}, 153149926Smarcel {"r60", (db_expr_t*)28, db_getrse}, 154149926Smarcel {"r61", (db_expr_t*)29, db_getrse}, 155149926Smarcel {"r62", (db_expr_t*)30, db_getrse}, 156149926Smarcel {"r63", (db_expr_t*)31, db_getrse}, 157149926Smarcel {"r64", (db_expr_t*)32, db_getrse}, 158149926Smarcel {"r65", (db_expr_t*)33, db_getrse}, 159149926Smarcel {"r66", (db_expr_t*)34, db_getrse}, 160149926Smarcel {"r67", (db_expr_t*)35, db_getrse}, 161149926Smarcel {"r68", (db_expr_t*)36, db_getrse}, 162149926Smarcel {"r69", (db_expr_t*)37, db_getrse}, 163149926Smarcel {"r70", (db_expr_t*)38, db_getrse}, 164149926Smarcel {"r71", (db_expr_t*)39, db_getrse}, 165149926Smarcel {"r72", (db_expr_t*)40, db_getrse}, 166149926Smarcel {"r73", (db_expr_t*)41, db_getrse}, 167149926Smarcel {"r74", (db_expr_t*)42, db_getrse}, 168149926Smarcel {"r75", (db_expr_t*)43, db_getrse}, 169149926Smarcel {"r76", (db_expr_t*)44, db_getrse}, 170149926Smarcel {"r77", (db_expr_t*)45, db_getrse}, 171149926Smarcel {"r78", (db_expr_t*)46, db_getrse}, 172149926Smarcel {"r79", (db_expr_t*)47, db_getrse}, 173149926Smarcel {"r80", (db_expr_t*)48, db_getrse}, 174149926Smarcel {"r81", (db_expr_t*)49, db_getrse}, 175149926Smarcel {"r82", (db_expr_t*)50, db_getrse}, 176149926Smarcel {"r83", (db_expr_t*)51, db_getrse}, 177149926Smarcel {"r84", (db_expr_t*)52, db_getrse}, 178149926Smarcel {"r85", (db_expr_t*)53, db_getrse}, 179149926Smarcel {"r86", (db_expr_t*)54, db_getrse}, 180149926Smarcel {"r87", (db_expr_t*)55, db_getrse}, 181149926Smarcel {"r88", (db_expr_t*)56, db_getrse}, 182149926Smarcel {"r89", (db_expr_t*)57, db_getrse}, 183149926Smarcel {"r90", (db_expr_t*)58, db_getrse}, 184149926Smarcel {"r91", (db_expr_t*)59, db_getrse}, 185149926Smarcel {"r92", (db_expr_t*)60, db_getrse}, 186149926Smarcel {"r93", (db_expr_t*)61, db_getrse}, 187149926Smarcel {"r94", (db_expr_t*)62, db_getrse}, 188149926Smarcel {"r95", (db_expr_t*)63, db_getrse}, 189149926Smarcel {"r96", (db_expr_t*)64, db_getrse}, 190149926Smarcel {"r97", (db_expr_t*)65, db_getrse}, 191149926Smarcel {"r98", (db_expr_t*)66, db_getrse}, 192149926Smarcel {"r99", (db_expr_t*)67, db_getrse}, 193149926Smarcel {"r100", (db_expr_t*)68, db_getrse}, 194149926Smarcel {"r101", (db_expr_t*)69, db_getrse}, 195149926Smarcel {"r102", (db_expr_t*)70, db_getrse}, 196149926Smarcel {"r103", (db_expr_t*)71, db_getrse}, 197149926Smarcel {"r104", (db_expr_t*)72, db_getrse}, 198149926Smarcel {"r105", (db_expr_t*)73, db_getrse}, 199149926Smarcel {"r106", (db_expr_t*)74, db_getrse}, 200149926Smarcel {"r107", (db_expr_t*)75, db_getrse}, 201149926Smarcel {"r108", (db_expr_t*)76, db_getrse}, 202149926Smarcel {"r109", (db_expr_t*)77, db_getrse}, 203149926Smarcel {"r110", (db_expr_t*)78, db_getrse}, 204149926Smarcel {"r111", (db_expr_t*)79, db_getrse}, 205149926Smarcel {"r112", (db_expr_t*)80, db_getrse}, 206149926Smarcel {"r113", (db_expr_t*)81, db_getrse}, 207149926Smarcel {"r114", (db_expr_t*)82, db_getrse}, 208149926Smarcel {"r115", (db_expr_t*)83, db_getrse}, 209149926Smarcel {"r116", (db_expr_t*)84, db_getrse}, 210149926Smarcel {"r117", (db_expr_t*)85, db_getrse}, 211149926Smarcel {"r118", (db_expr_t*)86, db_getrse}, 212149926Smarcel {"r119", (db_expr_t*)87, db_getrse}, 213149926Smarcel {"r120", (db_expr_t*)88, db_getrse}, 214149926Smarcel {"r121", (db_expr_t*)89, db_getrse}, 215149926Smarcel {"r122", (db_expr_t*)90, db_getrse}, 216149926Smarcel {"r123", (db_expr_t*)91, db_getrse}, 217149926Smarcel {"r124", (db_expr_t*)92, db_getrse}, 218149926Smarcel {"r125", (db_expr_t*)93, db_getrse}, 219149926Smarcel {"r126", (db_expr_t*)94, db_getrse}, 220149926Smarcel {"r127", (db_expr_t*)95, db_getrse}, 221149926Smarcel}; 222149926Smarcelstruct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 223149926Smarcel 224149926Smarcelstatic int 225149926Smarceldb_backtrace(struct thread *td, struct pcb *pcb, int count) 226149926Smarcel{ 227149926Smarcel struct unw_regstate rs; 228149926Smarcel struct trapframe *tf; 229149926Smarcel const char *name; 230149926Smarcel db_expr_t offset; 231149926Smarcel uint64_t bsp, cfm, ip, pfs, reg, sp; 232149926Smarcel c_db_sym_t sym; 233160312Sjhb int args, error, i; 234149926Smarcel 235149926Smarcel error = unw_create_from_pcb(&rs, pcb); 236160312Sjhb while (!error && count-- && !db_pager_quit) { 237149926Smarcel error = unw_get_cfm(&rs, &cfm); 238149926Smarcel if (!error) 239149926Smarcel error = unw_get_bsp(&rs, &bsp); 240149926Smarcel if (!error) 241149926Smarcel error = unw_get_ip(&rs, &ip); 242149926Smarcel if (!error) 243149926Smarcel error = unw_get_sp(&rs, &sp); 244149926Smarcel if (error) 245149926Smarcel break; 246149926Smarcel 247149926Smarcel args = IA64_CFM_SOL(cfm); 248149926Smarcel if (args > 8) 249149926Smarcel args = 8; 250149926Smarcel 251149926Smarcel error = unw_step(&rs); 252149926Smarcel if (!error) { 253149926Smarcel if (!unw_get_cfm(&rs, &pfs)) { 254149926Smarcel i = IA64_CFM_SOF(pfs) - IA64_CFM_SOL(pfs); 255149926Smarcel if (args > i) 256149926Smarcel args = i; 257149926Smarcel } 258149926Smarcel } 259149926Smarcel 260149926Smarcel sym = db_search_symbol(ip, DB_STGY_ANY, &offset); 261149926Smarcel db_symbol_values(sym, &name, NULL); 262149926Smarcel db_printf("%s(", name); 263219808Smarcel if (bsp >= VM_MAXUSER_ADDRESS) { 264149926Smarcel for (i = 0; i < args; i++) { 265149926Smarcel if ((bsp & 0x1ff) == 0x1f8) 266149926Smarcel bsp += 8; 267149926Smarcel db_read_bytes(bsp, sizeof(reg), (void*)®); 268149926Smarcel if (i > 0) 269149926Smarcel db_printf(", "); 270149926Smarcel db_printf("0x%lx", reg); 271149926Smarcel bsp += 8; 272149926Smarcel } 273149926Smarcel } else 274149926Smarcel db_printf("..."); 275149926Smarcel db_printf(") at "); 276149926Smarcel 277149926Smarcel db_printsym(ip, DB_STGY_PROC); 278149926Smarcel db_printf("\n"); 279149926Smarcel 280149926Smarcel if (error != ERESTART) 281149926Smarcel continue; 282219808Smarcel if (sp < VM_MAXUSER_ADDRESS) 283149926Smarcel break; 284149926Smarcel 285149926Smarcel tf = (struct trapframe *)(sp + 16); 286149926Smarcel if ((tf->tf_flags & FRAME_SYSCALL) != 0 || 287219808Smarcel tf->tf_special.iip < VM_MAXUSER_ADDRESS) 288149926Smarcel break; 289149926Smarcel 290149926Smarcel /* XXX ask if we should unwind across the trapframe. */ 291149926Smarcel db_printf("--- trapframe at %p\n", tf); 292149926Smarcel unw_delete(&rs); 293149926Smarcel error = unw_create_from_frame(&rs, tf); 294149926Smarcel } 295149926Smarcel 296149926Smarcel unw_delete(&rs); 297149926Smarcel /* 298149926Smarcel * EJUSTRETURN and ERESTART signal the end of a trace and 299149926Smarcel * are not really errors. 300149926Smarcel */ 301149926Smarcel return ((error > 0) ? error : 0); 302149926Smarcel} 303149926Smarcel 304149926Smarcelvoid 305149926Smarceldb_bkpt_clear(db_addr_t addr, BKPT_INST_TYPE *storage) 306149926Smarcel{ 307149926Smarcel BKPT_INST_TYPE tmp; 308149926Smarcel db_addr_t loc; 309149926Smarcel int slot; 310149926Smarcel 311149926Smarcel slot = addr & 0xfUL; 312149926Smarcel if (slot >= SLOT_COUNT) 313149926Smarcel return; 314149926Smarcel loc = (addr & ~0xfUL) + (slot << 2); 315149926Smarcel 316149926Smarcel db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); 317149926Smarcel tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); 318149926Smarcel tmp |= *storage << SLOT_SHIFT(slot); 319149926Smarcel db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); 320149926Smarcel} 321149926Smarcel 322149926Smarcelvoid 323149926Smarceldb_bkpt_skip(void) 324149926Smarcel{ 325149926Smarcel 326149926Smarcel if (kdb_frame == NULL) 327149926Smarcel return; 328149926Smarcel 329149926Smarcel kdb_frame->tf_special.psr += IA64_PSR_RI_1; 330149926Smarcel if ((kdb_frame->tf_special.psr & IA64_PSR_RI) > IA64_PSR_RI_2) { 331149926Smarcel kdb_frame->tf_special.psr &= ~IA64_PSR_RI; 332149926Smarcel kdb_frame->tf_special.iip += 16; 333149926Smarcel } 334149926Smarcel} 335149926Smarcel 336149926Smarcelvoid 337149926Smarceldb_bkpt_write(db_addr_t addr, BKPT_INST_TYPE *storage) 338149926Smarcel{ 339149926Smarcel BKPT_INST_TYPE tmp; 340149926Smarcel db_addr_t loc; 341149926Smarcel int slot; 342149926Smarcel 343149926Smarcel slot = addr & 0xfUL; 344149926Smarcel if (slot >= SLOT_COUNT) 345149926Smarcel return; 346149926Smarcel loc = (addr & ~0xfUL) + (slot << 2); 347149926Smarcel 348149926Smarcel db_read_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); 349149926Smarcel *storage = (tmp >> SLOT_SHIFT(slot)) & SLOT_MASK; 350149926Smarcel 351149926Smarcel tmp &= ~(SLOT_MASK << SLOT_SHIFT(slot)); 352149926Smarcel tmp |= (0x84000 << 6) << SLOT_SHIFT(slot); 353149926Smarcel db_write_bytes(loc, sizeof(BKPT_INST_TYPE), (char *)&tmp); 354149926Smarcel} 355149926Smarcel 356149926Smarceldb_addr_t 357149926Smarceldb_disasm(db_addr_t loc, boolean_t altfmt) 358149926Smarcel{ 359149926Smarcel char buf[32]; 360149926Smarcel struct asm_bundle bundle; 361149926Smarcel const struct asm_inst *i; 362149926Smarcel const char *tmpl; 363149926Smarcel int n, slot; 364149926Smarcel 365149926Smarcel slot = loc & 0xf; 366149926Smarcel loc &= ~0xful; 367149926Smarcel db_read_bytes(loc, 16, buf); 368149926Smarcel if (asm_decode((uintptr_t)buf, &bundle)) { 369149926Smarcel i = bundle.b_inst + slot; 370149926Smarcel tmpl = bundle.b_templ + slot; 371149926Smarcel if (*tmpl == ';' || (slot == 2 && bundle.b_templ[1] == ';')) 372149926Smarcel tmpl++; 373149926Smarcel if (*tmpl == 'L' || i->i_op == ASM_OP_NONE) { 374149926Smarcel db_printf("\n"); 375149926Smarcel goto out; 376149926Smarcel } 377149926Smarcel 378149926Smarcel /* Unit + slot. */ 379149926Smarcel db_printf("[%c%d] ", *tmpl, slot); 380149926Smarcel 381149926Smarcel /* Predicate. */ 382149926Smarcel if (i->i_oper[0].o_value != 0) { 383149926Smarcel asm_operand(i->i_oper+0, buf, loc); 384149926Smarcel db_printf("(%s) ", buf); 385149926Smarcel } else 386149926Smarcel db_printf(" "); 387149926Smarcel 388149926Smarcel /* Mnemonic & completers. */ 389149926Smarcel asm_mnemonic(i->i_op, buf); 390149926Smarcel db_printf(buf); 391149926Smarcel n = 0; 392149926Smarcel while (n < i->i_ncmpltrs) { 393149926Smarcel asm_completer(i->i_cmpltr + n, buf); 394149926Smarcel db_printf(buf); 395149926Smarcel n++; 396149926Smarcel } 397149926Smarcel db_printf(" "); 398149926Smarcel 399149926Smarcel /* Operands. */ 400149926Smarcel n = 1; 401149926Smarcel while (n < 7 && i->i_oper[n].o_type != ASM_OPER_NONE) { 402149926Smarcel if (n > 1) { 403149926Smarcel if (n == i->i_srcidx) 404149926Smarcel db_printf("="); 405149926Smarcel else 406149926Smarcel db_printf(","); 407149926Smarcel } 408149926Smarcel asm_operand(i->i_oper + n, buf, loc); 409149926Smarcel db_printf(buf); 410149926Smarcel n++; 411149926Smarcel } 412172690Smarcel if (tmpl[1] == ';') 413172690Smarcel db_printf(" ;;"); 414149926Smarcel } else { 415149926Smarcel tmpl = NULL; 416149926Smarcel slot = 2; 417149926Smarcel } 418149926Smarcel db_printf("\n"); 419149926Smarcel 420149926Smarcelout: 421149926Smarcel slot++; 422149926Smarcel if (slot == 1 && tmpl[1] == 'L') 423149926Smarcel slot++; 424149926Smarcel if (slot > 2) 425149926Smarcel slot = 16; 426149926Smarcel return (loc + slot); 427149926Smarcel} 428149926Smarcel 429149926Smarcelint 430149926Smarceldb_fncall_ia64(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[]) 431149926Smarcel{ 432149926Smarcel struct ia64_fdesc fdesc; 433149926Smarcel __db_f *f; 434149926Smarcel 435149926Smarcel f = (__db_f *)&fdesc; 436149926Smarcel fdesc.func = addr; 437149926Smarcel fdesc.gp = __db_gp; /* XXX doesn't work for modules. */ 438149926Smarcel *rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5], 439149926Smarcel args[6], args[7]); 440149926Smarcel return (1); 441149926Smarcel} 442149926Smarcel 443149926Smarcelstatic int 444149926Smarceldb_frame(struct db_variable *vp, db_expr_t *valuep, int op) 445149926Smarcel{ 446149926Smarcel uint64_t *reg; 447149926Smarcel 448149926Smarcel if (kdb_frame == NULL) 449149926Smarcel return (0); 450149926Smarcel reg = (uint64_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); 451149926Smarcel if (op == DB_VAR_GET) 452149926Smarcel *valuep = *reg; 453149926Smarcel else 454149926Smarcel *reg = *valuep; 455149926Smarcel return (1); 456149926Smarcel} 457149926Smarcel 458149926Smarcelstatic int 459149926Smarceldb_getip(struct db_variable *vp, db_expr_t *valuep, int op) 460149926Smarcel{ 461149926Smarcel u_long iip, slot; 462149926Smarcel 463149926Smarcel if (kdb_frame == NULL) 464149926Smarcel return (0); 465149926Smarcel 466149926Smarcel if (op == DB_VAR_GET) { 467149926Smarcel iip = kdb_frame->tf_special.iip; 468149926Smarcel slot = (kdb_frame->tf_special.psr >> 41) & 3; 469149926Smarcel *valuep = iip + slot; 470149926Smarcel } else { 471149926Smarcel iip = *valuep & ~0xf; 472149926Smarcel slot = *valuep & 0xf; 473149926Smarcel if (slot > 2) 474149926Smarcel return (0); 475149926Smarcel kdb_frame->tf_special.iip = iip; 476149926Smarcel kdb_frame->tf_special.psr &= ~IA64_PSR_RI; 477149926Smarcel kdb_frame->tf_special.psr |= slot << 41; 478149926Smarcel } 479149926Smarcel return (1); 480149926Smarcel} 481149926Smarcel 482149926Smarcelstatic int 483149926Smarceldb_getrse(struct db_variable *vp, db_expr_t *valuep, int op) 484149926Smarcel{ 485149926Smarcel u_int64_t *reg; 486149926Smarcel uint64_t bsp; 487149926Smarcel int nats, regno, sof; 488149926Smarcel 489149926Smarcel if (kdb_frame == NULL) 490149926Smarcel return (0); 491149926Smarcel 492149926Smarcel regno = (int)(intptr_t)valuep; 493149926Smarcel bsp = kdb_frame->tf_special.bspstore + kdb_frame->tf_special.ndirty; 494149926Smarcel sof = (int)(kdb_frame->tf_special.cfm & 0x7f); 495149926Smarcel 496149926Smarcel if (regno >= sof) 497149926Smarcel return (0); 498149926Smarcel 499149926Smarcel nats = (sof - regno + 63 - ((int)(bsp >> 3) & 0x3f)) / 63; 500149926Smarcel reg = (void*)(bsp - ((sof - regno + nats) << 3)); 501149926Smarcel if (op == DB_VAR_GET) 502149926Smarcel *valuep = *reg; 503149926Smarcel else 504149926Smarcel *reg = *valuep; 505149926Smarcel return (1); 506149926Smarcel} 507149926Smarcel 508149926Smarcelint 509149926Smarceldb_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 510149926Smarcel{ 511149926Smarcel 512149926Smarcel return (-1); 513149926Smarcel} 514149926Smarcel 515149926Smarcelvoid 516149926Smarceldb_md_list_watchpoints() 517149926Smarcel{ 518149926Smarcel 519149926Smarcel return; 520149926Smarcel} 521149926Smarcel 522149926Smarcelint 523149926Smarceldb_md_set_watchpoint(db_expr_t addr, db_expr_t size) 524149926Smarcel{ 525149926Smarcel 526149926Smarcel return (-1); 527149926Smarcel} 528149926Smarcel 529149926Smarcel/* 530149926Smarcel * Read bytes from kernel address space for debugger. 531149926Smarcel */ 532149926Smarcelint 533149926Smarceldb_read_bytes(vm_offset_t addr, size_t size, char *data) 534149926Smarcel{ 535149926Smarcel jmp_buf jb; 536149926Smarcel void *prev_jb; 537149926Smarcel char *src; 538149926Smarcel int ret; 539149926Smarcel 540149926Smarcel prev_jb = kdb_jmpbuf(jb); 541149926Smarcel ret = setjmp(jb); 542149926Smarcel if (ret == 0) { 543149926Smarcel src = (char *)addr; 544149926Smarcel while (size-- > 0) 545149926Smarcel *data++ = *src++; 546149926Smarcel } 547149926Smarcel (void)kdb_jmpbuf(prev_jb); 548149926Smarcel return (ret); 549149926Smarcel} 550149926Smarcel 551149926Smarcel/* 552149926Smarcel * Write bytes to kernel address space for debugger. 553149926Smarcel */ 554149926Smarcelint 555149926Smarceldb_write_bytes(vm_offset_t addr, size_t size, char *data) 556149926Smarcel{ 557149926Smarcel jmp_buf jb; 558149926Smarcel void *prev_jb; 559170474Smarcel size_t cnt; 560149926Smarcel char *dst; 561149926Smarcel int ret; 562149926Smarcel 563149926Smarcel prev_jb = kdb_jmpbuf(jb); 564149926Smarcel ret = setjmp(jb); 565149926Smarcel if (ret == 0) { 566149926Smarcel dst = (char *)addr; 567170474Smarcel cnt = size; 568170474Smarcel while (cnt-- > 0) 569149926Smarcel *dst++ = *data++; 570170474Smarcel kdb_cpu_sync_icache((void *)addr, size); 571149926Smarcel } 572149926Smarcel (void)kdb_jmpbuf(prev_jb); 573149926Smarcel return (ret); 574149926Smarcel} 575149926Smarcel 576149926Smarcelvoid 577149926Smarceldb_show_mdpcpu(struct pcpu *pc) 578149926Smarcel{ 579205429Smarcel struct pcpu_md *md = &pc->pc_md; 580205429Smarcel 581223526Smarcel db_printf("MD: vhpt = %#lx\n", md->vhpt); 582223526Smarcel db_printf("MD: lid = %#lx\n", md->lid); 583223526Smarcel db_printf("MD: clock = %#lx\n", md->clock); 584223526Smarcel db_printf("MD: clock_mode = %u\n", md->clock_mode); 585223526Smarcel db_printf("MD: clock_load = %#lx\n", md->clock_load); 586223526Smarcel db_printf("MD: stats = %p\n", &md->stats); 587223526Smarcel db_printf("MD: pmap = %p\n", md->current_pmap); 588149926Smarcel} 589149926Smarcel 590149926Smarcelvoid 591149926Smarceldb_trace_self(void) 592149926Smarcel{ 593149926Smarcel struct pcb pcb; 594149926Smarcel 595149926Smarcel savectx(&pcb); 596149926Smarcel db_backtrace(curthread, &pcb, -1); 597149926Smarcel} 598149926Smarcel 599149926Smarcelint 600149926Smarceldb_trace_thread(struct thread *td, int count) 601149926Smarcel{ 602149926Smarcel struct pcb *ctx; 603149926Smarcel 604149926Smarcel ctx = kdb_thr_ctx(td); 605149926Smarcel return (db_backtrace(td, ctx, count)); 606149926Smarcel} 607149926Smarcel 608171665Smarcel#ifdef EXCEPTION_TRACING 609171665Smarcel 610171665Smarcelextern long xtrace[]; 611171665Smarcelextern long *xhead; 612171665Smarcel 613171665SmarcelDB_COMMAND(xtrace, db_xtrace) 614171665Smarcel{ 615171665Smarcel long *p; 616171665Smarcel 617171665Smarcel p = (*xhead == 0) ? xtrace : xhead; 618171665Smarcel 619171665Smarcel db_printf("ITC\t\t IVT\t\t IIP\t\t IFA\t\t ISR\n"); 620171665Smarcel if (*p == 0) 621171665Smarcel return; 622171665Smarcel 623171665Smarcel do { 624171665Smarcel db_printf("%016lx %016lx %016lx %016lx %016lx\n", p[0], p[1], 625171665Smarcel p[2], p[3], p[4]); 626171665Smarcel p += 5; 627171665Smarcel if (p == (void *)&xhead) 628171665Smarcel p = xtrace; 629171665Smarcel } while (p != xhead); 630171665Smarcel} 631171665Smarcel 632171665Smarcel#endif 633