Enable collection of Nest PMUs on POWERPC platform

From: Deepthi Dharwar <deep...@linux.vnet.ibm.com>

Currently, POWER8 platforms supports reading of Nest/off-core
PMUs like memory read/write counters.

Required kernel framework to enable collection of these
nest PMUs is currently being discussed in the
community for mainline inclusion.
Link to the latest patch series: https://lkml.org/lkml/2015/6/25/170

Following patch enables collection of nest read and
write memory PMUs for any user using this library.

Signed-off-by: Deepthi Dharwar <deep...@linux.vnet.ibm.com>
Signed-off-by: Hemant Kumar <hem...@linux.vnet.ibm.com>
---
 include/perfmon/pfmlib.h         |    3 ++
 lib/Makefile                     |    5 ++-
 lib/events/powerpc_nest_events.h |   62 ++++++++++++++++++++++++++++++++++++++
 lib/pfmlib_common.c              |    2 +
 lib/pfmlib_power_priv.h          |    1 +
 lib/pfmlib_powerpc_nest.c        |   60 +++++++++++++++++++++++++++++++++++++
 lib/pfmlib_powerpc_perf_event.c  |   55 ++++++++++++++++++++++++++++++++++
 lib/pfmlib_priv.h                |    2 +
 8 files changed, 188 insertions(+), 2 deletions(-)
 create mode 100644 lib/events/powerpc_nest_events.h
 create mode 100644 lib/pfmlib_powerpc_nest.c

diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h
index c5aef21..2fb4744 100644
--- a/include/perfmon/pfmlib.h
+++ b/include/perfmon/pfmlib.h
@@ -289,6 +289,9 @@ typedef enum {
        PFM_PMU_INTEL_HSWEP_UNC_SB2,    /* Intel Haswell-EP S-Box 2 uncore */
        PFM_PMU_INTEL_HSWEP_UNC_SB3,    /* Intel Haswell-EP S-Box 3 uncore */
 
+    PFM_PMU_POWERPC_NEST_MCS_READ_BW,   /* POWERPC Nest Memory Read bandwidth 
*/
+    PFM_PMU_POWERPC_NEST_MCS_WRITE_BW,  /* POWERPC Nest Memory Write bandwidth 
*/
+
        /* MUST ADD NEW PMU MODELS HERE */
 
        PFM_PMU_MAX                     /* end marker */
diff --git a/lib/Makefile b/lib/Makefile
index 162b10e..1cc8765 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -117,7 +117,7 @@ SRCS += pfmlib_powerpc_perf_event.c
 endif
 
 INCARCH = $(INC_POWERPC)
-SRCS   += pfmlib_powerpc.c pfmlib_power4.c pfmlib_ppc970.c pfmlib_power5.c 
pfmlib_power6.c pfmlib_power7.c pfmlib_torrent.c pfmlib_power8.c
+SRCS   += pfmlib_powerpc.c pfmlib_power4.c pfmlib_ppc970.c pfmlib_power5.c 
pfmlib_power6.c pfmlib_power7.c pfmlib_torrent.c pfmlib_power8.c 
pfmlib_powerpc_nest.c
 CFLAGS += -DCONFIG_PFMLIB_ARCH_POWERPC
 endif
 
@@ -282,7 +282,8 @@ INC_POWERPC=events/ppc970_events.h  \
        events/power6_events.h          \
        events/power7_events.h          \
        events/power8_events.h          \
-       events/torrent_events.h
+       events/torrent_events.h         \
+       events/powerpc_nest_events.h
 
 INC_S390X=pfmlib_s390x_priv.h \
        events/s390x_cpumf_events.h
diff --git a/lib/events/powerpc_nest_events.h b/lib/events/powerpc_nest_events.h
new file mode 100644
index 0000000..2c8f155
--- /dev/null
+++ b/lib/events/powerpc_nest_events.h
@@ -0,0 +1,62 @@
+#ifndef __POWERPC_NEST_EVENTS_H__
+#define __POWERPC_NEST_EVENTS_H__
+
+#define POWERPC_PME_NEST_MCS_00 0
+#define POWERPC_PME_NEST_MCS_01 1
+#define POWERPC_PME_NEST_MCS_02 2
+#define POWERPC_PME_NEST_MCS_03 3
+
+static const pme_power_entry_t powerpc_nest_read_pe[] = {
+    [ POWERPC_PME_NEST_MCS_00 ] = {
+        .pme_name = "MCS_00",
+        .pme_code = 0x118,
+        .pme_short_desc = "Total Read Bandwidth seen on both MCS of MC0",
+        .pme_long_desc = "Total Read Bandwidth seen on both MCS of MC0",
+    },
+    [ POWERPC_PME_NEST_MCS_01 ] = {
+        .pme_name = "MCS_01",
+        .pme_code = 0x120,
+        .pme_short_desc = "Total Read Bandwidth seen on both MCS of MC1",
+        .pme_long_desc = "Total Read Bandwidth seen on both MCS of MC1",
+    },
+    [ POWERPC_PME_NEST_MCS_02 ] = {
+        .pme_name = "MCS_02",
+        .pme_code = 0x128,
+        .pme_short_desc = "Total Read Bandwidth seen on both MCS of MC2",
+        .pme_long_desc = "Total Read Bandwidth seen on both MCS of MC2",
+    },
+    [ POWERPC_PME_NEST_MCS_03 ] = {
+        .pme_name = "MCS_03",
+        .pme_code = 0x130,
+        .pme_short_desc = "Total Read Bandwidth seen on both MCS of MC3",
+        .pme_long_desc = "Total Read Bandwidth seen on both MCS of MC3",
+    },
+};
+
+static const pme_power_entry_t powerpc_nest_write_pe[] = {
+    [ POWERPC_PME_NEST_MCS_00 ] = {
+        .pme_name = "MCS_00",
+        .pme_code = 0x198,
+        .pme_short_desc = "Total Write Bandwidth seen on both MCS of MC0",
+        .pme_long_desc = "Total Write Bandwidth seen on both MCS of MC0",
+    },
+    [ POWERPC_PME_NEST_MCS_01 ] = {
+        .pme_name = "MCS_01",
+        .pme_code = 0x1a0,
+        .pme_short_desc = "Total Write Bandwidth seen on both MCS of MC1",
+        .pme_long_desc = "Total Write Bandwidth seen on both MCS of MC1",
+    },
+    [ POWERPC_PME_NEST_MCS_02 ] = {
+        .pme_name = "MCS_02",
+        .pme_code = 0x1a8,
+        .pme_short_desc = "Total Write Bandwidth seen on both MCS of MC2",
+        .pme_long_desc = "Total Write Bandwidth seen on both MCS of MC2",
+    },
+    [ POWERPC_PME_NEST_MCS_03 ] = {
+        .pme_name = "MCS_03",
+        .pme_code = 0x1b0,
+        .pme_short_desc = "Total Write Bandwidth seen on both MCS of MC3",
+        .pme_long_desc = "Total Write Bandwidth seen on both MCS of MC3",
+    },
+};
+#endif
diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c
index 1bd9097..a6a364e 100644
--- a/lib/pfmlib_common.c
+++ b/lib/pfmlib_common.c
@@ -220,6 +220,8 @@ static pfmlib_pmu_t *pfmlib_pmus[]=
        &power7_support,
        &power8_support,
        &torrent_support,
+    &powerpc_nest_mcs_read_support,
+    &powerpc_nest_mcs_write_support,
 #endif
 
 #ifdef CONFIG_PFMLIB_ARCH_SPARC
diff --git a/lib/pfmlib_power_priv.h b/lib/pfmlib_power_priv.h
index ce44d52..0d8b473 100644
--- a/lib/pfmlib_power_priv.h
+++ b/lib/pfmlib_power_priv.h
@@ -105,6 +105,7 @@ extern int pfm_gen_powerpc_validate_table(void *this, FILE 
*fp);
 extern void pfm_gen_powerpc_perf_validate_pattrs(void *this, 
pfmlib_event_desc_t *e);
 
 extern int pfm_gen_powerpc_get_perf_encoding(void *this, pfmlib_event_desc_t 
*e);
+extern int pfm_gen_powerpc_get_nest_perf_encoding(void *this, 
pfmlib_event_desc_t *e);
 #endif /* _POWER_REG_H */
 #endif
 
diff --git a/lib/pfmlib_powerpc_nest.c b/lib/pfmlib_powerpc_nest.c
new file mode 100644
index 0000000..8a8bf5b
--- /dev/null
+++ b/lib/pfmlib_powerpc_nest.c
@@ -0,0 +1,60 @@
+/*
+ * pfmlib_powerpc_nest.c
+ */
+
+#include "pfmlib_priv.h"
+#include "pfmlib_power_priv.h"
+#include "events/powerpc_nest_events.h"
+
+static int pfm_powerpc_nest_detect(void* this)
+{
+    if (__is_processor(PV_POWER8))
+        return PFM_SUCCESS;
+    return PFM_ERR_NOTSUPP;
+}
+
+pfmlib_pmu_t powerpc_nest_mcs_read_support={
+    .desc           = "POWERPC_NEST_MCS_RD_BW",
+    .name           = "powerpc_nest_mcs_read",
+    .pmu            = PFM_PMU_POWERPC_NEST_MCS_READ_BW,
+    .perf_name      = "Nest_MCS_Read_BW",
+    .pme_count      = LIBPFM_ARRAY_SIZE(powerpc_nest_read_pe),
+    .type           = PFM_PMU_TYPE_UNCORE,
+    .num_cntrs      = 4,
+    .num_fixed_cntrs    = 0,
+    .max_encoding       = 1,
+    .pe         = powerpc_nest_read_pe,
+    .pmu_detect     = pfm_powerpc_nest_detect,
+    .get_event_encoding[PFM_OS_NONE] = pfm_gen_powerpc_get_encoding,
+    PFMLIB_ENCODE_PERF(pfm_gen_powerpc_get_nest_perf_encoding),
+    PFMLIB_VALID_PERF_PATTRS(pfm_gen_powerpc_perf_validate_pattrs),
+    .get_event_first    = pfm_gen_powerpc_get_event_first,
+    .get_event_next     = pfm_gen_powerpc_get_event_next,
+    .event_is_valid     = pfm_gen_powerpc_event_is_valid,
+    .validate_table     = pfm_gen_powerpc_validate_table,
+    .get_event_info     = pfm_gen_powerpc_get_event_info,
+    .get_event_attr_info    = pfm_gen_powerpc_get_event_attr_info,
+};
+
+pfmlib_pmu_t powerpc_nest_mcs_write_support={
+    .desc           = "POWERPC_NEST_MCS_WR_BW",
+    .name           = "powerpc_nest_mcs_write",
+    .pmu            = PFM_PMU_POWERPC_NEST_MCS_WRITE_BW,
+    .perf_name      = "Nest_MCS_Write_BW",
+    .pme_count      = LIBPFM_ARRAY_SIZE(powerpc_nest_write_pe),
+    .type           = PFM_PMU_TYPE_UNCORE,
+    .num_cntrs      = 4,
+    .num_fixed_cntrs    = 0,
+    .max_encoding       = 1,
+    .pe         = powerpc_nest_write_pe,
+    .pmu_detect     = pfm_powerpc_nest_detect,
+    .get_event_encoding[PFM_OS_NONE] = pfm_gen_powerpc_get_encoding,
+    PFMLIB_ENCODE_PERF(pfm_gen_powerpc_get_nest_perf_encoding),
+    PFMLIB_VALID_PERF_PATTRS(pfm_gen_powerpc_perf_validate_pattrs),
+    .get_event_first    = pfm_gen_powerpc_get_event_first,
+    .get_event_next     = pfm_gen_powerpc_get_event_next,
+    .event_is_valid     = pfm_gen_powerpc_event_is_valid,
+    .validate_table     = pfm_gen_powerpc_validate_table,
+    .get_event_info     = pfm_gen_powerpc_get_event_info,
+    .get_event_attr_info    = pfm_gen_powerpc_get_event_attr_info,
+};
diff --git a/lib/pfmlib_powerpc_perf_event.c b/lib/pfmlib_powerpc_perf_event.c
index ec371c9..642439b 100644
--- a/lib/pfmlib_powerpc_perf_event.c
+++ b/lib/pfmlib_powerpc_perf_event.c
@@ -24,6 +24,7 @@
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
+#include <limits.h>
 
 /* private headers */
 #include "pfmlib_priv.h"               /* library private */
@@ -53,6 +54,60 @@ pfm_gen_powerpc_get_perf_encoding(void *this, 
pfmlib_event_desc_t *e)
        return PFM_SUCCESS;
 }
 
