112657Skvn/* $OpenBSD: db_machdep.c,v 1.2 1998/09/15 10:50:13 pefo Exp $ */ 212657Skvn 312657Skvn/*- 412657Skvn * Copyright (c) 1998 Per Fogelstrom, Opsycon AB 512657Skvn * 612657Skvn * Redistribution and use in source and binary forms, with or without 712657Skvn * modification, are permitted provided that the following conditions 812657Skvn * are met: 912657Skvn * 1. Redistributions of source code must retain the above copyright 1012657Skvn * notice, this list of conditions and the following disclaimer. 1112657Skvn * 2. Redistributions in binary form must reproduce the above copyright 1212657Skvn * notice, this list of conditions and the following disclaimer in the 1312657Skvn * documentation and/or other materials provided with the distribution. 1412657Skvn * 3. All advertising materials mentioning features or use of this software 1512657Skvn * must display the following acknowledgement: 1612657Skvn * This product includes software developed under OpenBSD by 1712657Skvn * Per Fogelstrom, Opsycon AB, Sweden. 1812657Skvn * 4. The name of the author may not be used to endorse or promote products 1912657Skvn * derived from this software without specific prior written permission. 2012657Skvn * 2112657Skvn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 2212657Skvn * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 2312657Skvn * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2412657Skvn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 2512657Skvn * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2612657Skvn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2712657Skvn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2813264Siveresov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2912657Skvn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3012657Skvn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3113482Siveresov * SUCH DAMAGE. 3213482Siveresov * 3313482Siveresov * JNPR: db_interface.c,v 1.6.2.1 2007/08/29 12:24:49 girish 3413482Siveresov */ 3513482Siveresov 3612657Skvn#include <sys/cdefs.h> 3712657Skvn__FBSDID("$FreeBSD: stable/11/sys/mips/mips/db_interface.c 327195 2017-12-26 10:07:17Z kib $"); 3813264Siveresov 3913264Siveresov#include <sys/types.h> 4013264Siveresov#include <sys/param.h> 4113264Siveresov#include <sys/systm.h> 4212657Skvn#include <sys/cons.h> 4313482Siveresov#include <sys/lock.h> 4412657Skvn#include <vm/vm.h> 4512657Skvn#include <vm/vm_object.h> 4612657Skvn#include <vm/vm_page.h> 4712657Skvn#include <vm/pmap.h> 4812657Skvn#include <vm/vm_map.h> 4912657Skvn#include <sys/user.h> 5012657Skvn#include <sys/proc.h> 5112657Skvn#include <sys/reboot.h> 5212657Skvn 5312657Skvn#include <machine/cache.h> 5412657Skvn#include <machine/db_machdep.h> 5512657Skvn#include <machine/mips_opcode.h> 5612657Skvn#include <machine/vmparam.h> 5712657Skvn#include <machine/md_var.h> 5812657Skvn#include <machine/setjmp.h> 5912657Skvn 6012657Skvn#include <ddb/ddb.h> 6112657Skvn#include <ddb/db_sym.h> 6212657Skvn#include <ddb/db_access.h> 6312657Skvn#include <ddb/db_output.h> 6412657Skvn#include <ddb/db_variables.h> 6512657Skvn#include <sys/kdb.h> 6612657Skvn 6712657Skvnstatic db_varfcn_t db_frame; 6812657Skvn 6912657Skvn#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) 7012657Skvnstruct db_variable db_regs[] = { 7112657Skvn { "at", DB_OFFSET(ast), db_frame }, 7212657Skvn { "v0", DB_OFFSET(v0), db_frame }, 7313264Siveresov { "v1", DB_OFFSET(v1), db_frame }, 7412657Skvn { "a0", DB_OFFSET(a0), db_frame }, 7512657Skvn { "a1", DB_OFFSET(a1), db_frame }, 7612657Skvn { "a2", DB_OFFSET(a2), db_frame }, 7712657Skvn { "a3", DB_OFFSET(a3), db_frame }, 7812657Skvn#if defined(__mips_n32) || defined(__mips_n64) 7912657Skvn { "a4", DB_OFFSET(a4), db_frame }, 8012657Skvn { "a5", DB_OFFSET(a5), db_frame }, 8112657Skvn { "a6", DB_OFFSET(a6), db_frame }, 8212657Skvn { "a7", DB_OFFSET(a7), db_frame }, 8312657Skvn { "t0", DB_OFFSET(t0), db_frame }, 8413264Siveresov { "t1", DB_OFFSET(t1), db_frame }, 8512657Skvn { "t2", DB_OFFSET(t2), db_frame }, 8612657Skvn { "t3", DB_OFFSET(t3), db_frame }, 8713264Siveresov#else 8812657Skvn { "t0", DB_OFFSET(t0), db_frame }, 8912657Skvn { "t1", DB_OFFSET(t1), db_frame }, 9013264Siveresov { "t2", DB_OFFSET(t2), db_frame }, 9112657Skvn { "t3", DB_OFFSET(t3), db_frame }, 9212657Skvn { "t4", DB_OFFSET(t4), db_frame }, 9312657Skvn { "t5", DB_OFFSET(t5), db_frame }, 9412657Skvn { "t6", DB_OFFSET(t6), db_frame }, 9512657Skvn { "t7", DB_OFFSET(t7), db_frame }, 9612657Skvn#endif 9712657Skvn { "s0", DB_OFFSET(s0), db_frame }, 9813264Siveresov { "s1", DB_OFFSET(s1), db_frame }, 9912657Skvn { "s2", DB_OFFSET(s2), db_frame }, 10012657Skvn { "s3", DB_OFFSET(s3), db_frame }, 10112657Skvn { "s4", DB_OFFSET(s4), db_frame }, 10212657Skvn { "s5", DB_OFFSET(s5), db_frame }, 10312657Skvn { "s6", DB_OFFSET(s6), db_frame }, 10412657Skvn { "s7", DB_OFFSET(s7), db_frame }, 10512657Skvn { "t8", DB_OFFSET(t8), db_frame }, 10612657Skvn { "t9", DB_OFFSET(t9), db_frame }, 10712657Skvn { "k0", DB_OFFSET(k0), db_frame }, 10812657Skvn { "k1", DB_OFFSET(k1), db_frame }, 10912657Skvn { "gp", DB_OFFSET(gp), db_frame }, 11012657Skvn { "sp", DB_OFFSET(sp), db_frame }, 11112657Skvn { "s8", DB_OFFSET(s8), db_frame }, 11213264Siveresov { "ra", DB_OFFSET(ra), db_frame }, 11312657Skvn { "sr", DB_OFFSET(sr), db_frame }, 11413482Siveresov { "lo", DB_OFFSET(mullo), db_frame }, 11513482Siveresov { "hi", DB_OFFSET(mulhi), db_frame }, 11612657Skvn { "bad", DB_OFFSET(badvaddr), db_frame }, 11713482Siveresov { "cs", DB_OFFSET(cause), db_frame }, 11813482Siveresov { "pc", DB_OFFSET(pc), db_frame }, 11913482Siveresov}; 12012657Skvnstruct db_variable *db_eregs = db_regs + nitems(db_regs); 12112657Skvn 12212657Skvnint (*do_db_log_stack_trace_cmd)(char *); 12313482Siveresov 12412657Skvnstatic int 12512657Skvndb_frame(struct db_variable *vp, db_expr_t *valuep, int op) 12612657Skvn{ 12712657Skvn register_t *reg; 12812657Skvn 12912657Skvn if (kdb_frame == NULL) 13012657Skvn return (0); 13112657Skvn 13212657Skvn reg = (register_t *)((uintptr_t)kdb_frame + (size_t)(intptr_t)vp->valuep); 13312657Skvn if (op == DB_VAR_GET) 13412657Skvn *valuep = *reg; 13512657Skvn else 13612657Skvn *reg = *valuep; 13712657Skvn return (1); 13812657Skvn} 13912657Skvn 14012657Skvnint 14112657Skvndb_read_bytes(vm_offset_t addr, size_t size, char *data) 14212657Skvn{ 14312657Skvn jmp_buf jb; 14412657Skvn void *prev_jb; 14513482Siveresov int ret; 14612657Skvn 14712657Skvn prev_jb = kdb_jmpbuf(jb); 14812657Skvn ret = setjmp(jb); 14912657Skvn if (ret == 0) { 15012657Skvn /* 15112657Skvn * 'addr' could be a memory-mapped I/O address. Try to 15212657Skvn * do atomic load/store in unit of size requested. 15312657Skvn * size == 8 is only atomic on 64bit or n32 kernel. 15412657Skvn */ 15512657Skvn if ((size == 2 || size == 4 || size == 8) && 15612657Skvn ((addr & (size -1)) == 0) && 15712657Skvn (((vm_offset_t)data & (size -1)) == 0)) { 15812657Skvn switch (size) { 15912657Skvn case 2: 16012657Skvn *(uint16_t *)data = *(uint16_t *)addr; 16113482Siveresov break; 16213482Siveresov case 4: 16313482Siveresov *(uint32_t *)data = *(uint32_t *)addr; 16413482Siveresov break; 16512657Skvn case 8: 16612657Skvn *(uint64_t *)data = *(uint64_t *)addr; 16712657Skvn break; 16812657Skvn } 16912657Skvn } else { 17012657Skvn char *src; 171 172 src = (char *)addr; 173 while (size-- > 0) 174 *data++ = *src++; 175 } 176 } 177 178 (void)kdb_jmpbuf(prev_jb); 179 return (ret); 180} 181 182int 183db_write_bytes(vm_offset_t addr, size_t size, char *data) 184{ 185 int ret; 186 jmp_buf jb; 187 void *prev_jb; 188 189 prev_jb = kdb_jmpbuf(jb); 190 ret = setjmp(jb); 191 192 if (ret == 0) { 193 /* 194 * 'addr' could be a memory-mapped I/O address. Try to 195 * do atomic load/store in unit of size requested. 196 * size == 8 is only atomic on 64bit or n32 kernel. 197 */ 198 if ((size == 2 || size == 4 || size == 8) && 199 ((addr & (size -1)) == 0) && 200 (((vm_offset_t)data & (size -1)) == 0)) { 201 switch (size) { 202 case 2: 203 *(uint16_t *)addr = *(uint16_t *)data; 204 break; 205 case 4: 206 *(uint32_t *)addr = *(uint32_t *)data; 207 break; 208 case 8: 209 *(uint64_t *)addr = *(uint64_t *)data; 210 break; 211 } 212 } else { 213 char *dst; 214 size_t len = size; 215 216 dst = (char *)addr; 217 while (len-- > 0) 218 *dst++ = *data++; 219 } 220 221 mips_icache_sync_range((db_addr_t) addr, size); 222 mips_dcache_wbinv_range((db_addr_t) addr, size); 223 } 224 (void)kdb_jmpbuf(prev_jb); 225 return (ret); 226} 227 228/* 229 * To do a single step ddb needs to know the next address 230 * that we will get to. It means that we need to find out 231 * both the address for a branch taken and for not taken, NOT! :-) 232 * MipsEmulateBranch will do the job to find out _exactly_ which 233 * address we will end up at so the 'dual bp' method is not 234 * requiered. 235 */ 236db_addr_t 237next_instr_address(db_addr_t pc, boolean_t bd) 238{ 239 db_addr_t next; 240 241 next = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, 0, 0); 242 return (next); 243} 244 245 246/* 247 * Decode instruction and figure out type. 248 */ 249int 250db_inst_type(int ins) 251{ 252 InstFmt inst; 253 int ityp = 0; 254 255 inst.word = ins; 256 switch ((int)inst.JType.op) { 257 case OP_SPECIAL: 258 switch ((int)inst.RType.func) { 259 case OP_JR: 260 ityp = IT_BRANCH; 261 break; 262 case OP_JALR: 263 case OP_SYSCALL: 264 ityp = IT_CALL; 265 break; 266 } 267 break; 268 269 case OP_BCOND: 270 switch ((int)inst.IType.rt) { 271 case OP_BLTZ: 272 case OP_BLTZL: 273 case OP_BGEZ: 274 case OP_BGEZL: 275 ityp = IT_BRANCH; 276 break; 277 278 case OP_BLTZAL: 279 case OP_BLTZALL: 280 case OP_BGEZAL: 281 case OP_BGEZALL: 282 ityp = IT_CALL; 283 break; 284 } 285 break; 286 287 case OP_JAL: 288 ityp = IT_CALL; 289 break; 290 291 case OP_J: 292 case OP_BEQ: 293 case OP_BEQL: 294 case OP_BNE: 295 case OP_BNEL: 296 case OP_BLEZ: 297 case OP_BLEZL: 298 case OP_BGTZ: 299 case OP_BGTZL: 300 ityp = IT_BRANCH; 301 break; 302 303 case OP_COP1: 304 switch (inst.RType.rs) { 305 case OP_BCx: 306 case OP_BCy: 307 ityp = IT_BRANCH; 308 break; 309 } 310 break; 311 312 case OP_LB: 313 case OP_LH: 314 case OP_LW: 315 case OP_LD: 316 case OP_LBU: 317 case OP_LHU: 318 case OP_LWU: 319 case OP_LWC1: 320 ityp = IT_LOAD; 321 break; 322 323 case OP_SB: 324 case OP_SH: 325 case OP_SW: 326 case OP_SD: 327 case OP_SWC1: 328 ityp = IT_STORE; 329 break; 330 } 331 return (ityp); 332} 333 334/* 335 * Return the next pc if the given branch is taken. 336 * MachEmulateBranch() runs analysis for branch delay slot. 337 */ 338db_addr_t 339branch_taken(int inst, db_addr_t pc) 340{ 341 db_addr_t ra; 342 register_t fpucsr; 343 344 /* TBD: when is fsr set */ 345 fpucsr = (curthread) ? curthread->td_pcb->pcb_regs.fsr : 0; 346 ra = (db_addr_t)MipsEmulateBranch(kdb_frame, pc, fpucsr, 0); 347 return (ra); 348} 349