]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Oct 2010 18:49:38 +0000 (11:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 29 Oct 2010 18:49:38 +0000 (11:49 -0700)
* '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

15 files changed:
Documentation/DocBook/kgdb.tmpl
arch/arm/include/asm/kgdb.h
arch/arm/kernel/kgdb.c
arch/blackfin/kernel/kgdb.c
arch/powerpc/include/asm/kgdb.h
arch/powerpc/kernel/kgdb.c
arch/x86/kernel/kgdb.c
drivers/misc/kgdbts.c
include/linux/kgdb.h
kernel/debug/debug_core.c
kernel/debug/kdb/kdb_main.c
samples/Kconfig
samples/Makefile
samples/kdb/Makefile [new file with mode: 0644]
samples/kdb/kdb_hello.c [new file with mode: 0644]

index 490d862c5f0ddffc748ebb56de4255ef0769c115..d71b57fcf116bcb263b8a761d2ebf87b3231f56a 100644 (file)
@@ -710,7 +710,18 @@ Task Addr       Pid   Parent [*] cpu State Thread     Command
         <listitem><para>A simple shell</para></listitem>
         <listitem><para>The kdb core command set</para></listitem>
         <listitem><para>A registration API to register additional kdb shell commands.</para>
-        <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>
+       <itemizedlist>
+        <listitem><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>
+        <listitem><para>For an example of how to dynamically register
+        a new kdb command you can build the kdb_hello.ko kernel module
+        from samples/kdb/kdb_hello.c.  To build this example you can
+        set CONFIG_SAMPLES=y and CONFIG_SAMPLE_KDB=m in your kernel
+        config.  Later run "modprobe kdb_hello" and the next time you
+        enter the kdb shell, you can run the "hello"
+        command.</para></listitem>
+       </itemizedlist></listitem>
         <listitem><para>The implementation for kdb_printf() which
         emits messages directly to I/O drivers, bypassing the kernel
         log.</para></listitem>
index 08265993227fc1d03bec79f7a420f63c005a3f2c..48066ce9ea34f64961111c487fbc4f26e037b842 100644 (file)
@@ -70,7 +70,8 @@ extern int kgdb_fault_expected;
 #define _GP_REGS               16
 #define _FP_REGS               8
 #define _EXTRA_REGS            2
-#define DBG_MAX_REG_NUM                (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
+#define GDB_MAX_REGS           (_GP_REGS + (_FP_REGS * 3) + _EXTRA_REGS)
+#define DBG_MAX_REG_NUM                (_GP_REGS + _FP_REGS + _EXTRA_REGS)
 
 #define KGDB_MAX_NO_CPUS       1
 #define BUFMAX                 400
@@ -93,7 +94,7 @@ extern int kgdb_fault_expected;
 #define _SPT                   13
 #define _LR                    14
 #define _PC                    15
-#define _CPSR                  (DBG_MAX_REG_NUM - 1)
+#define _CPSR                  (GDB_MAX_REGS - 1)
 
 /*
  * So that we can denote the end of a frame for tracing,
index d6e8b4d2e60dacde3ceff47584fe43b75ddb496d..778c2f7024ff57304227ce67665e749f39b05fc7 100644 (file)
@@ -79,7 +79,7 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task)
                return;
 
        /* Initialize to zero */
-       for (regno = 0; regno < DBG_MAX_REG_NUM; regno++)
+       for (regno = 0; regno < GDB_MAX_REGS; regno++)
                gdb_regs[regno] = 0;
 
        /* Otherwise, we have only some registers from switch_to() */
index 08bc44ea688313976e6d54b6cbb679e395271159..edae461b1c545d4f02e3c91ac664ec55012b9c4c 100644 (file)
@@ -320,7 +320,7 @@ static void bfin_correct_hw_break(void)
        }
 }
 
-void kgdb_disable_hw_debug(struct pt_regs *regs)
+static void bfin_disable_hw_debug(struct pt_regs *regs)
 {
        /* Disable hardware debugging while we are in kgdb */
        bfin_write_WPIACTL(0);
@@ -406,6 +406,7 @@ struct kgdb_arch arch_kgdb_ops = {
 #endif
        .set_hw_breakpoint = bfin_set_hw_break,
        .remove_hw_breakpoint = bfin_remove_hw_break,
+       .disable_hw_break = bfin_disable_hw_debug,
        .remove_all_hw_break = bfin_remove_all_hw_break,
        .correct_hw_break = bfin_correct_hw_break,
 };
index edd217006d270dc8ec112467d1d6fa048c8e0299..9db24e77b9f4bab53b471950b76ac626884e9960 100644 (file)
@@ -31,6 +31,7 @@ static inline void arch_kgdb_breakpoint(void)
        asm(".long 0x7d821008"); /* twge r2, r2 */
 }
 #define CACHE_FLUSH_IS_SAFE    1
