aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 14:49:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-29 14:49:38 -0400
commit1e431a9d6478940c0b5fcfa1c17a336fc0683409 (patch)
treece6b454ecbad4f535b9a18ef8605f8218a409ee6 /arch/powerpc
parent75d73126fd490e26a9bdfc2338ca068e71563e0b (diff)
parentff10b88b5a05c8f1646dd15fb9f6093c1384ff6d (diff)
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb: kgdb,ppc: Individual register get/set for ppc kgdbts: prevent re-entry to kgdbts before it unregisters debug_core,x86,blackfin: Clean up hw debug disable API kdb: Fix early debugging crash regression kgdb,arm: fix register dump kdb: fix per_cpu command to remove supress mask kdb: Add kdb kernel module sample
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kgdb.h1
-rw-r--r--arch/powerpc/kernel/kgdb.c188
2 files changed, 126 insertions, 63 deletions
diff --git a/arch/powerpc/include/asm/kgdb.h b/arch/powerpc/include/asm/kgdb.h
index edd217006d27..9db24e77b9f4 100644
--- a/arch/powerpc/include/asm/kgdb.h
+++ b/arch/powerpc/include/asm/kgdb.h
@@ -31,6 +31,7 @@ static inline void arch_kgdb_breakpoint(void)
31 asm(".long 0x7d821008"); /* twge r2, r2 */ 31 asm(".long 0x7d821008"); /* twge r2, r2 */
32} 32}
33#define CACHE_FLUSH_IS_SAFE 1 33#define CACHE_FLUSH_IS_SAFE 1
34#define DBG_MAX_REG_NUM 70
34 35
35/* The number bytes of registers we have to save depends on a few 36/* The number bytes of registers we have to save depends on a few
36 * things. For 64bit we default to not including vector registers and 37 * things. For 64bit we default to not including vector registers and
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 7f61a3ac787c..7a9db64f3f04 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -194,40 +194,6 @@ static int kgdb_dabr_match(struct pt_regs *regs)
194 ptr = (unsigned long *)ptr32; \ 194 ptr = (unsigned long *)ptr32; \
195 } while (0) 195 } while (0)
196 196
197
198void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
199{
200 unsigned long *ptr = gdb_regs;
201 int reg;
202
203 memset(gdb_regs, 0, NUMREGBYTES);
204
205 for (reg = 0; reg < 32; reg++)
206 PACK64(ptr, regs->gpr[reg]);
207
208#ifdef CONFIG_FSL_BOOKE
209#ifdef CONFIG_SPE
210 for (reg = 0; reg < 32; reg++)
211 PACK64(ptr, current->thread.evr[reg]);
212#else
213 ptr += 32;
214#endif
215#else
216 /* fp registers not used by kernel, leave zero */
217 ptr += 32 * 8 / sizeof(long);
218#endif
219
220 PACK64(ptr, regs->nip);
221 PACK64(ptr, regs->msr);
222 PACK32(ptr, regs->ccr);
223 PACK64(ptr, regs->link);
224 PACK64(ptr, regs->ctr);
225 PACK32(ptr, regs->xer);
226
227 BUG_ON((unsigned long)ptr >
228 (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
229}
230
231void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) 197void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
232{ 198{
233 struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp + 199 struct pt_regs *regs = (struct pt_regs *)(p->thread.ksp +
@@ -271,44 +237,140 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
271 (unsigned long)(((void *)gdb_regs) + NUMREGBYTES)); 237 (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
272} 238}
273 239
274#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0) 240#define GDB_SIZEOF_REG sizeof(unsigned long)
241#define GDB_SIZEOF_REG_U32 sizeof(u32)
275 242
276#define UNPACK32(dest, ptr) do { \ 243#ifdef CONFIG_FSL_BOOKE
277 u32 *ptr32; \ 244#define GDB_SIZEOF_FLOAT_REG sizeof(unsigned long)
278 ptr32 = (u32 *)ptr; \ 245#else
279 dest = *(ptr32++); \ 246#define GDB_SIZEOF_FLOAT_REG sizeof(u64)
280 ptr = (unsigned long *)ptr32; \ 247#endif
281 } while (0)
282 248
283void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) 249struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
284{ 250{
285 unsigned long *ptr = gdb_regs; 251 { "r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[0]) },
286 int reg; 252 { "r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[1]) },
287 253 { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[2]) },
288 for (reg = 0; reg < 32; reg++) 254 { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[3]) },
289 UNPACK64(regs->gpr[reg], ptr); 255 { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[4]) },
256 { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[5]) },
257 { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[6]) },
258 { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[7]) },
259 { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[8]) },
260 { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[9]) },
261 { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[10]) },
262 { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[11]) },
263 { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[12]) },
264 { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[13]) },
265 { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[14]) },
266 { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[15]) },
267 { "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[16]) },
268 { "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[17]) },
269 { "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[18]) },
270 { "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[19]) },
271 { "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[20]) },
272 { "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[21]) },
273 { "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[22]) },
274 { "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[23]) },
275 { "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[24]) },
276 { "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[25]) },
277 { "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[26]) },
278 { "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[27]) },
279 { "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[28]) },
280 { "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[29]) },
281 { "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[30]) },
282 { "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[31]) },
283
284 { "f0", GDB_SIZEOF_FLOAT_REG, 0 },
285 { "f1", GDB_SIZEOF_FLOAT_REG, 1 },
286 { "f2", GDB_SIZEOF_FLOAT_REG, 2 },
287 { "f3", GDB_SIZEOF_FLOAT_REG, 3 },
288 { "f4", GDB_SIZEOF_FLOAT_REG, 4 },
289 { "f5", GDB_SIZEOF_FLOAT_REG, 5 },
290 { "f6", GDB_SIZEOF_FLOAT_REG, 6 },
291 { "f7", GDB_SIZEOF_FLOAT_REG, 7 },
292 { "f8", GDB_SIZEOF_FLOAT_REG, 8 },
293 { "f9", GDB_SIZEOF_FLOAT_REG, 9 },
294 { "f10", GDB_SIZEOF_FLOAT_REG, 10 },
295 { "f11", GDB_SIZEOF_FLOAT_REG, 11 },
296 { "f12", GDB_SIZEOF_FLOAT_REG, 12 },
297 { "f13", GDB_SIZEOF_FLOAT_REG, 13 },
298 { "f14", GDB_SIZEOF_FLOAT_REG, 14 },
299 { "f15", GDB_SIZEOF_FLOAT_REG, 15 },
300 { "f16", GDB_SIZEOF_FLOAT_REG, 16 },
301 { "f17", GDB_SIZEOF_FLOAT_REG, 17 },
302 { "f18", GDB_SIZEOF_FLOAT_REG, 18 },
303 { "f19", GDB_SIZEOF_FLOAT_REG, 19 },
304 { "f20", GDB_SIZEOF_FLOAT_REG, 20 },
305 { "f21", GDB_SIZEOF_FLOAT_REG, 21 },
306 { "f22", GDB_SIZEOF_FLOAT_REG, 22 },
307 { "f23", GDB_SIZEOF_FLOAT_REG, 23 },
308 { "f24", GDB_SIZEOF_FLOAT_REG, 24 },
309 { "f25", GDB_SIZEOF_FLOAT_REG, 25 },
310 { "f26", GDB_SIZEOF_FLOAT_REG, 26 },
311 { "f27", GDB_SIZEOF_FLOAT_REG, 27 },
312 { "f28", GDB_SIZEOF_FLOAT_REG, 28 },
313 { "f29", GDB_SIZEOF_FLOAT_REG, 29 },
314 { "f30", GDB_SIZEOF_FLOAT_REG, 30 },
315 { "f31", GDB_SIZEOF_FLOAT_REG, 31 },
316
317 { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, nip) },
318 { "msr", GDB_SIZEOF_REG, offsetof(struct pt_regs, msr) },
319 { "cr", GDB_SIZEOF_REG_U32, offsetof(struct pt_regs, ccr) },
320 { "lr", GDB_SIZEOF_REG, offsetof(struct pt_regs, link) },
321 { "ctr", GDB_SIZEOF_REG_U32, offsetof(struct pt_regs, ctr) },
322 { "xer", GDB_SIZEOF_REG, offsetof(struct pt_regs, xer) },
323};
290 324
291#ifdef CONFIG_FSL_BOOKE 325char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
292#ifdef CONFIG_SPE 326{
293 for (reg = 0; reg < 32; reg++) 327 if (regno >= DBG_MAX_REG_NUM || regno < 0)
294 UNPACK64(current->thread.evr[reg], ptr); 328 return NULL;
329
330 if (regno < 32 || regno >= 64)
331 /* First 0 -> 31 gpr registers*/
332 /* pc, msr, ls... registers 64 -> 69 */
333 memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
334 dbg_reg_def[regno].size);
335
336 if (regno >= 32 && regno < 64) {
337 /* FP registers 32 -> 63 */
338#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
339 if (current)
340 memcpy(mem, current->thread.evr[regno-32],
341 dbg_reg_def[regno].size);
295#else 342#else
296 ptr += 32; 343 /* fp registers not used by kernel, leave zero */
344 memset(mem, 0, dbg_reg_def[regno].size);
297#endif 345#endif
346 }
347
348 return dbg_reg_def[regno].name;
349}
350
351int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
352{
353 if (regno >= DBG_MAX_REG_NUM || regno < 0)
354 return -EINVAL;
355
356 if (regno < 32 || regno >= 64)
357 /* First 0 -> 31 gpr registers*/
358 /* pc, msr, ls... registers 64 -> 69 */
359 memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
360 dbg_reg_def[regno].size);
361
362 if (regno >= 32 && regno < 64) {
363 /* FP registers 32 -> 63 */
364#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
365 memcpy(current->thread.evr[regno-32], mem,
366 dbg_reg_def[regno].size);
298#else 367#else
299 /* fp registers not used by kernel, leave zero */ 368 /* fp registers not used by kernel, leave zero */
300 ptr += 32 * 8 / sizeof(int); 369 return 0;
301#endif 370#endif
371 }
302 372
303 UNPACK64(regs->nip, ptr); 373 return 0;
304 UNPACK64(regs->msr, ptr);
305 UNPACK32(regs->ccr, ptr);
306 UNPACK64(regs->link, ptr);
307 UNPACK64(regs->ctr, ptr);
308 UNPACK32(regs->xer, ptr);
309
310 BUG_ON((unsigned long)ptr >
311 (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
312} 374}
313 375
314void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) 376void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)