New patch: thunderx2-uncore-support.patch New patch: moved-tx2-uncore-event-to-separate-file.patch New patch: add-thunderx2-dmc-events-and-ccpi-events.patch New patch: removed-extra-fields-from-tx2_unc_data_t.patch OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libpfm?expand=0&rev=49
378 lines
11 KiB
Diff
378 lines
11 KiB
Diff
From: Shay Gal-On <sgalon@marvell.com>
|
|
Date: Wed Oct 23 18:58:03 2019 -0700
|
|
Subject: ThunderX2 uncore support
|
|
Git-commit: 0b050ca9ba2a2bf74f87fa3a8b4ed8aec9d1dfa8
|
|
References: jsc#SLE-10000
|
|
Signed-off-by: Tony Jones <tonyj@suse.de>
|
|
X-Info: adjust for context, no 98218490 (CascadeLake X core PMU)
|
|
|
|
ThunderX2 uncore support
|
|
|
|
This patch adds ThundeX2 uncore PMUs support.
|
|
|
|
The following uncore PMUs are added:
|
|
- tx2_llc0, tx2_llc1 (last level cache)
|
|
- tx2_dmc0, tx2_dmc1 (memory controller)
|
|
|
|
Based on documentation available at:
|
|
https://www.marvell.com/documents/hrur6mybdvk5uki1w0z7/
|
|
|
|
Signed-off-by: Shay Gal-On <sgalon@marvell.com>
|
|
|
|
diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
|
|
index 09c673d..20d5feb 100644
|
|
--- a/include/perfmon/pfmlib.h
|
|
+++ b/include/perfmon/pfmlib.h
|
|
@@ -546,6 +546,11 @@ typedef enum {
|
|
PFM_PMU_INTEL_KNM_UNC_UBOX, /* Intel Knights Mill Ubox uncore */
|
|
PFM_PMU_INTEL_KNM_UNC_M2PCIE, /* Intel Knights Mill M2PCIe uncore */
|
|
PFM_PMU_ARM_THUNDERX2, /* Cavium ThunderX2 */
|
|
+
|
|
+ PFM_PMU_ARM_THUNDERX2_DMC0, /* Cavium ThunderX2 DMC unit 0 uncore */
|
|
+ PFM_PMU_ARM_THUNDERX2_DMC1, /* Cavium ThunderX2 DMC unit 1 uncore */
|
|
+ PFM_PMU_ARM_THUNDERX2_LLC0, /* Cavium ThunderX2 LLC unit 0 uncore */
|
|
+ PFM_PMU_ARM_THUNDERX2_LLC1, /* Cavium ThunderX2 LLC unit 1 uncore */
|
|
/* MUST ADD NEW PMU MODELS HERE */
|
|
|
|
PFM_PMU_MAX /* end marker */
|
|
diff --git a/lib/Makefile b/lib/Makefile
|
|
index 2eb3ebb..f45515d 100644
|
|
--- a/lib/Makefile
|
|
+++ b/lib/Makefile
|
|
@@ -188,7 +188,7 @@ SRCS += pfmlib_arm_perf_event.c
|
|
endif
|
|
|
|
INCARCH = $(INC_ARM64)
|
|
-SRCS += pfmlib_arm.c pfmlib_arm_armv8.c
|
|
+SRCS += pfmlib_arm.c pfmlib_arm_armv8.c pfmlib_tx2_unc_perf_event.c
|
|
CFLAGS += -DCONFIG_PFMLIB_ARCH_ARM64
|
|
endif
|
|
|
|
diff --git a/lib/events/arm_cavium_tx2_events.h b/lib/events/arm_cavium_tx2_events.h
|
|
index 198d33d..18d8931 100644
|
|
--- a/lib/events/arm_cavium_tx2_events.h
|
|
+++ b/lib/events/arm_cavium_tx2_events.h
|
|
@@ -835,3 +835,64 @@ static const arm_entry_t arm_thunderx2_pe[]={
|
|
.desc = "Scu hwpf next line requests generated"
|
|
},
|
|
};
|
|
+
|
|
+#define ARM_TX2_CORE_EVENT_COUNT (sizeof(arm_thunderx2_pe)/sizeof(arm_entry_t))
|
|
+
|
|
+/* L3C event IDs */
|
|
+#define L3_EVENT_READ_REQ 0xD
|
|
+#define L3_EVENT_WRITEBACK_REQ 0xE
|
|
+#define L3_EVENT_EVICT_REQ 0x13
|
|
+#define L3_EVENT_READ_HIT 0x17
|
|
+#define L3_EVENT_MAX 0x18
|
|
+
|
|
+/* DMC event IDs */
|
|
+#define DMC_EVENT_COUNT_CYCLES 0x1
|
|
+#define DMC_EVENT_WRITE_TXNS 0xB
|
|
+#define DMC_EVENT_DATA_TRANSFERS 0xD
|
|
+#define DMC_EVENT_READ_TXNS 0xF
|
|
+#define DMC_EVENT_MAX 0x10
|
|
+
|
|
+static const arm_entry_t arm_thunderx2_unc_dmc_pe[]={
|
|
+ {.name = "UNC_DMC_READS",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = DMC_EVENT_READ_TXNS,
|
|
+ .desc = "Memory read transactions"
|
|
+ },
|
|
+ {.name = "UNC_DMC_WRITES",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = DMC_EVENT_WRITE_TXNS,
|
|
+ .desc = "Memory write transactions"
|
|
+ },
|
|
+};
|
|
+
|
|
+#define ARM_TX2_CORE_DMC_COUNT (sizeof(arm_thunderx2_unc_dmc_pe)/sizeof(arm_entry_t))
|
|
+
|
|
+static const arm_entry_t arm_thunderx2_unc_llc_pe[]={
|
|
+ {.name = "UNC_LLC_READ",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = L3_EVENT_READ_REQ,
|
|
+ .desc = "Read requests to LLC"
|
|
+ },
|
|
+ {.name = "UNC_LLC_EVICT",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = L3_EVENT_EVICT_REQ,
|
|
+ .desc = "Evict requests to LLC"
|
|
+ },
|
|
+ {.name = "UNC_LLC_READ_HIT",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = L3_EVENT_READ_HIT,
|
|
+ .desc = "Read requests to LLC which hit"
|
|
+ },
|
|
+ {.name = "UNC_LLC_WB",
|
|
+ .modmsk = ARMV8_ATTRS,
|
|
+ .code = L3_EVENT_WRITEBACK_REQ,
|
|
+ .desc = "Writeback requests to LLC"
|
|
+ }
|
|
+};
|
|
+
|
|
+#define ARM_TX2_CORE_LLC_COUNT (sizeof(arm_thunderx2_unc_llc_pe)/sizeof(arm_entry_t))
|
|
+//Uncore accessor functions
|
|
+int
|
|
+pfm_tx2_unc_get_event_encoding(void *this, pfmlib_event_desc_t *e);
|
|
+int
|
|
+pfm_tx2_unc_get_perf_encoding(void *this, pfmlib_event_desc_t *e);
|
|
diff --git a/lib/pfmlib_arm_armv8.c b/lib/pfmlib_arm_armv8.c
|
|
index 0a3313f..35ff70f 100644
|
|
--- a/lib/pfmlib_arm_armv8.c
|
|
+++ b/lib/pfmlib_arm_armv8.c
|
|
@@ -203,3 +203,58 @@ pfmlib_pmu_t arm_thunderx2_support={
|
|
.get_event_nattrs = pfm_arm_get_event_nattrs,
|
|
};
|
|
|
|
+// For uncore, each socket has a separate perf name, otherwise they are the same, use macro
|
|
+
|
|
+#define DEFINE_TX2_DMC(n) \
|
|
+pfmlib_pmu_t arm_thunderx2_dmc##n##_support={ \
|
|
+ .desc = "Cavium ThunderX2 Node"#n" DMC", \
|
|
+ .name = "tx2_dmc"#n, \
|
|
+ .perf_name = "uncore_dmc_"#n, \
|
|
+ .pmu = PFM_PMU_ARM_THUNDERX2_DMC##n, \
|
|
+ .pme_count = LIBPFM_ARRAY_SIZE(arm_thunderx2_unc_dmc_pe), \
|
|
+ .type = PFM_PMU_TYPE_UNCORE, \
|
|
+ .pe = arm_thunderx2_unc_dmc_pe, \
|
|
+ .pmu_detect = pfm_arm_detect_thunderx2, \
|
|
+ .max_encoding = 1, \
|
|
+ .num_cntrs = 4, \
|
|
+ .get_event_encoding[PFM_OS_NONE] = pfm_tx2_unc_get_event_encoding, \
|
|
+ PFMLIB_ENCODE_PERF(pfm_tx2_unc_get_perf_encoding), \
|
|
+ .get_event_first = pfm_arm_get_event_first, \
|
|
+ .get_event_next = pfm_arm_get_event_next, \
|
|
+ .event_is_valid = pfm_arm_event_is_valid, \
|
|
+ .validate_table = pfm_arm_validate_table, \
|
|
+ .get_event_info = pfm_arm_get_event_info, \
|
|
+ .get_event_attr_info = pfm_arm_get_event_attr_info, \
|
|
+ PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),\
|
|
+ .get_event_nattrs = pfm_arm_get_event_nattrs, \
|
|
+};
|
|
+
|
|
+DEFINE_TX2_DMC(0);
|
|
+DEFINE_TX2_DMC(1);
|
|
+
|
|
+#define DEFINE_TX2_LLC(n) \
|
|
+pfmlib_pmu_t arm_thunderx2_llc##n##_support={ \
|
|
+ .desc = "Cavium ThunderX2 node "#n" LLC", \
|
|
+ .name = "tx2_llc"#n, \
|
|
+ .perf_name = "uncore_l3c_"#n, \
|
|
+ .pmu = PFM_PMU_ARM_THUNDERX2_LLC##n, \
|
|
+ .pme_count = LIBPFM_ARRAY_SIZE(arm_thunderx2_unc_llc_pe), \
|
|
+ .type = PFM_PMU_TYPE_UNCORE, \
|
|
+ .pe = arm_thunderx2_unc_llc_pe, \
|
|
+ .pmu_detect = pfm_arm_detect_thunderx2, \
|
|
+ .max_encoding = 1, \
|
|
+ .num_cntrs = 4, \
|
|
+ .get_event_encoding[PFM_OS_NONE] = pfm_tx2_unc_get_event_encoding, \
|
|
+ PFMLIB_ENCODE_PERF(pfm_tx2_unc_get_perf_encoding), \
|
|
+ .get_event_first = pfm_arm_get_event_first, \
|
|
+ .get_event_next = pfm_arm_get_event_next, \
|
|
+ .event_is_valid = pfm_arm_event_is_valid, \
|
|
+ .validate_table = pfm_arm_validate_table, \
|
|
+ .get_event_info = pfm_arm_get_event_info, \
|
|
+ .get_event_attr_info = pfm_arm_get_event_attr_info, \
|
|
+ PFMLIB_VALID_PERF_PATTRS(pfm_arm_perf_validate_pattrs),\
|
|
+ .get_event_nattrs = pfm_arm_get_event_nattrs, \
|
|
+};
|
|
+
|
|
+DEFINE_TX2_LLC(0);
|
|
+DEFINE_TX2_LLC(1);
|
|
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
|
|
index 2b6cbb4..8314d4b 100644
|
|
--- a/lib/pfmlib_common.c
|
|
+++ b/lib/pfmlib_common.c
|
|
@@ -490,6 +490,10 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
|
|
&arm_cortex_a53_support,
|
|
&arm_xgene_support,
|
|
&arm_thunderx2_support,
|
|
+ &arm_thunderx2_dmc0_support,
|
|
+ &arm_thunderx2_dmc1_support,
|
|
+ &arm_thunderx2_llc0_support,
|
|
+ &arm_thunderx2_llc1_support,
|
|
#endif
|
|
|
|
#ifdef CONFIG_PFMLIB_ARCH_S390X
|
|
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
|
|
index b0070a6..cb83f43 100644
|
|
--- a/lib/pfmlib_priv.h
|
|
+++ b/lib/pfmlib_priv.h
|
|
@@ -644,7 +644,13 @@ extern pfmlib_pmu_t arm_qcom_krait_support;
|
|
extern pfmlib_pmu_t arm_cortex_a57_support;
|
|
extern pfmlib_pmu_t arm_cortex_a53_support;
|
|
extern pfmlib_pmu_t arm_xgene_support;
|
|
+
|
|
extern pfmlib_pmu_t arm_thunderx2_support;
|
|
+extern pfmlib_pmu_t arm_thunderx2_dmc0_support;
|
|
+extern pfmlib_pmu_t arm_thunderx2_dmc1_support;
|
|
+extern pfmlib_pmu_t arm_thunderx2_llc0_support;
|
|
+extern pfmlib_pmu_t arm_thunderx2_llc1_support;
|
|
+
|
|
extern pfmlib_pmu_t mips_74k_support;
|
|
extern pfmlib_pmu_t s390x_cpum_cf_support;
|
|
extern pfmlib_pmu_t s390x_cpum_sf_support;
|
|
diff --git a/lib/pfmlib_tx2_unc_perf_event.c b/lib/pfmlib_tx2_unc_perf_event.c
|
|
new file mode 100644
|
|
index 0000000..1a04e1d
|
|
--- /dev/null
|
|
+++ b/lib/pfmlib_tx2_unc_perf_event.c
|
|
@@ -0,0 +1,139 @@
|
|
+#include <sys/types.h>
|
|
+#include <string.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdio.h>
|
|
+#include <stdarg.h>
|
|
+#include <limits.h>
|
|
+
|
|
+/* private headers */
|
|
+#include "pfmlib_priv.h"
|
|
+#include "pfmlib_perf_event_priv.h"
|
|
+#include "pfmlib_arm_priv.h"
|
|
+
|
|
+typedef union {
|
|
+ uint64_t val;
|
|
+ struct {
|
|
+ unsigned long unc_event:8; /* event code */
|
|
+ unsigned long unc_umask:8; /* unit mask */
|
|
+ unsigned long unc_res1:1; /* reserved */
|
|
+ unsigned long unc_rst:1; /* reset */
|
|
+ unsigned long unc_edge:1; /* edge detect */
|
|
+ unsigned long unc_res2:3; /* reserved */
|
|
+ unsigned long unc_en:1; /* enable */
|
|
+ unsigned long unc_inv:1; /* invert counter mask */
|
|
+ unsigned long unc_thres:8; /* counter mask */
|
|
+ unsigned long unc_res3:32; /* reserved */
|
|
+ } com; /* covers common fields for DMC/L3C */
|
|
+} tx2_unc_data_t;
|
|
+
|
|
+static void
|
|
+display_reg(void *this, pfmlib_event_desc_t *e, tx2_unc_data_t reg);
|
|
+static void
|
|
+display_com(void *this, pfmlib_event_desc_t *e, void *val);
|
|
+static int
|
|
+find_pmu_type_by_name(const char *name);
|
|
+
|
|
+int
|
|
+pfm_tx2_unc_get_event_encoding(void *this, pfmlib_event_desc_t *e)
|
|
+{
|
|
+ //from pe field in for the uncore, get the array with all the event defs
|
|
+ const arm_entry_t *event_list = this_pe(this);
|
|
+ tx2_unc_data_t reg;
|
|
+ //get code for the event from the table
|
|
+ reg.val = event_list[e->event].code;
|
|
+ //pass the data back to the caller
|
|
+ e->codes[0] = reg.val;
|
|
+ e->count = 1;
|
|
+ evt_strcat(e->fstr, "%s", event_list[e->event].name);
|
|
+ display_reg(this, e, reg);
|
|
+ return PFM_SUCCESS;
|
|
+}
|
|
+
|
|
+int
|
|
+pfm_tx2_unc_get_perf_encoding(void *this, pfmlib_event_desc_t *e)
|
|
+{
|
|
+ pfmlib_pmu_t *pmu = this;
|
|
+ struct perf_event_attr *attr = e->os_data;
|
|
+ tx2_unc_data_t reg;
|
|
+ int ret;
|
|
+
|
|
+ if (!pmu->get_event_encoding[PFM_OS_NONE])
|
|
+ return PFM_ERR_NOTSUPP;
|
|
+
|
|
+ ret = pmu->get_event_encoding[PFM_OS_NONE](this, e);
|
|
+ if (ret != PFM_SUCCESS)
|
|
+ return ret;
|
|
+ //get pmu type to probe
|
|
+ ret = find_pmu_type_by_name(pmu->perf_name);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ attr->type = ret;
|
|
+ //get code to provide to the uncore pmu probe
|
|
+ reg.val = e->codes[0];
|
|
+ attr->config = reg.val;
|
|
+
|
|
+ // if needed, can use attr->config1 or attr->config2 for extra info from event structure defines e->codes[i]
|
|
+
|
|
+ // uncore measures at all priv levels
|
|
+ attr->exclude_hv = 0;
|
|
+ attr->exclude_kernel = 0;
|
|
+ attr->exclude_user = 0;
|
|
+
|
|
+ return PFM_SUCCESS;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+display_reg(void *this, pfmlib_event_desc_t *e, tx2_unc_data_t reg)
|
|
+{
|
|
+ pfmlib_pmu_t *pmu = this;
|
|
+ if (pmu->display_reg)
|
|
+ pmu->display_reg(this, e, ®);
|
|
+ else
|
|
+ display_com(this, e, ®);
|
|
+}
|
|
+
|
|
+static void
|
|
+display_com(void *this, pfmlib_event_desc_t *e, void *val)
|
|
+{
|
|
+ const arm_entry_t *pe = this_pe(this);
|
|
+ tx2_unc_data_t *reg = val;
|
|
+
|
|
+ __pfm_vbprintf("[UNC=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
|
|
+ "inv=%d edge=%d thres=%d] %s\n",
|
|
+ reg->val,
|
|
+ reg->com.unc_event,
|
|
+ reg->com.unc_umask,
|
|
+ reg->com.unc_en,
|
|
+ reg->com.unc_inv,
|
|
+ reg->com.unc_edge,
|
|
+ reg->com.unc_thres,
|
|
+ pe[e->event].name);
|
|
+}
|
|
+
|
|
+static int
|
|
+find_pmu_type_by_name(const char *name)
|
|
+{
|
|
+ char filename[PATH_MAX];
|
|
+ FILE *fp;
|
|
+ int ret, type;
|
|
+
|
|
+ if (!name)
|
|
+ return PFM_ERR_NOTSUPP;
|
|
+
|
|
+ sprintf(filename, "/sys/bus/event_source/devices/%s/type", name);
|
|
+
|
|
+ fp = fopen(filename, "r");
|
|
+ if (!fp)
|
|
+ return PFM_ERR_NOTSUPP;
|
|
+
|
|
+ ret = fscanf(fp, "%d", &type);
|
|
+ if (ret != 1)
|
|
+ type = PFM_ERR_NOTSUPP;
|
|
+
|
|
+ fclose(fp);
|
|
+
|
|
+ return type;
|
|
+}
|
|
+
|
|
diff --git a/tests/validate_arm64.c b/tests/validate_arm64.c
|
|
index f7f021a..35eb6ef 100644
|
|
--- a/tests/validate_arm64.c
|
|
+++ b/tests/validate_arm64.c
|
|
@@ -177,6 +177,12 @@ static const test_event_t arm64_test_events[]={
|
|
.codes[0] = 0x8000008,
|
|
.fstr = "arm_thunderx2::INST_RETIRED:k=1:u=1:hv=0",
|
|
},
|
|
+ { SRC_LINE,
|
|
+ .name = "tx2_dmc1::UNC_DMC_READS",
|
|
+ .ret = PFM_SUCCESS,
|
|
+ .count = 1,
|
|
+ .codes[0] = 0xf,
|
|
+ },
|
|
};
|
|
#define NUM_TEST_EVENTS (int)(sizeof(arm64_test_events)/sizeof(test_event_t))
|
|
|