Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.43
      1  1.43       phx /*	$NetBSD: db_interface.c,v 1.43 2010/01/28 21:10:49 phx Exp $ */
      2   1.1  sakamoto /*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
      3  1.29     lukem 
      4  1.29     lukem #include <sys/cdefs.h>
      5  1.43       phx __KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.43 2010/01/28 21:10:49 phx Exp $");
      6   1.3  jonathan 
      7  1.10    simonb #define USERACC
      8  1.10    simonb 
      9   1.3  jonathan #include "opt_ddb.h"
     10  1.17       dbj #include "opt_kgdb.h"
     11  1.10    simonb #include "opt_ppcarch.h"
     12   1.1  sakamoto 
     13   1.1  sakamoto #include <sys/param.h>
     14   1.1  sakamoto #include <sys/proc.h>
     15   1.4    tsubai #include <sys/systm.h>
     16   1.6    kleink 
     17  1.11    simonb #include <dev/cons.h>
     18  1.11    simonb 
     19   1.7    tsubai #include <machine/db_machdep.h>
     20   1.7    tsubai #include <machine/frame.h>
     21  1.43       phx #include <powerpc/spr.h>
     22  1.43       phx #include <powerpc/cpu.h>
     23  1.43       phx #include <powerpc/bat.h>
     24  1.43       phx #include <powerpc/pte.h>
     25  1.43       phx 
     26  1.10    simonb #ifdef PPC_IBM4XX
     27  1.10    simonb #include <machine/tlb.h>
     28  1.10    simonb #include <uvm/uvm_extern.h>
     29  1.10    simonb #endif
     30   1.7    tsubai 
     31  1.17       dbj #ifdef DDB
     32   1.6    kleink #include <ddb/db_sym.h>
     33   1.6    kleink #include <ddb/db_command.h>
     34   1.6    kleink #include <ddb/db_extern.h>
     35   1.6    kleink #include <ddb/db_access.h>
     36  1.22       scw #include <ddb/db_lex.h>
     37   1.6    kleink #include <ddb/db_output.h>
     38   1.6    kleink #include <ddb/ddbvar.h>
     39  1.17       dbj #endif
     40  1.17       dbj 
     41  1.17       dbj #ifdef KGDB
     42  1.17       dbj #include <sys/kgdb.h>
     43  1.39   garbled #define db_printf printf
     44  1.17       dbj #endif
     45  1.17       dbj 
     46  1.17       dbj #include <dev/ofw/openfirm.h>
     47   1.1  sakamoto 
     48  1.11    simonb int	db_active = 0;
     49  1.11    simonb 
     50  1.19      matt db_regs_t ddb_regs;
     51   1.8    tsubai 
     52  1.10    simonb void ddb_trap(void);				/* Call into trap_subr.S */
     53  1.10    simonb int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
     54  1.43       phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
     55  1.43       phx static void db_show_bat(db_expr_t, bool, db_expr_t, const char *);
     56  1.43       phx static void db_show_mmu(db_expr_t, bool, db_expr_t, const char *);
     57  1.43       phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
     58  1.10    simonb #ifdef PPC_IBM4XX
     59  1.37      matt static void db_ppc4xx_ctx(db_expr_t, bool, db_expr_t, const char *);
     60  1.37      matt static void db_ppc4xx_pv(db_expr_t, bool, db_expr_t, const char *);
     61  1.37      matt static void db_ppc4xx_reset(db_expr_t, bool, db_expr_t, const char *);
     62  1.37      matt static void db_ppc4xx_tf(db_expr_t, bool, db_expr_t, const char *);
     63  1.37      matt static void db_ppc4xx_dumptlb(db_expr_t, bool, db_expr_t, const char *);
     64  1.37      matt static void db_ppc4xx_dcr(db_expr_t, bool, db_expr_t, const char *);
     65  1.22       scw static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
     66  1.22       scw static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
     67  1.10    simonb #ifdef USERACC
     68  1.37      matt static void db_ppc4xx_useracc(db_expr_t, bool, db_expr_t, const char *);
     69  1.10    simonb #endif
     70  1.10    simonb #endif /* PPC_IBM4XX */
     71   1.9    briggs 
     72  1.17       dbj #ifdef DDB
     73  1.43       phx const struct db_command db_machine_command_table[] = {
     74  1.43       phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
     75  1.43       phx 	{ DDB_ADD_CMD("bat",	db_show_bat,		0,
     76  1.43       phx 	  "Print BAT register translations", NULL,NULL) },
     77  1.43       phx 	{ DDB_ADD_CMD("mmu",	db_show_mmu,		0,
     78  1.43       phx 	  "Print MMU registers", NULL,NULL) },
     79  1.43       phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
     80  1.43       phx #ifdef PPC_IBM4XX
     81  1.43       phx 	{ DDB_ADD_CMD("ctx",	db_ppc4xx_ctx,		0,
     82  1.43       phx 	  "Print process MMU context information", NULL,NULL) },
     83  1.43       phx 	{ DDB_ADD_CMD("pv",	db_ppc4xx_pv,		0,
     84  1.43       phx 	  "Print PA->VA mapping information",
     85  1.43       phx 	  "address",
     86  1.43       phx 	  "   address:\tphysical address to look up") },
     87  1.43       phx 	{ DDB_ADD_CMD("reset",	db_ppc4xx_reset,	0,
     88  1.43       phx 	  "Reset the system ", NULL,NULL) },
     89  1.43       phx 	{ DDB_ADD_CMD("tf",	db_ppc4xx_tf,		0,
     90  1.43       phx 	  "Display the contents of the trapframe",
     91  1.43       phx 	  "address",
     92  1.43       phx 	  "   address:\tthe struct trapframe to print") },
     93  1.43       phx 	{ DDB_ADD_CMD("tlb",	db_ppc4xx_dumptlb,	0,
     94  1.43       phx 	  "Display instruction translation storage buffer information.",
     95  1.43       phx 	  NULL,NULL) },
     96  1.43       phx 	{ DDB_ADD_CMD("dcr",	db_ppc4xx_dcr,		CS_MORE|CS_SET_DOT,
     97  1.43       phx 	  "Set the DCR register",
     98  1.43       phx 	  "dcr",
     99  1.43       phx 	  "   dcr:\tNew DCR value (between 0x0 and 0x3ff)") },
    100  1.43       phx #ifdef USERACC
    101  1.43       phx 	{ DDB_ADD_CMD("user",	db_ppc4xx_useracc,	0,
    102  1.43       phx 	   "Display user memory.", "[address][,count]",
    103  1.43       phx 	   "   address:\tuserspace address to start\n"
    104  1.43       phx 	   "   count:\tnumber of bytes to display") },
    105  1.43       phx #endif
    106  1.43       phx #endif /* PPC_IBM4XX */
    107  1.43       phx 	{ DDB_ADD_CMD(NULL,	NULL,			0,
    108  1.43       phx 	  NULL,NULL,NULL) }
    109  1.43       phx };
    110  1.43       phx 
    111   1.1  sakamoto void
    112  1.31      matt cpu_Debugger(void)
    113   1.1  sakamoto {
    114   1.1  sakamoto 	ddb_trap();
    115   1.1  sakamoto }
    116  1.17       dbj #endif
    117   1.1  sakamoto 
    118   1.1  sakamoto int
    119  1.31      matt ddb_trap_glue(struct trapframe *frame)
    120   1.1  sakamoto {
    121  1.25   thorpej #ifdef PPC_IBM4XX
    122  1.25   thorpej 	if ((frame->srr1 & PSL_PR) == 0)
    123  1.25   thorpej 		return kdb_trap(frame->exc, frame);
    124  1.28      matt #else /* PPC_OEA */
    125  1.25   thorpej 	if ((frame->srr1 & PSL_PR) == 0 &&
    126  1.32      matt 	    (frame->exc == EXC_TRC ||
    127  1.32      matt 	     frame->exc == EXC_RUNMODETRC ||
    128  1.25   thorpej 	     (frame->exc == EXC_PGM && (frame->srr1 & 0x20000)) ||
    129  1.32      matt 	     frame->exc == EXC_BPT ||
    130  1.32      matt 	     frame->exc == EXC_DSI)) {
    131  1.17       dbj 		int type = frame->exc;
    132  1.17       dbj 		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
    133  1.17       dbj 			type = T_BREAKPOINT;
    134  1.17       dbj 		}
    135  1.17       dbj 		return kdb_trap(type, frame);
    136   1.1  sakamoto 	}
    137  1.25   thorpej #endif
    138   1.1  sakamoto 	return 0;
    139   1.8    tsubai }
    140   1.8    tsubai 
    141   1.8    tsubai int
    142  1.31      matt kdb_trap(int type, void *v)
    143   1.8    tsubai {
    144   1.8    tsubai 	struct trapframe *frame = v;
    145   1.8    tsubai 
    146  1.17       dbj #ifdef DDB
    147  1.30      matt 	if (db_recover != 0 && (type != -1 && type != T_BREAKPOINT)) {
    148  1.30      matt 		db_error("Faulted in DDB; continuing...\n");
    149  1.30      matt 		/* NOTREACHED */
    150   1.8    tsubai 	}
    151  1.17       dbj #endif
    152   1.8    tsubai 
    153   1.8    tsubai 	/* XXX Should switch to kdb's own stack here. */
    154   1.8    tsubai 
    155  1.12       wiz 	memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
    156   1.8    tsubai 	DDB_REGS->iar = frame->srr0;
    157   1.8    tsubai 	DDB_REGS->msr = frame->srr1;
    158  1.10    simonb 	DDB_REGS->lr = frame->lr;
    159  1.10    simonb 	DDB_REGS->ctr = frame->ctr;
    160  1.10    simonb 	DDB_REGS->cr = frame->cr;
    161  1.10    simonb 	DDB_REGS->xer = frame->xer;
    162  1.28      matt #ifdef PPC_OEA
    163  1.27      matt 	DDB_REGS->mq = frame->tf_xtra[TF_MQ];
    164  1.27      matt #endif
    165  1.16       dbj #ifdef PPC_IBM4XX
    166  1.27      matt 	DDB_REGS->dear = frame->dar;
    167  1.27      matt 	DDB_REGS->esr = frame->tf_xtra[TF_ESR];
    168  1.27      matt 	DDB_REGS->pid = frame->tf_xtra[TF_PID];
    169  1.10    simonb #endif
    170   1.8    tsubai 
    171  1.17       dbj #ifdef DDB
    172  1.11    simonb 	db_active++;
    173  1.11    simonb 	cnpollc(1);
    174  1.15       dbj 	db_trap(type, 0);
    175  1.11    simonb 	cnpollc(0);
    176  1.11    simonb 	db_active--;
    177  1.17       dbj #elif defined(KGDB)
    178  1.17       dbj 	if (!kgdb_trap(type, DDB_REGS))
    179  1.17       dbj 		return 0;
    180  1.17       dbj #endif
    181  1.17       dbj 
    182  1.17       dbj 	/* KGDB isn't smart about advancing PC if we
    183  1.17       dbj 	 * take a breakpoint trap after kgdb_active is set.
    184  1.17       dbj 	 * Therefore, we help out here.
    185  1.17       dbj 	 */
    186  1.17       dbj 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    187  1.17       dbj 		int bkpt;
    188  1.17       dbj 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    189  1.17       dbj 		if (bkpt== BKPT_INST) {
    190  1.17       dbj 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    191  1.17       dbj 		}
    192  1.17       dbj 	}
    193   1.8    tsubai 
    194  1.12       wiz 	memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    195   1.8    tsubai 	frame->srr0 = DDB_REGS->iar;
    196   1.8    tsubai 	frame->srr1 = DDB_REGS->msr;
    197  1.10    simonb 	frame->lr = DDB_REGS->lr;
    198  1.10    simonb 	frame->ctr = DDB_REGS->ctr;
    199  1.10    simonb 	frame->cr = DDB_REGS->cr;
    200  1.10    simonb 	frame->xer = DDB_REGS->xer;
    201  1.28      matt #ifdef PPC_OEA
    202  1.27      matt 	frame->tf_xtra[TF_MQ] = DDB_REGS->mq;
    203  1.27      matt #endif
    204  1.16       dbj #ifdef PPC_IBM4XX
    205  1.27      matt 	frame->dar = DDB_REGS->dear;
    206  1.27      matt 	frame->tf_xtra[TF_ESR] = DDB_REGS->esr;
    207  1.27      matt 	frame->tf_xtra[TF_PID] = DDB_REGS->pid;
    208  1.10    simonb #endif
    209   1.8    tsubai 
    210   1.8    tsubai 	return 1;
    211   1.1  sakamoto }
    212  1.10    simonb 
    213  1.43       phx #if defined (PPC_OEA) || defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE)
    214  1.43       phx static void
    215  1.43       phx print_battranslation(struct bat *bat, unsigned int blidx)
    216  1.43       phx {
    217  1.43       phx 	static const char *const batsizes[] = {
    218  1.43       phx 		"128kB",
    219  1.43       phx 		"256kB",
    220  1.43       phx 		"512kB",
    221  1.43       phx 		"1MB",
    222  1.43       phx 		"2MB",
    223  1.43       phx 		"4MB",
    224  1.43       phx 		"8MB",
    225  1.43       phx 		"16MB",
    226  1.43       phx 		"32MB",
    227  1.43       phx 		"64MB",
    228  1.43       phx 		"128MB",
    229  1.43       phx 		"256MB"
    230  1.43       phx 	};
    231  1.43       phx 	vsize_t len;
    232  1.43       phx 
    233  1.43       phx 	len = (0x20000L << blidx) - 1;
    234  1.43       phx 	db_printf("\t%08lx %08lx %5s: 0x%08lx..0x%08lx -> 0x%08lx physical\n",
    235  1.43       phx 	    bat->batu, bat->batl, batsizes[blidx], bat->batu & ~len,
    236  1.43       phx 	    (bat->batu & ~len) + len, bat->batl & ~len);
    237  1.43       phx }
    238  1.43       phx 
    239  1.43       phx static void
    240  1.43       phx print_batmodes(register_t super, register_t user, register_t pp)
    241  1.43       phx {
    242  1.43       phx 	static const char *const accessmodes[] = {
    243  1.43       phx 		"none",
    244  1.43       phx 		"ro soft",
    245  1.43       phx 		"read/write",
    246  1.43       phx 		"read only"
    247  1.43       phx 	};
    248  1.43       phx 
    249  1.43       phx 	db_printf("\tvalid: %c%c  access: %-10s  memory:",
    250  1.43       phx 	    super ? 'S' : '-', user ? 'U' : '-', accessmodes[pp]);
    251  1.43       phx }
    252  1.43       phx 
    253  1.43       phx static void
    254  1.43       phx print_wimg(register_t wimg)
    255  1.43       phx {
    256  1.43       phx 	if (wimg & BAT_W)
    257  1.43       phx 		db_printf(" wrthrough");
    258  1.43       phx 	if (wimg & BAT_I)
    259  1.43       phx 		db_printf(" nocache");
    260  1.43       phx 	if (wimg & BAT_M)
    261  1.43       phx 		db_printf(" coherent");
    262  1.43       phx 	if (wimg & BAT_G)
    263  1.43       phx 		db_printf(" guard");
    264  1.43       phx }
    265  1.43       phx 
    266  1.43       phx static void
    267  1.43       phx print_bat(struct bat *bat)
    268  1.43       phx {
    269  1.43       phx 	if ((bat->batu & BAT_V) == 0) {
    270  1.43       phx 		db_printf("\tdisabled\n\n");
    271  1.43       phx 		return;
    272  1.43       phx 	}
    273  1.43       phx 	print_battranslation(bat, 30 - __builtin_clz((bat->batu & BAT_BL)|2));
    274  1.43       phx 	print_batmodes(bat->batu & BAT_Vs, bat->batu & BAT_Vu,
    275  1.43       phx 	    bat->batl & BAT_PP);
    276  1.43       phx 	print_wimg(bat->batl & BAT_WIMG);
    277  1.43       phx 	db_printf("\n");
    278  1.43       phx }
    279  1.43       phx 
    280  1.43       phx #ifdef PPC_OEA601
    281  1.43       phx static void
    282  1.43       phx print_bat601(struct bat *bat)
    283  1.43       phx {
    284  1.43       phx 	if ((bat->batl & BAT601_V) == 0) {
    285  1.43       phx 		db_printf("\tdisabled\n\n");
    286  1.43       phx 		return;
    287  1.43       phx 	}
    288  1.43       phx 	print_battranslation(bat, 32 - __builtin_clz(bat->batl & BAT601_BSM));
    289  1.43       phx 	print_batmodes(bat->batu & BAT601_Ks, bat->batu & BAT601_Ku,
    290  1.43       phx 	    bat->batu & BAT601_PP);
    291  1.43       phx 	print_wimg(bat->batu & (BAT601_W | BAT601_I | BAT601_M));
    292  1.43       phx 	db_printf("\n");
    293  1.43       phx }
    294  1.43       phx #endif
    295  1.43       phx 
    296  1.43       phx static void
    297  1.43       phx db_show_bat(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    298  1.43       phx {
    299  1.43       phx 	struct bat ibat[4];
    300  1.43       phx 	struct bat dbat[4];
    301  1.43       phx 	unsigned int cpuvers;
    302  1.43       phx 	int i;
    303  1.43       phx 
    304  1.43       phx 	cpuvers = mfpvr() >> 16;
    305  1.43       phx 
    306  1.43       phx 	__asm volatile ("mfibatu %0,0" : "=r"(ibat[0].batu));
    307  1.43       phx 	__asm volatile ("mfibatl %0,0" : "=r"(ibat[0].batl));
    308  1.43       phx 	__asm volatile ("mfibatu %0,1" : "=r"(ibat[1].batu));
    309  1.43       phx 	__asm volatile ("mfibatl %0,1" : "=r"(ibat[1].batl));
    310  1.43       phx 	__asm volatile ("mfibatu %0,2" : "=r"(ibat[2].batu));
    311  1.43       phx 	__asm volatile ("mfibatl %0,2" : "=r"(ibat[2].batl));
    312  1.43       phx 	__asm volatile ("mfibatu %0,3" : "=r"(ibat[3].batu));
    313  1.43       phx 	__asm volatile ("mfibatl %0,3" : "=r"(ibat[3].batl));
    314  1.43       phx 
    315  1.43       phx 	if (cpuvers != MPC601) {
    316  1.43       phx 		/* The 601 has only four unified BATs */
    317  1.43       phx 		__asm volatile ("mfdbatu %0,0" : "=r"(dbat[0].batu));
    318  1.43       phx 		__asm volatile ("mfdbatl %0,0" : "=r"(dbat[0].batl));
    319  1.43       phx 		__asm volatile ("mfdbatu %0,1" : "=r"(dbat[1].batu));
    320  1.43       phx 		__asm volatile ("mfdbatl %0,1" : "=r"(dbat[1].batl));
    321  1.43       phx 		__asm volatile ("mfdbatu %0,2" : "=r"(dbat[2].batu));
    322  1.43       phx 		__asm volatile ("mfdbatl %0,2" : "=r"(dbat[2].batl));
    323  1.43       phx 		__asm volatile ("mfdbatu %0,3" : "=r"(dbat[3].batu));
    324  1.43       phx 		__asm volatile ("mfdbatl %0,3" : "=r"(dbat[3].batl));
    325  1.43       phx 	}
    326  1.43       phx 
    327  1.43       phx 	for (i = 0; i < 4; i++) {
    328  1.43       phx #ifdef PPC_OEA601
    329  1.43       phx 		if (cpuvers == MPC601) {
    330  1.43       phx 			db_printf("bat%d:", i);
    331  1.43       phx 			print_bat601(&ibat[i]);
    332  1.43       phx 		} else
    333  1.43       phx #endif
    334  1.43       phx 		{
    335  1.43       phx 			db_printf("ibat%d:", i);
    336  1.43       phx 			print_bat(&ibat[i]);
    337  1.43       phx 		}
    338  1.43       phx 	}
    339  1.43       phx 	if (cpuvers != MPC601) {
    340  1.43       phx 		for (i = 0; i < 4; i++) {
    341  1.43       phx 			db_printf("dbat%d:", i);
    342  1.43       phx 			print_bat(&dbat[i]);
    343  1.43       phx 		}
    344  1.43       phx 	}
    345  1.43       phx }
    346  1.43       phx 
    347  1.43       phx static void
    348  1.43       phx db_show_mmu(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    349  1.43       phx {
    350  1.43       phx 	paddr_t sdr1;
    351  1.43       phx #if !defined(PPC_OEA64) && !defined(PPC_OEA64_BRIDGE)
    352  1.43       phx 	register_t sr;
    353  1.43       phx 	vaddr_t saddr;
    354  1.43       phx 	int i;
    355  1.43       phx #endif
    356  1.43       phx 
    357  1.43       phx 	__asm volatile ("mfsdr1 %0" : "=r"(sdr1));
    358  1.43       phx 	db_printf("sdr1\t\t0x%08lx\n", sdr1);
    359  1.43       phx 
    360  1.43       phx #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE)
    361  1.43       phx 	__asm volatile ("mfasr %0" : "=r"(sdr1));
    362  1.43       phx 	db_printf("asr\t\t0x%08lx\n", sdr1);
    363  1.43       phx #else
    364  1.43       phx 	saddr = 0;
    365  1.43       phx 	for (i = 0; i<= 0xf; i++) {
    366  1.43       phx 		if ((i & 3) == 0)
    367  1.43       phx 			db_printf("sr%d-%d\t\t", i, i+3);
    368  1.43       phx 		__asm volatile ("mfsrin %0,%1" : "=r"(sr) : "r"(saddr));
    369  1.43       phx 		db_printf("0x%08lx   %c", sr, (i&3) == 3 ? '\n' : ' ');
    370  1.43       phx 		saddr += 1 << ADDR_SR_SHFT;
    371  1.43       phx 	}
    372  1.43       phx #endif
    373  1.43       phx }
    374  1.43       phx #endif /* PPC_OEA || PPC_OEA64 || PPC_OEA64_BRIDGE */
    375  1.43       phx 
    376  1.10    simonb #ifdef PPC_IBM4XX
    377  1.24       scw db_addr_t
    378  1.24       scw branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
    379  1.24       scw {
    380  1.24       scw 
    381  1.24       scw 	if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
    382  1.24       scw 		db_expr_t off;
    383  1.24       scw 		off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
    384  1.24       scw 		return (((inst & 0x2) ? 0 : pc) + off);
    385  1.24       scw 	}
    386  1.24       scw 
    387  1.24       scw 	if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
    388  1.24       scw 		db_expr_t off;
    389  1.24       scw 		off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
    390  1.24       scw 		return (((inst & 0x2) ? 0 : pc) + off);
    391  1.24       scw 	}
    392  1.24       scw 
    393  1.24       scw 	if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
    394  1.24       scw 		return (regs->lr);
    395  1.24       scw 
    396  1.24       scw 	if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
    397  1.24       scw 		return (regs->ctr);
    398  1.24       scw 
    399  1.24       scw 	db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
    400  1.24       scw 	    inst);
    401  1.24       scw 	return (0);
    402  1.24       scw }
    403  1.24       scw 
    404  1.43       phx 
    405  1.42       phx #ifdef DDB
    406  1.10    simonb static void
    407  1.37      matt db_ppc4xx_ctx(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    408  1.10    simonb {
    409  1.10    simonb 	struct proc *p;
    410  1.10    simonb 
    411  1.10    simonb 	/* XXX LOCKING XXX */
    412  1.10    simonb 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    413  1.10    simonb 		if (p->p_stat) {
    414  1.10    simonb 			db_printf("process %p:", p);
    415  1.10    simonb 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    416  1.10    simonb 				p->p_pid, p->p_vmspace->vm_map.pmap,
    417  1.10    simonb 				p->p_vmspace->vm_map.pmap->pm_ctx,
    418  1.10    simonb 				p->p_comm);
    419  1.10    simonb 		}
    420  1.10    simonb 	}
    421  1.10    simonb 	return;
    422  1.10    simonb }
    423  1.10    simonb 
    424  1.10    simonb static void
    425  1.37      matt db_ppc4xx_pv(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    426  1.10    simonb {
    427  1.10    simonb 	struct pv_entry {
    428  1.10    simonb 		struct pv_entry *pv_next;	/* Linked list of mappings */
    429  1.10    simonb 		vaddr_t pv_va;			/* virtual address of mapping */
    430  1.10    simonb 		struct pmap *pv_pm;
    431  1.10    simonb 	};
    432  1.10    simonb 	struct pv_entry *pa_to_pv(paddr_t);
    433  1.10    simonb 	struct pv_entry *pv;
    434  1.10    simonb 
    435  1.10    simonb 	if (!have_addr) {
    436  1.10    simonb 		db_printf("pv: <pa>\n");
    437  1.10    simonb 		return;
    438  1.10    simonb 	}
    439  1.10    simonb 	pv = pa_to_pv(addr);
    440  1.10    simonb 	db_printf("pv at %p\n", pv);
    441  1.10    simonb 	while (pv && pv->pv_pm) {
    442  1.10    simonb 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    443  1.10    simonb 			(void *)pv->pv_va, pv->pv_pm);
    444  1.10    simonb 		pv = pv->pv_next;
    445  1.10    simonb 	}
    446  1.10    simonb }
    447  1.10    simonb 
    448  1.10    simonb static void
    449  1.37      matt db_ppc4xx_reset(db_expr_t addr, bool have_addr, db_expr_t count,
    450  1.34       scw     const char *modif)
    451  1.10    simonb {
    452  1.10    simonb 	printf("Reseting...\n");
    453  1.10    simonb 	ppc4xx_reset();
    454  1.10    simonb }
    455  1.10    simonb 
    456  1.10    simonb static void
    457  1.37      matt db_ppc4xx_tf(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
    458  1.10    simonb {
    459  1.10    simonb 	struct trapframe *f;
    460  1.10    simonb 
    461  1.10    simonb 
    462  1.10    simonb 	if (have_addr) {
    463  1.10    simonb 		f = (struct trapframe *)addr;
    464  1.10    simonb 
    465  1.27      matt 		db_printf("r0-r3:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    466  1.10    simonb 			f->fixreg[0], f->fixreg[1],
    467  1.10    simonb 			f->fixreg[2], f->fixreg[3]);
    468  1.27      matt 		db_printf("r4-r7:  \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    469  1.10    simonb 			f->fixreg[4], f->fixreg[5],
    470  1.10    simonb 			f->fixreg[6], f->fixreg[7]);
    471  1.27      matt 		db_printf("r8-r11: \t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    472  1.10    simonb 			f->fixreg[8], f->fixreg[9],
    473  1.10    simonb 			f->fixreg[10], f->fixreg[11]);
    474  1.27      matt 		db_printf("r12-r15:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    475  1.10    simonb 			f->fixreg[12], f->fixreg[13],
    476  1.10    simonb 			f->fixreg[14], f->fixreg[15]);
    477  1.27      matt 		db_printf("r16-r19:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    478  1.10    simonb 			f->fixreg[16], f->fixreg[17],
    479  1.10    simonb 			f->fixreg[18], f->fixreg[19]);
    480  1.27      matt 		db_printf("r20-r23:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    481  1.10    simonb 			f->fixreg[20], f->fixreg[21],
    482  1.10    simonb 			f->fixreg[22], f->fixreg[23]);
    483  1.27      matt 		db_printf("r24-r27:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    484  1.10    simonb 			f->fixreg[24], f->fixreg[25],
    485  1.10    simonb 			f->fixreg[26], f->fixreg[27]);
    486  1.27      matt 		db_printf("r28-r31:\t%8.8lx %8.8lx %8.8lx %8.8lx\n",
    487  1.10    simonb 			f->fixreg[28], f->fixreg[29],
    488  1.10    simonb 			f->fixreg[30], f->fixreg[31]);
    489  1.10    simonb 
    490  1.27      matt 		db_printf("lr: %8.8lx cr: %8.8x xer: %8.8x ctr: %8.8lx\n",
    491  1.10    simonb 			f->lr, f->cr, f->xer, f->ctr);
    492  1.27      matt 		db_printf("srr0(pc): %8.8lx srr1(msr): %8.8lx "
    493  1.27      matt 			"dear: %8.8lx esr: %8.8x\n",
    494  1.27      matt 			f->srr0, f->srr1, f->dar, f->tf_xtra[TF_ESR]);
    495  1.10    simonb 		db_printf("exc: %8.8x pid: %8.8x\n",
    496  1.27      matt 			f->exc, f->tf_xtra[TF_PID]);
    497  1.10    simonb 	}
    498  1.10    simonb 	return;
    499  1.10    simonb }
    500  1.10    simonb 
    501  1.10    simonb static const char *const tlbsizes[] = {
    502  1.10    simonb 	  "1kB",
    503  1.10    simonb 	  "4kB",
    504  1.10    simonb 	 "16kB",
    505  1.10    simonb 	 "64kB",
    506  1.10    simonb 	"256kB",
    507  1.10    simonb 	  "1MB",
    508  1.10    simonb 	  "4MB",
    509  1.10    simonb 	 "16MB"
    510  1.10    simonb };
    511  1.10    simonb 
    512  1.10    simonb static void
    513  1.37      matt db_ppc4xx_dumptlb(db_expr_t addr, bool have_addr, db_expr_t count,
    514  1.34       scw     const char *modif)
    515  1.10    simonb {
    516  1.10    simonb 	int i, zone, tlbsize;
    517  1.10    simonb 	u_int zpr, pid, opid, msr;
    518  1.10    simonb 	u_long tlblo, tlbhi, tlbmask;
    519  1.10    simonb 
    520  1.10    simonb 	zpr = mfspr(SPR_ZPR);
    521  1.10    simonb 	for (i = 0; i < NTLB; i++) {
    522  1.36     perry 		__asm volatile("mfmsr %3;"
    523  1.10    simonb 			"mfpid %4;"
    524  1.10    simonb 			"li %0,0;"
    525  1.10    simonb 			"mtmsr %0;"
    526  1.10    simonb 			"sync; isync;"
    527  1.21   thorpej 			"tlbrelo %0,%5;"
    528  1.21   thorpej 			"tlbrehi %1,%5;"
    529  1.10    simonb 			"mfpid %2;"
    530  1.10    simonb 			"mtpid %4;"
    531  1.10    simonb 			"mtmsr %3;"
    532  1.10    simonb 			"sync; isync"
    533  1.10    simonb 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    534  1.10    simonb 			"=&r" (msr), "=&r" (opid) : "r" (i));
    535  1.10    simonb 
    536  1.10    simonb 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    537  1.10    simonb 			continue;
    538  1.10    simonb 
    539  1.10    simonb 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    540  1.10    simonb 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    541  1.10    simonb 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    542  1.10    simonb 
    543  1.10    simonb 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    544  1.10    simonb 			continue;
    545  1.10    simonb 
    546  1.10    simonb 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    547  1.10    simonb 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    548  1.10    simonb 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    549  1.10    simonb 		    pid,
    550  1.10    simonb 		    tlbhi & tlbmask,
    551  1.10    simonb 		    tlbsizes[tlbsize]);
    552  1.10    simonb 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    553  1.10    simonb 		    tlblo & tlbmask,
    554  1.10    simonb 		    zone,
    555  1.10    simonb 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    556  1.10    simonb 		    tlblo & TLB_EX ? "EX" : "  ",
    557  1.10    simonb 		    tlblo & TLB_WR ? "WR" : "  ",
    558  1.10    simonb 		    tlblo & TLB_W ? 'W' : ' ',
    559  1.10    simonb 		    tlblo & TLB_I ? 'I' : ' ',
    560  1.10    simonb 		    tlblo & TLB_M ? 'M' : ' ',
    561  1.10    simonb 		    tlblo & TLB_G ? 'G' : ' ',
    562  1.10    simonb 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    563  1.10    simonb 		    tlbhi & TLB_U0 ? "U0" : "  ");
    564  1.10    simonb 		db_printf("\n");
    565  1.10    simonb 	}
    566  1.22       scw }
    567  1.22       scw 
    568  1.22       scw static void
    569  1.37      matt db_ppc4xx_dcr(db_expr_t address, bool have_addr, db_expr_t count,
    570  1.34       scw     const char *modif)
    571  1.22       scw {
    572  1.22       scw 	db_expr_t new_value;
    573  1.22       scw 	db_expr_t addr;
    574  1.23       scw 
    575  1.23       scw 	if (address < 0 || address > 0x3ff)
    576  1.23       scw 		db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
    577  1.22       scw 
    578  1.22       scw 	addr = address;
    579  1.22       scw 
    580  1.22       scw 	while (db_expression(&new_value)) {
    581  1.22       scw 		db_printf("dcr 0x%lx\t\t%s = ", addr,
    582  1.22       scw 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    583  1.22       scw 		db_ppc4xx_mtdcr(addr, new_value);
    584  1.22       scw 		db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
    585  1.22       scw 		addr += 1;
    586  1.22       scw 	}
    587  1.22       scw 
    588  1.22       scw 	if (addr == address) {
    589  1.22       scw 		db_next = (db_addr_t)addr + 1;
    590  1.22       scw 		db_prev = (db_addr_t)addr;
    591  1.22       scw 		db_printf("dcr 0x%lx\t\t%s\n", addr,
    592  1.22       scw 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    593  1.22       scw 	} else {
    594  1.22       scw 		db_next = (db_addr_t)addr;
    595  1.22       scw 		db_prev = (db_addr_t)addr - 1;
    596  1.22       scw 	}
    597  1.22       scw 
    598  1.22       scw 	db_skip_to_eol();
    599  1.22       scw }
    600  1.22       scw 
    601  1.22       scw /*
    602  1.22       scw  * XXX Grossness Alert! XXX
    603  1.22       scw  *
    604  1.22       scw  * Please look away now if you don't like self-modifying code
    605  1.22       scw  */
    606  1.22       scw static u_int32_t db_ppc4xx_dcrfunc[4];
    607  1.22       scw 
    608  1.22       scw static db_expr_t
    609  1.22       scw db_ppc4xx_mfdcr(db_expr_t reg)
    610  1.22       scw {
    611  1.22       scw 	db_expr_t (*func)(void);
    612  1.22       scw 
    613  1.22       scw 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    614  1.22       scw 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    615  1.22       scw 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    616  1.22       scw 	db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg;	/* mfdcr reg, r3 */
    617  1.22       scw 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    618  1.22       scw 
    619  1.22       scw 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    620  1.22       scw 	func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
    621  1.22       scw 
    622  1.22       scw 	return ((*func)());
    623  1.22       scw }
    624  1.22       scw 
    625  1.22       scw static void
    626  1.22       scw db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
    627  1.22       scw {
    628  1.22       scw 	db_expr_t (*func)(db_expr_t);
    629  1.22       scw 
    630  1.22       scw 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    631  1.22       scw 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    632  1.22       scw 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    633  1.22       scw 	db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg;	/* mtdcr r3, reg */
    634  1.22       scw 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    635  1.22       scw 
    636  1.22       scw 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    637  1.22       scw 	func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
    638  1.22       scw 
    639  1.22       scw 	(*func)(val);
    640  1.10    simonb }
    641  1.10    simonb 
    642  1.10    simonb #ifdef USERACC
    643  1.10    simonb static void
    644  1.37      matt db_ppc4xx_useracc(db_expr_t addr, bool have_addr, db_expr_t count,
    645  1.34       scw     const char *modif)
    646  1.10    simonb {
    647  1.10    simonb 	static paddr_t oldaddr = -1;
    648  1.10    simonb 	int instr = 0;
    649  1.10    simonb 	int data;
    650  1.10    simonb 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    651  1.10    simonb 
    652  1.10    simonb 
    653  1.10    simonb 	if (!have_addr) {
    654  1.10    simonb 		addr = oldaddr;
    655  1.10    simonb 	}
    656  1.10    simonb 	if (addr == -1) {
    657  1.10    simonb 		db_printf("no address\n");
    658  1.10    simonb 		return;
    659  1.10    simonb 	}
    660  1.10    simonb 	addr &= ~0x3; /* align */
    661  1.10    simonb 	{
    662  1.34       scw 		const char *cp = modif;
    663  1.34       scw 		char c;
    664  1.10    simonb 		while ((c = *cp++) != 0)
    665  1.10    simonb 			if (c == 'i')
    666  1.10    simonb 				instr = 1;
    667  1.10    simonb 	}
    668  1.10    simonb 	while (count--) {
    669  1.10    simonb 		if (db_print_position() == 0) {
    670  1.10    simonb 			/* Always print the address. */
    671  1.10    simonb 			db_printf("%8.4lx:\t", addr);
    672  1.10    simonb 		}
    673  1.10    simonb 		oldaddr=addr;
    674  1.10    simonb 		copyin((void *)addr, &data, sizeof(data));
    675  1.10    simonb 		if (instr) {
    676  1.10    simonb 			opc_disasm(addr, data);
    677  1.10    simonb 		} else {
    678  1.10    simonb 			db_printf("%4.4x\n", data);
    679  1.10    simonb 		}
    680  1.10    simonb 		addr += 4;
    681  1.10    simonb 		db_end_line();
    682  1.10    simonb 	}
    683  1.10    simonb 
    684  1.10    simonb }
    685  1.10    simonb #endif
    686  1.10    simonb 
    687  1.39   garbled #endif /* DDB */
    688  1.39   garbled 
    689  1.10    simonb #endif /* PPC_IBM4XX */
    690