diff mbox series

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

Message ID 20220531091457.2208488-10-npiggin@gmail.com
State New
Headers show
Series [01/10] sbefifo: correct typo in thread target name | expand

Commit Message

Nicholas Piggin May 31, 2022, 9:14 a.m. UTC
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@gmail.com>
---
 src/pdbgproxy.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)
diff mbox series

Patch

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;
 			}