+#define DBG_MAX_REG_NUM     70
 
 /* The number bytes of registers we have to save depends on a few
  * things.  For 64bit we default to not including vector registers and
index 7f61a3ac787c9ae6f848939d311d8a8756733cfa..7a9db64f3f0438f8bf366b9cb2244f1ef3178004 100644 (file)
@@ -194,40 +194,6 @@ static int kgdb_dabr_match(struct pt_regs *regs)
        ptr = (unsigned long *)ptr32; \
        } while (0)
 
-
-void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
-{
-       unsigned long *ptr = gdb_regs;
-       int reg;
-
-       memset(gdb_regs, 0, NUMREGBYTES);
-
-       for (reg = 0; reg < 32; reg++)
-               PACK64(ptr, regs->gpr[reg]);
-
-#ifdef CONFIG_FSL_BOOKE
-#ifdef CONFIG_SPE
-       for (reg = 0; reg < 32; reg++)
-               PACK64(ptr, current->thread.evr[reg]);
-#else
-       ptr += 32;
-#endif
-#else
-       /* fp registers not used by kernel, leave zero */
-       ptr += 32 * 8 / sizeof(long);
-#endif
-
-       PACK64(ptr, regs->nip);
-       PACK64(ptr, regs->msr);
-       PACK32(ptr, regs->ccr);
-       PACK64(ptr, regs->link);
-       PACK64(ptr, regs->ctr);
-       PACK32(ptr, regs->xer);
-
-       BUG_ON((unsigned long)ptr >
-              (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
-}
-
 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 {
        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)
               (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
 }
 
-#define UNPACK64(dest, ptr) do { dest = *(ptr++); } while (0)
+#define GDB_SIZEOF_REG sizeof(unsigned long)
+#define GDB_SIZEOF_REG_U32 sizeof(u32)
 
-#define UNPACK32(dest, ptr) do {       \
-       u32 *ptr32;                   \
-       ptr32 = (u32 *)ptr;           \
-       dest = *(ptr32++);            \
-       ptr = (unsigned long *)ptr32; \
-       } while (0)
+#ifdef CONFIG_FSL_BOOKE
+#define GDB_SIZEOF_FLOAT_REG sizeof(unsigned long)
+#else
+#define GDB_SIZEOF_FLOAT_REG sizeof(u64)
+#endif
 
