1178172Simp/* $OpenBSD: db_machdep.c,v 1.2 1998/09/15 10:50:13 pefo Exp $ */ 2178172Simp 3178172Simp/*- 4178172Simp * Copyright (c) 1998 Per Fogelstrom, Opsycon AB 5178172Simp * 6178172Simp * Redistribution and use in source and binary forms, with or without 7178172Simp * modification, are permitted provided that the following conditions 8178172Simp * are met: 9178172Simp * 1. Redistributions of source code must retain the above copyright 10178172Simp * notice, this list of conditions and the following disclaimer. 11178172Simp * 2. Redistributions in binary form must reproduce the above copyright 12178172Simp * notice, this list of conditions and the following disclaimer in the 13178172Simp * documentation and/or other materials provided with the distribution. 14178172Simp * 3. All advertising materials mentioning features or use of this software 15178172Simp * must display the following acknowledgement: 16178172Simp * This product includes software developed under OpenBSD by 17178172Simp * Per Fogelstrom, Opsycon AB, Sweden. 18178172Simp * 4. The name of the author may not be used to endorse or promote products 19178172Simp * derived from this software without specific prior written permission. 20178172Simp * 21178172Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 22178172Simp * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23178172Simp * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 25178172Simp * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178172Simp * SUCH DAMAGE. 32178172Simp * 33178172Simp * JNPR: db_interface.c,v 1.6.2.1 2007/08/29 12:24:49 girish 34178172Simp */ 35178172Simp 36178172Simp#include <sys/cdefs.h> 37178172Simp__FBSDID("$FreeBSD$"); 38178172Simp 39178172Simp#include <sys/types.h> 40178172Simp#include <sys/param.h> 41178172Simp#include <sys/systm.h> 42178172Simp#include <sys/cons.h> 43178172Simp#include <sys/lock.h> 44178172Simp#include <vm/vm.h> 45178172Simp#include <vm/vm_object.h> 46178172Simp#include <vm/vm_page.h> 47178172Simp#include <vm/pmap.h> 48178172Simp#include <vm/vm_map.h> 49178172Simp#include <sys/user.h> 50178172Simp#include <sys/proc.h> 51178172Simp#include <sys/reboot.h> 52178172Simp 53178172Simp#include <machine/cache.h> 54178172Simp#include <machine/db_machdep.h> 55178172Simp#include <machine/mips_opcode.h> 56178172Simp#include <machine/vmparam.h> 57178172Simp#include <machine/md_var.h> 58178172Simp#define NO_REG_DEFS 1 /* Prevent asm.h from including regdef.h */ 59178172Simp#include <machine/asm.h> 60178172Simp#include <machine/setjmp.h> 61178172Simp 62178172Simp#include <ddb/ddb.h> 63178172Simp#include <ddb/db_sym.h> 64178172Simp#include <ddb/db_access.h> 65178172Simp#include <ddb/db_output.h> 66178172Simp#include <ddb/db_variables.h> 67178172Simp#include <sys/kdb.h> 68178172Simp 69178172Simpstatic db_varfcn_t db_frame; 70178172Simp 71178172Simp#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 72178172Simpstruct db_variable db_regs[] = { 73178172Simp { "at", DB_OFFSET(ast), db_frame }, 74178172Simp { "v0", DB_OFFSET(v0), db_frame }, 75178172Simp { "v1", DB_OFFSET(v1), db_frame }, 76178172Simp { "a0", DB_OFFSET(a0), db_frame }, 77178172Simp { "a1", DB_OFFSET(a1), db_frame }, 78178172Simp { "a2", DB_OFFSET(a2), db_frame }, 79178172Simp { "a3", DB_OFFSET(a3), db_frame }, 80178172Simp { "t0", DB_OFFSET(t0), db_frame }, 81178172Simp { "t1", DB_OFFSET(t1), db_frame }, 82178172Simp { "t2", DB_OFFSET(t2), db_frame }, 83178172Simp { "t3", DB_OFFSET(t3), db_frame }, 84178172Simp { "t4", DB_OFFSET(t4), db_frame }, 85178172Simp { "t5", DB_OFFSET(t5), db_frame }, 86178172Simp { "t6", DB_OFFSET(t6), db_frame }, 87178172Simp { "t7", DB_OFFSET(t7), db_frame }, 88178172Simp { "s0", DB_OFFSET(s0), db_frame }, 89178172Simp { "s1", DB_OFFSET(s1), db_frame }, 90178172Simp { "s2", DB_OFFSET(s2), db_frame }, 91178172Simp { "s3", DB_OFFSET(s3), db_frame }, 92178172Simp { "s4", DB_OFFSET(s4), db_frame }, 93178172Simp { "s5", DB_OFFSET(s5), db_frame }, 94178172Simp { "s6", DB_OFFSET(s6), db_frame }, 95178172Simp { "s7", DB_OFFSET(s7), db_frame }, 96178172Simp { "t8", DB_OFFSET(t8), db_frame }, 97178172Simp { "t9", DB_OFFSET(t9), db_frame }, 98178172Simp { "k0", DB_OFFSET(k0), db_frame }, 99178172Simp { "k1", DB_OFFSET(k1), db_frame }, 100178172Simp { "gp", DB_OFFSET(gp), db_frame }, 101178172Simp { "sp", DB_OFFSET(sp), db_frame }, 102178172Simp { "s8", DB_OFFSET(s8), db_frame }, 103178172Simp { "ra", DB_OFFSET(ra), db_frame }, 104178172Simp { "sr", DB_OFFSET(sr), db_frame }, 105178172Simp { "lo", DB_OFFSET(mullo), db_frame }, 106178172Simp { "hi", DB_OFFSET(mulhi), db_frame }, 107178172Simp { "bad", DB_OFFSET(badvaddr), db_frame }, 108178172Simp { "cs", DB_OFFSET(cause), db_frame }, 109178172Simp { "pc", DB_OFFSET(pc), db_frame }, 110178172Simp}; 111178172Simpstruct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); 112178172Simp 113178172Simpint (*do_db_log_stack_trace_cmd)(char *); 114178172Simp 115178172Simpstatic int 116178172Simpdb_frame(struct db_variable *vp, db_expr_t *valuep, int op) 117178172Simp{ 118209935Sjchandra register_t *reg; 119178172Simp 120178172Simp if (kdb_frame == NULL) 121178172Simp return (0); 122178172Simp 123209935Sjchandra reg = (register_t *)((uintptr_t)kdb_frame + (size_t)(intptr_t)vp->valuep); 124178172Simp if (op == DB_VAR_GET) 125178172Simp *valuep = *reg; 126178172Simp else 127178172Simp *reg = *valuep; 128178172Simp return (1); 129178172Simp} 130178172Simp 131178172Simpint 132178172Simpdb_read_bytes(vm_offset_t addr, size_t size, char *data) 133178172Simp{ 134178172Simp jmp_buf jb; 135178172Simp void *prev_jb; 136178172Simp int ret; 137178172Simp 138178172Simp prev_jb = kdb_jmpbuf(jb); 139178172Simp ret = setjmp(jb); 140178172Simp if (ret == 0) { 141178172Simp /* 142178172Simp * 'addr' could be a memory-mapped I/O address. Try to 143178172Simp * do atomic load/store in unit of size requested. 144178172Simp */ 145178172Simp if ((size == 2 || size == 4 || size == 8) && 146178172Simp ((addr & (size -1)) == 0) && 147178172Simp (((vm_offset_t)data & (size -1)) == 0)) { 148178172Simp switch (size) { 149178172Simp case 2: 150178172Simp *(uint16_t *)data = *(uint16_t *)addr; 151178172Simp break; 152178172Simp case 4: 153178172Simp *(uint32_t *)data = *(uint32_t *)addr; 154178172Simp break; 155178172Simp case 8: 156178172Simp atomic_load_64((volatile u_int64_t *)addr, 157178172Simp (u_int64_t *)data); 158178172Simp break; 159178172Simp } 160178172Simp } else { 161178172Simp char *src; 162178172Simp 163178172Simp src = (char *)addr; 164178172Simp while (size-- > 0) 165178172Simp *data++ = *src++; 166178172Simp } 167178172Simp } 168178172Simp 169178172Simp (void)kdb_jmpbuf(prev_jb); 170178172Simp return (ret); 171178172Simp} 172178172Simp 173178172Simpint 174178172Simpdb_write_bytes(vm_offset_t addr, size_t size, char *data) 175178172Simp{ 176178172Simp int ret; 177178172Simp jmp_buf jb; 178178172Simp void *prev_jb; 179178172Simp 180178172Simp prev_jb = kdb_jmpbuf(jb); 181178172Simp ret = setjmp(jb); 182178172Simp 183178172Simp if (ret == 0) { 184178172Simp /* 185178172Simp * 'addr' could be a memory-mapped I/O address. Try to 186178172Simp * do atomic load/store in unit of size requested. 187178172Simp */ 188178172Simp if ((size == 2 || size == 4 || size == 8) && 189178172Simp ((addr & (size -1)) == 0) && 190178172Simp (((vm_offset_t)data & (size -1)) == 0)) { 191178172Simp switch (size) { 192178172Simp case 2: 193178172Simp *(uint16_t *)addr = *(uint16_t *)data; 194178172Simp break; 195178172Simp case 4: 196178172Simp *(uint32_t *)addr = *(uint32_t *)data; 197178172Simp break; 198178172Simp case 8: 199178172Simp atomic_store_64((volatile u_int64_t *)addr, 200178172Simp (u_int64_t *)data); 201178172Simp break; 202178172Simp } 203178172Simp } else { 204178172Simp char *dst; 205178172Simp size_t len = size; 206178172Simp 207178172Simp dst = (char *)addr; 208178172Simp while (len-- > 0) 209178172Simp *dst++ = *data++; 210178172Simp } 211178172Simp 212178172Simp mips_icache_sync_range((db_addr_t) addr, size); 213178172Simp mips_dcache_wbinv_range((db_addr_t) addr, size); 214178172Simp } 215178172Simp (void)kdb_jmpbuf(prev_jb); 216178172Simp return (ret); 217178172Simp} 218178172Simp 219178172Simp/* 220178172Simp * To do a single step ddb needs to know the next address 221178172Simp * that we will get to. It means that we need to find out 222178172Simp * both the address for a branch taken and for not taken, NOT! :-) 223178172Simp * MipsEmulateBranch will do the job to find out _exactly_ which 224178172Simp * address we will end up at so the 'dual bp' method is not 225178172Simp * requiered. 226178172Simp */ 227178172Simpdb_addr_t 228178172Simpnext_instr_address(db_addr_t pc, boolean_t bd) 229178172Simp{ 230178172Simp db_addr_t next; 231178172Simp 232178172Simp next = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, 0, 0); 233178172Simp return (next); 234178172Simp} 235178172Simp 236178172Simp 237178172Simp/* 238178172Simp * Decode instruction and figure out type. 239178172Simp */ 240178172Simpint 241178172Simpdb_inst_type(int ins) 242178172Simp{ 243178172Simp InstFmt inst; 244178172Simp int ityp = 0; 245178172Simp 246178172Simp inst.word = ins; 247178172Simp switch ((int)inst.JType.op) { 248178172Simp case OP_SPECIAL: 249178172Simp switch ((int)inst.RType.func) { 250178172Simp case OP_JR: 251178172Simp ityp = IT_BRANCH; 252178172Simp break; 253178172Simp case OP_JALR: 254178172Simp case OP_SYSCALL: 255178172Simp ityp = IT_CALL; 256178172Simp break; 257178172Simp } 258178172Simp break; 259178172Simp 260178172Simp case OP_BCOND: 261178172Simp switch ((int)inst.IType.rt) { 262178172Simp case OP_BLTZ: 263178172Simp case OP_BLTZL: 264178172Simp case OP_BGEZ: 265178172Simp case OP_BGEZL: 266178172Simp ityp = IT_BRANCH; 267178172Simp break; 268178172Simp 269178172Simp case OP_BLTZAL: 270178172Simp case OP_BLTZALL: 271178172Simp case OP_BGEZAL: 272178172Simp case OP_BGEZALL: 273178172Simp ityp = IT_CALL; 274178172Simp break; 275178172Simp } 276178172Simp break; 277178172Simp 278178172Simp case OP_JAL: 279178172Simp ityp = IT_CALL; 280178172Simp break; 281178172Simp 282178172Simp case OP_J: 283178172Simp case OP_BEQ: 284178172Simp case OP_BEQL: 285178172Simp case OP_BNE: 286178172Simp case OP_BNEL: 287178172Simp case OP_BLEZ: 288178172Simp case OP_BLEZL: 289178172Simp case OP_BGTZ: 290178172Simp case OP_BGTZL: 291178172Simp ityp = IT_BRANCH; 292178172Simp break; 293178172Simp 294178172Simp case OP_COP1: 295178172Simp switch (inst.RType.rs) { 296178172Simp case OP_BCx: 297178172Simp case OP_BCy: 298178172Simp ityp = IT_BRANCH; 299178172Simp break; 300178172Simp } 301178172Simp break; 302178172Simp 303178172Simp case OP_LB: 304178172Simp case OP_LH: 305178172Simp case OP_LW: 306178172Simp case OP_LD: 307178172Simp case OP_LBU: 308178172Simp case OP_LHU: 309178172Simp case OP_LWU: 310178172Simp case OP_LWC1: 311178172Simp ityp = IT_LOAD; 312178172Simp break; 313178172Simp 314178172Simp case OP_SB: 315178172Simp case OP_SH: 316178172Simp case OP_SW: 317178172Simp case OP_SD: 318178172Simp case OP_SWC1: 319178172Simp ityp = IT_STORE; 320178172Simp break; 321178172Simp } 322178172Simp return (ityp); 323178172Simp} 324178172Simp 325178172Simp/* 326178172Simp * Return the next pc if the given branch is taken. 327178172Simp * MachEmulateBranch() runs analysis for branch delay slot. 328178172Simp */ 329178172Simpdb_addr_t 330178172Simpbranch_taken(int inst, db_addr_t pc) 331178172Simp{ 332178172Simp db_addr_t ra; 333178172Simp register_t fpucsr; 334178172Simp 335178172Simp /* TBD: when is fsr set */ 336178172Simp fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0; 337178172Simp ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0); 338178172Simp return (ra); 339178172Simp} 340