xref: /netbsd/sys/arch/powerpc/powerpc/kgdb_machdep.c (revision bf9ec67e)
1 /*	$NetBSD: kgdb_machdep.c,v 1.3 2002/01/06 00:35:13 dbj Exp $	*/
2 
3 /*
4  * Copyright 2001 Wasabi Systems, Inc.
5  * All rights reserved.
6  *
7  * Written by Allen Briggs for Wasabi Systems, Inc.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed for the NetBSD Project by
20  *      Wasabi Systems, Inc.
21  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22  *    or promote products derived from this software without specific prior
23  *    written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "opt_ddb.h"
39 
40 #if defined(DDB)
41 #error "Can't build DDB and KGDB together."
42 #endif
43 
44 /*
45  * Machine-dependent functions for remote KGDB.
46  */
47 
48 #include <sys/param.h>
49 #include <sys/kgdb.h>
50 #include <sys/systm.h>
51 
52 #include <uvm/uvm_extern.h>
53 
54 #include <machine/bat.h>
55 #include <machine/reg.h>
56 #include <machine/trap.h>
57 #include <machine/pmap.h>
58 
59 /*
60  * Determine if the memory at va..(va+len) is valid.
61  */
62 int
63 kgdb_acc(vaddr_t va, size_t len)
64 {
65 	vaddr_t   last_va;
66 	paddr_t   pa;
67 	u_int msr;
68 	u_int batu;
69 
70 	/* If translation is off, everything is fair game */
71 	asm volatile ("mfmsr %0" : "=r"(msr));
72 	if ((msr & PSL_DR) == 0) {
73 		return 1;
74 	}
75 
76 	/* Now check battable registers */
77 	asm volatile ("mfdbatu %0,0" : "=r"(batu));
78 	if (BAT_VALID_P(batu,msr) &&
79 			BAT_VA_MATCH_P(batu,va) &&
80 			(batu & BAT_PP) != BAT_PP_NONE) {
81 		return 1;
82 	}
83 	asm volatile ("mfdbatu %0,1" : "=r"(batu));
84 	if (BAT_VALID_P(batu,msr) &&
85 			BAT_VA_MATCH_P(batu,va) &&
86 			(batu & BAT_PP) != BAT_PP_NONE) {
87 		return 1;
88 	}
89 	asm volatile ("mfdbatu %0,2" : "=r"(batu));
90 	if (BAT_VALID_P(batu,msr) &&
91 			BAT_VA_MATCH_P(batu,va) &&
92 			(batu & BAT_PP) != BAT_PP_NONE) {
93 		return 1;
94 	}
95 	asm volatile ("mfdbatu %0,3" : "=r"(batu));
96 	if (BAT_VALID_P(batu,msr) &&
97 			BAT_VA_MATCH_P(batu,va) &&
98 			(batu & BAT_PP) != BAT_PP_NONE) {
99 		return 1;
100 	}
101 
102 	last_va = va + len;
103 	va  &= ~PGOFSET;
104 	last_va &= ~PGOFSET;
105 
106 	do {
107 		/*
108 		 * I think this should be able to handle
109 		 * non-pmap_kernel() va's, too.
110 		 */
111 		if (!pmap_extract(pmap_kernel(), va, &pa))
112 			return 0;
113 		va += PAGE_SIZE;
114 	} while (va <= last_va);
115 
116 	return (1);
117 }
118 
119 /*
120  * Translate a trap number into a unix compatible signal value.
121  * (gdb only understands unix signal numbers).  Some of these are bogus
122  * and should be reviewed.
123  */
124 int
125 kgdb_signal(type)
126 	int type;
127 {
128 	switch (type) {
129 #ifdef PPC_IBM4XX
130 	case EXC_PIT:		/* 40x - Programmable interval timer */
131 	case EXC_FIT:		/* 40x - Fixed interval timer */
132 		return SIGALRM
133 
134 	case EXC_CII:		/* 40x - Critical input interrupt */
135 	case EXC_WDOG:		/* 40x - Watchdog timer */
136 	case EXC_DEBUG:		/* 40x - Debug trap */
137 		return SIGTRAP;
138 
139 	case EXC_DTMISS:	/* 40x - Instruction TLB miss */
140 	case EXC_ITMISS:	/* 40x - Data TLB miss */
141 		return SIGSEGV;
142 #endif
143 
144 #ifdef PPC_MPC6XX
145 	case EXC_PERF:		/* 604/750/7400 - Performance monitoring */
146 	case EXC_BPT:		/* 604/750/7400 - Instruction breakpoint */
147 	case EXC_SMI:		/* 604/750/7400 - System management interrupt */
148 	case EXC_THRM:		/* 750/7400 - Thermal management interrupt */
149 		return SIGTRAP;
150 
151 	case EXC_IMISS:		/* 603 - Instruction translation miss */
152 	case EXC_DLMISS:	/* 603 - Data load translation miss */
153 	case EXC_DSMISS:	/* 603 - Data store translation miss */
154 		return SIGSEGV;
155 
156 	case EXC_RST:		/* All but IBM 4xx - Reset */
157 		return SIGURG;
158 
159 	case EXC_VEC:		/* 7400 - Altivec unavailable */
160 	case EXC_VECAST:	/* 7400 - Altivec assist */
161 		return SIGFPE;
162 #endif
163 
164 	case EXC_DECR:		/* Decrementer interrupt */
165 		return SIGALRM;
166 
167 	case EXC_EXI:		/* External interrupt */
168 		return SIGINT;
169 
170 	case EXC_PGM:		/* Program interrupt */
171 	case EXC_ALI:		/* Alignment */
172 		return SIGILL;
173 
174   case T_BREAKPOINT:
175 	case EXC_MCHK:		/* Machine check */
176 	case EXC_TRC:		/* Trace */
177 		return SIGTRAP;
178 
179 	case EXC_ISI:		/* Instruction storage interrupt */
180 	case EXC_DSI:		/* Data storage interrupt */
181 		return SIGSEGV;
182 
183 	case EXC_FPU:		/* Floating point unavailable */
184 	case EXC_FPA:		/* Floating-point assist */
185 		return SIGFPE;
186 
187 	case EXC_SC:		/* System call */
188 		return SIGURG;
189 
190 	case EXC_RSVD:		/* Reserved */
191 	case EXC_AST:		/* Floating point unavailable */
192 	default:
193 		return SIGEMT;
194 	}
195 }
196 
197 /*
198  * Translate the values stored in the kernel regs struct to the format
199  * understood by gdb.
200  */
201 void
202 kgdb_getregs(regs, gdb_regs)
203 	db_regs_t *regs;
204 	kgdb_reg_t *gdb_regs;
205 {
206 	memcpy(gdb_regs, regs, 32 * sizeof(unsigned long));
207 	gdb_regs[KGDB_PPC_PC_REG]  = regs->iar;
208 	gdb_regs[KGDB_PPC_MSR_REG] = regs->msr;
209 	gdb_regs[KGDB_PPC_CR_REG]  = regs->cr;
210 	gdb_regs[KGDB_PPC_LR_REG]  = regs->lr;
211 	gdb_regs[KGDB_PPC_CTR_REG] = regs->ctr;
212 	gdb_regs[KGDB_PPC_XER_REG] = regs->xer;
213 }
214 
215 /*
216  * Reverse the above.
217  */
218 void
219 kgdb_setregs(regs, gdb_regs)
220 	db_regs_t *regs;
221 	kgdb_reg_t *gdb_regs;
222 {
223 	regs->xer = gdb_regs[KGDB_PPC_XER_REG];
224 	regs->ctr = gdb_regs[KGDB_PPC_CTR_REG];
225 	regs->lr  = gdb_regs[KGDB_PPC_LR_REG];
226 	regs->cr  = gdb_regs[KGDB_PPC_CR_REG];
227 	regs->msr = gdb_regs[KGDB_PPC_MSR_REG];
228 	regs->iar = gdb_regs[KGDB_PPC_PC_REG];
229 	memcpy(regs, gdb_regs, 32 * sizeof(unsigned long));
230 }
231 
232 /*
233  * Trap into kgdb to wait for debugger to connect,
234  * noting on the console why nothing else is going on.
235  */
236 void
237 kgdb_connect(verbose)
238 	int verbose;
239 {
240 
241 	if (kgdb_dev < 0)
242 		return;
243 
244 	if (verbose)
245 		printf("kgdb waiting...");
246 
247 	asm volatile(BKPT_ASM);
248 
249 	if (verbose && kgdb_active) {
250 		printf("kgdb connected.\n");
251 	}
252 
253 	kgdb_debug_panic = 1;
254 }
255 
256 /*
257  * Decide what to do on panic.
258  * (This is called by panic, like Debugger())
259  */
260 void
261 kgdb_panic()
262 {
263 	if (kgdb_dev >= 0 && kgdb_debug_panic) {
264 		printf("entering kgdb\n");
265 		kgdb_connect(kgdb_active == 0);
266 	}
267 }
268