-void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
 {
-       unsigned long *ptr = gdb_regs;
-       int reg;
-
-       for (reg = 0; reg < 32; reg++)
-               UNPACK64(regs->gpr[reg], ptr);
+       { "r0", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[0]) },
+       { "r1", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[1]) },
+       { "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[2]) },
+       { "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[3]) },
+       { "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[4]) },
+       { "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[5]) },
+       { "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[6]) },
+       { "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[7]) },
+       { "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[8]) },
+       { "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[9]) },
+       { "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[10]) },
+       { "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[11]) },
+       { "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[12]) },
+       { "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[13]) },
+       { "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[14]) },
+       { "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[15]) },
+       { "r16", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[16]) },
+       { "r17", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[17]) },
+       { "r18", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[18]) },
+       { "r19", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[19]) },
+       { "r20", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[20]) },
+       { "r21", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[21]) },
+       { "r22", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[22]) },
+       { "r23", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[23]) },
+       { "r24", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[24]) },
+       { "r25", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[25]) },
+       { "r26", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[26]) },
+       { "r27", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[27]) },
+       { "r28", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[28]) },
+       { "r29", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[29]) },
+       { "r30", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[30]) },
+       { "r31", GDB_SIZEOF_REG, offsetof(struct pt_regs, gpr[31]) },
+
+       { "f0", GDB_SIZEOF_FLOAT_REG, 0 },
+       { "f1", GDB_SIZEOF_FLOAT_REG, 1 },
+       { "f2", GDB_SIZEOF_FLOAT_REG, 2 },
+       { "f3", GDB_SIZEOF_FLOAT_REG, 3 },
+       { "f4", GDB_SIZEOF_FLOAT_REG, 4 },
+       { "f5", GDB_SIZEOF_FLOAT_REG, 5 },
+       { "f6", GDB_SIZEOF_FLOAT_REG, 6 },
+       { "f7", GDB_SIZEOF_FLOAT_REG, 7 },
+       { "f8", GDB_SIZEOF_FLOAT_REG, 8 },
+       { "f9", GDB_SIZEOF_FLOAT_REG, 9 },
+       { "f10", GDB_SIZEOF_FLOAT_REG, 10 },
+       { "f11", GDB_SIZEOF_FLOAT_REG, 11 },
+       { "f12", GDB_SIZEOF_FLOAT_REG, 12 },
+       { "f13", GDB_SIZEOF_FLOAT_REG, 13 },
+       { "f14", GDB_SIZEOF_FLOAT_REG, 14 },
+       { "f15", GDB_SIZEOF_FLOAT_REG, 15 },
+       { "f16", GDB_SIZEOF_FLOAT_REG, 16 },
+       { "f17", GDB_SIZEOF_FLOAT_REG, 17 },
+       { "f18", GDB_SIZEOF_FLOAT_REG, 18 },
+       { "f19", GDB_SIZEOF_FLOAT_REG, 19 },
+       { "f20", GDB_SIZEOF_FLOAT_REG, 20 },
+       { "f21", GDB_SIZEOF_FLOAT_REG, 21 },
+       { "f22", GDB_SIZEOF_FLOAT_REG, 22 },
+       { "f23", GDB_SIZEOF_FLOAT_REG, 23 },
+       { "f24", GDB_SIZEOF_FLOAT_REG, 24 },
+       { "f25", GDB_SIZEOF_FLOAT_REG, 25 },
+       { "f26", GDB_SIZEOF_FLOAT_REG, 26 },
+       { "f27", GDB_SIZEOF_FLOAT_REG, 27 },
+       { "f28", GDB_SIZEOF_FLOAT_REG, 28 },
+       { "f29", GDB_SIZEOF_FLOAT_REG, 29 },
+       { "f30", GDB_SIZEOF_FLOAT_REG, 30 },
+       { "f31", GDB_SIZEOF_FLOAT_REG, 31 },
+
+       { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, nip) },
+       { "msr", GDB_SIZEOF_REG, offsetof(struct pt_regs, msr) },
+       { "cr", GDB_SIZEOF_REG_U32, offsetof(struct pt_regs, ccr) },
+       { "lr", GDB_SIZEOF_REG, offsetof(struct pt_regs, link) },
+       { "ctr", GDB_SIZEOF_REG_U32, offsetof(struct pt_regs, ctr) },
+       { "xer", GDB_SIZEOF_REG, offsetof(struct pt_regs, xer) },
+};
 
-#ifdef CONFIG_FSL_BOOKE
-#ifdef CONFIG_SPE
-       for (reg = 0; reg < 32; reg++)
-               UNPACK64(current->thread.evr[reg], ptr);
+char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (regno >= DBG_MAX_REG_NUM || regno < 0)
+               return NULL;
+
+       if (regno < 32 || regno >= 64)
+               /* First 0 -> 31 gpr registers*/
+               /* pc, msr, ls... registers 64 -> 69 */
+               memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
+                               dbg_reg_def[regno].size);
+
+       if (regno >= 32 && regno < 64) {
+               /* FP registers 32 -> 63 */
+#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
+               if (current)
+                       memcpy(mem, current->thread.evr[regno-32],
+                                       dbg_reg_def[regno].size);
 #else
-       ptr += 32;
+               /* fp registers not used by kernel, leave zero */
+               memset(mem, 0, dbg_reg_def[regno].size);
 #endif
+       }
+
+       return dbg_reg_def[regno].name;
+}
+
+int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
+{
+       if (regno >= DBG_MAX_REG_NUM || regno < 0)
+               return -EINVAL;
+
+       if (regno < 32 || regno >= 64)
+               /* First 0 -> 31 gpr registers*/
+               /* pc, msr, ls... registers 64 -> 69 */
+               memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
+                               dbg_reg_def[regno].size);
+
+       if (regno >= 32 && regno < 64) {
+               /* FP registers 32 -> 63 */
+#if defined(CONFIG_FSL_BOOKE) && defined(CONFIG_SPE)
+               memcpy(current->thread.evr[regno-32], mem,
+                               dbg_reg_def[regno].size);
 #else
-       /* fp registers not used by kernel, leave zero */
-       ptr += 32 * 8 / sizeof(int);
+               /* fp registers not used by kernel, leave zero */
+               return 0;
 #endif
+       }
 
