On Thu, 3 Jun 2004 11:51:45 -0500, 
[EMAIL PROTECTED] wrote:
>Is anybody working on per_cpu variable printing for KDB?
>I'm finding that looking up per-cpu values is tedious and
>error prone, esp. on systems with more than a few cpu's.

In my tree, to be released as part of kdb v4.4-2.6.6-common-2 this
weekend.  It goes over kdb v4.4-2.6.6-common-1.


Index: linux/Documentation/kdb/kdb.mm
===================================================================
--- linux.orig/Documentation/kdb/kdb.mm Fri Jun  4 14:02:29 2004
+++ linux/Documentation/kdb/kdb.mm      Fri Jun  4 16:31:36 2004
@@ -1,4 +1,4 @@
-.TH KDB 8 "May 17, 2004"
+.TH KDB 8 "June 4, 2004"
 .hy 0
 .SH NAME
 Built-in Kernel Debugger for Linux - v4.4
@@ -148,6 +148,7 @@ mdr Display raw memory contents
 mds    Display memory contents symbolically
 mm     Modify memory contents, words
 mmW    Modify memory contents, bytes
+per_cpu        Display per_cpu variables
 pid    Change the default process context
 ps     Display process status
 reboot Reboot the machine
@@ -267,6 +268,18 @@ lsmod
 Internal command to list modules.
 This does not use any kernel nor user space services so can be used at any time.
 .TP 8
+per_cpu <variable_name> [<length>] [<cpu>]
+Display the values of a per_cpu variable, the variable_name is
+specified without the \fIper_cpu__\fR prefix.
+Length is the length of the variable, 1-8, if omitted or 0 it defaults
+to the size of the machine's register.
+To display the variable on a specific cpu, the third parameter is the
+cpu number.
+When the third parameter is omitted, the variable's value is printed
+from all cpus, except that zero values are suppressed.
+For each cpu, per_cpu prints the cpu number, the address of the
+variable and its value.
+.TP 8
 pid <number>
 Change the current process context, with no parameters it displays the
 current process.
Index: linux/kdb/ChangeLog
===================================================================
--- linux.orig/kdb/ChangeLog    Fri Jun  4 14:04:39 2004
+++ linux/kdb/ChangeLog Fri Jun  4 14:07:52 2004
@@ -2,6 +2,7 @@
 
        * Avoid recursion problems in kdb_init().
        * Add standard archkdb commands.
+       * Add per_cpu command.
 
 2004-05-23 Keith Owens  <[EMAIL PROTECTED]>
 
Index: linux/kdb/kdbmain.c
===================================================================
--- linux.orig/kdb/kdbmain.c    Fri Jun  4 14:02:31 2004
+++ linux/kdb/kdbmain.c Fri Jun  4 16:59:31 2004
@@ -3408,6 +3408,109 @@ kdb_summary(int argc, const char **argv,
        return 0;
 }
 
