[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