-       UNPACK64(regs->nip, ptr);
-       UNPACK64(regs->msr, ptr);
-       UNPACK32(regs->ccr, ptr);
-       UNPACK64(regs->link, ptr);
-       UNPACK64(regs->ctr, ptr);
-       UNPACK32(regs->xer, ptr);
-
-       BUG_ON((unsigned long)ptr >
-              (unsigned long)(((void *)gdb_regs) + NUMREGBYTES));
+       return 0;
 }
 
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
index d81cfebb848f2fd5c61e7a4524a26c00d3d2f66d..ec592caac4b4e11b5d7ac0bc2986d6617ac4b90b 100644 (file)
@@ -387,7 +387,7 @@ kgdb_set_hw_break(unsigned long addr, int len, enum kgdb_bptype bptype)
  *     disable hardware debugging while it is processing gdb packets or
  *     handling exception.
  */
-void kgdb_disable_hw_debug(struct pt_regs *regs)
+static void kgdb_disable_hw_debug(struct pt_regs *regs)
 {
        int i;
        int cpu = raw_smp_processor_id();
@@ -724,6 +724,7 @@ struct kgdb_arch arch_kgdb_ops = {
        .flags                  = KGDB_HW_BREAKPOINT,
        .set_hw_breakpoint      = kgdb_set_hw_break,
        .remove_hw_breakpoint   = kgdb_remove_hw_break,
+       .disable_hw_break       = kgdb_disable_hw_debug,
        .remove_all_hw_break    = kgdb_remove_all_hw_break,
        .correct_hw_break       = kgdb_correct_hw_break,
 };
index 72450237a0f418e0a41552cbdefd7943545add78..59c118c19a910e9950a04a069dacf62352a25e9a 100644 (file)
@@ -1044,12 +1044,6 @@ static int __init init_kgdbts(void)
        return configure_kgdbts();
 }
 
-static void cleanup_kgdbts(void)
-{
-       if (configured == 1)
-               kgdb_unregister_io_module(&kgdbts_io_ops);
-}
-
 static int kgdbts_get_char(void)
 {
        int val = 0;
@@ -1081,10 +1075,8 @@ static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp)
                return 0;
        }
 
-       if (kgdb_connected) {
-               printk(KERN_ERR
-              "kgdbts: Cannot reconfigure while KGDB is connected.\n");
-
+       if (configured == 1) {
+               printk(KERN_ERR "kgdbts: ERROR: Already configured and running.\n");
                return -EBUSY;
        }
 
@@ -1093,9 +1085,6 @@ static int param_set_kgdbts_var(const char *kmessage, struct kernel_param *kp)
        if (config[len - 1] == '\n')
                config[len - 1] = '\0';
 
-       if (configured == 1)
-               cleanup_kgdbts();
-
        /* Go and configure with the new params. */
        return configure_kgdbts();
 }
@@ -1123,7 +1112,6 @@ static struct kgdb_io kgdbts_io_ops = {
 };
 
 module_init(init_kgdbts);
-module_exit(cleanup_kgdbts);
 module_param_call(kgdbts, param_set_kgdbts_var, param_get_string, &kps, 0644);
 MODULE_PARM_DESC(kgdbts, "<A|V1|V2>[F#|S#][N#]");
 MODULE_DESCRIPTION("KGDB Test Suite");
index cc96f0f23e04a545ffd3dfc7faff7d27fb7d61f1..092e4250a4583f735140221d5f4dd7a4667d3d69 100644 (file)
@@ -35,16 +35,6 @@ struct pt_regs;
  */
 extern int kgdb_skipexception(int exception, struct pt_regs *regs);
 
-/**
- *     kgdb_disable_hw_debug - (optional) Disable hardware debugging hook
- *     @regs: Current &struct pt_regs.
- *
- *     This function will be called if the particular architecture must
- *     disable hardware debugging while it is processing gdb packets or
- *     handling exception.
- */
-extern void kgdb_disable_hw_debug(struct pt_regs *regs);
-
 struct tasklet_struct;
 struct task_struct;
 struct uart_port;
