diff mbox series

[02/12] libpdbg: Add nhtm hardware unit for p10

Message ID 20210802054112.461728-3-jniethe5@gmail.com
State Superseded
Headers show
Series P10 HTM Support | expand

Commit Message

Jordan Niethe Aug. 2, 2021, 5:41 a.m. UTC
p10 also has a Nest HTM. The biggest change is that on p10 there are two
nhtm units. Add support for it.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
 libpdbg/htm.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++----
 p10.dts.m4    |  12 +--
 2 files changed, 226 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/libpdbg/htm.c b/libpdbg/htm.c
index 43cef84522ef..ded46d2987a1 100644
--- a/libpdbg/htm.c
+++ b/libpdbg/htm.c
@@ -35,6 +35,7 @@ 
 			rc;})
 
 #define MIN(x,y) ((x < y) ? x : y)
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
 
 #define DEBUGFS_POWERPC "/sys/kernel/debug/powerpc"
 #define DEBUGFS_SCOM DEBUGFS_POWERPC"/scom"
@@ -75,10 +76,34 @@ 
 #define   HTM_MEM_SCOPE			PPC_BITMASK(1,3)
 /* Note: the next 3 change on P9 */
 #define   HTM_MEM_PRIORITY		PPC_BITMASK(4,5)
+#define   HTM_MEM_PRIORITY_P10		PPC_BITMASK(4)
 #define   HTM_MEM_SIZE_SMALL		PPC_BIT(13)
+#define   HTM_MEM_SIZE_SMALL_P10	PPC_BIT(5)
 #define   HTM_MEM_BASE			PPC_BITMASK(14,39)
+#define   HTM_MEM_BASE_P10		PPC_BITMASK(8,39)
 #define	  HTM_MEM_SIZE			PPC_BITMASK(40,48)
 #define HTM_STATUS			2
+#define   HTM1_STATUS_MASK		PPC_BITMASK(22,39)
+#define   HTM1_STATUS_CRESP_OV		PPC_BIT(22)
+#define	  HTM1_STATUS_REPAIR		PPC_BIT(23)
+#define   HTM1_STATUS_BUF_WAIT		PPC_BIT(24)
+#define   HTM1_STATUS_TRIG_DROPPED	PPC_BIT(25)
+#define   HTM1_STATUS_ADDR_ERROR	PPC_BIT(26)
+#define   HTM1_STATUS_REC_DROPPED	PPC_BIT(27)
+#define   HTM1_STATUS_INIT		PPC_BIT(28)
+#define   HTM1_STATUS_PREREQ		PPC_BIT(29)
+#define   HTM1_STATUS_READY		PPC_BIT(30)
+#define   HTM1_STATUS_TRACING		PPC_BIT(31)
+#define   HTM1_STATUS_PAUSED		PPC_BIT(32)
+#define   HTM1_STATUS_FLUSH		PPC_BIT(33)
+#define   HTM1_STATUS_COMPLETE		PPC_BIT(34)
+#define   HTM1_STATUS_ENABLE		PPC_BIT(35)
+#define   HTM1_STATUS_STAMP		PPC_BIT(36)
+#define   HTM1_STATUS_SCOM_ERROR	PPC_BIT(37)
+#define   HTM1_STATUS_PARITY_ERROR	PPC_BIT(38)
+#define   HTM1_STATUS_INVALID_CRESP	PPC_BIT(39)
+#define   HTM1_STATUS_STATE_MASK	(PPC_BITMASK(28,36) | HTM_STATUS_REPAIR)
+#define	  HTM1_STATUS_ERROR_MASK	(HTM_STATUS_CRESP_OV | PPC_BITMASK(24,27) | PPC_BITMASK(37,39))
 #define   HTM_STATUS_MASK		PPC_BITMASK(2,19)
 #define   HTM_STATUS_CRESP_OV		PPC_BIT(2)
 #define	  HTM_STATUS_REPAIR		PPC_BIT(3)
@@ -102,6 +127,8 @@ 
 #define	  HTM_STATUS_ERROR_MASK		(HTM_STATUS_CRESP_OV | PPC_BITMASK(4,7) | PPC_BITMASK(17,19))
 #define HTM_LAST_ADDRESS		3
 #define   HTM_LAST_ADDRESS_MASK		PPC_BITMASK(8,56)
