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.