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