Home | History | Annotate | Line # | Download | only in sparc64
      1 /*	$NetBSD: db_interface.c,v 1.140 2026/02/25 05:34:42 skrll Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1996-2002 Eduardo Horvath.  All rights reserved.
      5  * Mach Operating System
      6  * Copyright (c) 1991,1990 Carnegie Mellon University
      7  * All Rights Reserved.
      8  *
      9  * Permission to use, copy, modify and distribute this software and its
     10  * documentation is hereby granted, provided that both the copyright
     11  * notice and this permission notice appear in all copies of the
     12  * software, derivative works or modified versions, and any portions
     13  * thereof, and that both notices appear in supporting documentation.
     14  *
     15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     18  *
     19  * Carnegie Mellon requests users of this software to return to
     20  *
     21  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     22  *  School of Computer Science
     23  *  Carnegie Mellon University
     24  *  Pittsburgh PA 15213-3890
     25  *
     26  * any improvements or extensions that they make and grant Carnegie the
     27  * rights to redistribute these changes.
     28  *
     29  *	From: db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
     30  */
     31 
     32 /*
     33  * Interface to new debugger.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.140 2026/02/25 05:34:42 skrll Exp $");
     38 
     39 #ifdef _KERNEL_OPT
     40 #include "opt_ddb.h"
     41 #include "opt_multiprocessor.h"
     42 #endif
     43 
     44 #include <sys/param.h>
     45 #include <sys/proc.h>
     46 #include <sys/reboot.h>
     47 #include <sys/systm.h>
     48 #include <sys/atomic.h>
     49 
     50 #include <uvm/uvm.h>
     51 
     52 #include <dev/cons.h>
     53 
     54 #include <machine/db_machdep.h>
     55 #include <ddb/db_active.h>
     56 #include <ddb/db_command.h>
     57 #include <ddb/db_sym.h>
     58 #include <ddb/db_variables.h>
     59 #include <ddb/db_user.h>
     60 #include <ddb/db_extern.h>
     61 #include <ddb/db_access.h>
     62 #include <ddb/db_output.h>
     63 #include <ddb/db_interface.h>
     64 #include <ddb/ddbvar.h>
     65 
     66 #include <machine/instr.h>
     67 #include <machine/cpu.h>
     68 #ifdef _KERNEL
     69 #include <machine/promlib.h>
     70 #endif
     71 #include <machine/ctlreg.h>
     72 #include <machine/pmap.h>
     73 #include <machine/intr.h>
     74 #include <machine/vmparam.h>
     75 
     76 #ifdef _KERNEL
     77 #include "fb.h"
     78 #else
     79 #include <stddef.h>
     80 #include <stdbool.h>
     81 #endif
     82 
     83 extern struct traptrace {
     84 	unsigned short tl:3,	/* Trap level */
     85 		ns:4,		/* PCB nsaved */
     86 		tt:9;		/* Trap type */
     87 	unsigned short pid;	/* PID */
     88 	u_int tstate;		/* tstate */
     89 	u_int tsp;		/* sp */
     90 	u_int tpc;		/* pc */
     91 	u_int tfault;		/* MMU tag access */
     92 } trap_trace[], trap_trace_end[];
     93 
     94 void fill_ddb_regs_from_tf(struct trapframe64 *tf);
     95 void ddb_restore_state(void);
     96 bool ddb_running_on_this_cpu(void);
     97 
     98 #ifdef DDB
     99 int	db_active = 0;
    100 #endif
    101 
    102 extern char *trap_type[];
    103 
    104 void kdb_kbd_trap(struct trapframe64 *);
    105 void db_prom_cmd(db_expr_t, bool, db_expr_t, const char *);
    106 void db_lwp_cmd(db_expr_t, bool, db_expr_t, const char *);
    107 void db_proc_cmd(db_expr_t, bool, db_expr_t, const char *);
    108 void db_ctx_cmd(db_expr_t, bool, db_expr_t, const char *);
    109 void db_dump_pcb(db_expr_t, bool, db_expr_t, const char *);
    110 void db_dump_pv(db_expr_t, bool, db_expr_t, const char *);
    111 void db_setpcb(db_expr_t, bool, db_expr_t, const char *);
    112 void db_dump_dtlb(db_expr_t, bool, db_expr_t, const char *);
    113 void db_dump_itlb(db_expr_t, bool, db_expr_t, const char *);
    114 void db_dump_dtsb(db_expr_t, bool, db_expr_t, const char *);
    115 void db_dump_itsb(db_expr_t, bool, db_expr_t, const char *);
    116 void db_pmap_kernel(db_expr_t, bool, db_expr_t, const char *);
    117 void db_pload_cmd(db_expr_t, bool, db_expr_t, const char *);
    118 void db_pmap_cmd(db_expr_t, bool, db_expr_t, const char *);
    119 void db_traptrace(db_expr_t, bool, db_expr_t, const char *);
    120 void db_watch(db_expr_t, bool, db_expr_t, const char *);
    121 void db_pm_extract(db_expr_t, bool, db_expr_t, const char *);
    122 void db_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
    123 void db_sir_cmd(db_expr_t, bool, db_expr_t, const char *);
    124 
    125 #ifdef DDB
    126 static void db_dump_pmap(struct pmap *);
    127 static void db_print_trace_entry(struct traptrace *, int);
    128 
    129 #ifdef MULTIPROCESSOR
    130 
    131 #define NOCPU -1
    132 
    133 static int db_suspend_others(void);
    134 static void ddb_suspend(struct trapframe64 *);
    135 void db_resume_others(void);
    136 
    137 int ddb_cpu = NOCPU;
    138 
    139 bool
    140 ddb_running_on_this_cpu(void)
    141 {
    142 	return ddb_cpu == cpu_number();
    143 }
    144 
    145 static int
    146 db_suspend_others(void)
    147 {
    148 	int cpu_me = cpu_number();
    149 	bool win;
    150 
    151 	if (cpus == NULL)
    152 		return 1;
    153 
    154 	win = atomic_cas_32(&ddb_cpu, NOCPU, cpu_me) == (uint32_t)NOCPU;
    155 	if (win)
    156 		mp_pause_cpus();
    157 
    158 	return win;
    159 }
    160 
    161 void
    162 db_resume_others(void)
    163 {
    164 	int cpu_me = cpu_number();
    165 
    166 	if (atomic_cas_32(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
    167 		mp_resume_cpus();
    168 }
    169 
    170 static void
    171 ddb_suspend(struct trapframe64 *tf)
    172 {
    173 
    174 	sparc64_ipi_pause_thiscpu(tf);
    175 }
    176 #endif /* MULTIPROCESSOR */
    177 
    178 /*
    179  * Received keyboard interrupt sequence.
    180  */
    181 void
    182 kdb_kbd_trap(struct trapframe64 *tf)
    183 {
    184 	if (db_active == 0 /* && (boothowto & RB_KDB) */) {
    185 		printf("\n\nkernel: keyboard interrupt tf=%p\n", tf);
    186 		kdb_trap(-1, tf);
    187 	}
    188 }
    189 
    190 void
    191 fill_ddb_regs_from_tf(struct trapframe64 *tf)
    192 {
    193 	extern int savetstate(struct trapstate *);
    194 
    195 #ifdef MULTIPROCESSOR
    196 	static db_regs_t ddbregs[CPUSET_MAXNUMCPU];
    197 
    198 	curcpu()->ci_ddb_regs = &ddbregs[cpu_number()];
    199 #else
    200 	static db_regs_t ddbregs;
    201 
    202 	curcpu()->ci_ddb_regs = &ddbregs;
    203 #endif
    204 
    205 	DDB_REGS->db_tf = *tf;
    206 #ifdef __arch64__
    207 	DDB_REGS->db_fr = *(struct frame64 *)(uintptr_t)tf->tf_out[6];
    208 #else
    209     {
    210 	struct frame32 *tf32 = (struct frame32 *)(uintptr_t)tf->tf_out[6];
    211 	int i;
    212 
    213 	for (i = 0; i < 8; i++)
    214 		DDB_REGS->db_fr.fr_local[i] = (uint32_t)tf32->fr_local[i];
    215 	for (i = 0; i < 6; i++)
    216 		DDB_REGS->db_fr.fr_arg[i] = (uint32_t)tf32->fr_arg[i];
    217 	DDB_REGS->db_fr.fr_fp = tf32->fr_fp;
    218 	DDB_REGS->db_fr.fr_pc = tf32->fr_pc;
    219     }
    220 #endif
    221 
    222 	if (fplwp) {
    223 		savefpstate(fplwp->l_md.md_fpstate);
    224 		DDB_REGS->db_fpstate = *fplwp->l_md.md_fpstate;
    225 		loadfpstate(fplwp->l_md.md_fpstate);
    226 	}
    227 	/* We should do a proper copyin and xlate 64-bit stack frames, but... */
    228 /*	if (tf->tf_tstate & TSTATE_PRIV) { .. } */
    229 
    230 #if 0
    231 	/* make sure this is not causing ddb problems. */
    232 	if (tf->tf_out[6] & 1) {
    233 		if ((unsigned)(tf->tf_out[6] + BIAS) > (unsigned)KERNBASE)
    234 			DDB_REGS->db_fr = *(struct frame64 *)(tf->tf_out[6] + BIAS);
    235 		else
    236 			copyin((void *)(tf->tf_out[6] + BIAS), &DDB_REGS->db_fr, sizeof(struct frame64));
    237 	} else {
    238 		struct frame32 tfr;
    239 		int i;
    240 
    241 		/* First get a local copy of the frame32 */
    242 		if ((unsigned)(tf->tf_out[6]) > (unsigned)KERNBASE)
    243 			tfr = *(struct frame32 *)tf->tf_out[6];
    244 		else
    245 			copyin((void *)(tf->tf_out[6]), &tfr, sizeof(struct frame32));
    246 		/* Now copy each field from the 32-bit value to the 64-bit value */
    247 		for (i=0; i<8; i++)
    248 			DDB_REGS->db_fr.fr_local[i] = tfr.fr_local[i];
    249 		for (i=0; i<6; i++)
    250 			DDB_REGS->db_fr.fr_arg[i] = tfr.fr_arg[i];
    251 		DDB_REGS->db_fr.fr_fp = (long)tfr.fr_fp;
    252 		DDB_REGS->db_fr.fr_pc = tfr.fr_pc;
    253 	}
    254 #else
    255 	int i;
    256 	for (i=0; i<8; i++)
    257 	  DDB_REGS->db_fr.fr_local[i] = tf->tf_local[i];
    258 	for (i=0; i<6; i++)
    259 	  DDB_REGS->db_fr.fr_arg[i] = tf->tf_in[i];
    260 	/* XXX tp and pc are missing */
    261 #endif
    262 	DDB_REGS->db_tl = savetstate(&DDB_REGS->db_ts[0]);
    263 }
    264 
    265 void
    266 ddb_restore_state(void)
    267 {
    268 	extern void restoretstate(int, struct trapstate *);
    269 
    270 	restoretstate(DDB_REGS->db_tl, &DDB_REGS->db_ts[0]);
    271 	if (fplwp) {
    272 		*fplwp->l_md.md_fpstate = DDB_REGS->db_fpstate;
    273 		loadfpstate(fplwp->l_md.md_fpstate);
    274 	}
    275 }
    276 
    277 /*
    278  *  kdb_trap - field a TRACE or BPT trap
    279  */
    280 int
    281 kdb_trap(int type, struct trapframe64 *tf)
    282 {
    283 	int s;
    284 	extern int trap_trace_dis;
    285 	extern int doing_shutdown;
    286 
    287 	trap_trace_dis++;
    288 	doing_shutdown++;
    289 #if NFB > 0
    290 	fb_unblank();
    291 #endif
    292 	switch (type) {
    293 	case T_BREAKPOINT:	/* breakpoint */
    294 		break;
    295 	case -1:		/* keyboard interrupt */
    296 		printf("kdb tf=%p\n", tf);
    297 		break;
    298 	default:
    299 		if (!db_onpanic && db_recover==0)
    300 			return (0);
    301 
    302 		printf("kernel trap %x: %s\n", type, trap_type[type & 0x1ff]);
    303 		if (db_recover != 0) {
    304 			prom_abort();
    305 			db_error("Faulted in DDB; continuing...\n");
    306 			prom_abort();
    307 			/*NOTREACHED*/
    308 		}
    309 		db_recover = (label_t *)1;
    310 	}
    311 
    312 	/* Should switch to kdb`s own stack here. */
    313 	write_all_windows();
    314 
    315 #if defined(MULTIPROCESSOR)
    316 	if (!db_suspend_others()) {
    317 		ddb_suspend(tf);
    318 		return 1;
    319 	}
    320 #endif
    321 
    322 	/* Initialise local dbregs storage from trap frame */
    323 	fill_ddb_regs_from_tf(tf);
    324 
    325 	s = splhigh();
    326 	db_active++;
    327 	cnpollc(true);
    328 	/* Need to do spl stuff till cnpollc works */
    329 	db_dump_ts(0, 0, 0, 0);
    330 	db_trap(type, 0/*code*/);
    331 	ddb_restore_state();
    332 	cnpollc(false);
    333 	db_active--;
    334 
    335 	splx(s);
    336 
    337 	*tf = DDB_REGS->db_tf;
    338 	curcpu()->ci_ddb_regs = NULL;
    339 
    340 	trap_trace_dis--;
    341 	doing_shutdown--;
    342 
    343 #if defined(MULTIPROCESSOR)
    344 	db_resume_others();
    345 #endif
    346 
    347 	return (1);
    348 }
    349 #endif	/* DDB */
    350 
    351 #ifdef _KERNEL
    352 /*
    353  * Read bytes from kernel address space for debugger.
    354  */
    355 void
    356 db_read_bytes(db_addr_t addr, size_t size, char *data)
    357 {
    358 	char *src;
    359 
    360 	src = (char *)(uintptr_t)addr;
    361 	while (size-- > 0) {
    362 		*data++ = probeget((paddr_t)(u_long)src++, ASI_P, 1);
    363 	}
    364 }
    365 
    366 
    367 /*
    368  * Write bytes to kernel address space for debugger.
    369  */
    370 void
    371 db_write_bytes(db_addr_t addr, size_t size, const char *data)
    372 {
    373 	char *dst;
    374 	extern paddr_t pmap_kextract(vaddr_t va);
    375 	extern vaddr_t ektext;
    376 
    377 	dst = (char *)(uintptr_t)addr;
    378 	while (size-- > 0) {
    379 		if ((dst >= (char *)VM_MIN_KERNEL_ADDRESS) &&
    380 			 (dst < (char *)ektext))
    381 			/* Read Only mapping -- need to do a bypass access */
    382 			stba(pmap_kextract((vaddr_t)dst), ASI_PHYS_CACHED, *data);
    383 		else
    384 			*dst = *data;
    385 		dst++, data++;
    386 	}
    387 
    388 }
    389 #endif
    390 
    391 #ifdef DDB
    392 void
    393 Debugger(void)
    394 {
    395 	/* We use the breakpoint to trap into DDB */
    396 	__asm("ta 1; nop");
    397 }
    398 
    399 void
    400 db_prom_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    401 {
    402 	prom_abort();
    403 }
    404 
    405 /*
    406  * Dump the [ID]TLB's.
    407  *
    408  * Spitfire has 64 entry TLBs for instruction and data.
    409  *
    410  * Cheetah has 5 TLBs in total:
    411  *	instruction tlbs - it16, it128 -- 16 and 128 entry TLBs
    412  *	data tlbs - dt16, dt512_0, dt512_1 -- 16, and 2*512 entry TLBs
    413  *
    414  * The TLB chosen is chosen depending on the values in bits 16/17,
    415  * and the address is the index shifted 3 bits left.
    416  *
    417  * These are in db_tlb_access.S:
    418  *	void print_dtlb(size_t tlbsize, int tlbmask)
    419  *	void print_itlb(size_t tlbsize, int tlbmask)
    420  */
    421 
    422 void
    423 db_dump_dtlb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    424 {
    425 	extern void print_dtlb(size_t /*tlbsize*/, int /*tlbmask*/);
    426 
    427 	if (CPU_IS_USIII_UP()) {
    428 		print_dtlb(TLB_SIZE_CHEETAH_D16, TLB_CHEETAH_D16);
    429 		db_printf("DT512_0:\n");
    430 		print_dtlb(TLB_SIZE_CHEETAH_D512_0, TLB_CHEETAH_D512_0);
    431 		db_printf("DT512_1:\n");
    432 		print_dtlb(TLB_SIZE_CHEETAH_D512_1, TLB_CHEETAH_D512_1);
    433 	} else
    434 		print_dtlb(TLB_SIZE_SPITFIRE, 0);
    435 }
    436 
    437 void
    438 db_dump_itlb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    439 {
    440 	extern void print_itlb(size_t /*tlbsize*/, int /*tlbmask*/);
    441 
    442 	if (CPU_IS_USIII_UP()) {
    443 		print_itlb(TLB_SIZE_CHEETAH_I16, TLB_CHEETAH_I16);
    444 		db_printf("IT128:\n");
    445 		print_itlb(TLB_SIZE_CHEETAH_I128, TLB_CHEETAH_I128);
    446 	} else
    447 		print_itlb(TLB_SIZE_SPITFIRE, 0);
    448 }
    449 
    450 void
    451 db_pload_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    452 {
    453 	static paddr_t oldaddr = -1;
    454 	int asi = ASI_PHYS_CACHED;
    455 
    456 	if (!have_addr) {
    457 		addr = oldaddr;
    458 	}
    459 	if (addr == -1) {
    460 		db_printf("no address\n");
    461 		return;
    462 	}
    463 	addr &= ~0x7; /* align */
    464 	{
    465 		register char c;
    466 		register const char *cp = modif;
    467 		while ((c = *cp++) != 0)
    468 			if (c == 'u')
    469 				asi = ASI_AIUS;
    470 	}
    471 	while (count--) {
    472 		if (db_print_position() == 0) {
    473 			/* Always print the address. */
    474 			db_printf("%16.16lx:\t", (long)addr);
    475 		}
    476 		oldaddr=addr;
    477 		db_printf("%8.8lx\n", (long)ldxa(addr, asi));
    478 		addr += 8;
    479 		if (db_print_position() != 0)
    480 			db_end_line();
    481 	}
    482 }
    483 
    484 /* XXX no locking; shouldn't matter */
    485 int64_t pseg_get_real(struct pmap *, vaddr_t);
    486 
    487 void
    488 db_dump_pmap(struct pmap *pm)
    489 {
    490 	/* print all valid pages in the kernel pmap */
    491 	unsigned long long i, j, k, data0, data1;
    492 	paddr_t *pdir, *ptbl;
    493 
    494 	for (i = 0; i < STSZ; i++) {
    495 		pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED);
    496 		if (!pdir) {
    497 			continue;
    498 		}
    499 		db_printf("pdir %lld at %lx:\n", i, (long)pdir);
    500 		for (k = 0; k < PDSZ; k++) {
    501 			ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED);
    502 			if (!ptbl) {
    503 				continue;
    504 			}
    505 			db_printf("\tptable %lld:%lld at %lx:\n", i, k, (long)ptbl);
    506 			for (j = 0; j < PTSZ; j++) {
    507 				data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
    508 				j++;
    509 				data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
    510 				if (!data0 && !data1) {
    511 					continue;
    512 				}
    513 				db_printf("%016llx: %016llx\t",
    514 					  (i << STSHIFT) | (k << PDSHIFT) | ((j - 1) << PTSHIFT),
    515 					  data0);
    516 				db_printf("%016llx: %016llx\n",
    517 					  (i << STSHIFT) | (k << PDSHIFT) | (j << PTSHIFT),
    518 					  data1);
    519 			}
    520 		}
    521 	}
    522 }
    523 
    524 void
    525 db_pmap_kernel(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    526 {
    527 	int i, j, full = 0;
    528 	uint64_t data;
    529 
    530 	{
    531 		register char c;
    532 		register const char *cp = modif;
    533 		while ((c = *cp++) != 0)
    534 			if (c == 'f')
    535 				full = 1;
    536 	}
    537 	if (have_addr) {
    538 		/* lookup an entry for this VA */
    539 
    540 		if ((data = pseg_get_real(pmap_kernel(), (vaddr_t)addr))) {
    541 			db_printf("pmap_kernel(%p)->pm_segs[%lx][%lx][%lx]=>%qx\n",
    542 				  (void *)(uintptr_t)addr, (u_long)va_to_seg(addr),
    543 				  (u_long)va_to_dir(addr), (u_long)va_to_pte(addr),
    544 				  (unsigned long long)data);
    545 		} else {
    546 			db_printf("No mapping for %p\n", (void *)(uintptr_t)addr);
    547 		}
    548 		return;
    549 	}
    550 
    551 	db_printf("pmap_kernel(%p) psegs %p phys %llx\n",
    552 		  pmap_kernel(), pmap_kernel()->pm_segs,
    553 		  (unsigned long long)pmap_kernel()->pm_physaddr);
    554 	if (full) {
    555 		db_dump_pmap(pmap_kernel());
    556 	} else {
    557 		for (j=i=0; i<STSZ; i++) {
    558 			long seg = (long)ldxa((vaddr_t)pmap_kernel()->pm_segs[i], ASI_PHYS_CACHED);
    559 			if (seg)
    560 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
    561 		}
    562 	}
    563 }
    564 
    565 void
    566 db_pm_extract(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    567 {
    568 	if (have_addr) {
    569 		paddr_t pa;
    570 
    571 		if (pmap_extract(pmap_kernel(), addr, &pa))
    572 			db_printf("pa = %llx\n", (long long)pa);
    573 		else
    574 			db_printf("%p not found\n", (void *)(uintptr_t)addr);
    575 	} else
    576 		db_printf("pmap_extract: no address\n");
    577 }
    578 
    579 void
    580 db_pmap_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    581 {
    582 	struct pmap* pm=NULL;
    583 	int i, j=0, full = 0;
    584 
    585 	{
    586 		register char c;
    587 		register const char *cp = modif;
    588 		if (modif)
    589 			while ((c = *cp++) != 0)
    590 				if (c == 'f')
    591 					full = 1;
    592 	}
    593 	if (curlwp && curlwp->l_proc->p_vmspace)
    594 		pm = curlwp->l_proc->p_vmspace->vm_map.pmap;
    595 	if (have_addr)
    596 		pm = (struct pmap*)(uintptr_t)addr;
    597 
    598 	db_printf("pmap %p: ctx %x refs %d physaddr %llx psegs %p\n",
    599 		pm, pmap_ctx(pm), pm->pm_refs,
    600 		(unsigned long long)pm->pm_physaddr, pm->pm_segs);
    601 
    602 	if (full) {
    603 		db_dump_pmap(pm);
    604 	} else {
    605 		for (i=0; i<STSZ; i++) {
    606 			long seg = (long)ldxa((vaddr_t)pmap_kernel()->pm_segs[i], ASI_PHYS_CACHED);
    607 			if (seg)
    608 				db_printf("seg %d => %lx%c", i, seg, (j++%4)?'\t':'\n');
    609 		}
    610 	}
    611 }
    612 
    613 #define TSBENTS (512 << tsbsize)
    614 extern pte_t *tsb_dmmu, *tsb_immu;
    615 extern int tsbsize;
    616 
    617 void db_dump_tsb_common(pte_t *);
    618 
    619 void
    620 db_dump_dtsb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    621 {
    622 
    623 	db_printf("DTSB:\n");
    624 	db_dump_tsb_common(curcpu()->ci_tsb_dmmu);
    625 }
    626 
    627 void
    628 db_dump_itsb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    629 {
    630 
    631 	db_printf("ITSB:\n");
    632 	db_dump_tsb_common(curcpu()->ci_tsb_immu);
    633 }
    634 
    635 void
    636 db_dump_tsb_common(pte_t *tsb)
    637 {
    638 	uint64_t tag, data;
    639 	int i;
    640 
    641 	for (i = 0; i < TSBENTS; i++) {
    642 		tag = tsb[i].tag;
    643 		data = tsb[i].data;
    644 		db_printf("%4d:%4d:%08x %08x:%08x ", i,
    645 			  (int)((tag & TSB_TAG_G) ? -1 : TSB_TAG_CTX(tag)),
    646 			  (int)((i << 13) | TSB_TAG_VA(tag)),
    647 			  (int)(data >> 32), (int)data);
    648 		i++;
    649 		tag = tsb[i].tag;
    650 		data = tsb[i].data;
    651 		db_printf("%4d:%4d:%08x %08x:%08x\n", i,
    652 			  (int)((tag & TSB_TAG_G) ? -1 : TSB_TAG_CTX(tag)),
    653 			  (int)((i << 13) | TSB_TAG_VA(tag)),
    654 			  (int)(data >> 32), (int)data);
    655 	}
    656 }
    657 
    658 void db_page_cmd(db_expr_t, bool, db_expr_t, const char *);
    659 void
    660 db_page_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    661 {
    662 
    663 	if (!have_addr) {
    664 		db_printf("Need paddr for page\n");
    665 		return;
    666 	}
    667 
    668 	db_printf("pa %llx pg %p\n", (unsigned long long)addr,
    669 	    PHYS_TO_VM_PAGE(addr));
    670 }
    671 
    672 void
    673 db_lwp_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    674 {
    675 	struct lwp *l;
    676 
    677 	l = curlwp;
    678 	if (have_addr)
    679 		l = (struct lwp*)(uintptr_t)addr;
    680 	if (l == NULL) {
    681 		db_printf("no current lwp\n");
    682 		return;
    683 	}
    684 	db_printf("lwp %p: lid %d\n", l, l->l_lid);
    685 	db_printf("wchan:%p pri:%d epri:%d tf:%p\n",
    686 		  l->l_wchan, l->l_priority, lwp_eprio(l), l->l_md.md_tf);
    687 	db_printf("pcb: %p fpstate: %p\n", lwp_getpcb(l),
    688 		l->l_md.md_fpstate);
    689 	return;
    690 }
    691 
    692 void
    693 db_proc_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    694 {
    695 	struct proc *p = NULL;
    696 
    697 	if (curlwp)
    698 		p = curlwp->l_proc;
    699 	if (have_addr)
    700 		p = (struct proc*)(uintptr_t)addr;
    701 	if (p == NULL) {
    702 		db_printf("no current process\n");
    703 		return;
    704 	}
    705 	db_printf("process %p:", p);
    706 	db_printf("pid:%d vmspace:%p pmap:%p ctx:%x\n",
    707 		  p->p_pid, p->p_vmspace, p->p_vmspace->vm_map.pmap,
    708 		  pmap_ctx(p->p_vmspace->vm_map.pmap));
    709 	db_printf("maxsaddr:%p ssiz:%dpg or %llxB\n",
    710 		  p->p_vmspace->vm_maxsaddr, p->p_vmspace->vm_ssize,
    711 		  (unsigned long long)ctob(p->p_vmspace->vm_ssize));
    712 	db_printf("profile timer: %" PRId64 " sec %ld nsec\n",
    713 		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_sec,
    714 		  p->p_stats->p_timer[ITIMER_PROF].it_value.tv_nsec);
    715 	return;
    716 }
    717 
    718 void
    719 db_ctx_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    720 {
    721 	struct proc *p;
    722 	struct lwp *l;
    723 	struct pcb *pcb;
    724 
    725 	/* XXX LOCKING XXX */
    726 	LIST_FOREACH(p, &allproc, p_list) {
    727 		if (p->p_stat) {
    728 			db_printf("process %p:", p);
    729 			db_printf("pid:%d pmap:%p ctx:%x\n",
    730 				p->p_pid, p->p_vmspace->vm_map.pmap,
    731 				pmap_ctx(p->p_vmspace->vm_map.pmap));
    732 			LIST_FOREACH(l, &p->p_lwps, l_sibling) {
    733 				pcb = lwp_getpcb(l);
    734 				db_printf("\tlwp %p: lid:%d tf:%p fpstate %p "
    735 					"lastcall:%s\n",
    736 					l, l->l_lid, l->l_md.md_tf, l->l_md.md_fpstate,
    737 					(pcb->lastcall) ?
    738 					pcb->lastcall : "Null");
    739 			}
    740 		}
    741 	}
    742 	return;
    743 }
    744 
    745 void
    746 db_dump_pcb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    747 {
    748 	struct pcb *pcb;
    749 	int i;
    750 
    751 	pcb = curpcb;
    752 	if (have_addr)
    753 		pcb = (struct pcb*)(uintptr_t)addr;
    754 
    755 	db_printf("pcb@%p sp:%p pc:%p cwp:%d pil:%d nsaved:%x onfault:%p\nlastcall:%s\nfull windows:\n",
    756 		  pcb, (void *)(long)pcb->pcb_sp, (void *)(long)pcb->pcb_pc, pcb->pcb_cwp,
    757 		  pcb->pcb_pil, pcb->pcb_nsaved, (void *)pcb->pcb_onfault,
    758 		  (pcb->lastcall)?pcb->lastcall:"Null");
    759 
    760 	for (i=0; i<pcb->pcb_nsaved; i++) {
    761 		db_printf("win %d: at %llx local, in\n", i,
    762 			  (unsigned long long)pcb->pcb_rw[i+1].rw_in[6]);
    763 		db_printf("%16llx %16llx %16llx %16llx\n",
    764 			  (unsigned long long)pcb->pcb_rw[i].rw_local[0],
    765 			  (unsigned long long)pcb->pcb_rw[i].rw_local[1],
    766 			  (unsigned long long)pcb->pcb_rw[i].rw_local[2],
    767 			  (unsigned long long)pcb->pcb_rw[i].rw_local[3]);
    768 		db_printf("%16llx %16llx %16llx %16llx\n",
    769 			  (unsigned long long)pcb->pcb_rw[i].rw_local[4],
    770 			  (unsigned long long)pcb->pcb_rw[i].rw_local[5],
    771 			  (unsigned long long)pcb->pcb_rw[i].rw_local[6],
    772 			  (unsigned long long)pcb->pcb_rw[i].rw_local[7]);
    773 		db_printf("%16llx %16llx %16llx %16llx\n",
    774 			  (unsigned long long)pcb->pcb_rw[i].rw_in[0],
    775 			  (unsigned long long)pcb->pcb_rw[i].rw_in[1],
    776 			  (unsigned long long)pcb->pcb_rw[i].rw_in[2],
    777 			  (unsigned long long)pcb->pcb_rw[i].rw_in[3]);
    778 		db_printf("%16llx %16llx %16llx %16llx\n",
    779 			  (unsigned long long)pcb->pcb_rw[i].rw_in[4],
    780 			  (unsigned long long)pcb->pcb_rw[i].rw_in[5],
    781 			  (unsigned long long)pcb->pcb_rw[i].rw_in[6],
    782 			  (unsigned long long)pcb->pcb_rw[i].rw_in[7]);
    783 	}
    784 }
    785 
    786 
    787 void
    788 db_setpcb(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    789 {
    790 	struct proc *p;
    791 	int ctx;
    792 
    793 	if (!have_addr) {
    794 		db_printf("What PID do you want to map in?\n");
    795 		return;
    796 	}
    797 
    798 	LIST_FOREACH(p, &allproc, p_list) {
    799 		if (p->p_stat && p->p_pid == addr) {
    800 			if (p->p_vmspace->vm_map.pmap == pmap_kernel()) {
    801 				db_printf("PID %ld has a kernel context.\n",
    802 				    (long)addr);
    803 				return;
    804 			}
    805 			ctx = pmap_ctx(p->p_vmspace->vm_map.pmap);
    806 			if (ctx < 0) {
    807 				ctx = -ctx;
    808 				pmap_ctx(p->p_vmspace->vm_map.pmap) = ctx;
    809 			} else if (ctx == 0) {
    810 				pmap_activate_pmap(p->p_vmspace->vm_map.pmap);
    811 				ctx = pmap_ctx(p->p_vmspace->vm_map.pmap);
    812 			}
    813 			if (ctx > 0) {
    814 				if (CPU_IS_USIII_UP())
    815 					switchtoctx_usiii(ctx);
    816 				else
    817 					switchtoctx_us(ctx);
    818 				return;
    819 			}
    820 			db_printf("could not activate pmap for PID %ld.\n",
    821 			    (long)addr);
    822 			return;
    823 		}
    824 	}
    825 	db_printf("PID %ld not found.\n", (long)addr);
    826 }
    827 
    828 static void
    829 db_print_trace_entry(struct traptrace *te, int i)
    830 {
    831 	db_printf("%d:%d p:%d tt:%x:%llx:%llx %llx:%llx ", i,
    832 		  (int)te->tl, (int)te->pid,
    833 		  (int)te->tt, (unsigned long long)te->tstate,
    834 		  (unsigned long long)te->tfault, (unsigned long long)te->tsp,
    835 		  (unsigned long long)te->tpc);
    836 	db_printsym((u_long)te->tpc, DB_STGY_PROC, db_printf);
    837 	db_printf(": ");
    838 	if ((te->tpc && !(te->tpc&0x3)) &&
    839 	    curlwp &&
    840 	    (curproc->p_pid == te->pid)) {
    841 		db_disasm((u_long)te->tpc, 0);
    842 	} else db_printf("\n");
    843 }
    844 
    845 void
    846 db_traptrace(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    847 {
    848 	int i, start = 0, full = 0, reverse = 0;
    849 	struct traptrace *end;
    850 
    851 	start = 0;
    852 	end = &trap_trace_end[0];
    853 
    854 	{
    855 		register char c;
    856 		register const char *cp = modif;
    857 		if (modif)
    858 			while ((c = *cp++) != 0) {
    859 				if (c == 'f')
    860 					full = 1;
    861 				if (c == 'r')
    862 					reverse = 1;
    863 			}
    864 	}
    865 
    866 	if (have_addr) {
    867 		start = addr / (sizeof (struct traptrace));
    868 		if (&trap_trace[start] > &trap_trace_end[0]) {
    869 			db_printf("Address out of range.\n");
    870 			return;
    871 		}
    872 		if (!full) end =  &trap_trace[start+1];
    873 	}
    874 
    875 	db_printf("#:tl p:pid tt:tt:tstate:tfault sp:pc\n");
    876 	if (reverse) {
    877 		if (full && start)
    878 			for (i=start; --i;) {
    879 				db_print_trace_entry(&trap_trace[i], i);
    880 			}
    881 		i = (end - &trap_trace[0]);
    882 		while(--i > start) {
    883 			db_print_trace_entry(&trap_trace[i], i);
    884 		}
    885 	} else {
    886 		for (i=start; &trap_trace[i] < end ; i++) {
    887 			db_print_trace_entry(&trap_trace[i], i);
    888 		}
    889 		if (full && start)
    890 			for (i=0; i < start ; i++) {
    891 				db_print_trace_entry(&trap_trace[i], i);
    892 			}
    893 	}
    894 }
    895 
    896 /*
    897  * Use physical or virtual watchpoint registers -- ugh
    898  *
    899  * UltraSPARC I and II have both a virtual and physical
    900  * watchpoint register.  They are controlled by the LSU
    901  * control register.
    902  */
    903 void
    904 db_watch(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    905 {
    906 	int phys = 0;
    907 	int read = 0;
    908 	int width = 8; /* Default to 8 bytes */
    909 	int64_t mask = 0xff;
    910 
    911 #define	WATCH_VR	(1L<<22)
    912 #define	WATCH_VW	(1L<<21)
    913 #define	WATCH_PR	(1L<<24)
    914 #define	WATCH_PW	(1L<<23)
    915 #define	WATCH_PM_SHIFT	33
    916 #define	WATCH_PM	(((uint64_t)0xffffL)<<WATCH_PM_SHIFT)
    917 #define	WATCH_VM_SHIFT	25
    918 #define	WATCH_VM	(((uint64_t)0xffffL)<<WATCH_VM_SHIFT)
    919 
    920 	{
    921 		register char c;
    922 		register const char *cp = modif;
    923 		if (modif)
    924 			while ((c = *cp++) != 0)
    925 				switch (c) {
    926 				case 'p':
    927 					/* Physical watchpoint */
    928 					phys = 1;
    929 					break;
    930 				case 'r':
    931 					/* Trap reads too */
    932 					read = 1;
    933 					break;
    934 				case 'b':
    935 					width = 1;
    936 					mask = 0x1 << (addr & 0x7);
    937 					break;
    938 				case 'h':
    939 					width = 2;
    940 					mask = 0x3 << (addr & 0x6);
    941 					break;
    942 				case 'l':
    943 					width = 4;
    944 					mask = 0x7 << (addr & 0x4);
    945 					break;
    946 				case 'L':
    947 					width = 8;
    948 					mask = 0xf;
    949 					break;
    950 				default:
    951 					break;
    952 				}
    953 	}
    954 
    955 	if (have_addr) {
    956 		/* turn on the watchpoint */
    957 		int64_t tmp = ldxa(0, ASI_MCCR);
    958 
    959 		if (phys) {
    960 			tmp &= ~WATCH_PM;
    961 			tmp |= WATCH_PW | (mask << WATCH_PM_SHIFT);
    962 			if (read) tmp |= WATCH_PR;
    963 
    964 			stxa(PHYSICAL_WATCHPOINT, ASI_DMMU, addr);
    965 			db_printf("Setting physical watchpoint to %llx-%llx\n",
    966 				(long long)addr, (long long)addr + width);
    967 		} else {
    968 			tmp &= ~WATCH_VM;
    969 			tmp |= WATCH_VW | (mask << WATCH_VM_SHIFT);
    970 			if (read) tmp |= WATCH_VR;
    971 
    972 			stxa(VIRTUAL_WATCHPOINT, ASI_DMMU, addr);
    973 			db_printf("Setting virtual watchpoint to %llx-%llx\n",
    974 				(long long)addr, (long long)addr + width);
    975 		}
    976 		stxa(0, ASI_MCCR, tmp);
    977 	} else {
    978 		/* turn off the watchpoint */
    979 		int64_t tmp = ldxa(0, ASI_MCCR);
    980 		if (phys) {
    981 			tmp &= ~(WATCH_PM|WATCH_PR|WATCH_PW);
    982 			db_printf("Disabling physical watchpoint\n");
    983 		} else {
    984 			tmp &= ~(WATCH_VM|WATCH_VR|WATCH_VW);
    985 			db_printf("Disabling virtual watchpoint\n");
    986 		}
    987 		stxa(0, ASI_MCCR, tmp);
    988 	}
    989 }
    990 
    991 /* XXX this belongs in cpu.c */
    992 static void cpu_debug_dump(void);
    993 static void
    994 cpu_debug_dump(void)
    995 {
    996 	struct cpu_info *ci;
    997 
    998 	for (ci = cpus; ci; ci = ci->ci_next) {
    999 		db_printf("cpu%d: self 0x%08lx lwp 0x%08lx pcb 0x%08lx "
   1000 			  "fplwp 0x%08lx\n", ci->ci_index, (u_long)ci->ci_self,
   1001 			  (u_long)ci->ci_curlwp, (u_long)ci->ci_cpcb,
   1002 			  (u_long)ci->ci_fplwp);
   1003 	}
   1004 }
   1005 
   1006 void
   1007 db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
   1008 {
   1009 #ifdef MULTIPROCESSOR
   1010 	struct cpu_info *ci;
   1011 #endif
   1012 
   1013 	if (!have_addr) {
   1014 		cpu_debug_dump();
   1015 		return;
   1016 	}
   1017 #ifdef MULTIPROCESSOR
   1018 	for (ci = cpus; ci != NULL; ci = ci->ci_next)
   1019 		if (ci->ci_index == addr)
   1020 			break;
   1021 	if (ci == NULL) {
   1022 		db_printf("CPU %ld not configured\n", (long)addr);
   1023 		return;
   1024 	}
   1025 	if (ci != curcpu()) {
   1026 		if (!mp_cpu_is_paused(ci->ci_index)) {
   1027 			db_printf("CPU %ld not paused\n", (long)addr);
   1028 			return;
   1029 		}
   1030 		/* no locking needed - all other cpus are paused */
   1031 		ddb_cpu = ci->ci_index;
   1032 		mp_resume_cpu(ddb_cpu);
   1033 		sparc64_do_pause();
   1034 	}
   1035 #endif
   1036 }
   1037 
   1038 void
   1039 db_sir_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
   1040 {
   1041 
   1042 	__asm("sir; nop");
   1043 }
   1044 
   1045 const struct db_command db_machine_command_table[] = {
   1046 	{ DDB_ADD_CMD("ctx",	db_ctx_cmd,	0,
   1047 	  "Print process MMU context information", NULL,NULL) },
   1048 #ifdef MULTIPROCESSOR
   1049 	{ DDB_ADD_CMD("cpu",	db_cpu_cmd,	0,
   1050 	  "switch to another cpu", "cpu-no", NULL) },
   1051 #endif
   1052 	{ DDB_ADD_CMD("dtlb",	db_dump_dtlb,	0,
   1053 	  "Display data translation look-aside buffer context information.",
   1054 	  NULL,NULL) },
   1055 	{ DDB_ADD_CMD("itlb",	db_dump_itlb,	0,
   1056 	  "Display instruction translation look-aside buffer information.",
   1057 	  NULL,NULL) },
   1058 	{ DDB_ADD_CMD("dtsb",	db_dump_dtsb,	0,
   1059 	  "Display data translation storage buffer information.", NULL,NULL) },
   1060 	{ DDB_ADD_CMD("itsb",	db_dump_itsb,	0,
   1061 	  "Display instruction translation storage buffer information.",
   1062 	  NULL,NULL) },
   1063 	{ DDB_ADD_CMD("extract",	db_pm_extract,	0,
   1064 	  "Extract the physical address from the kernel pmap.",
   1065 	  "address", "   address:\tvirtual address to look up") },
   1066 	{ DDB_ADD_CMD("fpstate",	db_dump_fpstate,0,
   1067 	  "Dump the FPU state." ,NULL,NULL) },
   1068 	{ DDB_ADD_CMD("kmap",	db_pmap_kernel,	0,
   1069 	  "Display information about mappings in the kernel pmap.",
   1070 	  "[/f] [address]",
   1071 	  "   address:\tdisplay the mapping for this virtual address\n"
   1072 	  "   /f:\tif no address is given, display a full dump of the pmap") },
   1073 	{ DDB_ADD_CMD("lwp",	db_lwp_cmd,	0,
   1074 	  "Display a struct lwp",
   1075 	  "[address]",
   1076 	  "   address:\tthe struct lwp to print (curlwp otherwise)") },
   1077 	{ DDB_ADD_CMD("pcb",	db_dump_pcb,	0,
   1078 	  "Display information about a struct pcb",
   1079 	  "[address]",
   1080 	  "   address:\tthe struct pcb to print (curpcb otherwise)") },
   1081 	{ DDB_ADD_CMD("pctx",	db_setpcb,	0,
   1082 	  "Attempt to change MMU process context","pid",
   1083 	  "   pid:\tthe process id to switch the MMU context to") },
   1084 	{ DDB_ADD_CMD("page",	db_page_cmd,	0,
   1085 	  "Display the address of a struct vm_page given a physical address",
   1086 	   "pa", "   pa:\tphysical address to look up") },
   1087 	{ DDB_ADD_CMD("phys",	db_pload_cmd,	0,
   1088 	   "Display physical memory.", "[address][,count]",
   1089 	   "   address:\tphysical address to start (8 byte aligned)\n"
   1090 	   "   count:\tnumber of bytes to display") },
   1091 	{ DDB_ADD_CMD("pmap",	db_pmap_cmd,	0,
   1092 	   "Display the pmap", "[/f] [pm_addr]",
   1093 	   "   pm_addr:\tAddress of struct pmap to display\n"
   1094 	   "   /f:\tdo a full dump of the pmap") },
   1095 	{ DDB_ADD_CMD("proc",	db_proc_cmd,	0,
   1096 	  "Display some information about a process",
   1097 	  "[addr]","   addr:\tstruct proc address (curproc otherwise)") },
   1098 	{ DDB_ADD_CMD("prom",	db_prom_cmd,	0,
   1099 	  "Enter the OFW PROM.", NULL,NULL) },
   1100 	{ DDB_ADD_CMD("pv",		db_dump_pv,	0,
   1101 	  "Display a struct pv for a physical address",
   1102 	  "pa", "   pa:\tphysical address of a managed page") },
   1103 	{ DDB_ADD_CMD("sir",	db_sir_cmd,	0,
   1104 	  "do a Software Initiated Reset (entering PROM)", NULL,NULL) },
   1105 	{ DDB_ADD_CMD("stack",		db_dump_stack,	0,
   1106 	  "Dump the window stack.", "[/u] [addr]",
   1107 	  "   addr:\tstart address of dump (current stack otherwise)\n"
   1108 	  "   /u:\tcontinue trace into userland") },
   1109 	{ DDB_ADD_CMD("tf",		db_dump_trap,	0,
   1110 	  "Display full trap frame state.",
   1111 	  "[/u] [addr]",
   1112 	  "   addr:\tdisplay this trap frame (current kernel frame otherwise)\n"
   1113 	  "   /u:\tdisplay the current userland trap frame") },
   1114 	{ DDB_ADD_CMD("ts",		db_dump_ts,	0,
   1115 	  "Display trap state.", NULL,NULL) },
   1116 	{ DDB_ADD_CMD("traptrace",	db_traptrace,	0,
   1117 	  "Display or set trap trace information.",
   1118 	  "[/fr] [addr]",
   1119 	  "   addr:\tstart address of trace\n"
   1120 	  "   /f:\tdisplay full information\n"
   1121 	  "   /r:\treverse the trace order") },
   1122 	{ DDB_ADD_CMD("watch",	db_watch,	0,
   1123 	  "Set or clear a physical or virtual hardware watchpoint.",
   1124 	  "[/prbhlL] [addr]",
   1125 	  "   addr:\tset the breakpoint (clear watchpoint if not present)\n"
   1126 	  "   /p:\taddress is physical\n"
   1127 	  "   /r:\ttrap on reads too (otherwise only write access)\n"
   1128 	  "   /b:\t8 bit\n"
   1129 	  "   /h:\t16 bit\n"
   1130 	  "   /l:\t32 bit\n"
   1131 	  "   /L:\t64 bit") },
   1132 	{ DDB_ADD_CMD("window",	db_dump_window,	0,
   1133 	  "Print register window information",
   1134 	  "[no]", "   no:\tstack frame number (0, i.e. top, if missing)") },
   1135 	{ DDB_END_CMD },
   1136 };
   1137 #endif	/* DDB */
   1138 
   1139 /*
   1140  * support for SOFTWARE_SSTEP:
   1141  * return the next pc if the given branch is taken.
   1142  *
   1143  * note: in the case of conditional branches with annul,
   1144  * this actually returns the next pc in the "not taken" path,
   1145  * but in that case next_instr_address() will return the
   1146  * next pc in the "taken" path.  so even tho the breakpoints
   1147  * are backwards, everything will still work, and the logic is
   1148  * much simpler this way.
   1149  */
   1150 db_addr_t
   1151 db_branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
   1152 {
   1153     union instr insn;
   1154     db_addr_t npc;
   1155 
   1156     npc = DDB_REGS->db_tf.tf_npc;
   1157 
   1158     insn.i_int = inst;
   1159 
   1160     /*
   1161      * if this is not an annulled conditional branch, the next pc is "npc".
   1162      */
   1163 
   1164     if (insn.i_any.i_op != IOP_OP2 || insn.i_branch.i_annul != 1)
   1165 	return npc;
   1166 
   1167     switch (insn.i_op2.i_op2) {
   1168       case IOP2_Bicc:
   1169       case IOP2_FBfcc:
   1170       case IOP2_BPcc:
   1171       case IOP2_FBPfcc:
   1172       case IOP2_CBccc:
   1173 	/* branch on some condition-code */
   1174 	switch (insn.i_branch.i_cond)
   1175 	{
   1176 	  case Icc_A: /* always */
   1177 	    return pc + ((inst << 10) >> 8);
   1178 
   1179 	  default: /* all other conditions */
   1180 	    return npc + 4;
   1181 	}
   1182 
   1183       case IOP2_BPr:
   1184 	/* branch on register, always conditional */
   1185 	return npc + 4;
   1186 
   1187       default:
   1188 	/* not a branch */
   1189 	printf("branch_taken() on non-branch");
   1190 	return pc;
   1191     }
   1192 }
   1193 
   1194 bool
   1195 db_inst_branch(int inst)
   1196 {
   1197     union instr insn;
   1198 
   1199     insn.i_int = inst;
   1200 
   1201     if (insn.i_any.i_op != IOP_OP2)
   1202 	return false;
   1203 
   1204     switch (insn.i_op2.i_op2) {
   1205       case IOP2_BPcc:
   1206       case IOP2_Bicc:
   1207       case IOP2_BPr:
   1208       case IOP2_FBPfcc:
   1209       case IOP2_FBfcc:
   1210       case IOP2_CBccc:
   1211 	return true;
   1212 
   1213       default:
   1214 	return false;
   1215     }
   1216 }
   1217 
   1218 
   1219 bool
   1220 db_inst_call(int inst)
   1221 {
   1222     union instr insn;
   1223 
   1224     insn.i_int = inst;
   1225 
   1226     switch (insn.i_any.i_op) {
   1227       case IOP_CALL:
   1228 	return true;
   1229 
   1230       case IOP_reg:
   1231 	return (insn.i_op3.i_op3 == IOP3_JMPL) && !db_inst_return(inst);
   1232 
   1233       default:
   1234 	return false;
   1235     }
   1236 }
   1237 
   1238 
   1239 bool
   1240 db_inst_unconditional_flow_transfer(int inst)
   1241 {
   1242     union instr insn;
   1243 
   1244     insn.i_int = inst;
   1245 
   1246     if (db_inst_call(inst))
   1247 	return true;
   1248 
   1249     if (insn.i_any.i_op != IOP_OP2)
   1250 	return false;
   1251 
   1252     switch (insn.i_op2.i_op2)
   1253     {
   1254       case IOP2_BPcc:
   1255       case IOP2_Bicc:
   1256       case IOP2_FBPfcc:
   1257       case IOP2_FBfcc:
   1258       case IOP2_CBccc:
   1259 	return insn.i_branch.i_cond == Icc_A;
   1260 
   1261       default:
   1262 	return false;
   1263     }
   1264 }
   1265 
   1266 
   1267 bool
   1268 db_inst_return(int inst)
   1269 {
   1270     return (inst == I_JMPLri(I_G0, I_O7, 8) ||		/* ret */
   1271 	    inst == I_JMPLri(I_G0, I_I7, 8));		/* retl */
   1272 }
   1273 
   1274 bool
   1275 db_inst_trap_return(int inst)
   1276 {
   1277     union instr insn;
   1278 
   1279     insn.i_int = inst;
   1280 
   1281     return (insn.i_any.i_op == IOP_reg &&
   1282 	    insn.i_op3.i_op3 == IOP3_RETT);
   1283 }
   1284 
   1285 
   1286 int
   1287 db_inst_load(int inst)
   1288 {
   1289     union instr insn;
   1290 
   1291     insn.i_int = inst;
   1292 
   1293     if (insn.i_any.i_op != IOP_mem)
   1294 	return 0;
   1295 
   1296     switch (insn.i_op3.i_op3) {
   1297       case IOP3_LD:
   1298       case IOP3_LDUB:
   1299       case IOP3_LDUH:
   1300       case IOP3_LDD:
   1301       case IOP3_LDSB:
   1302       case IOP3_LDSH:
   1303       case IOP3_LDSTUB:
   1304       case IOP3_SWAP:
   1305       case IOP3_LDA:
   1306       case IOP3_LDUBA:
   1307       case IOP3_LDUHA:
   1308       case IOP3_LDDA:
   1309       case IOP3_LDSBA:
   1310       case IOP3_LDSHA:
   1311       case IOP3_LDSTUBA:
   1312       case IOP3_SWAPA:
   1313       case IOP3_LDF:
   1314       case IOP3_LDFSR:
   1315       case IOP3_LDDF:
   1316       case IOP3_LFC:
   1317       case IOP3_LDCSR:
   1318       case IOP3_LDDC:
   1319 	return 1;
   1320 
   1321       default:
   1322 	return 0;
   1323     }
   1324 }
   1325 
   1326 int
   1327 db_inst_store(int inst)
   1328 {
   1329     union instr insn;
   1330 
   1331     insn.i_int = inst;
   1332 
   1333     if (insn.i_any.i_op != IOP_mem)
   1334 	return 0;
   1335 
   1336     switch (insn.i_op3.i_op3) {
   1337       case IOP3_ST:
   1338       case IOP3_STB:
   1339       case IOP3_STH:
   1340       case IOP3_STD:
   1341       case IOP3_LDSTUB:
   1342       case IOP3_SWAP:
   1343       case IOP3_STA:
   1344       case IOP3_STBA:
   1345       case IOP3_STHA:
   1346       case IOP3_STDA:
   1347       case IOP3_LDSTUBA:
   1348       case IOP3_SWAPA:
   1349       case IOP3_STF:
   1350       case IOP3_STFSR:
   1351       case IOP3_STDFQ:
   1352       case IOP3_STDF:
   1353       case IOP3_STC:
   1354       case IOP3_STCSR:
   1355       case IOP3_STDCQ:
   1356       case IOP3_STDC:
   1357 	return 1;
   1358 
   1359       default:
   1360 	return 0;
   1361     }
   1362 }
   1363