Add support for the sampling facility to allow hardware-based sampling using CPU cycles. The cpum_sf PMU provides two perf events supporting available sampling functions.
Many existing pfmlib functions of the counter facility support (cpum_cf) have been reused. Signed-off-by: Hendrik Brueckner <brueck...@linux.vnet.ibm.com> --- include/perfmon/pfmlib.h | 2 + lib/events/s390x_cpumf_events.h | 16 +++++++ lib/pfmlib_common.c | 1 + lib/pfmlib_priv.h | 1 + lib/pfmlib_s390x_cpumf.c | 91 ++++++++++++++++++++++++++++----------- 5 files changed, 86 insertions(+), 25 deletions(-) diff --git a/include/perfmon/pfmlib.h b/include/perfmon/pfmlib.h index 5434a96..6a90dd5 100644 --- a/include/perfmon/pfmlib.h +++ b/include/perfmon/pfmlib.h @@ -198,6 +198,8 @@ typedef enum { PFM_PMU_ARM_QCOM_KRAIT, /* Qualcomm Krait */ + PFM_PMU_S390X_CPUM_SF, /* s390x: CPU-M sampling facility */ + /* MUST ADD NEW PMU MODELS HERE */ PFM_PMU_MAX /* end marker */ diff --git a/lib/events/s390x_cpumf_events.h b/lib/events/s390x_cpumf_events.h index 5e27fe6..e00b088 100644 --- a/lib/events/s390x_cpumf_events.h +++ b/lib/events/s390x_cpumf_events.h @@ -840,4 +840,20 @@ static const pme_cpumf_ctr_t cpumcf_zec12_counters[] = { }, }; +static const pme_cpumf_ctr_t cpumsf_counters[] = { + { + .ctrnum = 720896, + .ctrset = CPUMF_CTRSET_NONE, + .name = "SF_CYCLES_BASIC", + .desc = "Sample CPU cycles using basic-sampling mode", + }, + { + .ctrnum = 774144, + .ctrset = CPUMF_CTRSET_NONE, + .name = "SF_CYCLES_BASIC_DIAG", + .desc = "Sample CPU cycle using diagnostic-sampling mode" + " (not for ordinary use)", + }, +}; + #endif /* __S390X_CPUMF_EVENTS_H__ */ diff --git a/lib/pfmlib_common.c b/lib/pfmlib_common.c index 861f475..987bae4 100644 --- a/lib/pfmlib_common.c +++ b/lib/pfmlib_common.c @@ -167,6 +167,7 @@ static pfmlib_pmu_t *pfmlib_pmus[]= #endif #ifdef CONFIG_PFMLIB_ARCH_S390X &s390x_cpum_cf_support, + &s390x_cpum_sf_support, #endif #ifdef __linux__ &perf_event_support, diff --git a/lib/pfmlib_priv.h b/lib/pfmlib_priv.h index 287222d..530f68c 100644 --- a/lib/pfmlib_priv.h +++ b/lib/pfmlib_priv.h @@ -294,6 +294,7 @@ extern pfmlib_pmu_t arm_1176_support; extern pfmlib_pmu_t arm_qcom_krait_support; extern pfmlib_pmu_t mips_74k_support; extern pfmlib_pmu_t s390x_cpum_cf_support; +extern pfmlib_pmu_t s390x_cpum_sf_support; extern pfmlib_os_t *pfmlib_os; extern pfmlib_os_t pfmlib_os_perf; diff --git a/lib/pfmlib_s390x_cpumf.c b/lib/pfmlib_s390x_cpumf.c index e3aaaf0..db2a215 100644 --- a/lib/pfmlib_s390x_cpumf.c +++ b/lib/pfmlib_s390x_cpumf.c @@ -1,7 +1,7 @@ /* - * PMU support for the CPU-measurement counter facility + * PMU support for the CPU-measurement facilities * - * Copyright IBM Corp. 2012 + * Copyright IBM Corp. 2012, 2014 * Contributed by Hendrik Brueckner <brueck...@linux.vnet.ibm.com> * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -34,17 +34,25 @@ #include "events/s390x_cpumf_events.h" -#define CPUMF_DEVICE_DIR "/sys/bus/event_source/devices/cpum_cf" -#define SYS_INFO "/proc/sysinfo" +#define CPUM_CF_DEVICE_DIR "/sys/bus/event_source/devices/cpum_cf" +#define CPUM_SF_DEVICE_DIR "/sys/bus/event_source/devices/cpum_sf" +#define SYS_INFO "/proc/sysinfo" /* CPU-measurement counter list (pmu events) */ static pme_cpumf_ctr_t *cpumcf_pe = NULL; -/* Detect the CPU-measurement facility */ +/* Detect the CPU-measurement counter and sampling facilities */ static int pfm_cpumcf_detect(void *this) { - if (access(CPUMF_DEVICE_DIR, R_OK)) + if (access(CPUM_CF_DEVICE_DIR, R_OK)) + return PFM_ERR_NOTSUPP; + return PFM_SUCCESS; +} + +static int pfm_cpumsf_detect(void *this) +{ + if (access(CPUM_SF_DEVICE_DIR, R_OK)) return PFM_ERR_NOTSUPP; return PFM_SUCCESS; } @@ -156,7 +164,7 @@ static void pfm_cpumcf_exit(void *this) free(cpumcf_pe); } -static int pfm_cpumcf_get_encoding(void *this, pfmlib_event_desc_t *e) +static int pfm_cpumf_get_encoding(void *this, pfmlib_event_desc_t *e) { const pme_cpumf_ctr_t *pe = this_pe(this); @@ -167,12 +175,12 @@ static int pfm_cpumcf_get_encoding(void *this, pfmlib_event_desc_t *e) return PFM_SUCCESS; } -static int pfm_cpumcf_get_event_first(void *this) +static int pfm_cpumf_get_event_first(void *this) { return 0; } -static int pfm_cpumcf_get_event_next(void *this, int idx) +static int pfm_cpumf_get_event_next(void *this, int idx) { pfmlib_pmu_t *pmu = this; @@ -181,26 +189,20 @@ static int pfm_cpumcf_get_event_next(void *this, int idx) return idx + 1; } -static int pfm_cpumcf_event_is_valid(void *this, int idx) +static int pfm_cpumf_event_is_valid(void *this, int idx) { pfmlib_pmu_t *pmu = this; return (idx >= 0 && idx < pmu->pme_count); } -static int pfm_cpumcf_validate_table(void *this, FILE *fp) +static int pfm_cpumf_validate_table(void *this, FILE *fp) { pfmlib_pmu_t *pmu = this; const pme_cpumf_ctr_t *pe = this_pe(this); int i, rc; rc = PFM_ERR_INVAL; - if (pmu->pme_count > CPUMF_COUNTER_MAX) { - fprintf(fp, "pmu: %s: pme number exceeded maximum\n", - pmu->name); - goto failed; - } - for (i = 0; i < pmu->pme_count; i++) { if (!pe[i].name) { fprintf(fp, "pmu: %s event: %i: No name\n", @@ -219,7 +221,20 @@ failed: return rc; } -static int pfm_cpumcf_get_event_info(void *this, int idx, +static int pfm_cpumcf_validate_table(void *this, FILE *fp) +{ + pfmlib_pmu_t *pmu = this; + + if (pmu->pme_count > CPUMF_COUNTER_MAX) { + fprintf(fp, "pmu: %s: pme number exceeded maximum\n", + pmu->name); + return PFM_ERR_INVAL; + } + + return pfm_cpumf_validate_table(this, fp); +} + +static int pfm_cpumf_get_event_info(void *this, int idx, pfm_event_info_t *info) { pfmlib_pmu_t *pmu = this; @@ -238,7 +253,7 @@ static int pfm_cpumcf_get_event_info(void *this, int idx, return PFM_SUCCESS; } -static int pfm_cpumcf_get_event_attr_info(void *this, int idx, int umask_idx, +static int pfm_cpumf_get_event_attr_info(void *this, int idx, int umask_idx, pfm_event_attr_info_t *info) { /* Attributes are not supported */ @@ -263,12 +278,38 @@ pfmlib_pmu_t s390x_cpum_cf_support = { .pmu_init = pfm_cpumcf_init, .pmu_terminate = pfm_cpumcf_exit, - .get_event_encoding[PFM_OS_NONE] = pfm_cpumcf_get_encoding, + .get_event_encoding[PFM_OS_NONE] = pfm_cpumf_get_encoding, PFMLIB_ENCODE_PERF(pfm_s390x_get_perf_encoding), - .get_event_first = pfm_cpumcf_get_event_first, - .get_event_next = pfm_cpumcf_get_event_next, - .event_is_valid = pfm_cpumcf_event_is_valid, + .get_event_first = pfm_cpumf_get_event_first, + .get_event_next = pfm_cpumf_get_event_next, + .event_is_valid = pfm_cpumf_event_is_valid, .validate_table = pfm_cpumcf_validate_table, - .get_event_info = pfm_cpumcf_get_event_info, - .get_event_attr_info = pfm_cpumcf_get_event_attr_info, + .get_event_info = pfm_cpumf_get_event_info, + .get_event_attr_info = pfm_cpumf_get_event_attr_info, +}; + +pfmlib_pmu_t s390x_cpum_sf_support = { + .desc = "CPU-measurement sampling facility", + .name = "cpum_sf", + .pmu = PFM_PMU_S390X_CPUM_SF, + .type = PFM_PMU_TYPE_CORE, + .flags = PFMLIB_PMU_FL_ARCH_DFL, + + .num_cntrs = 0, /* no general-purpose counters */ + .num_fixed_cntrs = 2, /* fixed counters only */ + .max_encoding = 1, + + .pe = cpumsf_counters, + .pme_count = LIBPFM_ARRAY_SIZE(cpumsf_counters), + + .pmu_detect = pfm_cpumsf_detect, + + .get_event_encoding[PFM_OS_NONE] = pfm_cpumf_get_encoding, + PFMLIB_ENCODE_PERF(pfm_s390x_get_perf_encoding), + .get_event_first = pfm_cpumf_get_event_first, + .get_event_next = pfm_cpumf_get_event_next, + .event_is_valid = pfm_cpumf_event_is_valid, + .validate_table = pfm_cpumf_validate_table, + .get_event_info = pfm_cpumf_get_event_info, + .get_event_attr_info = pfm_cpumf_get_event_attr_info, }; -- 1.7.5.4 ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121054471&iu=/4140/ostg.clktrk _______________________________________________ perfmon2-devel mailing list perfmon2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/perfmon2-devel