[Pdbg] [PATCH 2/3] libpdbg/p10chip: add basic thread direct controls
Nicholas Piggin
npiggin at gmail.com
Mon Dec 21 21:17:32 AEDT 2020
This adds support for stop, start, sreset.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
libpdbg/p10_fapi_targets.c | 20 --------
libpdbg/p10chip.c | 101 +++++++++++++++++++++++++++++++++++++
2 files changed, 101 insertions(+), 20 deletions(-)
diff --git a/libpdbg/p10_fapi_targets.c b/libpdbg/p10_fapi_targets.c
index 6023389..0f16735 100644
--- a/libpdbg/p10_fapi_targets.c
+++ b/libpdbg/p10_fapi_targets.c
@@ -488,25 +488,6 @@ static struct chiplet p10_chiplet = {
};
DECLARE_HW_UNIT(p10_chiplet);
-static int p10_thread_probe(struct pdbg_target *target)
-{
- struct thread *thread = target_to_thread(target);
-
- thread->id = pdbg_target_index(target);
-
- return 0;
-}
-
-static struct thread p10_thread = {
- .target = {
- .name = "POWER10 Thread",
- .compatible = "ibm,power10-thread",
- .class = "thread",
- .probe = p10_thread_probe,
- },
-};
-DECLARE_HW_UNIT(p10_thread);
-
static uint64_t no_translate(struct pdbg_target *target, uint64_t addr)
{
/* No translation performed */
@@ -540,6 +521,5 @@ static void register_p10_fapi_targets(void)
pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pauc_hw_unit);
pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_pau_hw_unit);
pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_chiplet_hw_unit);
- pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit);
pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_fc_hw_unit);
}
diff --git a/libpdbg/p10chip.c b/libpdbg/p10chip.c
index f26e4ca..87d34e5 100644
--- a/libpdbg/p10chip.c
+++ b/libpdbg/p10chip.c
@@ -22,8 +22,16 @@
#include "chip.h"
#include "debug.h"
+/*
+ * NOTE!
+ * All timeouts and scom procedures in general through the file should be kept
+ * in synch with skiboot (e.g., core/direct-controls.c) as far as possible.
+ * If you fix a bug here, fix it in skiboot, and vice versa.
+ */
+
#define P10_CORE_THREAD_STATE 0x28412
#define P10_THREAD_INFO 0x28413
+#define P10_DIRECT_CONTROL 0x28449
#define P10_RAS_STATUS 0x28454
/* PCB Slave registers */
@@ -31,6 +39,7 @@
#define SPECIAL_WKUP_DONE PPC_BIT(1)
#define QME_SPWU_FSP 0xE8834
+#define RAS_STATUS_TIMEOUT 100 /* 100ms */
#define SPECIAL_WKUP_TIMEOUT 100 /* 100ms */
static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data)
@@ -40,6 +49,13 @@ static int thread_read(struct thread *thread, uint64_t addr, uint64_t *data)
return pib_read(core, addr, data);
}
+static uint64_t thread_write(struct thread *thread, uint64_t addr, uint64_t data)
+{
+ struct pdbg_target *chip = pdbg_target_require_parent("core", &thread->target);
+
+ return pib_write(chip, addr, data);
+}
+
struct thread_state p10_thread_state(struct thread *thread)
{
struct thread_state thread_state;
@@ -89,6 +105,90 @@ struct thread_state p10_thread_state(struct thread *thread)
return thread_state;
}
+static int p10_thread_probe(struct pdbg_target *target)
+{
+ struct thread *thread = target_to_thread(target);
+
+ thread->id = pdbg_target_index(target);
+ thread->status = thread->state(thread);
+
+ return 0;
+}
+
+static void p10_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 p10_thread_start(struct thread *thread)
+{
+ if (!(thread->status.quiesced))
+ return 1;
+
+ if ((!(thread->status.active)) ||
+ (thread->status.sleep_state == PDBG_THREAD_STATE_STOP)) {
+ /* Inactive or active and stopped: Clear Maint */
+ thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(3 + 8*thread->id));
+ } else {
+ /* Active and not stopped: Start */
+ thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(6 + 8*thread->id));
+ }
+
+ thread->status = thread->state(thread);
+
+ return 0;
+}
+
+static int p10_thread_stop(struct thread *thread)
+{
+ int i = 0;
+
+ thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(7 + 8*thread->id));
+ while (!(thread->state(thread).quiesced)) {
+ usleep(1000);
+ if (i++ > RAS_STATUS_TIMEOUT) {
+ PR_ERROR("Unable to quiesce thread\n");
+ break;
+ }
+ }
+ thread->status = thread->state(thread);
+
+ return 0;
+}
+
+static int p10_thread_sreset(struct thread *thread)
+{
+ /* Can only sreset if a thread is quiesced */
+ if (!(thread->status.quiesced))
+ return 1;
+
+ thread_write(thread, P10_DIRECT_CONTROL, PPC_BIT(4 + 8*thread->id));
+
+ thread->status = thread->state(thread);
+
+ return 0;
+}
+
+static struct thread p10_thread = {
+ .target = {
+ .name = "POWER10 Thread",
+ .compatible = "ibm,power10-thread",
+ .class = "thread",
+ .probe = p10_thread_probe,
+ .release = p10_thread_release,
+ },
+ .state = p10_thread_state,
+ .start = p10_thread_start,
+ .stop = p10_thread_stop,
+ .sreset = p10_thread_sreset,
+};
+DECLARE_HW_UNIT(p10_thread);
+
static int p10_core_probe(struct pdbg_target *target)
{
struct core *core = target_to_core(target);
@@ -190,5 +290,6 @@ DECLARE_HW_UNIT(p10_core);
__attribute__((constructor))
static void register_p10chip(void)
{
+ pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_thread_hw_unit);
pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_core_hw_unit);
}
--
2.23.0
More information about the Pdbg
mailing list