Hi Keith,
Here is a patch against kdb-v4.4 for linux-2.6.7 that adds support
to dump memory given a physical address. It adds a command "mdp"
and works similar to commands "md" and the like.
The changes are all in the "common" patch and should work on all
archs. I have tested on x86 and ppc64.
Thanks,
Ananth
diff -Naurp temp/linux-2.6.7/include/linux/kdbprivate.h
linux-2.6.7/include/linux/kdbprivate.h
--- temp/linux-2.6.7/include/linux/kdbprivate.h 2004-07-29 12:31:51.000000000 +0530
+++ linux-2.6.7/include/linux/kdbprivate.h 2004-07-29 11:39:33.000000000 +0530
@@ -109,6 +109,8 @@ extern int kdb_putarea_size(unsigned lon
#define kdb_getarea(x,addr) kdb_getarea_size(&(x), addr, sizeof((x)))
#define kdb_putarea(addr,x) kdb_putarea_size(addr, &(x), sizeof((x)))
+extern int kdb_getphysword(unsigned long *word,
+ unsigned long addr, size_t size);
extern int kdb_getword(unsigned long *, unsigned long, size_t);
extern int kdb_putword(unsigned long, unsigned long, size_t);
diff -Naurp temp/linux-2.6.7/kdb/kdbmain.c linux-2.6.7/kdb/kdbmain.c
--- temp/linux-2.6.7/kdb/kdbmain.c 2004-07-29 12:31:51.000000000 +0530
+++ linux-2.6.7/kdb/kdbmain.c 2004-07-30 15:35:33.000000000 +0530
@@ -2045,7 +2045,7 @@ kdb_mdr(kdb_machreg_t addr, unsigned int
static void
kdb_md_line(const char *fmtstr, kdb_machreg_t addr,
int symbolic, int nosect, int bytesperword,
- int num, int repeat)
+ int num, int repeat, int phys)
{
/* print just one line of data */
kdb_symtab_t symtab;
@@ -2055,10 +2055,16 @@ kdb_md_line(const char *fmtstr, kdb_mach
unsigned long word;
memset(cbuf, '\0', sizeof(cbuf));
- kdb_printf(kdb_machreg_fmt0 " ", addr);
+ if (phys)
+ kdb_printf("phys " kdb_machreg_fmt0 " ", addr);
+ else
+ kdb_printf(kdb_machreg_fmt0 " ", addr);
for (i = 0; i < num && repeat--; i++) {
- if (kdb_getword(&word, addr, bytesperword))
+ if (phys) {
+ if (kdb_getphysword(&word, addr, bytesperword))
+ break;
+ } else if (kdb_getword(&word, addr, bytesperword))
break;
kdb_printf(fmtstr, word);
if (symbolic)
@@ -2129,6 +2135,7 @@ kdb_md(int argc, const char **argv, cons
long offset = 0;
int symbolic = 0;
int valid = 0;
+ int phys = 0;
kdbgetintenv("MDCOUNT", &mdcount);
kdbgetintenv("RADIX", &radix);
@@ -2164,6 +2171,9 @@ kdb_md(int argc, const char **argv, cons
valid = 1;
else if (strcmp(argv[0], "mds") == 0)
valid = 1;
+ else if (strcmp(argv[0], "mdp") == 0) {
+ phys = valid = 1;
+ }
if (!valid)
return KDB_NOTFOUND;
@@ -2262,11 +2272,15 @@ kdb_md(int argc, const char **argv, cons
int n, z, num = (symbolic ? 1 : (16 / bytesperword));
for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) {
- if (kdb_getword(&word, a, bytesperword) || word)
+ if (phys) {
+ if (kdb_getphysword(&word, a, bytesperword)
+ || word)
+ break;
+ } else if (kdb_getword(&word, a, bytesperword) || word)
break;
}
n = min(num, repeat);
- kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, num, repeat);
+ kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, num, repeat,
phys);
addr += bytesperword * n;
repeat -= n;
z = (z + num - 1) / num;
@@ -3488,7 +3502,7 @@ kdb_per_cpu(int argc, const char **argv,
kdb_printf("%5d ", cpu);
kdb_md_line(fmtstr, addr,
bytesperword == sizeof(kdb_machreg_t),
- 1, bytesperword, 1, 1);
+ 1, bytesperword, 1, 1, 0);
}
if (cpus_weight(suppress) == 0)
return 0;
@@ -3694,6 +3708,7 @@ kdb_inittab(void)
kdb_register_repeat("md", kdb_md, "<vaddr>", "Display Memory Contents, also
mdWcN, e.g. md8c1", 1, KDB_REPEAT_NO_ARGS);
kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>", "Display Raw Memory",
0, KDB_REPEAT_NO_ARGS);
+ kdb_register_repeat("mdp", kdb_md, "<paddr> <bytes>", "Display Raw Memory",
0, KDB_REPEAT_NO_ARGS);
kdb_register_repeat("mds", kdb_md, "<vaddr>", "Display Memory Symbolically",
0, KDB_REPEAT_NO_ARGS);
kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>", "Modify Memory
Contents", 0, KDB_REPEAT_NO_ARGS);
kdb_register_repeat("id", kdb_id, "<vaddr>", "Display Instructions", 1,
KDB_REPEAT_NO_ARGS);
@@ -3860,6 +3875,7 @@ EXPORT_SYMBOL(kdb_putarea_size);
EXPORT_SYMBOL(kdb_getuserarea_size);
EXPORT_SYMBOL(kdb_putuserarea_size);
EXPORT_SYMBOL(kdb_getword);
+EXPORT_SYMBOL(kdb_getphysword);
EXPORT_SYMBOL(kdb_putword);
EXPORT_SYMBOL(kdbgetularg);
EXPORT_SYMBOL(kdbgetenv);
diff -Naurp temp/linux-2.6.7/kdb/kdbsupport.c linux-2.6.7/kdb/kdbsupport.c
--- temp/linux-2.6.7/kdb/kdbsupport.c 2004-07-29 12:31:51.000000000 +0530
+++ linux-2.6.7/kdb/kdbsupport.c 2004-07-30 15:40:30.000000000 +0530
@@ -739,6 +739,92 @@ int kdb_putarea_size(unsigned long addr,
return(ret);
}
+/*
+ * kdb_getphys
+ *
+ * Read data from a physical address. Validate the address is in range,
+ * use kmap_atomic() to get data
+ *
+ * Similar to kdb_getarea() - but for phys addresses
+ *
+ * Inputs:
+ * res Pointer to the word to receive the result
+ * addr Physical address of the area to copy
+ * size Size of the area
+ * Outputs:
+ * none.
+ * Returns:
+ * 0 for success, < 0 for error.
+ * Locking:
+ * none.
+ */
+static int kdb_getphys(void *res, unsigned long addr, size_t size)
+{
+ unsigned long pfn;
+ void *vaddr;
+ struct page *page;
+
+ pfn = (addr >> PAGE_SHIFT);
+ if (!pfn_valid(pfn))
+ return 1;
+ page = pfn_to_page(pfn);
+ vaddr = kmap_atomic(page, KM_KDB);
+ memcpy(res, vaddr + (addr & (PAGE_SIZE -1)), size);
+ kunmap_atomic(vaddr, KM_KDB);
+
+ return 0;
+}
+
+/*
+ * kdb_getphysword
+ *
+ * Inputs:
+ * word Pointer to the word to receive the result.
+ * addr Address of the area to copy.
+ * size Size of the area.
+ * Outputs:
+ * none.
+ * Returns:
+ * 0 for success, < 0 for error.
+ * Locking:
+ * none.
+ */
+int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size)
+{
+ int diag;
+ __u8 w1;
+ __u16 w2;
+ __u32 w4;
+ __u64 w8;
+ *word = 0; /* Default value if addr or size is invalid */
+
+ switch (size) {
+ case 1:
+ if (!(diag = kdb_getphys(&w1, addr, sizeof(w1))))
+ *word = w1;
+ break;
+ case 2:
+ if (!(diag = kdb_getphys(&w2, addr, sizeof(w2))))
+ *word = w2;
+ break;
+ case 4:
+ if (!(diag = kdb_getphys(&w4, addr, sizeof(w4))))
+ *word = w4;
+ break;
+ case 8:
+ if (size <= sizeof(*word)) {
+ if (!(diag = kdb_getphys(&w8, addr, sizeof(w8))))
+ *word = w8;
+ break;
+ }
+ /* drop through */
+ default:
+ diag = KDB_BADWIDTH;
+ kdb_printf("kdb_getphysword: bad width %ld\n", (long) size);
+ }
+ return(diag);
+}
+
/*
* kdb_getword
*
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.