[Pdbg] [PATCH 09/10] gdbserver: Fix POWER10 fused-core SPATTN register handling

Nicholas Piggin npiggin at gmail.com
Tue May 31 19:14:56 AEST 2022


POWER10 in fused-core mode, when a thread executes an attn instruction,
the SPATTN thread bits are set according to fused-core thread ID. The
SPATTN registers for both small cores become set.

So use fc_id, and add logic to clear thread IDs that belong to the
other small core in the pair.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 src/pdbgproxy.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index 29845762..5d06c243 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -928,39 +928,56 @@ static void v_contc(uint64_t *stack, void *priv)
 static bool thread_check_attn(struct pdbg_target *target)
 {
 	struct thread *thread = target_to_thread(target);
-	struct pdbg_target *core;
+	struct pdbg_target *parent;
 	uint64_t spattn;
 
 	if (pdbg_target_compatible(target, "ibm,power8-thread")) {
 		return true; /* XXX */
 	} else if (pdbg_target_compatible(target, "ibm,power9-thread")) {
-		core = pdbg_target_require_parent("core", target);
-		if (pib_read(core, P9_SPATTN, &spattn)) {
+		parent = pdbg_target_require_parent("core", target);
+		if (pib_read(parent, P9_SPATTN, &spattn)) {
 			PR_ERROR("SPATTN read failed\n");
 			return false;
 		}
 
+		/* XXX: does this need to use fc_id like P10? */
 		if (spattn & PPC_BIT(1 + 4*thread->id)) {
 			uint64_t mask = ~PPC_BIT(1 + 4*thread->id);
 
-			if (pib_write(core, P9_SPATTN_AND, mask)) {
+			if (pib_write(parent, P9_SPATTN_AND, mask)) {
 				PR_ERROR("SPATTN clear failed\n");
 				return false;
 			}
 
 			return true;
 		}
+
 	} else if (pdbg_target_compatible(target, "ibm,power10-thread")) {
-		core = pdbg_target_require_parent("core", target);
-		if (pib_read(core, P10_SPATTN, &spattn)) {
+		struct core *core;
+
+		parent = pdbg_target_require_parent("core", target);
+		core = target_to_core(target);
+
+		if (pib_read(parent, P10_SPATTN, &spattn)) {
 			PR_ERROR("SPATTN read failed\n");
 			return false;
 		}
 
-		if (spattn & PPC_BIT(1 + 4*thread->id)) {
-			uint64_t mask = ~PPC_BIT(1 + 4*thread->id);
+		/* Workaround SPATTN being set in both small-core regs */
+		if (core->status.fused_core_mode &&
+				(spattn & PPC_BIT(1 + 4*(thread->fc_id ^ 1)))) {
+			uint64_t mask = ~PPC_BIT(1 + 4*(thread->fc_id ^ 1));
+
+			if (pib_write(parent, P10_SPATTN_AND, mask)) {
+				PR_ERROR("SPATTN clear failed\n");
+				return false;
+			}
+		}
+
+		if (spattn & PPC_BIT(1 + 4*thread->fc_id)) {
+			uint64_t mask = ~PPC_BIT(1 + 4*thread->fc_id);
 
-			if (pib_write(core, P10_SPATTN_AND, mask)) {
+			if (pib_write(parent, P10_SPATTN_AND, mask)) {
 				PR_ERROR("SPATTN clear failed\n");
 				return false;
 			}
-- 
2.35.1



More information about the Pdbg mailing list