diff options
-rw-r--r-- | libpdbg/chip.c | 9 | ||||
-rw-r--r-- | libpdbg/operations.h | 1 | ||||
-rw-r--r-- | libpdbg/p9chip.c | 17 | ||||
-rw-r--r-- | libpdbg/target.h | 1 | ||||
-rw-r--r-- | src/main.c | 13 |
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() @@ -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); |