+/*
+ * kdb_per_cpu
+ *
+ *     This function implements the 'per_cpu' command.
+ *
+ * Inputs:
+ *     argc    argument count
+ *     argv    argument vector
+ *     envp    environment vector
+ *     regs    registers at time kdb was entered.
+ * Outputs:
+ *     None.
+ * Returns:
+ *     zero for success, a kdb diagnostic if error
+ * Locking:
+ *     none.
+ * Remarks:
+ */
+
+static int
+kdb_per_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs)
+{
+       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;
+
+       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;
+       }
+       if (argc >=2 && (diag = kdbgetularg(argv[2], &bytesperword)))
+               return diag;
+       if (!bytesperword)
+               bytesperword = sizeof(kdb_machreg_t);
+       else if (bytesperword > sizeof(kdb_machreg_t))
+               return KDB_BADWIDTH;
+       sprintf(fmtstr, "%%0%dlx ", (int)(2*bytesperword));
+       if (argc >= 3) {
+               if ((diag = kdbgetularg(argv[3], &whichcpu)))
+                       return diag;
+               if (!cpu_online(whichcpu)) {
+                       kdb_printf("cpu %ld is not online\n", whichcpu);
+                       return KDB_BADCPUNUM;
+               }
+       }
+
+       /* Most architectures use __per_cpu_offset[cpu], some use
+        * __per_cpu_offset(cpu), smp has no __per_cpu_offset.
+        */
+#ifdef __per_cpu_offset
+#define KDB_PCU(cpu) __per_cpu_offset(cpu)
+#else
+#ifdef CONFIG_SMP
+#define KDB_PCU(cpu) __per_cpu_offset[cpu]
+#else
+#define KDB_PCU(cpu) 0
+#endif
+#endif
+
+       for_each_online_cpu(cpu) {
+               if (whichcpu != ~0UL && whichcpu != cpu)
+                       continue;
+               addr = symtab.sym_start + KDB_PCU(cpu);
+               if ((diag = kdb_getword(&val, addr, bytesperword))) {
+                       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 == sizeof(kdb_machreg_t),
+                       1, bytesperword, 1, 1);
+       }
+       if (cpus_weight(suppress) == 0)
+               return 0;
+       kdb_printf("Zero suppressed cpu(s):");
+       for (cpu = first_cpu(suppress); cpu < NR_CPUS; cpu = next_cpu(cpu, suppress)) {
+               kdb_printf(" %d", cpu);
+               if (cpu == NR_CPUS-1 || next_cpu(cpu, suppress) != cpu + 1)
+                       continue;
+               while (cpu < NR_CPUS && next_cpu(cpu, suppress) == cpu + 1)
+                       ++cpu;
+               kdb_printf("-%d", cpu);
+       }
+       kdb_printf("\n");
+
+#undef KDB_PCU
+
+       return 0;
+}
+
 
 /*
  * kdb_register_repeat
@@ -3625,6 +3728,7 @@ kdb_inittab(void)
        kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"", "Define a 
set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>", "Send a signal to a 
process", 0, KDB_REPEAT_NONE);
        kdb_register_repeat("summary", kdb_summary, "", "Summarize the system", 4, 
KDB_REPEAT_NONE);
+       kdb_register_repeat("per_cpu", kdb_per_cpu, "", "Display per_cpu variables", 
3, KDB_REPEAT_NONE);
 
        /* Any kdb commands that are not in the base code but are required
         * earlier than normal initcall processing.
Index: linux/scripts/kallsyms.c
===================================================================
--- linux.orig/scripts/kallsyms.c       Fri Jun  4 14:02:29 2004
+++ linux/scripts/kallsyms.c    Fri Jun  4 15:45:59 2004
@@ -22,7 +22,7 @@ struct sym_entry {
 
 static struct sym_entry *table;
 static int size, cnt;
-static unsigned long long _stext, _etext, _sinittext, _einittext, _end;
+static unsigned long long _stext, _etext, _sinittext, _einittext, __per_cpu_end;
 #ifdef CONFIG_KDB
 #define kdb 1
 #else
@@ -57,7 +57,7 @@ read_symbol(FILE *in, struct sym_entry *
 static int
 symbol_valid(struct sym_entry *s)
 {
-       if ((s->addr < _stext || (kdb && s->addr > _end) || (!kdb && s->addr > _etext))
+       if ((s->addr < _stext || (kdb && s->addr > __per_cpu_end) || (!kdb && s->addr 
> _etext))
            && (s->addr < _sinittext || s->addr > _einittext))
                return 0;
 
@@ -99,8 +99,8 @@ read_map(FILE *in)
                        _sinittext = table[i].addr;
                if (strcmp(table[i].sym, "_einittext") == 0)
                        _einittext = table[i].addr;
-               if (kdb && strcmp(table[i].sym, "_end") == 0)
-                       _end = table[i].addr;
+               if (kdb && strcmp(table[i].sym, "__per_cpu_end") == 0)
+                       __per_cpu_end = table[i].addr;
        }
 }
 


---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.

Reply via email to