[Pdbg] [PATCH 14/14] pdbg: add 'regs' command
Nicholas Piggin
npiggin at gmail.com
Mon Apr 9 17:35:22 AEST 2018
This uses ramming to pull out basic registers. These should be
expanded to include important / all SPRs. CR is notably absent
too, which requires a bit more ramming code.
$ sudo ./pdbg -p 0 -c 12 -t 3 regs
NIA : 0xc00000000003278c
LR : 0xc000000000090a30
CTR: 0xc000000000032750
MSR : 0x9000000000001033
GPRS:
0x0000000000000000 0xc000000ff55c7a60
0xc00000000112e700 0x0000000000000002
0x000000000000000f 0xc000000000fe4570
0x0000000000000800 0x0000000000000a67
0x0000000000000000 0x0000000000000000
0xc000000ff55c4000 0x000000000005acde
0xc0000000009cb990 0xc000000ffffde800
0xc000000ff55c7f90 0x0000000000000000
0x0000000000000000 0xc000000000029c58
0xc00000000003e7b0 0xc000000000fb51e0
0x0000000000000800 0xc000000001160204
0x0000000000000028 0x0000000000000000
0x00000000000000a0 0x0000000000000006
0x0000000000000000 0x0000000000000006
0xc000000001092468 0x00000000003003ff
0x0000000000300332 0x2000000000300332
This should be made target specific in some way, but for the
moment this works reasonably well.
Ramming remains set over all register extraction, by keeping
another state variable around. This helps to speed things up
and minimise disturbance to the host.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
I noticed a lockup when ramming was set and destroyed on each
register read, but batching them up has been pretty stable. This
should be debugged, but even so it seems better to batch them.
It might be some hardware issue that requires a delay to be put
in, not really sure.
libpdbg/chip.c | 92 +++++++++++++++++++++++++++++++++++++++++++----
libpdbg/libpdbg.h | 1 +
src/main.c | 1 +
src/thread.c | 16 +++++++++
src/thread.h | 1 +
5 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/libpdbg/chip.c b/libpdbg/chip.c
index 06ea4e9..59ef127 100644
--- a/libpdbg/chip.c
+++ b/libpdbg/chip.c
@@ -24,6 +24,8 @@
#include "operations.h"
#include "bitutils.h"
+static bool ram_setup = false;
+
static uint64_t mfspr(uint64_t reg, uint64_t spr)
{
if (reg > 31)
@@ -40,6 +42,17 @@ static uint64_t mtspr(uint64_t spr, uint64_t reg)
return MTSPR_OPCODE | (reg << 21) | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
}
+#if 0
+static uint64_t mfocr(uint64_t reg, uint64_t cr)
+{
+ if (reg > 7)
+ PR_ERROR("Invalid register specified\n");
+
+// return MFOCR_OPCODE | (reg << 21) | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
+ return 0;
+}
+#endif
+
static uint64_t mfnia(uint64_t reg)
{
if (reg > 31)
@@ -136,17 +149,12 @@ int ram_sreset_thread(struct pdbg_target *thread_target)
* data. Note that only register r0 is saved and restored so opcodes
* must not touch other registers.
*/
-static int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes,
+static int __ram_instructions(struct thread *thread, uint64_t *opcodes,
uint64_t *results, int len, unsigned int lpar)
{
uint64_t opcode = 0, r0 = 0, r1 = 0, scratch = 0;
int i;
int exception = 0;
- struct thread *thread;
-
- assert(!strcmp(thread_target->class, "thread"));
- thread = target_to_thread(thread_target);
- CHECK_ERR(thread->ram_setup(thread));
/* RAM instructions */
for (i = -2; i < len + 2; i++) {
@@ -178,7 +186,25 @@ static int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes
results[i] = scratch;
}
- CHECK_ERR(thread->ram_destroy(thread));
+ return exception;
+}
+
+static int ram_instructions(struct pdbg_target *thread_target, uint64_t *opcodes,
+ uint64_t *results, int len, unsigned int lpar)
+{
+ struct thread *thread;
+ int exception = 0;
+
+ assert(!strcmp(thread_target->class, "thread"));
+ thread = target_to_thread(thread_target);
+
+ if (!ram_setup)
+ CHECK_ERR(thread->ram_setup(thread));
+
+ exception = __ram_instructions(thread, opcodes, results, len, lpar);
+
+ if (!ram_setup)
+ CHECK_ERR(thread->ram_destroy(thread));
return exception;
}
@@ -254,6 +280,18 @@ int ram_getmsr(struct pdbg_target *thread, uint64_t *value)
return 0;
}
+#if 0
+int ram_getcr(struct pdbg_target *thread, int cr, uint64_t *value)
+{
+ uint64_t opcodes[] = {mfocr(0, cr), mtspr(277, 0)};
+ uint64_t results[] = {0, 0};
+
+ CHECK_ERR(ram_instructions(thread, opcodes, results, ARRAY_SIZE(opcodes), 0));
+ *value = results[1];
+ return 0;
+}
+#endif
+
int ram_putmsr(struct pdbg_target *thread, uint64_t value)
{
uint64_t opcodes[] = {mfspr(0, 277), mtmsr(0)};
@@ -272,3 +310,43 @@ int ram_getmem(struct pdbg_target *thread, uint64_t addr, uint64_t *value)
*value = results[3];
return 0;
}
+
+int ram_state_thread(struct pdbg_target *thread)
+{
+ struct thread *t;
+ uint64_t value;
+ int i;
+
+ assert(!strcmp(thread->class, "thread"));
+ t = target_to_thread(thread);
+
+ CHECK_ERR(t->ram_setup(t));
+ ram_setup = true;
+
+ ram_getnia(thread, &value);
+ printf("NIA : 0x%016lx\n", value);
+
+ ram_getspr(thread, 0x8, &value);
+ printf("LR : 0x%016lx\n", value);
+
+ ram_getspr(thread, 0x9, &value);
+ printf("CTR: 0x%016lx\n", value);
+
+// ram_getcr(thread, 0x9, &value);
+// printf("CR: 0x%08lx\n", value);
+
+ ram_getmsr(thread, &value);
+ printf("MSR : 0x%016lx\n", value);
+
+ printf("GPRS:\n");
+ for (i = 0; i < 32; i++) {
+ ram_getgpr(thread, i, &value);
+ printf(" 0x%016lx", value);
+ if (i % 2 == 1)
+ printf("\n");
+ }
+
+ CHECK_ERR(t->ram_destroy(t));
+
+ return 0;
+}
diff --git a/libpdbg/libpdbg.h b/libpdbg/libpdbg.h
index e57058a..be01218 100644
--- a/libpdbg/libpdbg.h
+++ b/libpdbg/libpdbg.h
@@ -65,6 +65,7 @@ int ram_start_thread(struct pdbg_target *target);
int ram_step_thread(struct pdbg_target *target, int steps);
int ram_stop_thread(struct pdbg_target *target);
int ram_sreset_thread(struct pdbg_target *target);
+int ram_state_thread(struct pdbg_target *target);
uint64_t thread_status(struct pdbg_target *target);
#define THREAD_STATUS_DISABLED PPC_BIT(0)
diff --git a/src/main.c b/src/main.c
index 368bc4e..7a522b9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -104,6 +104,7 @@ static struct action expert_actions[] = {
};
static struct action actions[] = {
+ { "regs", "", "State", &thread_state },
{ "sreset", "", "Reset", &thread_sreset },
{ "probe", "", "", &handle_probe },
};
diff --git a/src/thread.c b/src/thread.c
index 6001bb3..0e1ff0b 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -102,6 +102,11 @@ static int sreset_thread(struct pdbg_target *thread_target, uint32_t index, uint
return ram_sreset_thread(thread_target) ? 0 : 1;
}
+static int state_thread(struct pdbg_target *thread_target, uint32_t index, uint64_t *unused, uint64_t *unused1)
+{
+ return ram_state_thread(thread_target) ? 0 : 1;
+}
+
int thread_start(int optind, int argc, char *argv[])
{
int err;
@@ -154,3 +159,14 @@ int thread_sreset(int optind, int argc, char *argv[])
return err;
}
+
+int thread_state(int optind, int argc, char *argv[])
+{
+ int err;
+
+ err = for_each_target("thread", state_thread, NULL, NULL);
+
+ pdbg_target_release();
+
+ return err;
+}
diff --git a/src/thread.h b/src/thread.h
index 01a8034..5fc2a80 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -22,3 +22,4 @@ int thread_step(int optind, int argc, char *argv[]);
int thread_stop(int optind, int argc, char *argv[]);
int thread_status_print(int optind, int argc, char *argv[]);
int thread_sreset(int optind, int argc, char *argv[]);
+int thread_state(int optind, int argc, char *argv[]);
--
2.17.0
More information about the Pdbg
mailing list