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"); | ||