+#define HTM1_LAST_ADDRESS		4
+#define   HTM1_LAST_ADDRESS_MASK	PPC_BITMASK(8,56)
 #define HTM_SCOM_TRIGGER		4
 #define	  HTM_TRIG_START		PPC_BIT(0)
 #define   HTM_TRIG_STOP			PPC_BIT(1)
@@ -132,6 +159,24 @@ 
 #define NHTM_FLEX_MUX			9
 #define   NHTM_FLEX_MUX_MASK		PPC_BITMASK(0,35)
 #define   NHTM_FLEX_DEFAULT		0xCB3456129
+#define   NHTM_FLEX_MUX_MASK_P10	PPC_BITMASK(0,39)
+#define   NHTM_FLEX_DEFAULT_P10		0xCB34561567
+#define NHTM_ADDR_PAT			0xb
+#define   NHTM_ADDR_PAT_MASK		PPC_BITMASK(0, 55)
+#define NHTM_ADDR_MASK			0xc
+#define   NHTM_ADDR_MASK_MASK		PPC_BITMASK(0, 55)
+#define NHTM_STOP_FILTER		0xd
+#define   NHTM_STOP_FILTER_TTAG_PAT	PPC_BITMASK(0, 14)
+#define   NHTM_STOP_FILTER_TTAG_MASK	PPC_BITMASK(15, 29)
+#define   NHTM_STOP_FILTER_TTYPE_PAT	PPC_BITMASK(30, 36)
+#define   NHTM_STOP_FILTER_TTYPE_MASK	PPC_BITMASK(37, 43)
+#define   NHTM_STOP_FILTER_CRESP_PAT	PPC_BITMASK(44, 48)
+#define   NHTM_STOP_FILTER_CRESP_MASK	PPC_BITMASK(49, 53)
+#define   NHTM_STOP_CYCLES		PPC_BITMASK(54, 60)
+#define NHTM_STOP_FILT_ADDR_PAT		0xe
+#define   NHTM_STOP_FILT_ADDR_PAT_MASK	PPC_BITMASK(0, 55)
+#define NHTM_STOP_FILT_ADDR_MASK	0xf
+#define   NHTM_STOP_FILT_ADDR_MASK_MASK	PPC_BITMASK(0, 55)
 
 enum htm_state {
 	INIT,
@@ -161,14 +206,25 @@  enum htm_error {
 
 struct htm_status {
 	enum htm_state state;
+	enum htm_state state1;
 	enum htm_error error;
+	enum htm_error error1;
 	bool mem_size_select;
 	uint16_t mem_size;
 	uint64_t mem_base;
 	uint64_t mem_last;
+	uint64_t mem_last1;
 	uint64_t raw;
 };
 
+/* Some of the nhtm registers on P10 have moved address slightly */
+static unsigned long reg_off(struct htm *htm, unsigned long reg)
+{
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm"))
+		return reg + 1;
+	return reg;
+}
+
 static struct htm *check_and_convert(struct pdbg_target *target)
 {
 	if (!pdbg_target_is_class(target, "nhtm") &&
@@ -292,6 +348,37 @@  static int get_status(struct htm *htm, struct htm_status *status)
 		status->error = NONE;
 	}
 
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		switch (status->raw & HTM1_STATUS_ERROR_MASK) {
+		case HTM1_STATUS_CRESP_OV:
+			status->error1 = CRESP_OV;
+			break;
+		case HTM1_STATUS_BUF_WAIT:
+			status->error1 = BUF_WAIT;
+			break;
+		case HTM1_STATUS_TRIG_DROPPED:
+			status->error1 = TRIGGER_DROPPED;
+			break;
+		case HTM1_STATUS_ADDR_ERROR:
+			status->error1 = ADDR_ERROR;
+			break;
+		case HTM1_STATUS_REC_DROPPED:
+			status->error1 = RECORD_DROPPED;
+			break;
+		case HTM1_STATUS_SCOM_ERROR:
+			status->error1 = SCOM_ERROR;
+			break;
+		case HTM1_STATUS_PARITY_ERROR:
+			status->error1 = PARITY_ERROR;
+			break;
+		case HTM1_STATUS_INVALID_CRESP:
+			status->error1 = INVALID_CRESP;
+			break;
+		default:
+			status->error1 = NONE;
+		}
+	}
+
 	switch (status->raw & HTM_STATUS_STATE_MASK) {
 	case HTM_STATUS_REPAIR:
 		status->state = REPAIR;
@@ -327,16 +414,63 @@  static int get_status(struct htm *htm, struct htm_status *status)
 		status->state = UNINITIALIZED;
 	}
 
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		switch (status->raw & HTM1_STATUS_STATE_MASK) {
+		case HTM1_STATUS_REPAIR:
+			status->state1 = REPAIR;
+			break;
+		case HTM1_STATUS_INIT:
+			status->state1 = INIT;
+			break;
+		case HTM1_STATUS_PREREQ:
+			status->state1 = PREREQ;
+			break;
+		case HTM1_STATUS_READY:
+			status->state1 = READY;
+			break;
+		case HTM1_STATUS_TRACING:
+			status->state1 = TRACING;
+			break;
+		case HTM1_STATUS_PAUSED:
+			status->state1 = PAUSED;
+			break;
+		case HTM1_STATUS_FLUSH:
+			status->state1 = FLUSH;
+			break;
+		case HTM1_STATUS_COMPLETE:
+			status->state1 = COMPLETE;
+			break;
+		case HTM1_STATUS_ENABLE:
+			status->state1 = ENABLE;
+			break;
+		case HTM1_STATUS_STAMP:
+			status->state1 = STAMP;
+			break;
+		default:
+			status->state1 = UNINITIALIZED;
+		}
+	}
+
 	if (HTM_ERR(pib_read(&htm->target, HTM_MEMORY_CONF, &val)))
 		return -1;
 
-	status->mem_size_select = val & HTM_MEM_SIZE_SMALL;
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		status->mem_size_select = val & HTM_MEM_SIZE_SMALL_P10;
+		status->mem_base = val & HTM_MEM_BASE_P10;
+	} else {
+		status->mem_size_select = val & HTM_MEM_SIZE_SMALL;
+		status->mem_base = val & HTM_MEM_BASE;
+	}
 	status->mem_size = GETFIELD(HTM_MEM_SIZE,val);
