libpfm/thunderx2-uncore-support.patch
Tony Jones 71e4f7a0f0 - Add Cavium ThunderX2 uncore support (jsc#SLE-10000)
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
2020-03-03 03:01:33 +00:00

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, &reg);
+ else
+ display_com(this, e, &reg);
+}
+
+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))