diff mbox series

[02/10] gdbserver: Fix attn enable HID change icache flushing sequence

Message ID 20220531091457.2208488-3-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
Changing the HID attn enable bit on POWER9 and POWER10 requires the
icache to be flushed *after* ATTN is changed. It is not clear that it
may be done at the same time, so move it to after the attn bit change.

Flushing the icache with HID requires a 0->1 edge and the bit does not
reset back to 0, so first write 1 then 0 ready for the next flush.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 src/pdbgproxy.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/src/pdbgproxy.c b/src/pdbgproxy.c
index 13b72408..2d579a4a 100644
--- a/src/pdbgproxy.c
+++ b/src/pdbgproxy.c
@@ -303,6 +303,9 @@  static int thread_set_attn(struct pdbg_target *target, bool enable)
 				return 0;
 			hid &= ~POWER8_HID_ENABLE_ATTN;
 		}
+		if (thread_putspr(target, SPR_HID, hid))
+			return -1;
+
 	} else if (pdbg_target_compatible(target, "ibm,power9-thread")) {
 		if (enable) {
 			if (hid & POWER9_HID_ENABLE_ATTN)
@@ -314,7 +317,22 @@  static int thread_set_attn(struct pdbg_target *target, bool enable)
 				return 0;
 			hid &= ~POWER9_HID_ENABLE_ATTN;
 		}
-		hid |= POWER9_HID_FLUSH_ICACHE;
+
+		if (hid & POWER9_HID_FLUSH_ICACHE) {
+			PR_WARNING("set_attn found HID flush icache bit unexpectedly set\n");
+			hid &= ~POWER9_HID_FLUSH_ICACHE;
+		}
+
+		/* Change the ENABLE_ATTN bit in the register */
+		if (thread_putspr(target, SPR_HID, hid))
+			return -1;
+		/* FLUSH_ICACHE 0->1 to flush */
+		if (thread_putspr(target, SPR_HID, hid | POWER9_HID_FLUSH_ICACHE))
+			return -1;
+		/* Restore FLUSH_ICACHE back to 0 */
+		if (thread_putspr(target, SPR_HID, hid))
+			return -1;
+
 	} else if (pdbg_target_compatible(target, "ibm,power10-thread")) {
 		if (enable) {
 			if (hid & POWER10_HID_ENABLE_ATTN)
@@ -326,14 +344,24 @@  static int thread_set_attn(struct pdbg_target *target, bool enable)
 				return 0;
 			hid &= ~POWER10_HID_ENABLE_ATTN;
 		}
-		hid |= POWER10_HID_FLUSH_ICACHE;
+		if (hid & POWER10_HID_FLUSH_ICACHE) {
+			PR_WARNING("set_attn found HID flush icache bit unexpectedly set\n");
+			hid &= ~POWER10_HID_FLUSH_ICACHE;
+		}
+
+		/* Change the ENABLE_ATTN bit in the register */
+		if (thread_putspr(target, SPR_HID, hid))
+			return -1;
+		/* FLUSH_ICACHE 0->1 to flush */
+		if (thread_putspr(target, SPR_HID, hid | POWER10_HID_FLUSH_ICACHE))
+			return -1;
+		/* Restore FLUSH_ICACHE back to 0 */
+		if (thread_putspr(target, SPR_HID, hid))
+			return -1;
 	} else {
 		return -1;
 	}
 
-	if (thread_putspr(target, SPR_HID, hid))
-		return -1;
-
 	return 0;
 }