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 <paulus@ozlabs.org>
pull/169/head
Paul Mackerras 4 years ago
parent dd2e71930c
commit 3340d8aa9f

@ -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);

Loading…
Cancel
Save