summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2017-07-31 15:08:00 +1000
committerAlistair Popple <alistair@popple.id.au>2017-07-31 15:08:00 +1000
commitac22a4005d40e6e7d23cc1a7e73c4da8b8b6a898 (patch)
tree3ccb51c1ebaff165ea45e60e903c9ba5f644390b
parent5aa6dd48db50d93188f6f5fe2966f802ba85d5b1 (diff)
downloadpdbg-ac22a4005d40e6e7d23cc1a7e73c4da8b8b6a898.tar.gz
pdbg-ac22a4005d40e6e7d23cc1a7e73c4da8b8b6a898.zip
libpdbg: Add sreset command
Signed-off-by: Alistair Popple <alistair@popple.id.au>
-rw-r--r--libpdbg/chip.c9
-rw-r--r--libpdbg/operations.h1
-rw-r--r--libpdbg/p9chip.c17
-rw-r--r--libpdbg/target.h1
-rw-r--r--src/main.c13
5 files changed, 40 insertions, 1 deletions
diff --git a/libpdbg/chip.c b/libpdbg/chip.c
index 70d349d..539438a 100644
--- a/libpdbg/chip.c
+++ b/libpdbg/chip.c
@@ -115,6 +115,15 @@ int ram_stop_thread(struct target *thread_target)
return thread->stop(thread);
}
+int ram_sreset_thread(struct target *thread_target)
+{
+ struct thread *thread;
+
+ assert(!strcmp(thread_target->class, "thread"));
+ thread = target_to_thread(thread_target);
+ return thread->sreset(thread);
+}
+
/*
* RAMs the opcodes in *opcodes and store the results of each opcode
* into *results. *results must point to an array the same size as
diff --git a/libpdbg/operations.h b/libpdbg/operations.h
index 62ff5c4..2290f3b 100644
--- a/libpdbg/operations.h
+++ b/libpdbg/operations.h
@@ -68,6 +68,7 @@ uint64_t thread_status(struct thread *thread);
int ram_stop_thread(struct target *thread);
int ram_step_thread(struct target *thread, int count);
int ram_start_thread(struct target *thread);
+int ram_sreset_thread(struct target *thread);
void fsi_destroy(struct target *target);
/* GDB server functionality */
diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c
index 677401e..96ce067 100644
--- a/libpdbg/p9chip.c
+++ b/libpdbg/p9chip.c
@@ -107,6 +107,22 @@ static int p9_thread_stop(struct thread *thread)
return 0;
}
+static int p9_thread_sreset(struct thread *thread)
+{
+ /* Can only sreset if a thread is inactive, at least on DD1 */
+ if (p9_get_thread_status(thread) != (THREAD_STATUS_QUIESCE | THREAD_STATUS_ACTIVE))
+ return 1;
+
+ /* This will force SRR1[46:47] == 0b00 which means the kernel should
+ * enter xmon. However it will hide the fact we may have come from a
+ * powersave state in which register contents were lost. We need a
+ * kernel side fix for that. */
+ thread_write(thread, P9_DIRECT_CONTROL, PPC_BIT(32 + 8*thread->id));
+ thread_write(thread, P9_DIRECT_CONTROL, PPC_BIT(4 + 8*thread->id));
+
+ return 0;
+}
+
static int p9_ram_setup(struct thread *thread)
{
struct dt_node *dn;
@@ -192,6 +208,7 @@ struct thread p9_thread = {
},
.start = p9_thread_start,
.stop = p9_thread_stop,
+ .sreset = p9_thread_sreset,
.ram_setup = p9_ram_setup,
.ram_instruction = p9_ram_instruction,
.ram_destroy = p9_ram_destroy,
diff --git a/libpdbg/target.h b/libpdbg/target.h
index ba91cf5..cd7a183 100644
--- a/libpdbg/target.h
+++ b/libpdbg/target.h
@@ -112,6 +112,7 @@ struct thread {
int (*step)(struct thread *, int);
int (*start)(struct thread *);
int (*stop)(struct thread *);
+ int (*sreset)(struct thread *);
/* ram_setup() should be called prior to using ram_instruction() to
* actually ram the instruction and return the result. ram_destroy()
diff --git a/src/main.c b/src/main.c
index 7531ce3..f1b0967 100644
--- a/src/main.c
+++ b/src/main.c
@@ -41,7 +41,7 @@ enum command { GETCFAM = 1, PUTCFAM, GETSCOM, PUTSCOM, \
GETMEM, PUTMEM, GETGPR, GETNIA, GETSPR, \
GETMSR, PUTGPR, PUTNIA, PUTSPR, PUTMSR, \
STOP, START, THREADSTATUS, STEP, PROBE, \
- GETVMEM };
+ GETVMEM, SRESET };
#define MAX_CMD_ARGS 3
enum command cmd = 0;
@@ -184,6 +184,9 @@ enum command parse_cmd(char *optarg)
} else if (strcmp(optarg, "stop") == 0) {
cmd = STOP;
cmd_min_arg_count = 0;
+ } else if (strcmp(optarg, "sreset") == 0) {
+ cmd = SRESET;
+ cmd_min_arg_count = 0;
} else if (strcmp(optarg, "threadstatus") == 0) {
cmd = THREADSTATUS;
cmd_min_arg_count = 0;
@@ -569,6 +572,11 @@ static int stop_thread(struct target *thread_target, uint32_t index, uint64_t *u
return ram_stop_thread(thread_target) ? 0 : 1;
}
+static int sreset_thread(struct target *thread_target, uint32_t index, uint64_t *unused, uint64_t *unused1)
+{
+ return ram_sreset_thread(thread_target) ? 0 : 1;
+}
+
static void enable_dn(struct dt_node *dn)
{
struct dt_property *p;
@@ -835,6 +843,9 @@ int main(int argc, char *argv[])
case STOP:
rc = for_each_target("thread", stop_thread, NULL, NULL);
break;
+ case SRESET:
+ rc = for_each_target("thread", sreset_thread, NULL, NULL);
+ break;
case PROBE:
rc = 1;
print_target(dt_root, 0);
OpenPOWER on IntegriCloud