diff options
| author | Alistair Popple <alistair@popple.id.au> | 2018-08-10 14:47:47 +1000 |
|---|---|---|
| committer | Alistair Popple <alistair@popple.id.au> | 2018-08-13 15:26:36 +1000 |
| commit | a1a93b8b9b5eab179ad241e841ec2379f7277244 (patch) | |
| tree | 8207f5dba30238b82a0c03ebad3ed07d1e0feb35 | |
| parent | 9bf63c61da9137429263d5697ff837069b86a1ff (diff) | |
| download | pdbg-a1a93b8b9b5eab179ad241e841ec2379f7277244.tar.gz pdbg-a1a93b8b9b5eab179ad241e841ec2379f7277244.zip | |
libpdbg: Don't release special wakeup when threads are quiesced
Signed-off-by: Alistair Popple <alistair@popple.id.au>
| -rw-r--r-- | libpdbg/p9chip.c | 40 | ||||
| -rw-r--r-- | libpdbg/target.h | 1 |
2 files changed, 41 insertions, 0 deletions
diff --git a/libpdbg/p9chip.c b/libpdbg/p9chip.c index 2585f11..189d80a 100644 --- a/libpdbg/p9chip.c +++ b/libpdbg/p9chip.c @@ -125,6 +125,15 @@ static int p9_thread_probe(struct pdbg_target *target) return 0; } +static void p9_thread_release(struct pdbg_target *target) +{ + struct core *core = target_to_core(pdbg_target_require_parent("core", target)); + struct thread *thread = target_to_thread(target); + + if (thread->status.quiesced) + /* This thread is still quiesced so don't release spwkup */ + core->release_spwkup = false;} + static int p9_thread_start(struct thread *thread) { if (!(thread->status.quiesced)) @@ -392,6 +401,7 @@ static struct thread p9_thread = { .compatible = "ibm,power9-thread", .class = "thread", .probe = p9_thread_probe, + .release = p9_thread_release, }, .start = p9_thread_start, .stop = p9_thread_stop, @@ -472,6 +482,7 @@ static int p9_chiplet_getring(struct chiplet *chiplet, uint64_t ring_addr, int64 static int p9_core_probe(struct pdbg_target *target) { + struct core *core = target_to_core(target); int i = 0; uint64_t value; @@ -493,12 +504,41 @@ static int p9_core_probe(struct pdbg_target *target) } } while (!(value & SPECIAL_WKUP_DONE)); + /* Child threads will set this to false if they are released while quiesced */ + core->release_spwkup = true; + return 0; } static void p9_core_release(struct pdbg_target *target) { + struct pdbg_target *child; + struct core *core = target_to_core(target); + enum pdbg_target_status status; + usleep(1); /* enforce small delay before and after it is cleared */ + + /* Probe and release all threads to ensure release_spwkup is up to + * date */ + pdbg_for_each_target("thread", target, child) { + status = pdbg_target_status(child); + + /* This thread has already been release so should have set + * release_spwkup to false if it was quiesced, */ + if (status == PDBG_TARGET_RELEASED) + continue; + + status = pdbg_target_probe(child); + if (status != PDBG_TARGET_ENABLED) + continue; + + /* Release the thread to ensure release_spwkup is updated. */ + pdbg_target_release(child); + } + + if (!core->release_spwkup) + return; + pib_write(target, PPM_SPWKUP_FSP, 0); usleep(10000); } diff --git a/libpdbg/target.h b/libpdbg/target.h index 6c2fa17..9f055ac 100644 --- a/libpdbg/target.h +++ b/libpdbg/target.h @@ -131,6 +131,7 @@ struct fsi { struct core { struct pdbg_target target; + bool release_spwkup; }; #define target_to_core(x) container_of(x, struct core, target) |

