diff --git a/cpacfstats/Makefile b/cpacfstats/Makefile index b7e79548..944e5c3d 100644 --- a/cpacfstats/Makefile +++ b/cpacfstats/Makefile @@ -2,28 +2,10 @@ include ../common.mak ALL_CPPFLAGS += -DVERSION=$(VERSION) - -ifeq (${HAVE_PFM},0) - -all: - $(SKIP) HAVE_PFM=0 - -install: - $(SKIP) HAVE_PFM=0 - -else - -check_dep: - $(call check_dep, \ - "cpacfstats", \ - "perfmon/pfmlib.h", \ - "libpfm-devel or libpfm4-dev", \ - "HAVE_PFM=0") - -all: check_dep cpacfstats cpacfstatsd +all: cpacfstats cpacfstatsd cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o - $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -lpfm -o $@ + $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ cpacfstats: cpacfstats.o stats_sock.o $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ @@ -34,7 +16,6 @@ install: all $(INSTALL) -m 644 cpacfstatsd.8 $(DESTDIR)$(MANDIR)/man8 $(INSTALL) -m 644 cpacfstats.1 $(DESTDIR)$(MANDIR)/man1 -endif clean: rm -f *.o *~ cpacfstatsd cpacfstats diff --git a/cpacfstats/perf_crypto.c b/cpacfstats/perf_crypto.c index 77b0b768..a1e2ddca 100644 --- a/cpacfstats/perf_crypto.c +++ b/cpacfstats/perf_crypto.c @@ -9,33 +9,33 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#include #include #include #define __STDC_FORMAT_MACROS #include -#include -#include -#include +#include +#include #include #include #include #include +#include #include #include "cpacfstats.h" -#define PERF_ECC_COUNTER_NAME "cpum_cf::ECC_FUNCTION_COUNT" - /* correlation between counter and perf counter string */ static const struct { - char pfm_name[80]; + char pmu[20]; + char pfm_name[60]; enum ctr_e ctr; } pmf_counter_name[ALL_COUNTER] = { - {"cpum_cf::DEA_FUNCTIONS", DES_FUNCTIONS}, - {"cpum_cf::AES_FUNCTIONS", AES_FUNCTIONS}, - {"cpum_cf::SHA_FUNCTIONS", SHA_FUNCTIONS}, - {"cpum_cf::PRNG_FUNCTIONS", PRNG_FUNCTIONS}, - {PERF_ECC_COUNTER_NAME, ECC_FUNCTIONS} + {"cpum_cf", "DEA_FUNCTIONS", DES_FUNCTIONS}, + {"cpum_cf", "AES_FUNCTIONS", AES_FUNCTIONS}, + {"cpum_cf", "SHA_FUNCTIONS", SHA_FUNCTIONS}, + {"cpum_cf", "PRNG_FUNCTIONS", PRNG_FUNCTIONS}, + {"cpum_cf", "ECC_FUNCTION_COUNT", ECC_FUNCTIONS} }; /* @@ -58,23 +58,93 @@ static int *ctr_fds[ALL_COUNTER]; static int ecc_supported; +static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, + int cpu, int group_fd, unsigned long flags) +{ + int ret; + + ret = syscall(__NR_perf_event_open, hw_event, pid, cpu, + group_fd, flags); + return ret; +} + +static int perf_supported(void) +{ + return !access("/proc/sys/kernel/perf_event_paranoid", R_OK); +} + +static int perf_counter_supported(const char *pmu, const char *counter) +{ + char buf[PATH_MAX]; + + if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/events/%s", + pmu, counter) >= PATH_MAX) { + eprint("overflow in path name"); + return 0; + } + return !access(buf, R_OK); +} + +static int perf_event_encode(struct perf_event_attr *attr, + const char *pmu, const char *event) +{ + FILE *f; + int eventid; + int pmutype; + char buf[PATH_MAX]; + + if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/events/%s", + pmu, event) >= PATH_MAX) { + eprint("overflow in path name"); + return -1; + } + f = fopen(buf, "r"); + if (!f) { + eprint("Event %s for pmu %s not found (%d:%s)\n", event, pmu, + errno, strerror(errno)); + return -1; + } + if (fscanf(f, "event=0x%x\n", &eventid) != 1) { + fclose(f); + eprint("Event file %s has invalid format\n", buf); + return -1; + } + fclose(f); + if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/type", + pmu) >= PATH_MAX) { + eprint("overflow in path name"); + return -1; + } + f = fopen(buf, "r"); + if (!f) { + eprint("Event %s for pmu %s not found (%d:%s)\n", event, pmu, + errno, strerror(errno)); + return -1; + } + if (fscanf(f, "%d\n", &pmutype) != 1) { + fclose(f); + eprint("Type file %s has invalid format\n", buf); + return -1; + } + attr->type = pmutype; + attr->config = eventid; + return 0; +} + int perf_init(void) { - int i, cpus, ctr, cpu, ec, *fds; + int i, cpus, ctr, cpu, *fds; memset(ctr_fds, 0, sizeof(ctr_fds)); /* initialize performance monitoring library */ - ec = pfm_initialize(); - if (ec != PFM_SUCCESS) { - eprint("Pfm_initialize() returned with failure (%d:%s)\n", - ec, pfm_strerror(ec)); + if (!perf_supported()) { + eprint("Performance counter not supported"); return -1; } /* Check if ECC is supported on current hardware */ - if (pfm_find_event(PERF_ECC_COUNTER_NAME) >= 0) - ecc_supported = 1; + ecc_supported = perf_counter_supported("cpum_cf", "ECC_FUNCTION_COUNT"); /* get number of logical processors */ cpus = sysconf(_SC_NPROCESSORS_ONLN); @@ -111,26 +181,17 @@ int perf_init(void) } for (cpu = 0; cpu < cpus; cpu++) { - pfm_perf_encode_arg_t pfm_arg; struct perf_event_attr pfm_event; int fd; - memset(&pfm_arg, 0, sizeof(pfm_arg)); memset(&pfm_event, 0, sizeof(pfm_event)); - pfm_arg.attr = &pfm_event; - pfm_arg.size = sizeof(pfm_arg); pfm_event.size = sizeof(pfm_event); - - /* encode the counters perf event into pfm_arg.attr */ - ec = pfm_get_os_event_encoding( - pmf_counter_name[i].pfm_name, - PFM_PLM0, - PFM_OS_PERF_EVENT, - &pfm_arg); - if (ec != PFM_SUCCESS) { - eprint("Pfm_initialize() for %s failed (%d:%s)\n", + if (perf_event_encode(&pfm_event, + pmf_counter_name[i].pmu, + pmf_counter_name[i].pfm_name)) { + eprint("Failed to initialize counter %s for pmu %s\n", pmf_counter_name[i].pfm_name, - ec, pfm_strerror(ec)); + pmf_counter_name[i].pmu); return -1; }