[PATCH] Add support to display memory given the physical address

Ananth N Mavinakayanahalli ananth at in.ibm.com
Mon Aug 2 06:05:54 PDT 2004


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.


More information about the kdb mailing list