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.

Reply via email to