Add commands that are like the other "md" commands but that allow you to read memory that's in the IO space.
Signed-off-by: Douglas Anderson <diand...@chromium.org> --- kernel/debug/kdb/kdb_main.c | 38 +++++++++++++++++++++++---- kernel/debug/kdb/kdb_private.h | 1 + kernel/debug/kdb/kdb_support.c | 48 ++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index be72657741a5..a90d1e1482c2 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c @@ -1526,7 +1526,7 @@ static int kdb_mdr(int argc, const char **argv) */ static void kdb_md_line(const char *fmtstr, unsigned long addr, bool symbolic, bool nosect, int bytesperword, - int num, int repeat, bool phys) + int num, int repeat, bool phys, bool do_iomap) { /* print just one line of data */ kdb_symtab_t symtab; @@ -1543,7 +1543,10 @@ static void kdb_md_line(const char *fmtstr, unsigned long addr, kdb_printf(kdb_machreg_fmt0 " ", addr); for (i = 0; i < num && repeat--; i++) { - if (phys) { + if (do_iomap) { + if (kdb_getioword(&word, addr, bytesperword)) + break; + } else if (phys) { if (kdb_getphysword(&word, addr, bytesperword)) break; } else if (kdb_getword(&word, addr, bytesperword)) @@ -1646,6 +1649,7 @@ static int kdb_md(int argc, const char **argv) bool symbolic = false; bool valid = false; bool phys = false; + bool do_iomap = false; kdbgetintenv("MDCOUNT", &mdcount); kdbgetintenv("RADIX", &radix); @@ -1655,6 +1659,8 @@ static int kdb_md(int argc, const char **argv) valid = true; else if (kdb_md_parse_arg0("mdp", argv[0], &repeat, &bytesperword)) phys = valid = true; + else if (kdb_md_parse_arg0("mdi", argv[0], &repeat, &bytesperword)) + do_iomap = valid = true; else if (strcmp(argv[0], "mds") == 0) valid = true; @@ -1765,7 +1771,11 @@ static int kdb_md(int argc, const char **argv) if (KDB_FLAG(CMD_INTERRUPT)) return 0; for (a = addr, z = 0; z < repeat; a += bytesperword, ++z) { - if (phys) { + if (do_iomap) { + if (kdb_getioword(&word, a, bytesperword) + || word) + break; + } else if (phys) { if (kdb_getphysword(&word, a, bytesperword) || word) break; @@ -1774,7 +1784,7 @@ static int kdb_md(int argc, const char **argv) } n = min(num, repeat); kdb_md_line(fmtstr, addr, symbolic, nosect, bytesperword, - num, repeat, phys); + num, repeat, phys, do_iomap); addr += bytesperword * n; repeat -= n; z = (z + num - 1) / num; @@ -2604,7 +2614,7 @@ static int kdb_per_cpu(int argc, const char **argv) kdb_printf("%5d ", cpu); kdb_md_line(fmtstr, addr, bytesperword == KDB_WORD_SIZE, - 1, bytesperword, 1, 1, 0); + true, bytesperword, 1, 1, false, false); } #undef KDB_PCU return 0; @@ -2717,6 +2727,24 @@ static kdbtab_t maintab[] = { .help = "Display RAM given a PA using word size (W); show N words", .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, }, + { .name = "mdi", + .func = kdb_md, + .usage = "<paddr> <bytes>", + .help = "Display IO Memory", + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .name = "mdiW", + .func = kdb_md, + .usage = "<paddr> <bytes>", + .help = "Display IO Memory using word size (W)", + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, + { .name = "mdiWcN", + .func = kdb_md, + .usage = "<paddr> <bytes>", + .help = "Display IO Memory using word size (W); show N words", + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, + }, { .name = "mdr", .func = kdb_mdr, .usage = "<vaddr> <bytes>", diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 1f685d9f16f9..caece6240140 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -97,6 +97,7 @@ extern int kdb_putarea_size(unsigned long, void *, size_t); #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_getioword(unsigned long *word, unsigned long addr, size_t size); extern int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size); extern int kdb_getword(unsigned long *, unsigned long, size_t); diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index 0a39497140bf..5a4e3a0e96a5 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -19,6 +19,7 @@ #include <linux/ptrace.h> #include <linux/highmem.h> #include <linux/hardirq.h> +#include <linux/io.h> #include <linux/delay.h> #include <linux/uaccess.h> #include <linux/kdb.h> @@ -331,6 +332,53 @@ static int kdb_getphys(void *res, unsigned long addr, size_t size) return 0; } +/* + * kdb_getioword + * Inputs: + * word Pointer to the word to receive the result. + * addr Address of the area to copy. + * size Size of the area. + * Returns: + * 0 for success, < 0 for error. + */ +int kdb_getioword(unsigned long *word, unsigned long addr, size_t size) +{ + void __iomem *mapped = ioremap(addr, size); + int diag = 0; + + *word = 0; /* Default value if addr or size is invalid */ + + if (!mapped) + return KDB_BADADDR; + + switch (size) { + case 1: + *word = readb(mapped); + break; + case 2: + *word = readw(mapped); + break; + case 4: + *word = readl(mapped); + break; + case 8: +#ifdef CONFIG_64BIT + if (size <= sizeof(*word)) { + *word = readq(mapped); + break; + } +#endif + fallthrough; + default: + kdb_func_printf("bad width %zu\n", size); + diag = KDB_BADWIDTH; + } + + iounmap(mapped); + + return diag; +} + /* * kdb_getphysword * Inputs: -- 2.45.2.627.g7a2c4fd464-goog _______________________________________________ Kgdb-bugreport mailing list Kgdb-bugreport@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport