@@ -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);
}
@@ -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 >;
};
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(-)