mw_debug: Add support for reading GSPRs and writing memory
authorPaul Mackerras <paulus@ozlabs.org>
Sat, 2 May 2020 03:31:07 +0000 (13:31 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 8 May 2020 02:12:01 +0000 (12:12 +1000)
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 <paulus@ozlabs.org>
scripts/mw_debug/mw_debug.c

index f1a7cabb391a49abfe354b358787a9e297e00891..8359242eb800bfb2c1e64cccc377c4fbe1b5fd4c 100644 (file)
 #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);