-	status->mem_base = val & HTM_MEM_BASE;
 
 	if (HTM_ERR(pib_read(&htm->target, HTM_LAST_ADDRESS, &status->mem_last)))
 		return -1;
 
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		if (HTM_ERR(pib_read(&htm->target, HTM1_LAST_ADDRESS, &status->mem_last1)))
+			return -1;
+	}
+
 	return 0;
 }
 
@@ -540,18 +674,19 @@  static int configure_nhtm(struct htm *htm, bool wrap)
 		return -1;
 
 	/* Stop on core xstop */
-	if (HTM_ERR(pib_write(&htm->target, HTM_TRIGGER_CONTROL, HTM_CTRL_XSTOP_STOP)))
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, HTM_TRIGGER_CONTROL),
+			      HTM_CTRL_XSTOP_STOP)))
 		return -1;;
 
 	/*
 	 * These values are taken from a cronus booted system.
 	 */
-	if (HTM_ERR(pib_write(&htm->target, NHTM_FILTER_CONTROL,
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, NHTM_FILTER_CONTROL),
 			NHTM_FILTER_MASK | /* no pattern matching */
 			NHTM_FILTER_CRESP_MASK))) /* no pattern matching */
 		return -1;
 
-	if (HTM_ERR(pib_write(&htm->target, NHTM_TTYPE_FILTER_CONTROL,
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, NHTM_TTYPE_FILTER_CONTROL),
 			NHTM_TTYPE_TYPE_MASK | /* no pattern matching */
 			NHTM_TTYPE_SIZE_MASK ))) /* no pattern matching */
 		return -1;
@@ -566,6 +701,35 @@  static int configure_nhtm(struct htm *htm, bool wrap)
 		}
 	}
 
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		if (HTM_ERR(pib_read(&htm->target, reg_off(htm, NHTM_FLEX_MUX), &val)))
+			return -1;
+
+		if (GETFIELD(NHTM_FLEX_MUX_MASK_P10, val) != NHTM_FLEX_DEFAULT_P10) {
+			PR_ERROR("The HTM Flex wasn't default value\n");
+			return -1;
+		}
+
+		if (HTM_ERR(pib_write(&htm->target, NHTM_ADDR_PAT, 0)))
+			return -1;
+
+		if (HTM_ERR(pib_write(&htm->target, NHTM_ADDR_MASK, NHTM_ADDR_MASK_MASK)))
+			return -1;
+
+		if (HTM_ERR(pib_write(&htm->target, NHTM_STOP_FILTER,
+				      NHTM_STOP_FILTER_TTAG_MASK |
+				      NHTM_STOP_FILTER_TTYPE_MASK |
+				      NHTM_STOP_FILTER_CRESP_MASK)))
+			return -1;
+
+		if (HTM_ERR(pib_write(&htm->target, NHTM_STOP_FILT_ADDR_PAT, 0)))
+			return -1;
+
+		if (HTM_ERR(pib_write(&htm->target, NHTM_STOP_FILT_ADDR_MASK,
+				      NHTM_STOP_FILT_ADDR_MASK_MASK)))
+			return -1;
+	}
+
 	return 0;
 }
 