+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;
+}
+
+
+int
+pfm_gen_powerpc_get_nest_perf_encoding(void *this, pfmlib_event_desc_t *e)
+{
+    pfmlib_pmu_t *pmu = this;
+    struct perf_event_attr *attr = e->os_data;
+    int ret;
+
+    if (!pmu->get_event_encoding[PFM_OS_NONE])
+        return PFM_ERR_NOTSUPP;
+
+    /*
+     * encoding routine changes based on PMU model
+     */
+    ret = pmu->get_event_encoding[PFM_OS_NONE](this, e);
+    if (ret != PFM_SUCCESS)
+         return ret;
+
+    ret = find_pmu_type_by_name(pmu->perf_name);
+    if (ret < 0)
+        return ret;
+
+    attr->type = ret;
+    attr->config = e->codes[0];
+
+    return PFM_SUCCESS;
+}
+
+
 void
 pfm_gen_powerpc_perf_validate_pattrs(void *this, pfmlib_event_desc_t *e)
 {
diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h
index 41ccf7b..b5e2d0c 100644
--- a/lib/pfmlib_priv.h
+++ b/lib/pfmlib_priv.h
@@ -359,6 +359,8 @@ extern pfmlib_pmu_t power6_support;
 extern pfmlib_pmu_t power7_support;
 extern pfmlib_pmu_t power8_support;
 extern pfmlib_pmu_t torrent_support;
+extern pfmlib_pmu_t powerpc_nest_mcs_read_support;
+extern pfmlib_pmu_t powerpc_nest_mcs_write_support;
 extern pfmlib_pmu_t sparc_support;
 extern pfmlib_pmu_t sparc_ultra12_support;
 extern pfmlib_pmu_t sparc_ultra3_support;

Regards,
Deepthi


------------------------------------------------------------------------------
Don't Limit Your Business. Reach for the Cloud.
GigeNET's Cloud Solutions provide you with the tools and support that
you need to offload your IT needs and focus on growing your business.
Configured For All Businesses. Start Your Cloud Today.
https://www.gigenetcloud.com/
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to