From 3340d8aa9fac6acaef70d3f48ed8e47d8afb7374 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 2 May 2020 13:31:07 +1000 Subject: [PATCH] mw_debug: Add support for reading GSPRs and writing memory This adds a "gpr" command for reading 1 or more GPRs/fast SPRs, and a "mw" command for writing an 8-byte value to memory. It also adds an "icreset" command for resetting the instruction cache and fixes the "creset" command to actually reset the core instead of starting it. The MSR is now printed along with the NIA in the status information. Signed-off-by: Paul Mackerras --- scripts/mw_debug/mw_debug.c | 81 +++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index f1a7cab..8359242 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -33,6 +33,10 @@ #define DBG_CORE_STAT_TERM (1 << 2) #define DBG_CORE_NIA 0x12 +#define DBG_CORE_MSR 0x13 + +#define DBG_CORE_GSPR_INDEX 0x14 +#define DBG_CORE_GSPR_DATA 0x15 static bool debug; @@ -356,11 +360,12 @@ static int dmi_write(uint8_t addr, uint64_t data) static void core_status(void) { - uint64_t stat, nia; + uint64_t stat, nia, msr; const char *statstr, *statstr2; check(dmi_read(DBG_CORE_STAT, &stat), "reading core status"); check(dmi_read(DBG_CORE_NIA, &nia), "reading core NIA"); + check(dmi_read(DBG_CORE_MSR, &msr), "reading core MSR"); if (debug) printf("Core status = 0x%llx\n", (unsigned long long)stat); @@ -378,6 +383,7 @@ static void core_status(void) statstr = "odd state (TERM but no STOP)"; printf("Core: %s%s\n", statstr, statstr2); printf(" NIA: %016llx\n", (unsigned long long)nia); + printf(" MSR: %016llx\n", msr); } static void core_stop(void) @@ -392,7 +398,7 @@ static void core_start(void) static void core_reset(void) { - check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_START), "resetting core"); + check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_RESET), "resetting core"); } static void core_step(void) @@ -413,19 +419,47 @@ static void icache_reset(void) check(dmi_write(DBG_CORE_CTRL, DBG_CORE_CTRL_ICRESET), "resetting icache"); } +static const char *fast_spr_names[] = +{ + "lr", "ctr", "srr0", "srr1", "hsrr0", "hsrr1", + "sprg0", "sprg1", "sprg2", "sprg3", + "hsprg0", "hsprg1", "xer" +}; + +static void gpr_read(uint64_t reg, uint64_t count) +{ + uint64_t data; + + reg &= 0x3f; + if (reg + count > 64) + count = 64 - reg; + for (; count != 0; --count, ++reg) { + check(dmi_write(DBG_CORE_GSPR_INDEX, reg), "setting GPR index"); + data = 0xdeadbeef; + check(dmi_read(DBG_CORE_GSPR_DATA, &data), "reading GPR data"); + if (reg <= 31) + printf("r%d", reg); + else if ((reg - 32) < sizeof(fast_spr_names) / sizeof(fast_spr_names[0])) + printf("%s", fast_spr_names[reg - 32]); + else + printf("gspr%d", reg); + printf(":\t%016llx\n", data); + } +} + static void mem_read(uint64_t addr, uint64_t count) { uint64_t data; int i, rc; - rc = dmi_write(2, 0x7ff); + rc = dmi_write(DBG_WB_CTRL, 0x7ff); if (rc < 0) return; - rc = dmi_write(0, addr); + rc = dmi_write(DBG_WB_ADDR, addr); if (rc < 0) return; for (i = 0; i < count; i++) { - rc = dmi_read(1, &data); + rc = dmi_read(DBG_WB_DATA, &data); if (rc < 0) return; printf("%016llx: %016llx\n", @@ -435,6 +469,13 @@ static void mem_read(uint64_t addr, uint64_t count) } } +static void mem_write(uint64_t addr, uint64_t data) +{ + check(dmi_write(DBG_WB_CTRL, 0x7ff), "writing WB_CTRL"); + check(dmi_write(DBG_WB_ADDR, addr), "writing WB_ADDR"); + check(dmi_write(DBG_WB_DATA, data), "writing WB_DATA"); +} + static void load(const char *filename, uint64_t addr) { uint64_t data; @@ -445,13 +486,8 @@ static void load(const char *filename, uint64_t addr) fprintf(stderr, "Failed to open '%s': %s\n", filename, strerror(errno)); exit(1); } - // XX dumb, do better - rc = dmi_write(2, 0x7ff); - if (rc < 0) - return; - rc = dmi_write(0, addr); - if (rc < 0) - return; + check(dmi_write(DBG_WB_CTRL, 0x7ff), "writing WB_CTRL"); + check(dmi_write(DBG_WB_ADDR, addr), "writing WB_ADDR"); count = 0; for (;;) { data = 0; @@ -459,7 +495,7 @@ static void load(const char *filename, uint64_t addr) if (rc <= 0) break; // if (rc < 8) XXX fixup endian ? - dmi_write(1, data); + check(dmi_write(DBG_WB_DATA, data), "writing WB_DATA"); count += 8; if (!(count % 1024)) printf("%x...\n", count); @@ -544,6 +580,8 @@ int main(int argc, char *argv[]) dmi_write(addr, data); } else if (strcmp(argv[i], "creset") == 0) { core_reset(); + } else if (strcmp(argv[i], "icreset") == 0) { + icache_reset(); } else if (strcmp(argv[i], "stop") == 0) { core_stop(); } else if (strcmp(argv[i], "start") == 0) { @@ -563,6 +601,14 @@ int main(int argc, char *argv[]) if (((i+1) < argc) && isdigit(argv[i+1][0])) count = strtoul(argv[++i], NULL, 16); mem_read(addr, count); + } else if (strcmp(argv[i], "mw") == 0) { + uint64_t addr, data; + + if ((i+2) >= argc) + usage(argv[0]); + addr = strtoul(argv[++i], NULL, 16); + data = strtoul(argv[++i], NULL, 16); + mem_write(addr, data); } else if (strcmp(argv[i], "load") == 0) { const char *filename; uint64_t addr = 0; @@ -573,6 +619,15 @@ int main(int argc, char *argv[]) if (((i+1) < argc) && isdigit(argv[i+1][0])) addr = strtoul(argv[++i], NULL, 16); load(filename, addr); + } else if (strcmp(argv[i], "gpr") == 0) { + uint64_t reg, count = 1; + + if ((i+1) >= argc) + usage(argv[0]); + reg = strtoul(argv[++i], NULL, 10); + if (((i+1) < argc) && isdigit(argv[i+1][0])) + count = strtoul(argv[++i], NULL, 10); + gpr_read(reg, count); } else { fprintf(stderr, "Unknown command %s\n", argv[i]); exit(1); -- 2.30.2