@@ -577,9 +741,13 @@  static int deconfigure_nhtm(struct htm *htm)
 	return 0;
 }
 
-static int is_startable(struct htm_status *status)
+static int is_startable(struct htm *htm, struct htm_status *status)
 {
-	return (status->state == READY || status->state == PAUSED);
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm"))
+		return ((status->state == READY || status->state == PAUSED) &&
+			(status->state1 == READY || status->state1 == PAUSED));
+	else
+		return (status->state == READY || status->state == PAUSED);
 }
 
 static char *get_debugfs_file(struct htm *htm, const char *file)
@@ -715,7 +883,10 @@  static int configure_memory(struct htm *htm)
 	small = 0;
 	if (size < 512*1024*1024)
 		small = 1;
-	val = SETFIELD(HTM_MEM_SIZE_SMALL, val, small);
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm"))
+		val = SETFIELD(HTM_MEM_SIZE_SMALL_P10, val, small);
+	else
+		val = SETFIELD(HTM_MEM_SIZE_SMALL, val, small);
 	shift = 29; /* large */
 	if (small)
 		shift = 24;
@@ -728,13 +899,16 @@  static int configure_memory(struct htm *htm)
 	 * already shifted correct as read from the kernel, or'ing it
 	 * in works fine.
 	 */
-	val = SETFIELD(HTM_MEM_BASE, val, 0);
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm"))
+		val = SETFIELD(HTM_MEM_BASE_P10, val, 0);
+	else
+		val = SETFIELD(HTM_MEM_BASE, val, 0);
 	val |= base;
 
 	if (HTM_ERR(pib_write(&htm->target, HTM_MEMORY_CONF, val)))
 		return -1;
 
-	if (HTM_ERR(pib_write(&htm->target, HTM_SCOM_TRIGGER, HTM_TRIG_RESET)))
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, HTM_SCOM_TRIGGER), HTM_TRIG_RESET)))
 		return -1;
 
 	return 0;
@@ -800,16 +974,16 @@  static int __do_htm_start(struct htm *htm, bool wrap)
 	if (HTM_ERR(get_status(htm, &status)))
 		return -1;
 
-	if (!is_startable(&status)) {
+	if (!is_startable(htm, &status)) {
 		PR_ERROR("HTM not in a startable state!\n");
 		return -1;
 	}
 
 	PR_INFO("* Sending START trigger to HTM\n");
-	if (HTM_ERR(pib_write(&htm->target, HTM_SCOM_TRIGGER, HTM_TRIG_MARK_VALID)))
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, HTM_SCOM_TRIGGER), HTM_TRIG_MARK_VALID)))
 		return -1;
 
-	if (HTM_ERR(pib_write(&htm->target, HTM_SCOM_TRIGGER, HTM_TRIG_START)))
+	if (HTM_ERR(pib_write(&htm->target, reg_off(htm, HTM_SCOM_TRIGGER), HTM_TRIG_START)))
 		return -1;
 
 	if (htm_toggle_debug_bit(htm))
