summaryrefslogtreecommitdiffstats
path: root/libpdbg
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2018-05-03 16:27:00 +1000
committerAlistair Popple <alistair@popple.id.au>2018-05-18 11:19:21 +1000
commitacf6c036e30815c1e326c4ecdf478eaed89a9f29 (patch)
tree15413256804686a7b0f0ded12db9eedf321daa61 /libpdbg
parent0ae26a3925994ee7036e3da545bcc136c7d22314 (diff)
downloadpdbg-acf6c036e30815c1e326c4ecdf478eaed89a9f29.tar.gz
pdbg-acf6c036e30815c1e326c4ecdf478eaed89a9f29.zip
libpdbg/p9chip.c: ram allow ram to be used on running threads
Like the sreset change, this allows rammers to use !expert mode. Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Diffstat (limited to 'libpdbg')
-rw-r--r--libpdbg/operations.h10
-rw-r--r--libpdbg/p9chip.c60
-rw-r--r--libpdbg/target.h2
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. */
OpenPOWER on IntegriCloud