@@ -243,6 +233,8 @@ extern void kgdb_arch_late(void);
  * breakpoint.
  * @remove_hw_breakpoint: Allow an architecture to specify how to remove a
  * hardware breakpoint.
+ * @disable_hw_break: Allow an architecture to specify how to disable
+ * hardware breakpoints for a single cpu.
  * @remove_all_hw_break: Allow an architecture to specify how to remove all
  * hardware breakpoints.
  * @correct_hw_break: Allow an architecture to specify how to correct the
@@ -256,6 +248,7 @@ struct kgdb_arch {
        int     (*remove_breakpoint)(unsigned long, char *);
        int     (*set_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
        int     (*remove_hw_breakpoint)(unsigned long, int, enum kgdb_bptype);
+       void    (*disable_hw_break)(struct pt_regs *regs);
        void    (*remove_all_hw_break)(void);
        void    (*correct_hw_break)(void);
 };
index fec596da9bd0c19b2e6959098e7cb50ed0564d79..cefd4a11f6d9e27b2ae146ef0be6bf940bf41587 100644 (file)
@@ -209,18 +209,6 @@ int __weak kgdb_skipexception(int exception, struct pt_regs *regs)
        return 0;
 }
 
-/**
- *     kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb.
- *     @regs: Current &struct pt_regs.
- *
- *     This function will be called if the particular architecture must
- *     disable hardware debugging while it is processing gdb packets or
- *     handling exception.
- */
-void __weak kgdb_disable_hw_debug(struct pt_regs *regs)
-{
-}
-
 /*
  * Some architectures need cache flushes when we set/clear a
  * breakpoint:
@@ -484,7 +472,9 @@ static int kgdb_cpu_enter(struct kgdb_state *ks, struct pt_regs *regs,
                atomic_inc(&masters_in_kgdb);
        else
                atomic_inc(&slaves_in_kgdb);
-       kgdb_disable_hw_debug(ks->linux_regs);
+
+       if (arch_kgdb_ops.disable_hw_break)
+               arch_kgdb_ops.disable_hw_break(regs);
 
 acquirelock:
        /*
index d7bda21a106b572ee95c22fd1e59524914944ed4..37755d621924e5256b3494d5e94b57415be5a3f1 100644 (file)
@@ -1127,7 +1127,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
                /* special case below */
        } else {
                kdb_printf("\nEntering kdb (current=0x%p, pid %d) ",
-                          kdb_current, kdb_current->pid);
+                          kdb_current, kdb_current ? kdb_current->pid : 0);
 #if defined(CONFIG_SMP)
                kdb_printf("on processor %d ", raw_smp_processor_id());
 #endif
