diff options
-rw-r--r-- | libpdbg/operations.h | 10 | ||||
-rw-r--r-- | libpdbg/p9chip.c | 60 | ||||
-rw-r--r-- | libpdbg/target.h | 2 |
3 files changed, 66 insertions, 6 deletions
diff --git a/libpdbg/operations.h b/libpdbg/operations.h index 7ee4cb2..88ddce2 100644 --- a/libpdbg/operations.h +++ b/libpdbg/operations.h @@ -22,13 +22,21 @@ /* Error codes */ #define EFSI 1 +#define PRINT_ERR PR_DEBUG("%s: %d\n", __FUNCTION__, __LINE__) #define CHECK_ERR(x) do { \ if (x) { \ - PR_DEBUG("%s: %d\n", __FUNCTION__, __LINE__); \ + PRINT_ERR; \ return x; \ } \ } while(0) +#define CHECK_ERR_GOTO(label, x) do { \ + if (x) { \ + PRINT_ERR; \ + goto label; \ + } \ + } while(0) + #define FSI2PIB_BASE 0x1000 /* Alter display unit functions */ diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c index 3dafcf2..7182ae1 100644 --- a/libpdbg/p9chip.c +++ b/libpdbg/p9chip.c @@ -214,12 +214,52 @@ static int p9_thread_sreset(struct thread *thread) return 0; } +static void ram_nonexpert_cleanup(struct thread *thread) +{ + struct pdbg_target *target; + struct core *chip = target_to_core(thread->target.parent); + + if (pdbg_expert_mode) + return; + + /* We can only ram a thread if all the threads on the core/chip are + * quiesced */ + dt_for_each_compatible(&chip->target, target, "ibm,power9-thread") { + struct thread *tmp; + + tmp = target_to_thread(target); + if (tmp->ram_did_quiesce) { + p9_thread_start(tmp); + tmp->ram_did_quiesce = false; + } + } +} + static int p9_ram_setup(struct thread *thread) { struct pdbg_target *target; struct core *chip = target_to_core(thread->target.parent); uint64_t value; + if (pdbg_expert_mode) + goto expert; + + dt_for_each_compatible(&chip->target, target, "ibm,power9-thread") { + struct thread *tmp; + + p9_thread_probe(target); + tmp = target_to_thread(target); + /* Something already quiesced it, fail*/ + if (tmp->status & THREAD_STATUS_QUIESCE) + goto out_fail; + if (!(tmp->status & THREAD_STATUS_QUIESCE)) { + if (p9_thread_stop(tmp)) + goto out_fail; + tmp->ram_did_quiesce = true; + } + } + +expert: /* We can only ram a thread if all the threads on the core/chip are * quiesced */ dt_for_each_compatible(&chip->target, target, "ibm,power9-thread") { @@ -230,7 +270,7 @@ static int p9_ram_setup(struct thread *thread) p9_thread_probe(target); tmp = target_to_thread(target); if (!(tmp->status & THREAD_STATUS_QUIESCE)) - return 1; + goto out_fail; } /* Wait for NEST_ACTIVE to clear */ @@ -244,18 +284,26 @@ static int p9_ram_setup(struct thread *thread) } while (value & PPC_BIT(23)); /* Activate thread for ramming */ - CHECK_ERR(thread_write(thread, P9_THREAD_INFO, PPC_BIT(18 + thread->id))); + CHECK_ERR_GOTO(out_fail, + thread_write(thread, P9_THREAD_INFO, PPC_BIT(18 + thread->id))); /* Enable ram mode */ - CHECK_ERR(thread_write(thread, P9_RAM_MODEREG, PPC_BIT(0))); + CHECK_ERR_GOTO(out_fail, + thread_write(thread, P9_RAM_MODEREG, PPC_BIT(0))); /* Setup SPRC to use SPRD */ - CHECK_ERR(thread_write(thread, P9_SPR_MODE, 0x00000ff000000000)); - CHECK_ERR(thread_write(thread, P9_SCOMC, 0x0)); + CHECK_ERR_GOTO(out_fail, + thread_write(thread, P9_SPR_MODE, 0x00000ff000000000)); + CHECK_ERR_GOTO(out_fail, + thread_write(thread, P9_SCOMC, 0x0)); thread->status = p9_get_thread_status(thread); return 0; + +out_fail: + ram_nonexpert_cleanup(thread); + return 1; } @@ -352,6 +400,8 @@ static int p9_ram_destroy(struct thread *thread) thread->status = p9_get_thread_status(thread); + ram_nonexpert_cleanup(thread); + return 0; } diff --git a/libpdbg/target.h b/libpdbg/target.h index 3e7dc08..701c51f 100644 --- a/libpdbg/target.h +++ b/libpdbg/target.h @@ -151,6 +151,8 @@ struct thread { int (*stop)(struct thread *); int (*sreset)(struct thread *); + bool ram_did_quiesce; /* was the thread quiesced by ram mode */ + /* ram_setup() should be called prior to using ram_instruction() to * actually ram the instruction and return the result. ram_destroy() * should be called at completion to clean-up. */ |