summaryrefslogtreecommitdiffstats
path: root/libpdbg/chip.c
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2016-11-22 12:46:35 +1100
committerAlistair Popple <alistair@popple.id.au>2016-11-22 12:51:27 +1100
commitadf7f8391b4e429668fdb9e8834de9a0570d533d (patch)
tree8cba0452a65f8cc9dfeaa3e73d34ec3c9b8f73da /libpdbg/chip.c
parent749351433237295a86afcf451b947bc6621b946f (diff)
downloadpdbg-adf7f8391b4e429668fdb9e8834de9a0570d533d.tar.gz
pdbg-adf7f8391b4e429668fdb9e8834de9a0570d533d.zip
libpdbg/chip.c: Add command to read virtual addresses
Adds a command to read a 64-bit word from a given virtual address. The address is read in the current thread context and may cause an exception. In the case of exception it will be raised on the host when thread execution is resumed. Signed-off-by: Alistair Popple <alistair@popple.id.au>
Diffstat (limited to 'libpdbg/chip.c')
-rw-r--r--libpdbg/chip.c55
1 files changed, 45 insertions, 10 deletions
diff --git a/libpdbg/chip.c b/libpdbg/chip.c
index 9a0b963..39a5194 100644
--- a/libpdbg/chip.c
+++ b/libpdbg/chip.c
@@ -77,6 +77,7 @@
#define MTMSR_OPCODE 0x7c000124UL
#define MFSPR_OPCODE 0x7c0002a6UL
#define MTSPR_OPCODE 0x7c0003a6UL
+#define LD_OPCODE 0xe8000000UL
static uint64_t mfspr(uint64_t reg, uint64_t spr)
{
@@ -126,6 +127,14 @@ static uint64_t mtmsr(uint64_t reg)
return MTMSR_OPCODE | (reg << 21);
}
+static uint64_t ld(uint64_t rt, uint64_t ds, uint64_t ra)
+{
+ if ((rt > 31) | (ra > 31) | (ds > 0x3fff))
+ PR_ERROR("Invalid register specified\n");
+
+ return LD_OPCODE | (rt << 21) | (ra << 16) | (ds << 2);
+}
+
static int assert_special_wakeup(struct target *chip)
{
int i = 0;
@@ -295,10 +304,11 @@ int ram_start_thread(struct target *thread)
static int ram_instructions(struct target *thread, uint64_t *opcodes,
uint64_t *results, int len, unsigned int lpar)
{
- uint64_t ram_mode, val, opcode, r0 = 0;
+ uint64_t ram_mode, val, opcode, r0 = 0, r1 = 0;
struct target *chiplet = thread->next;
int thread_id = (thread->base >> 4) & 0x7;
int i;
+ int exception = 0;
/* Activate RAM mode */
CHECK_ERR(read_target(chiplet, RAM_MODE_REG, &ram_mode));
@@ -313,17 +323,23 @@ static int ram_instructions(struct target *thread, uint64_t *opcodes,
CHECK_ERR(write_target(chiplet, L0_SCOM_SPRC_REG, SCOM_SPRC_SCRATCH_SPR));
/* RAM instructions */
- for (i = -1; i <= len; i++) {
- if (i < 0)
+ for (i = -2; i < len + 2; i++) {
+ if (i == -2)
+ opcode = mtspr(277, 1);
+ else if (i == -1)
/* Save r0 (assumes opcodes don't touch other registers) */
opcode = mtspr(277, 0);
else if (i < len) {
CHECK_ERR(write_target(chiplet, SCR0_REG, results[i]));
opcode = opcodes[i];
- } else if (i >= len) {
+ } else if (i == len) {
/* Restore r0 */
CHECK_ERR(write_target(chiplet, SCR0_REG, r0));
opcode = mfspr(0, 277);
+ } else if (i == len + 1) {
+ /* Restore r1 */
+ CHECK_ERR(write_target(chiplet, SCR0_REG, r1));
+ opcode = mfspr(0, 277);
}
/* ram instruction */
@@ -334,14 +350,23 @@ static int ram_instructions(struct target *thread, uint64_t *opcodes,
/* wait for completion */
do {
CHECK_ERR(read_target(chiplet, RAM_STATUS_REG, &val));
- } while (!val);
-
- if (!(val & RAM_STATUS))
- PR_ERROR("RAMMING failed with status 0x%llx\n", val);
+ } while (!((val & PPC_BIT(1)) || ((val & PPC_BIT(2)) && (val & PPC_BIT(3)))));
+
+ if (!(val & PPC_BIT(1))) {
+ exception = GETFIELD(PPC_BITMASK(2,3), val) == 0x3;
+ if (exception) {
+ /* Skip remaining instructions */
+ i = len - 1;
+ continue;
+ } else
+ PR_ERROR("RAMMING failed with status 0x%llx\n", val);
+ }
/* Save the results */
CHECK_ERR(read_target(chiplet, SCR0_REG, &val));
- if (i < 0)
+ if (i == -2)
+ r1 = val;
+ else if (i == -1)
r0 = val;
else if (i < len)
results[i] = val;
@@ -351,7 +376,7 @@ static int ram_instructions(struct target *thread, uint64_t *opcodes,
ram_mode &= ~RAM_MODE_ENABLE;
CHECK_ERR(write_target(chiplet, RAM_MODE_REG, ram_mode));
- return 0;
+ return exception;
}
/*
@@ -434,6 +459,16 @@ int ram_putmsr(struct target *thread, uint64_t value)
return 0;
}
+int ram_getmem(struct target *thread, uint64_t addr, uint64_t *value)
+{
+ uint64_t opcodes[] = {mfspr(0, 277), mfspr(1, 277), ld(0, 0, 1), mtspr(277, 0)};
+ uint64_t results[] = {0xdeaddeaddeaddead, addr, 0, 0};
+
+ CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0));
+ *value = results[3];
+ return 0;
+}
+
int thread_target_init(struct target *thread, const char *name, uint64_t thread_id, struct target *next)
{
target_init(thread, name, 0x13000 | (thread_id << 4), NULL, NULL, NULL, next);
OpenPOWER on IntegriCloud