[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