@@ -2603,20 +2603,17 @@ static int kdb_summary(int argc, const char **argv)
  */
 static int kdb_per_cpu(int argc, const char **argv)
 {
-       char buf[256], fmtstr[64];
-       kdb_symtab_t symtab;
-       cpumask_t suppress = CPU_MASK_NONE;
-       int cpu, diag;
-       unsigned long addr, val, bytesperword = 0, whichcpu = ~0UL;
+       char fmtstr[64];
+       int cpu, diag, nextarg = 1;
+       unsigned long addr, symaddr, val, bytesperword = 0, whichcpu = ~0UL;
 
        if (argc < 1 || argc > 3)
                return KDB_ARGCOUNT;
 
-       snprintf(buf, sizeof(buf), "per_cpu__%s", argv[1]);
-       if (!kdbgetsymval(buf, &symtab)) {
-               kdb_printf("%s is not a per_cpu variable\n", argv[1]);
-               return KDB_BADADDR;
-       }
+       diag = kdbgetaddrarg(argc, argv, &nextarg, &symaddr, NULL, NULL);
+       if (diag)
+               return diag;
+
        if (argc >= 2) {
                diag = kdbgetularg(argv[2], &bytesperword);
                if (diag)
@@ -2649,46 +2646,25 @@ static int kdb_per_cpu(int argc, const char **argv)
 #define KDB_PCU(cpu) 0
 #endif
 #endif
-
        for_each_online_cpu(cpu) {
+               if (KDB_FLAG(CMD_INTERRUPT))
+                       return 0;
+
                if (whichcpu != ~0UL && whichcpu != cpu)
                        continue;
-               addr = symtab.sym_start + KDB_PCU(cpu);
+               addr = symaddr + KDB_PCU(cpu);
                diag = kdb_getword(&val, addr, bytesperword);
                if (diag) {
                        kdb_printf("%5d " kdb_bfd_vma_fmt0 " - unable to "
                                   "read, diag=%d\n", cpu, addr, diag);
                        continue;
                }
-#ifdef CONFIG_SMP
-               if (!val) {
-                       cpu_set(cpu, suppress);
-                       continue;
-               }
-#endif /* CONFIG_SMP */
                kdb_printf("%5d ", cpu);
                kdb_md_line(fmtstr, addr,
                        bytesperword == KDB_WORD_SIZE,
                        1, bytesperword, 1, 1, 0);
        }
-       if (cpus_weight(suppress) == 0)
-               return 0;
-       kdb_printf("Zero suppressed cpu(s):");
-       for (cpu = first_cpu(suppress); cpu < num_possible_cpus();
-            cpu = next_cpu(cpu, suppress)) {
-               kdb_printf(" %d", cpu);
-               if (cpu == num_possible_cpus() - 1 ||
-                   next_cpu(cpu, suppress) != cpu + 1)
-                       continue;
-               while (cpu < num_possible_cpus() &&
-                      next_cpu(cpu, suppress) == cpu + 1)
-                       ++cpu;
-               kdb_printf("-%d", cpu);
-       }
-       kdb_printf("\n");
-
 #undef KDB_PCU
-
        return 0;
 }
 
index 954a1d550c5f04cf4e344c1dc5e47b8708d044d8..e03cf0e374d7e85e72ec93f8ae23e1d5cb480544 100644 (file)
@@ -54,4 +54,11 @@ config SAMPLE_KFIFO
 
          If in doubt, say "N" here.
 
+config SAMPLE_KDB
+       tristate "Build kdb command exmaple -- loadable modules only"
+       depends on KGDB_KDB && m
+       help
+         Build an example of how to dynamically add the hello
+         command to the kdb shell.
+
 endif # SAMPLES
index 76b3c3455c292b844c1cc14ec138cddf58d46a20..f26c0959fd861645ae2b179af02534b71ef4da2d 100644 (file)
@@ -1,4 +1,4 @@
 # Makefile for Linux samples code
 
 obj-$(CONFIG_SAMPLES)  += kobject/ kprobes/ tracepoints/ trace_events/ \
-                          hw_breakpoint/ kfifo/
+                          hw_breakpoint/ kfifo/ kdb/
diff --git a/samples/kdb/Makefile b/samples/kdb/Makefile
new file mode 100644 (file)
index 0000000..fbedf39
--- /dev/null
@@ -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 (file)
index 0000000..c1c2fa0
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Created by: Jason Wessel <jason.wessel@windriver.com>
+ *
+ * Copyright (c) 2010 Wind River Systems, Inc.  All Rights Reserved.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kdb.h>
+
+/*
+ * All kdb shell command call backs receive argc and argv, where
+ * argv[0] is the command the end user typed
+ */
+static int kdb_hello_cmd(int argc, const char **argv)
+{
+       if (argc > 1)
+               return KDB_ARGCOUNT;
+
+       if (argc)
+               kdb_printf("Hello %s.\n", argv[1]);
+       else
+               kdb_printf("Hello world!\n");
+
+       return 0;
+}
+
+
+static int __init kdb_hello_cmd_init(void)
+{
+       /*
+        * Registration of a dynamically added kdb command is done with
+        * kdb_register() with the arguments being:
+        *   1: The name of the shell command
+        *   2: The function that processes the command
+        *   3: Description of the usage of any arguments
+        *   4: Descriptive text when you run help
+        *   5: Number of characters to complete the command
+        *      0 == type the whole command
+        *      1 == match both "g" and "go" for example
+        */
+       kdb_register("hello", kdb_hello_cmd, "[string]",
+                    "Say Hello World or Hello [string]", 0);
+       return 0;
+}
+
+static void __exit kdb_hello_cmd_exit(void)
+{
+       kdb_unregister("hello");
+}
+
+module_init(kdb_hello_cmd_init);
+module_exit(kdb_hello_cmd_exit);
+
+MODULE_AUTHOR("WindRiver");
+MODULE_DESCRIPTION("KDB example to add a hello command");
+MODULE_LICENSE("GPL");