@@ -843,7 +1017,7 @@  static int do_htm_stop(struct htm *htm)
 	}
 	if (status.state == TRACING) {
 		PR_INFO("* Sending STOP trigger to HTM\n");
-		if (HTM_ERR(pib_write(&htm->target, HTM_SCOM_TRIGGER, HTM_TRIG_STOP)))
+		if (HTM_ERR(pib_write(&htm->target, reg_off(htm, HTM_SCOM_TRIGGER), HTM_TRIG_STOP)))
 			return -1;
 	} else {
 		PR_INFO("* Skipping STOP trigger, HTM is not running\n");
@@ -1008,9 +1182,9 @@  static int do_htm_dump(struct htm *htm, char *filename)
 {
 	char *trace_file;
 	struct htm_status status;
-	uint64_t last, end, trace_size;
+	uint64_t last, end, trace_size, last1 = 0;
 	int trace_fd, dump_fd;
-	uint32_t eyecatcher;
+	uint64_t eyecatcher;
 	size_t r;
 	bool wrapped;
 
@@ -1025,6 +1199,11 @@  static int do_htm_dump(struct htm *htm, char *filename)
 		return -1;
 	}
 
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm") && status.state1 != COMPLETE) {
+		PR_INFO("* Skipping DUMP tigger, HTM1 is not in complete state\n");
+		return -1;
+	}
+
 	trace_file = get_debugfs_file(htm, "trace");
 	if (!trace_file)
 		return -1;
@@ -1036,7 +1215,12 @@  static int do_htm_dump(struct htm *htm, char *filename)
 		goto out3;
 	}
 
-	r = read(trace_fd, &eyecatcher, 4);
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm")) {
+		lseek(trace_fd, 8, SEEK_SET);
+		r = read(trace_fd, &eyecatcher, 8);
+	} else {
+		r = read(trace_fd, &eyecatcher, 4);
+	}
 	if (r == -1) {
 		PR_ERROR("Failed to read from %s: %m\n", trace_file);
 		goto out2;
@@ -1045,6 +1229,8 @@  static int do_htm_dump(struct htm *htm, char *filename)
 	if (eyecatcher == 0x00f0efac)
 		wrapped = false;
 	last = status.mem_last - status.mem_base;
+	if (pdbg_target_compatible(&htm->target, "ibm,power10-nhtm"))
+		last1 = status.mem_last1 - status.mem_base;
 	end = htm_trace_size(&status);
 	trace_size = wrapped ? end : last;
 
@@ -1083,7 +1269,7 @@  static int do_htm_dump(struct htm *htm, char *filename)
 	r = lseek(trace_fd, 0, SEEK_SET);
 	if (r == -1)
 		goto out1;
-	r = copy_file(dump_fd, trace_fd, last);
+	r = copy_file(dump_fd, trace_fd, MAX(last1, last));
 	if (r)
 		goto out1;
 	r = 1;
@@ -1193,10 +1379,26 @@  static struct htm p8_chtm = {
 };
 DECLARE_HW_UNIT(p8_chtm);
 
+static struct htm p10_nhtm = {
+	.target = {
+		.name = "POWER10 Nest HTM",
+		.compatible = "ibm,power10-nhtm",
+		.class = "nhtm",
+		.probe = nhtm_probe,
+	},
+	.start = do_htm_start,
+	.stop = do_htm_stop,
+	.record = do_htm_record,
+	.status = do_htm_status,
+	.dump = do_htm_dump,
+};
+DECLARE_HW_UNIT(p10_nhtm);
+
 __attribute__((constructor))
 static void register_htm(void)
 {
 	pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p8_nhtm_hw_unit);
 	pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p9_nhtm_hw_unit);
+	pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p10_nhtm_hw_unit);
 	pdbg_hwunit_register(PDBG_DEFAULT_BACKEND, &p8_chtm_hw_unit);
 }
diff --git a/p10.dts.m4 b/p10.dts.m4
index 52e62f017106..d58086962bfb 100644
--- a/p10.dts.m4
+++ b/p10.dts.m4
@@ -316,21 +316,21 @@  define(`CHIP',
 			#size-cells = < 0x01 >;
 			index = < 0x$1 >;
 
-			adu@90000 {
+			adu@3001C00 {
 				compatible = "ibm,power10-adu";
-				reg = < 0x00 0x90000 0x50 >;
+				reg = < 0x00 0x3001C00 0x50 >;
 				system-path = "/mem$1";
 			};
 
-			htm@5012880 {
+			htm@3011C80 {
 				compatible = "ibm,power10-nhtm";
-				reg = < 0x00 0x5012880 0x40 >;
+				reg = < 0x00 0x3011C80 0x40 >;
 				index = < 0x$1 >;
 			};
 
-			htm@50128C0 {
+			htm@30120C0 {
 				compatible = "ibm,power10-nhtm";
-				reg = < 0x00 0x50128c0 0x40 >;
+				reg = < 0x00 0x30120C0 0x40 >;
 				index = < 0x$1 >;
 			};