xref: /netbsd/sys/arch/powerpc/powerpc/kgdb_machdep.c (revision 6550d01e)
1 /*	$NetBSD: kgdb_machdep.c,v 1.22 2010/03/02 21:53:20 matt 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 <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.22 2010/03/02 21:53:20 matt Exp $");
40 
41 #include "opt_ddb.h"
42 
43 /*
44  * Machine-dependent functions for remote KGDB.
45  */
46 
47 #include <sys/param.h>
48 #include <sys/kgdb.h>
49 #include <sys/systm.h>
50 
51 #include <uvm/uvm_extern.h>
52 
53 #include <machine/reg.h>
54 #include <machine/trap.h>
55 #include <machine/pmap.h>
56 
57 #include <powerpc/spr.h>
58 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
59 #include <powerpc/oea/spr.h>
60 #include <powerpc/oea/bat.h>
61 
62 #elif defined (PPC_OEA64)
63 #include <powerpc/oea/spr.h>
64 
65 #elif defined (PPC_IBM4XX)
66 #include <powerpc/booke/spr.h>
67 
68 #elif defined (PPC_BOOKE)
69 #include <powerpc/booke/spr.h>
70 
71 #else
72 #error unknown architecture
73 #endif
74 
75 /*
76  * Determine if the memory at va..(va+len) is valid.
77  */
78 int
79 kgdb_acc(vaddr_t va, size_t len)
80 {
81 	vaddr_t   last_va;
82 	paddr_t   pa;
83 	u_int msr;
84 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
85 	u_int batu, batl;
86 #endif
87 
88 	/* If translation is off, everything is fair game */
89 	__asm volatile ("mfmsr %0" : "=r"(msr));
90 	if ((msr & PSL_DR) == 0) {
91 		return 1;
92 	}
93 
94 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
95 	/* Now check battable registers */
96 #ifdef PPC_OEA601
97 	if ((mfpvr() >> 16) == MPC601) {
98 		__asm volatile ("mfibatl %0,0" : "=r"(batl));
99 		__asm volatile ("mfibatu %0,0" : "=r"(batu));
100 		if (BAT601_VALID_P(batl) &&
101 				BAT601_VA_MATCH_P(batu,batl,va))
102 			return 1;
103 		__asm volatile ("mfibatl %0,1" : "=r"(batl));
104 		__asm volatile ("mfibatu %0,1" : "=r"(batu));
105 		if (BAT601_VALID_P(batl) &&
106 				BAT601_VA_MATCH_P(batu,batl,va))
107 			return 1;
108 		__asm volatile ("mfibatl %0,2" : "=r"(batl));
109 		__asm volatile ("mfibatu %0,2" : "=r"(batu));
110 		if (BAT601_VALID_P(batl) &&
111 				BAT601_VA_MATCH_P(batu,batl,va))
112 			return 1;
113 		__asm volatile ("mfibatl %0,3" : "=r"(batl));
114 		__asm volatile ("mfibatu %0,3" : "=r"(batu));
115 		if (BAT601_VALID_P(batl) &&
116 				BAT601_VA_MATCH_P(batu,batl,va))
117 			return 1;
118 	} else {
119 #endif /* PPC_OEA601 */
120 		__asm volatile ("mfdbatu %0,0" : "=r"(batu));
121 		if (BAT_VALID_P(batu,msr) &&
122 				BAT_VA_MATCH_P(batu,va) &&
123 				(batu & BAT_PP) != BAT_PP_NONE) {
124 			return 1;
125 		}
126 		__asm volatile ("mfdbatu %0,1" : "=r"(batu));
127 		if (BAT_VALID_P(batu,msr) &&
128 				BAT_VA_MATCH_P(batu,va) &&
129 				(batu & BAT_PP) != BAT_PP_NONE) {
130 			return 1;
131 		}
132 		__asm volatile ("mfdbatu %0,2" : "=r"(batu));
133 		if (BAT_VALID_P(batu,msr) &&
134 				BAT_VA_MATCH_P(batu,va) &&
135 				(batu & BAT_PP) != BAT_PP_NONE) {
136 			return 1;
137 		}
138 		__asm volatile ("mfdbatu %0,3" : "=r"(batu));
139 		if (BAT_VALID_P(batu,msr) &&
140 				BAT_VA_MATCH_P(batu,va) &&
141 				(batu & BAT_PP) != BAT_PP_NONE) {
142 			return 1;
143 #ifdef PPC_OEA601
144 		}
145 #endif
146 	}
147 #endif /* PPC_OEA || PPC_OEA601 || PPC_OEA64_BRIDGE */
148 
149 #if defined(PPC_IBM4XX)
150 	/* Is it (supposed to be) TLB-reserved mapping? */
151 	if (va < VM_MIN_KERNEL_ADDRESS || va > VM_MAX_KERNEL_ADDRESS)
152 		return (1);
153 #endif
154 
155 	last_va = va + len;
156 	va  &= ~PGOFSET;
157 	last_va &= ~PGOFSET;
158 
159 	do {
160 		/*
161 		 * I think this should be able to handle
162 		 * non-pmap_kernel() va's, too.
163 		 */
164 		if (!pmap_extract(pmap_kernel(), va, &pa))
165 			return 0;
166 		va += PAGE_SIZE;
167 	} while (va <= last_va);
168 
169 	return (1);
170 }
171 
172 /*
173  * Translate a trap number into a unix compatible signal value.
174  * (gdb only understands unix signal numbers).  Some of these are bogus
175  * and should be reviewed.
176  */
177 int
178 kgdb_signal(int type)
179 {
180 	switch (type) {
181 #if defined (PPC_IBM4XX) || defined (PPC_BOOKE)
182 	case EXC_PIT:		/* 40x - Programmable interval timer */
183 	case EXC_FIT:		/* 40x - Fixed interval timer */
184 		return SIGALRM;
185 
186 	case EXC_CII:		/* 40x - Critical input interrupt */
187 	case EXC_WDOG:		/* 40x - Watchdog timer */
188 	case EXC_DEBUG:		/* 40x - Debug trap */
189 		return SIGTRAP;
190 
191 	case EXC_DTMISS:	/* 40x - Instruction TLB miss */
192 	case EXC_ITMISS:	/* 40x - Data TLB miss */
193 		return SIGSEGV;
194 #endif
195 
196 #if defined (PPC_OEA) || defined (PPC_OEA601) || defined (PPC_OEA64_BRIDGE)
197 	case EXC_PERF:		/* 604/750/7400 - Performance monitoring */
198 	case EXC_BPT:		/* 604/750/7400 - Instruction breakpoint */
199 	case EXC_SMI:		/* 604/750/7400 - System management interrupt */
200 	case EXC_THRM:		/* 750/7400 - Thermal management interrupt */
201 		return SIGTRAP;
202 
203 	case EXC_IMISS:		/* 603 - Instruction translation miss */
204 	case EXC_DLMISS:	/* 603 - Data load translation miss */
205 	case EXC_DSMISS:	/* 603 - Data store translation miss */
206 		return SIGSEGV;
207 
208 	case EXC_RST:		/* All but IBM 4xx - Reset */
209 		return SIGURG;
210 
211 	case EXC_VEC:		/* 7400 - Altivec unavailable */
212 	case EXC_VECAST:	/* 7400 - Altivec assist */
213 		return SIGFPE;
214 #endif
215 
216 	case EXC_DECR:		/* Decrementer interrupt */
217 		return SIGALRM;
218 
219 	case EXC_EXI:		/* External interrupt */
220 		return SIGINT;
221 
222 	case EXC_PGM:		/* Program interrupt */
223 	case EXC_ALI:		/* Alignment */
224 		return SIGILL;
225 
226   case T_BREAKPOINT:
227 	case EXC_MCHK:		/* Machine check */
228 	case EXC_TRC:		/* Trace */
229 		return SIGTRAP;
230 
231 	case EXC_ISI:		/* Instruction storage interrupt */
232 	case EXC_DSI:		/* Data storage interrupt */
233 		return SIGSEGV;
234 
235 	case EXC_FPU:		/* Floating point unavailable */
236 	case EXC_FPA:		/* Floating-point assist */
237 		return SIGFPE;
238 
239 	case EXC_SC:		/* System call */
240 		return SIGURG;
241 
242 	case EXC_RSVD:		/* Reserved */
243 	case EXC_AST:		/* Floating point unavailable */
244 	default:
245 		return SIGEMT;
246 	}
247 }
248 
249 /*
250  * Translate the values stored in the kernel regs struct to the format
251  * understood by gdb.
252  */
253 void
254 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
255 {
256 	memcpy(gdb_regs, regs, 32 * sizeof(unsigned long));
257 	gdb_regs[KGDB_PPC_PC_REG]  = regs->iar;
258 	gdb_regs[KGDB_PPC_MSR_REG] = regs->msr;
259 	gdb_regs[KGDB_PPC_CR_REG]  = regs->cr;
260 	gdb_regs[KGDB_PPC_LR_REG]  = regs->lr;
261 	gdb_regs[KGDB_PPC_CTR_REG] = regs->ctr;
262 	gdb_regs[KGDB_PPC_XER_REG] = regs->xer;
263 }
264 
265 /*
266  * Reverse the above.
267  */
268 void
269 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
270 {
271 	regs->xer = gdb_regs[KGDB_PPC_XER_REG];
272 	regs->ctr = gdb_regs[KGDB_PPC_CTR_REG];
273 	regs->lr  = gdb_regs[KGDB_PPC_LR_REG];
274 	regs->cr  = gdb_regs[KGDB_PPC_CR_REG];
275 	regs->msr = gdb_regs[KGDB_PPC_MSR_REG];
276 	regs->iar = gdb_regs[KGDB_PPC_PC_REG];
277 	memcpy(regs, gdb_regs, 32 * sizeof(unsigned long));
278 }
279 
280 /*
281  * Trap into kgdb to wait for debugger to connect,
282  * noting on the console why nothing else is going on.
283  */
284 void
285 kgdb_connect(int verbose)
286 {
287 	if (kgdb_dev == NODEV)
288 		return;
289 
290 	if (verbose)
291 		printf("kgdb waiting...");
292 
293 	__asm volatile(BKPT_ASM);
294 
295 	if (verbose && kgdb_active) {
296 		printf("kgdb connected.\n");
297 	}
298 
299 	kgdb_debug_panic = 1;
300 }
301 
302 /*
303  * Decide what to do on panic.
304  * (This is called by panic, like Debugger())
305  */
306 void
307 kgdb_panic(void)
308 {
309 	if (kgdb_dev != NODEV && kgdb_debug_panic) {
310 		printf("entering kgdb\n");
311 		kgdb_connect(kgdb_active == 0);
312 	}
313 }
314