diff options
-rw-r--r-- | Documentation/DocBook/kgdb.tmpl | 13 | ||||
-rw-r--r-- | arch/arm/include/asm/kgdb.h | 5 | ||||
-rw-r--r-- | arch/arm/kernel/kgdb.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kgdb.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/kgdb.c | 188 | ||||
-rw-r--r-- | arch/x86/kernel/kgdb.c | 3 | ||||
-rw-r--r-- | drivers/misc/kgdbts.c | 16 | ||||
-rw-r--r-- | include/linux/kgdb.h | 13 | ||||
-rw-r--r-- | kernel/debug/debug_core.c | 16 | ||||
-rw-r--r-- | kernel/debug/kdb/kdb_main.c | 48 | ||||
-rw-r--r-- | samples/Kconfig | 7 | ||||
-rw-r--r-- | samples/Makefile | 2 | ||||
-rw-r--r-- | samples/kdb/Makefile | 1 | ||||
-rw-r--r-- | samples/kdb/kdb_hello.c | 60 |
15 files changed, 235 insertions, 143 deletions
diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl index 490d862c5f0d..d71b57fcf116 100644 --- a/Documentation/DocBook/kgdb.tmpl +++ b/Documentation/DocBook/kgdb.tmpl | |||
@@ -710,7 +710,18 @@ Task Addr Pid Parent [*] cpu State Thread Command | |||
710 | <listitem><para>A simple shell</para></listitem> | 710 | <listitem><para>A simple shell</para></listitem> |
711 | <listitem><para>The kdb core command set</para></listitem> | 711 | <listitem><para>The kdb core command set</para></listitem> |
712 | <listitem><para>A registration API to register additional kdb shell commands.</para> | 712 | <listitem><para>A registration API to register additional kdb shell commands.</para> |
713 | <para>A good example of a self-contained kdb module is the "ftdump" command for dumping the ftrace buffer. See: kernel/trace/trace_kdb.c</para></listitem> | 713 | <itemizedlist> |
714 | <listitem><para>A good example of a self-contained kdb module | ||
715 | is the "ftdump" command for dumping the ftrace buffer. See: | ||
716 | kernel/trace/trace_kdb.c</para></listitem> | ||
717 | <listitem><para>For an example of how to dynamically register | ||
718 | a new kdb command you can build the kdb_hello.ko kernel module | ||
719 | from samples/kdb/kdb_hello.c. To build this example you can | ||
720 | set CONFIG_SAMPLES=y and CONFIG_SAMPLE_KDB=m in your kernel | ||
721 | config. Later run "modprobe kdb_hello" and the next time you | ||
722 | enter the kdb shell, you can run the "hello" | ||
723 | command.</para></listitem> | ||
724 | </itemizedlist></listitem> | ||
714 | <listitem><para>The implementation for kdb_printf() which | 725 | <listitem><para>The implementation for kdb_printf() which |
715 | emits messages directly to I/O drivers, bypassing the kernel | 726 | emits messages directly to I/O drivers, bypassing the kernel |
716 | log.</para></listitem> | 727 | log.</para></listitem> |
diff --git a/arch/arm/include/asm/kgdb.h b/arch/arm/include/asm/kgdb.h index 08265993227f..48066ce9ea34 100644 --- a/arch/arm/include/asm/kgdb.h +++ b/arch/arm/include/asm/kgdb.h | |||
@@ -70,7 +70,8 @@ extern int kgdb_fault_expected; | |||
70 | #define _GP_REGS 16 | 70 | #define _GP_REGS 16 |
71 | #define _FP_REGS 8 | 71 | #define _FP_REGS 8 |
72 | #define _EXTRA_REGS 2 | 72 | #define _EXTRA_REGS 2 |
73 | #define DBG_MAX_REG_NUM (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS) | 73 | #define GDB_MAX_REGS (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS) |
74 | #define DBG_MAX_REG_NUM (_GP_REGS + _FP_REGS + _EXTRA_REGS) | ||
74 | 75 | ||
75 | #define KGDB_MAX_NO_CPUS 1 | 76 | #define KGDB_MAX_NO_CPUS 1 |
76 | #define BUFMAX 400 | 77 | #define BUFMAX 400 |
@@ -93,7 +94,7 @@ extern int kgdb_fault_expected; | |||
93 | #define _SPT 13 | 94 | #define _SPT 13 |
94 | #define _LR 14 | 95 | #define _LR 14 |
95 | #define _PC 15 | 96 | #define _PC 15 |
96 | #define _CPSR (DBG_MAX_REG_NUM - 1) | 97 | #define _CPSR (GDB_MAX_REGS - 1) |
97 | 98 | ||
98 | /* | 99 | /* |
99 | * So that we can denote the end of a frame for tracing, | 100 | * So that we can denote the end of a frame for tracing, |
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index d6e8b4d2e60d..778c2f7024ff 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -79,7 +79,7 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) | |||
79 | return; | 79 | return; |
80 | 80 | ||
81 | /* Initialize to zero */ | 81 | /* Initialize to zero */ |
82 | for (regno = 0; regno < DBG_MAX_REG_NUM; regno++) | 82 | for (regno = 0; regno < GDB_MAX_REGS; regno++) |
83 | gdb_regs[regno] = 0; | 83 | gdb_regs[regno] = 0; |
84 | 84 | ||
85 | /* Otherwise, we have only some registers from switch_to() */ | 85 | /* Otherwise, we have only some registers from switch_to() */ |
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index 08bc44ea6883..edae461b1c54 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -320,7 +320,7 @@ static void bfin_correct_hw_break(void) | |||
320 | } | 320 | } |
321 | } | 321 | } |
322 | 322 | ||
323 | void kgdb_disable_hw_debug(struct pt_regs *regs) | 323 | static void bfin_disable_hw_debug(struct pt_regs *regs) |
324 | { | 324 | { |
325 | /* Disable hardware debugging while we are in kgdb */ | 325 | /* Disable hardware debugging while we are in kgdb */ |
326 | bfin_write_WPIACTL(0); | 326 | bfin_write_WPIACTL(0); |
@@ -406,6 +406,7 @@ struct kgdb_arch arch_kgdb_ops = { | |||
406 | #endif | 406 | #endif |
407 | .set_hw_breakpoint = bfin_set_hw_break, | 407 | .set_hw_breakpoint = bfin_set_hw_break, |
408 | .remove_hw_breakpoint = bfin_remove_hw_break, | 408 | .remove_hw_breakpoint = bfin_remove_hw_break, |
409 | .disable_hw_break = bfin_disable_hw_debug, | ||
409 | .remove_all_hw_break = bfin_remove_all_hw_break, | 410 | .remove_all_hw_break = bfin_remove_all_hw_break, |
410 | .correct_hw_break = bfin_correct_hw_break, | 411 | .correct_hw_break = bfin_correct_hw_break, |
411 | }; | 412 | }; |
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 | |||
198 | void 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 | |||
231 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | 197 | void 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 | ||
283 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 249 | struct 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 | 325 | char *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 | |||
351 | int 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 | ||
314 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) | 376 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) |
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index d81cfebb848f..ec592caac4b4 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -387,7 +387,7 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype) | |||
387 | * disable hardware debugging while it is processing gdb packets or | 387 | * disable hardware debugging while it is processing gdb packets or |
388 | * handling exception. | 388 | * handling exception. |
389 | */ | 389 | */ |
390 | void kgdb_disable_hw_debug(struct pt_regs *regs) | 390 | static void kgdb_disable_hw_debug(struct pt_regs *regs) |
391 | { | 391 | { |
392 | int i; | 392 | int i; |
393 | int cpu = raw_smp_processor_id(); | 393 | int cpu = raw_smp_processor_id(); |
@@ -724,6 +724,7 @@ struct kgdb_arch arch_kgdb_ops = { | |||
724 | .flags = KGDB_HW_BREAKPOINT, | 724 | .flags = KGDB_HW_BREAKPOINT, |
725 | .set_hw_breakpoint = kgdb_set_hw_break, | 725 | .set_hw_breakpoint = kgdb_set_hw_break, |
726 | .remove_hw_breakpoint = kgdb_remove_hw_break, | 726 | .remove_hw_breakpoint = kgdb_remove_hw_break, |
727 | .disable_hw_break = kgdb_disable_hw_debug, | ||
727 | .remove_all_hw_break = kgdb_remove_all_hw_break, | 728 | .remove_all_hw_break = kgdb_remove_all_hw_break, |
728 | .correct_hw_break = kgdb_correct_hw_break, | 729 | .correct_hw_break = kgdb_correct_hw_break, |
729 | }; | 730 | }; |
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 72450237a0f4..59c118c19a91 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c | |||
@@ -1044,12 +1044,6 @@ static int __init init_kgdbts(void) | |||
1044 | return configure_kgdbts(); | 1044 | return configure_kgdbts(); |
1045 | } | 1045 | } |
1046 | 1046 | ||
1047 | static void cleanup_kgdbts(void) | ||
1048 | { | ||
1049 | if (configured == 1) | ||
1050 | kgdb_unregister_io_module(&kgdbts_io_ops); | ||
1051 | } | ||
1052 | |||
1053 | static int kgdbts_get_char(void) | 1047 | static int kgdbts_get_char(void) |
1054 | { | 1048 | { |
1055 | int val = 0; | 1049 | int val = 0; |
@@ -1081,10 +1075,8 @@ static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp) | |||
1081 | return 0; | 1075 | return 0; |
1082 | } | 1076 | } |
1083 | 1077 | ||
1084 | if (kgdb_connected) { | 1078 | if (configured == 1) { |
1085 | printk(KERN_ERR | 1079 | printk(KERN_ERR "kgdbts: ERROR: Already configured and running.\n"); |
1086 | "kgdbts: Cannot reconfigure while KGDB is connected.\n"); | ||
1087 | |||
1088 | return -EBUSY; | 1080 | return -EBUSY; |
1089 | } | 1081 | } |
1090 | 1082 | ||
@@ -1093,9 +1085,6 @@ static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp) | |||
1093 | if (config[len - 1] == '\n') | 1085 | if (config[len - 1] == '\n') |
1094 | config[len - 1] = '\0'; | 1086 | config[len - 1] = '\0'; |
1095 | 1087 | ||
1096 | if (configured == 1) | ||
1097 | cleanup_kgdbts(); | ||
1098 | |||
1099 | /* Go and configure with the new params. */ | 1088 | /* Go and configure with the new params. */ |
1100 | return configure_kgdbts(); | 1089 | return configure_kgdbts(); |
1101 | } | 1090 | } |
@@ -1123,7 +1112,6 @@ static struct kgdb_io kgdbts_io_ops = { | |||
1123 | }; | 1112 | }; |
1124 | 1113 | ||
1125 | module_init(init_kgdbts); | 1114 | module_init(init_kgdbts); |
1126 | module_exit(cleanup_kgdbts); | ||
1127 | module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644); | 1115 | module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644); |
1128 | MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]"); | 1116 | MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]"); |
1129 | MODULE_DESCRIPTION("KGDB Test Suite"); | 1117 | MODULE_DESCRIPTION("KGDB Test Suite"); |
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index cc96f0f23e04..092e4250a458 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h | |||
@@ -35,16 +35,6 @@ struct pt_regs; | |||
35 | */ | 35 | */ |
36 | extern int kgdb_skipexception(int exception, struct pt_regs *regs); | 36 | extern int kgdb_skipexception(int exception, struct pt_regs *regs); |
37 | 37 | ||
38 | /** | ||
39 | * kgdb_disable_hw_debug - (optional) Disable hardware debugging hook | ||
40 | * @regs: Current &struct pt_regs. | ||
41 | * | ||
42 | * This function will be called if the particular architecture must | ||
43 | * disable hardware debugging while it is processing gdb packets or | ||
44 | * handling exception. | ||
45 | */ | ||
46 | extern void kgdb_disable_hw_debug(struct pt_regs *regs); | ||
47 | |||
48 | struct tasklet_struct; | 38 | struct tasklet_struct; |
49 | struct task_struct; | 39 | struct task_struct; |
50 | struct uart_port; | 40 | struct uart_port; |
@@ -243,6 +233,8 @@ extern void kgdb_arch_late(void); | |||
243 | * breakpoint. | 233 | * breakpoint. |
244 | * @remove_hw_breakpoint: Allow an architecture to specify how to remove a | 234 | * @remove_hw_breakpoint: Allow an architecture to specify how to remove a |
245 | * hardware breakpoint. | 235 | * hardware breakpoint. |
236 | * @disable_hw_break: Allow an architecture to specify how to disable | ||
237 | * hardware breakpoints for a single cpu. | ||
246 | * @remove_all_hw_break: Allow an architecture to specify how to remove all | 238 | * @remove_all_hw_break: Allow an architecture to specify how to remove all |
247 | * hardware breakpoints. | 239 | * hardware breakpoints. |
248 | * @correct_hw_break: Allow an architecture to specify how to correct the | 240 | * @correct_hw_break: Allow an architecture to specify how to correct the |
@@ -256,6 +248,7 @@ struct kgdb_arch { | |||
256 | int (*remove_breakpoint)(unsigned long, char *); | 248 | int (*remove_breakpoint)(unsigned long, char *); |
257 | int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); | 249 | int (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); |
258 | int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); | 250 | int (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype); |
251 | void (*disable_hw_break)(struct pt_regs *regs); | ||
259 | void (*remove_all_hw_break)(void); | 252 | void (*remove_all_hw_break)(void); |
260 | void (*correct_hw_break)(void); | 253 | void (*correct_hw_break)(void); |
261 | }; | 254 | }; |
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index fec596da9bd0..cefd4a11f6d9 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
@@ -209,18 +209,6 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs) | |||
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | 211 | ||
212 | /** | ||
213 | * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb. | ||
214 | * @regs: Current &struct pt_regs. | ||
215 | * | ||
216 | * This function will be called if the particular architecture must | ||
217 | * disable hardware debugging while it is processing gdb packets or | ||
218 | * handling exception. | ||
219 | */ | ||
220 | void __weak kgdb_disable_hw_debug(struct pt_regs *regs) | ||
221 | { | ||
222 | } | ||
223 | |||
224 | /* | 212 | /* |
225 | * Some architectures need cache flushes when we set/clear a | 213 | * Some architectures need cache flushes when we set/clear a |
226 | * breakpoint: | 214 | * breakpoint: |
@@ -484,7 +472,9 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs, | |||
484 | atomic_inc(&masters_in_kgdb); | 472 | atomic_inc(&masters_in_kgdb); |
485 | else | 473 | else |
486 | atomic_inc(&slaves_in_kgdb); | 474 | atomic_inc(&slaves_in_kgdb); |
487 | kgdb_disable_hw_debug(ks->linux_regs); | 475 | |
476 | if (arch_kgdb_ops.disable_hw_break) | ||
477 | arch_kgdb_ops.disable_hw_break(regs); | ||
488 | 478 | ||
489 | acquirelock: | 479 | acquirelock: |
490 | /* | 480 | /* |
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index d7bda21a106b..37755d621924 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
@@ -1127,7 +1127,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, | |||
1127 | /* special case below */ | 1127 | /* special case below */ |
1128 | } else { | 1128 | } else { |
1129 | kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", | 1129 | kdb_printf("\nEntering kdb (current=0x%p, pid %d) ", |
1130 | kdb_current, kdb_current->pid); | 1130 | kdb_current, kdb_current ? kdb_current->pid : 0); |
1131 | #if defined(CONFIG_SMP) | 1131 | #if defined(CONFIG_SMP) |
1132 | kdb_printf("on processor %d ", raw_smp_processor_id()); | 1132 | kdb_printf("on processor %d ", raw_smp_processor_id()); |
1133 | #endif | 1133 | #endif |
@@ -2603,20 +2603,17 @@ static int kdb_summary(int argc, const char **argv) | |||
2603 | */ | 2603 | */ |
2604 | static int kdb_per_cpu(int argc, const char **argv) | 2604 | static int kdb_per_cpu(int argc, const char **argv) |
2605 | { | 2605 | { |
2606 | char buf[256], fmtstr[64]; | 2606 | char fmtstr[64]; |
2607 | kdb_symtab_t symtab; | 2607 | int cpu, diag, nextarg = 1; |
2608 | cpumask_t suppress = CPU_MASK_NONE; | 2608 | unsigned long addr, symaddr, val, bytesperword = 0, whichcpu = ~0UL; |
2609 | int cpu, diag; | ||
2610 | unsigned long addr, val, bytesperword = 0, whichcpu = ~0UL; | ||
2611 | 2609 | ||
2612 | if (argc < 1 || argc > 3) | 2610 | if (argc < 1 || argc > 3) |
2613 | return KDB_ARGCOUNT; | 2611 | return KDB_ARGCOUNT; |
2614 | 2612 | ||
2615 | snprintf(buf, sizeof(buf), "per_cpu__%s", argv[1]); | 2613 | diag = kdbgetaddrarg(argc, argv, &nextarg, &symaddr, NULL, NULL); |
2616 | if (!kdbgetsymval(buf, &symtab)) { | 2614 | if (diag) |
2617 | kdb_printf("%s is not a per_cpu variable\n", argv[1]); | 2615 | return diag; |
2618 | return KDB_BADADDR; | 2616 | |
2619 | } | ||
2620 | if (argc >= 2) { | 2617 | if (argc >= 2) { |
2621 | diag = kdbgetularg(argv[2], &bytesperword); | 2618 | diag = kdbgetularg(argv[2], &bytesperword); |
2622 | if (diag) | 2619 | if (diag) |
@@ -2649,46 +2646,25 @@ static int kdb_per_cpu(int argc, const char **argv) | |||
2649 | #define KDB_PCU(cpu) 0 | 2646 | #define KDB_PCU(cpu) 0 |
2650 | #endif | 2647 | #endif |
2651 | #endif | 2648 | #endif |
2652 | |||
2653 | for_each_online_cpu(cpu) { | 2649 | for_each_online_cpu(cpu) { |
2650 | if (KDB_FLAG(CMD_INTERRUPT)) | ||
2651 | return 0; | ||
2652 | |||
2654 | if (whichcpu != ~0UL && whichcpu != cpu) | 2653 | if (whichcpu != ~0UL && whichcpu != cpu) |
2655 | continue; | 2654 | continue; |
2656 | addr = symtab.sym_start + KDB_PCU(cpu); | 2655 | addr = symaddr + KDB_PCU(cpu); |
2657 | diag = kdb_getword(&val, addr, bytesperword); | 2656 | diag = kdb_getword(&val, addr, bytesperword); |
2658 | if (diag) { | 2657 | if (diag) { |
2659 | kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to " | 2658 | kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to " |
2660 | "read, diag=%d\n", cpu, addr, diag); | 2659 | "read, diag=%d\n", cpu, addr, diag); |
2661 | continue; | 2660 | continue; |
2662 | } | 2661 | } |
2663 | #ifdef CONFIG_SMP | ||
2664 | if (!val) { | ||
2665 | cpu_set(cpu, suppress); | ||
2666 | continue; | ||
2667 | } | ||
2668 | #endif /* CONFIG_SMP */ | ||
2669 | kdb_printf("%5d ", cpu); | 2662 | kdb_printf("%5d ", cpu); |
2670 | kdb_md_line(fmtstr, addr, | 2663 | kdb_md_line(fmtstr, addr, |
2671 | bytesperword == KDB_WORD_SIZE, | 2664 | bytesperword == KDB_WORD_SIZE, |
2672 | 1, bytesperword, 1, 1, 0); | 2665 | 1, bytesperword, 1, 1, 0); |
2673 | } | 2666 | } |
2674 | if (cpus_weight(suppress) == 0) | ||
2675 | return 0; | ||
2676 | kdb_printf("Zero suppressed cpu(s):"); | ||
2677 | for (cpu = first_cpu(suppress); cpu < num_possible_cpus(); | ||
2678 | cpu = next_cpu(cpu, suppress)) { | ||
2679 | kdb_printf(" %d", cpu); | ||
2680 | if (cpu == num_possible_cpus() - 1 || | ||
2681 | next_cpu(cpu, suppress) != cpu + 1) | ||
2682 | continue; | ||
2683 | while (cpu < num_possible_cpus() && | ||
2684 | next_cpu(cpu, suppress) == cpu + 1) | ||
2685 | ++cpu; | ||
2686 | kdb_printf("-%d", cpu); | ||
2687 | } | ||
2688 | kdb_printf("\n"); | ||
2689 | |||
2690 | #undef KDB_PCU | 2667 | #undef KDB_PCU |
2691 | |||
2692 | return 0; | 2668 | return 0; |
2693 | } | 2669 | } |
2694 | 2670 | ||
diff --git a/samples/Kconfig b/samples/Kconfig index 954a1d550c5f..e03cf0e374d7 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
@@ -54,4 +54,11 @@ config SAMPLE_KFIFO | |||
54 | 54 | ||
55 | If in doubt, say "N" here. | 55 | If in doubt, say "N" here. |
56 | 56 | ||
57 | config SAMPLE_KDB | ||
58 | tristate "Build kdb command exmaple -- loadable modules only" | ||
59 | depends on KGDB_KDB && m | ||
60 | help | ||
61 | Build an example of how to dynamically add the hello | ||
62 | command to the kdb shell. | ||
63 | |||
57 | endif # SAMPLES | 64 | endif # SAMPLES |
diff --git a/samples/Makefile b/samples/Makefile index 76b3c3455c29..f26c0959fd86 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # Makefile for Linux samples code | 1 | # Makefile for Linux samples code |
2 | 2 | ||
3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/ \ |
4 | hw_breakpoint/ kfifo/ | 4 | hw_breakpoint/ kfifo/ kdb/ |
diff --git a/samples/kdb/Makefile b/samples/kdb/Makefile new file mode 100644 index 000000000000..fbedf39d9356 --- /dev/null +++ b/samples/kdb/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_SAMPLE_KDB) += kdb_hello.o | |||
diff --git a/samples/kdb/kdb_hello.c b/samples/kdb/kdb_hello.c new file mode 100644 index 000000000000..c1c2fa0f62c2 --- /dev/null +++ b/samples/kdb/kdb_hello.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Created by: Jason Wessel <jason.wessel@windriver.com> | ||
3 | * | ||
4 | * Copyright (c) 2010 Wind River Systems, Inc. All Rights Reserved. | ||
5 | * | ||
6 | * This file is licensed under the terms of the GNU General Public | ||
7 | * License version 2. This program is licensed "as is" without any | ||
8 | * warranty of any kind, whether express or implied. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/kdb.h> | ||
13 | |||
14 | /* | ||
15 | * All kdb shell command call backs receive argc and argv, where | ||
16 | * argv[0] is the command the end user typed | ||
17 | */ | ||
18 | static int kdb_hello_cmd(int argc, const char **argv) | ||
19 | { | ||
20 | if (argc > 1) | ||
21 | return KDB_ARGCOUNT; | ||
22 | |||
23 | if (argc) | ||
24 | kdb_printf("Hello %s.\n", argv[1]); | ||
25 | else | ||
26 | kdb_printf("Hello world!\n"); | ||
27 | |||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | |||
32 | static int __init kdb_hello_cmd_init(void) | ||
33 | { | ||
34 | /* | ||
35 | * Registration of a dynamically added kdb command is done with | ||
36 | * kdb_register() with the arguments being: | ||
37 | * 1: The name of the shell command | ||
38 | * 2: The function that processes the command | ||
39 | * 3: Description of the usage of any arguments | ||
40 | * 4: Descriptive text when you run help | ||
41 | * 5: Number of characters to complete the command | ||
42 | * 0 == type the whole command | ||
43 | * 1 == match both "g" and "go" for example | ||
44 | */ | ||
45 | kdb_register("hello", kdb_hello_cmd, "[string]", | ||
46 | "Say Hello World or Hello [string]", 0); | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static void __exit kdb_hello_cmd_exit(void) | ||
51 | { | ||
52 | kdb_unregister("hello"); | ||
53 | } | ||
54 | |||
55 | module_init(kdb_hello_cmd_init); | ||
56 | module_exit(kdb_hello_cmd_exit); | ||
57 | |||
58 | MODULE_AUTHOR("WindRiver"); | ||
59 | MODULE_DESCRIPTION("KDB example to add a hello command"); | ||
60 | MODULE_LICENSE("GPL"); | ||