diff --git a/cpacfstats/Makefile b/cpacfstats/Makefile index aa92e0c8..774147d8 100644 --- a/cpacfstats/Makefile +++ b/cpacfstats/Makefile @@ -21,10 +21,11 @@ ALL_CPPFLAGS += -DVERSION=$(VERSION) all: check_dep cpacfstats cpacfstatsd -cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o +cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \ + $(rootdir)/libutil/libutil.a $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@ -cpacfstats: cpacfstats.o stats_sock.o +cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ install: all diff --git a/cpacfstats/cpacfstats.c b/cpacfstats/cpacfstats.c index 2b783cb7..f29b8da6 100644 --- a/cpacfstats/cpacfstats.c +++ b/cpacfstats/cpacfstats.c @@ -55,168 +55,6 @@ static const char *const counter_str[] = { [PAI_KERNEL] = "pai_kernel" }; -/* Strings for the pai counter details. Note that this is 0-based - * while PoP is 1-based. - */ -static const char *const pai_str[] = { - [ 0] = "KM DES", - [ 1] = "KM 2key TDES", - [ 2] = "KM TDES", - [ 3] = "KM DES protected key", - [ 4] = "KM 2key TDES protected key", - [ 5] = "KM TDES protected key", - [ 6] = "KM AES 128bit", - [ 7] = "KM AES 192bit", - [ 8] = "KM AES 256bit", - [ 9] = "KM AES 128bit protected key", - [ 10] = "KM AES 192bit protected key", - [ 11] = "KM AES 256bit protected key", - [ 12] = "KM AES-XTS 128bit", - [ 13] = "KM AES-XTS 256bit", - [ 14] = "KM AES-XTS 128bit protected key", - [ 15] = "KM AES-XTS 256bit protected key", - [ 16] = "KMC DES", - [ 17] = "KMC 2key TDES", - [ 18] = "KMC TDES", - [ 19] = "KMC DES protected key", - [ 20] = "KMC 2key TDES protected key", - [ 21] = "KMC TDES protected key", - [ 22] = "KMC AES 128bit", - [ 23] = "KMC AES 192bit", - [ 24] = "KMC AES 256bit", - [ 25] = "KMC AES 128bit protected key", - [ 26] = "KMC AES 192bit protected key", - [ 27] = "KMC AES 256bit protected key", - [ 28] = "KMC PRNG", - [ 29] = "KMA AES 128bit", - [ 30] = "KMA AES 192bit", - [ 31] = "KMA AES 256bit", - [ 32] = "KMA AES 128bit protected key", - [ 33] = "KMA AES 192bit protected key", - [ 34] = "KMA AES 256bit protected key", - [ 35] = "KMF DES", - [ 36] = "KMF 2key TDES", - [ 37] = "KMF TDES", - [ 38] = "KMF DES protected key", - [ 39] = "KMF 2key TDES protected key", - [ 40] = "KMF TDES protected key", - [ 41] = "KMF AES 128bit", - [ 42] = "KMF AES 192bit", - [ 43] = "KMF AES 256bit", - [ 44] = "KMF AES 128bit protected key", - [ 45] = "KMF AES 192bit protected key", - [ 46] = "KMF AES 256bit protected key", - [ 47] = "KMCTR DES", - [ 48] = "KMCTR 2key TDES", - [ 49] = "KMCTR TDES", - [ 50] = "KMCTR DES protected key", - [ 51] = "KMCTR 2key TDES protected key", - [ 52] = "KMCTR TDES protected key", - [ 53] = "KMCTR AES 128bit", - [ 54] = "KMCTR AES 192bit", - [ 55] = "KMCTR AES 256bit", - [ 56] = "KMCTR AES 128bit protected key", - [ 57] = "KMCTR AES 192bit protected key", - [ 58] = "KMCTR AES 256bit protected key", - [ 59] = "KMO DES", - [ 60] = "KMO 2key TDES", - [ 61] = "KMO TDES", - [ 62] = "KMO DES protected key", - [ 63] = "KMO 2key TDES protected key", - [ 64] = "KMO TDES protected key", - [ 65] = "KMO AES 128bit", - [ 66] = "KMO AES 192bit", - [ 67] = "KMO AES 256bit", - [ 68] = "KMO AES 128bit protected key", - [ 69] = "KMO AES 192bit protected key", - [ 70] = "KMO AES 256bit protected key", - [ 71] = "KIMD SHA1", - [ 72] = "KIMD SHA256", - [ 73] = "KIMD SHA512", - [ 74] = "KIMD SHA3-224", - [ 75] = "KIMD SHA3-256", - [ 76] = "KIMD SHA3-384", - [ 77] = "KIMD SHA3-512", - [ 78] = "KIMD SHAKE 128", - [ 79] = "KIMD SHAKE 256", - [ 80] = "KIMD GHASH", - [ 81] = "KLMD SHA1", - [ 82] = "KLMD SHA256", - [ 83] = "KLMD SHA512", - [ 84] = "KLMD SHA3-224", - [ 85] = "KLMD SHA3-256", - [ 86] = "KLMD SHA3-384", - [ 87] = "KLMD SHA3-512", - [ 88] = "KLMD SHAKE 128", - [ 89] = "KLMD SHAKE 256", - [ 90] = "KMAC DES", - [ 91] = "KMAC 2key TDES", - [ 92] = "KMAC TDES", - [ 93] = "KMAC DES protected key", - [ 94] = "KMAC 2key TDES protected key", - [ 95] = "KMAC TDES protected key", - [ 96] = "KMAC AES 128bit", - [ 97] = "KMAC AES 192bit", - [ 98] = "KMAC AES 256bit", - [ 99] = "KMAC AES 128bit protected key", - [100] = "KMAC AES 192bit protected key", - [101] = "KMAC AES 256bit protected key", - [102] = "PCC Last Block CMAC DES", - [103] = "PCC Last Block CMAC 2key TDES", - [104] = "PCC Last Block CMAC TDES", - [105] = "PCC Last Block CMAC DES protected key", - [106] = "PCC Last Block CMAC 2key TDES protected key", - [107] = "PCC Last Block CMAC TDES protected key", - [108] = "PCC Last Block CMAC AES 128bit", - [109] = "PCC Last Block CMAC AES 192bit", - [110] = "PCC Last Block CMAC AES 256bit", - [111] = "PCC Last Block CMAC AES 128bit protected key", - [112] = "PCC Last Block CMAC AES 192bit protected key", - [113] = "PCC Last Block CMAC AES 256bit protected key", - [114] = "PCC XTS Parameter AES 128bit", - [115] = "PCC XTS Parameter AES 256bit", - [116] = "PCC XTS Parameter AES 128bit protected key", - [117] = "PCC XTS Parameter AES 256bit protected key", - [118] = "PCC Scalar Mult P256", - [119] = "PCC Scalar Mult P384", - [120] = "PCC Scalar Mult P521", - [121] = "PCC Scalar Mult Ed25519", - [122] = "PCC Scalar Mult Ed448", - [123] = "PCC Scalar Mult X25519", - [124] = "PCC Scalar Mult X448", - [125] = "PRNO SHA512 DRNG", - [126] = "PRNO TRNG Query Ratio", - [127] = "PRNO TRNG", - [128] = "KDSA ECDSA Verify P256", - [129] = "KDSA ECDSA Verify P384", - [130] = "KDSA ECDSA Verify P521", - [131] = "KDSA ECDSA Sign P256", - [132] = "KDSA ECDSA Sign P384", - [133] = "KDSA ECDSA Sign P521", - [134] = "KDSA ECDSA Sign P256 protected key", - [135] = "KDSA ECDSA Sign P384 protected key", - [136] = "KDSA ECDSA Sign P521 protected key", - [137] = "KDSA EdDSA Verify Ed25519", - [138] = "KDSA EdDSA Verify Ed448", - [139] = "KDSA EdDSA Sign Ed25519", - [140] = "KDSA EdDSA Sign Ed448", - [141] = "KDSA EdDSA Sign Ed25519 protected key", - [142] = "KDSA EdDSA Sign Ed448 protected key", - [143] = "PCKMO DES", - [144] = "PCKMO 2key TDES", - [145] = "PCKMO TDES", - [146] = "PCKMO AES 128bit", - [147] = "PCKMO AES 192bit", - [148] = "PCKMO AES 256bit", - [149] = "PCKMO ECC P256", - [150] = "PCKMO ECC P384", - [151] = "PCKMO ECC P521", - [152] = "PCKMO ECC Ed25519", - [153] = "PCKMO ECC Ed448", - [154] = "Reserved 1", - [155] = "Reserved 2" -}; - static int paiprintnonzero; @@ -275,7 +113,8 @@ static void json_print_virtual_counter_answer(int s, int ctr, int state, uint64_t value) { int paictr = 0, paistate = 0, ec; - uint64_t i, paivalue = 0, maxnum; + uint64_t i, paivalue = 0; + unsigned int maxnum; const char *space; switch (ctr) { @@ -288,11 +127,11 @@ static void json_print_virtual_counter_answer(int s, int ctr, printf("\"value\":%d}", !!value); return; case PAI_USER: - maxnum = NUM_PAI_USER; + maxnum = get_num_user_space_ctrs(); space = "user"; break; case PAI_KERNEL: - maxnum = NUM_PAI_KERNEL; + maxnum = MAX_NUM_PAI; space = "kernel"; break; default: @@ -304,7 +143,7 @@ static void json_print_virtual_counter_answer(int s, int ctr, return; if (value > maxnum) { eprint("Incompatible versions detected!\n"); - eprint("Expected %"PRIu64" counter space for %s, but got %"PRIu64"\n", + eprint("Expected %lu counter space for %s, but got %lu\n", maxnum, space, value); exit(EXIT_FAILURE); } @@ -315,18 +154,18 @@ static void json_print_virtual_counter_answer(int s, int ctr, /* No more data for this virtual event after error. */ return; } - if (paictr > NUM_PAI_KERNEL) { + if (paictr > MAX_NUM_PAI) { eprint("Pai counter number too big: %d\n", paictr); } else { printjsonsep(); printf("{\"counter\":\"%s\",\"space\":\"%s\",\"counterid\":%d,", - pai_str[paictr], space, paictr + 1); + get_ctr_name(paictr), space, paictr + 1); if (paistate < 0) { printf("\"error\":%d}", paistate); /* Protocol does not send further counters. */ return; } - printf("\"value\":%"PRIu64"}", paivalue); + printf("\"value\":%lu}", paivalue); } } } @@ -341,7 +180,8 @@ static void print_virtual_counter_answer(int s, [UNSUPPORTED] = "unsupported" }; int paictr = 0, paistate = 0, ec; - uint64_t i, paivalue = 0, maxnum; + uint64_t i, paivalue = 0; + unsigned int maxnum; const char *ctrstr; switch (ctr) { @@ -350,11 +190,11 @@ static void print_virtual_counter_answer(int s, printf(" hotplug detected\n"); return; case PAI_USER: - maxnum = NUM_PAI_USER; + maxnum = get_num_user_space_ctrs(); ctrstr = "pai_user"; break; case PAI_KERNEL: - maxnum = NUM_PAI_KERNEL; + maxnum = MAX_NUM_PAI; ctrstr = "pai_kernel"; break; default: @@ -372,7 +212,7 @@ static void print_virtual_counter_answer(int s, return; if (value > maxnum) { eprint("Incompatible versions detected!\n"); - eprint("Expected %"PRIu64" counters for %s, but got %"PRIu64"\n", + eprint("Expected %lu counters for %s, but got %lu\n", maxnum, ctrstr, value); exit(EXIT_FAILURE); } @@ -383,10 +223,10 @@ static void print_virtual_counter_answer(int s, /* No more data for this virtual event after error. */ return; } - if (paictr > NUM_PAI_KERNEL) + if (paictr > MAX_NUM_PAI) eprint("Pai counter number too big: %d\n", paictr); else if (!paiprintnonzero || paivalue > 0) - printf(" %-45s: %"PRIu64"\n", pai_str[paictr], paivalue); + printf(" %-45s: %lu\n", get_ctr_name(paictr), paivalue); } } @@ -402,7 +242,7 @@ static void print_answer(int s, int ctr, int state, uint64_t value) else if (state == UNSUPPORTED) printf(" %s counter: unsupported\n", counter_str[ctr]); else - printf(" %s counter: %"PRIu64"\n", counter_str[ctr], value); + printf(" %s counter: %lu\n", counter_str[ctr], value); } @@ -417,7 +257,7 @@ static void json_print_answer(int s, int ctr, int state, uint64_t value) } else if (state == ENABLED) { printjsonsep(); printf("{\"counter\":\"%s\",", counter_str[ctr]); - printf("\"value\":%"PRIu64"}", value); + printf("\"value\":%lu}", value); } } diff --git a/cpacfstats/cpacfstats.h b/cpacfstats/cpacfstats.h index c458dc7d..171efc69 100644 --- a/cpacfstats/cpacfstats.h +++ b/cpacfstats/cpacfstats.h @@ -20,12 +20,22 @@ #define DEFAULT_RECV_TIMEOUT (30 * 1000) /* - * Number of PAI counters for user space. This excludes PCKMO since - * this instruction is privileged. + * Number of PAI counters. Contains all counters regardless of kernel or user + * space */ -#define NUM_PAI_USER 143 -/* Number of PAI counters for kernel space. Contains all counters. */ -#define NUM_PAI_KERNEL 156 +#define MAX_NUM_PAI 156 + +/* + * This is the sysfs directory from which cpacfstatsd daemon application loads + * the available PAI counters + */ +#define SYSFS_PAI_COUNTER "/sys/bus/event_source/devices/pai_crypto/events/" + +/* + * Note that this is the first kernel only counter in the 1-based list of the + * architecture and NOT from the 0-based list in the cpacfstats code! + */ +#define FIRST_KERNEL_ONLY_COUNTER 144 int eprint(const char *format, ...); @@ -67,6 +77,12 @@ enum state_e { UNSUPPORTED }; +enum counter_type { + SUPPRESS_COUNTER = 0, + KERNEL_AND_USER_COUNTER, + KERNEL_ONLY_COUNTER, +}; + /* * query send from client to daemon * Consist of: @@ -122,15 +138,23 @@ int recv_msg(int sfd, struct msg *m, int timeout); /* perf_crypto.c */ -int perf_init(void); +int perf_init(unsigned int *supported_counters); void perf_stop(void); void perf_close(void); -int perf_enable_ctr(enum ctr_e ctr); -int perf_disable_ctr(enum ctr_e ctr); -int perf_reset_ctr(enum ctr_e ctr, uint64_t *value); -int perf_read_ctr(enum ctr_e ctr, uint64_t *value); +int perf_enable_ctr(enum ctr_e ctr, unsigned int *supported_counters); +int perf_disable_ctr(enum ctr_e ctr, unsigned int *supported_counters); +int perf_reset_ctr(enum ctr_e ctr, uint64_t *value, unsigned int + *supported_counters); +int perf_read_ctr(enum ctr_e ctr, uint64_t *value, unsigned int + *supported_counters); int perf_ecc_supported(void); int perf_ctr_state(enum ctr_e ctr); int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value); +/* cpacfstats_common.c */ + +enum counter_type is_user_space(unsigned int ctr); +const char *get_ctr_name(unsigned int ctr); +unsigned int get_num_user_space_ctrs(void); + #endif diff --git a/cpacfstats/cpacfstats_common.c b/cpacfstats/cpacfstats_common.c new file mode 100644 index 00000000..f8c5dc60 --- /dev/null +++ b/cpacfstats/cpacfstats_common.c @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: MIT */ +/* + * cpacfstats_common.c - shared code by daemon and client + * + * Copyright IBM Corp. 2024 + */ + +#include +#include +#include "cpacfstats.h" + +struct pai_counter { + const char *str; + const unsigned int counter_type; +}; + +/* + * Strings for the pai counter details. + * Integer indicating if kernel space is needed (0 for user, KERNEL_ONLY_COUNTER for kernel) + * Note that this is 0-based while PoP is 1-based. + * + * When adding new items to this list add the counter number in the pai_idx + * list in cpacfstatsd.c and increase the number of total counters in + * cpacfstats.h. + */ +const struct pai_counter pai[] = { + [ 0] = {"KM DES", KERNEL_AND_USER_COUNTER}, + [ 1] = {"KM 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 2] = {"KM TDES", KERNEL_AND_USER_COUNTER}, + [ 3] = {"KM DES protected key", KERNEL_AND_USER_COUNTER}, + [ 4] = {"KM 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 5] = {"KM TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 6] = {"KM AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 7] = {"KM AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 8] = {"KM AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 9] = {"KM AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 10] = {"KM AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 11] = {"KM AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 12] = {"KM AES-XTS 128bit", KERNEL_AND_USER_COUNTER}, + [ 13] = {"KM AES-XTS 256bit", KERNEL_AND_USER_COUNTER}, + [ 14] = {"KM AES-XTS 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 15] = {"KM AES-XTS 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 16] = {"KMC DES", KERNEL_AND_USER_COUNTER}, + [ 17] = {"KMC 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 18] = {"KMC TDES", KERNEL_AND_USER_COUNTER}, + [ 19] = {"KMC DES protected key", KERNEL_AND_USER_COUNTER}, + [ 20] = {"KMC 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 21] = {"KMC TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 22] = {"KMC AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 23] = {"KMC AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 24] = {"KMC AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 25] = {"KMC AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 26] = {"KMC AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 27] = {"KMC AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 28] = {"KMC PRNG", KERNEL_AND_USER_COUNTER}, + [ 29] = {"KMA AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 30] = {"KMA AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 31] = {"KMA AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 32] = {"KMA AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 33] = {"KMA AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 34] = {"KMA AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 35] = {"KMF DES", KERNEL_AND_USER_COUNTER}, + [ 36] = {"KMF 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 37] = {"KMF TDES", KERNEL_AND_USER_COUNTER}, + [ 38] = {"KMF DES protected key", KERNEL_AND_USER_COUNTER}, + [ 39] = {"KMF 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 40] = {"KMF TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 41] = {"KMF AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 42] = {"KMF AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 43] = {"KMF AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 44] = {"KMF AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 45] = {"KMF AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 46] = {"KMF AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 47] = {"KMCTR DES", KERNEL_AND_USER_COUNTER}, + [ 48] = {"KMCTR 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 49] = {"KMCTR TDES", KERNEL_AND_USER_COUNTER}, + [ 50] = {"KMCTR DES protected key", KERNEL_AND_USER_COUNTER}, + [ 51] = {"KMCTR 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 52] = {"KMCTR TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 53] = {"KMCTR AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 54] = {"KMCTR AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 55] = {"KMCTR AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 56] = {"KMCTR AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 57] = {"KMCTR AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 58] = {"KMCTR AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 59] = {"KMO DES", KERNEL_AND_USER_COUNTER}, + [ 60] = {"KMO 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 61] = {"KMO TDES", KERNEL_AND_USER_COUNTER}, + [ 62] = {"KMO DES protected key", KERNEL_AND_USER_COUNTER}, + [ 63] = {"KMO 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 64] = {"KMO TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 65] = {"KMO AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 66] = {"KMO AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 67] = {"KMO AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 68] = {"KMO AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [ 69] = {"KMO AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [ 70] = {"KMO AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [ 71] = {"KIMD SHA1", KERNEL_AND_USER_COUNTER}, + [ 72] = {"KIMD SHA256", KERNEL_AND_USER_COUNTER}, + [ 73] = {"KIMD SHA512", KERNEL_AND_USER_COUNTER}, + [ 74] = {"KIMD SHA3-224", KERNEL_AND_USER_COUNTER}, + [ 75] = {"KIMD SHA3-256", KERNEL_AND_USER_COUNTER}, + [ 76] = {"KIMD SHA3-384", KERNEL_AND_USER_COUNTER}, + [ 77] = {"KIMD SHA3-512", KERNEL_AND_USER_COUNTER}, + [ 78] = {"KIMD SHAKE 128", KERNEL_AND_USER_COUNTER}, + [ 79] = {"KIMD SHAKE 256", KERNEL_AND_USER_COUNTER}, + [ 80] = {"KIMD GHASH", KERNEL_AND_USER_COUNTER}, + [ 81] = {"KLMD SHA1", KERNEL_AND_USER_COUNTER}, + [ 82] = {"KLMD SHA256", KERNEL_AND_USER_COUNTER}, + [ 83] = {"KLMD SHA512", KERNEL_AND_USER_COUNTER}, + [ 84] = {"KLMD SHA3-224", KERNEL_AND_USER_COUNTER}, + [ 85] = {"KLMD SHA3-256", KERNEL_AND_USER_COUNTER}, + [ 86] = {"KLMD SHA3-384", KERNEL_AND_USER_COUNTER}, + [ 87] = {"KLMD SHA3-512", KERNEL_AND_USER_COUNTER}, + [ 88] = {"KLMD SHAKE 128", KERNEL_AND_USER_COUNTER}, + [ 89] = {"KLMD SHAKE 256", KERNEL_AND_USER_COUNTER}, + [ 90] = {"KMAC DES", KERNEL_AND_USER_COUNTER}, + [ 91] = {"KMAC 2key TDES", KERNEL_AND_USER_COUNTER}, + [ 92] = {"KMAC TDES", KERNEL_AND_USER_COUNTER}, + [ 93] = {"KMAC DES protected key", KERNEL_AND_USER_COUNTER}, + [ 94] = {"KMAC 2key TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 95] = {"KMAC TDES protected key", KERNEL_AND_USER_COUNTER}, + [ 96] = {"KMAC AES 128bit", KERNEL_AND_USER_COUNTER}, + [ 97] = {"KMAC AES 192bit", KERNEL_AND_USER_COUNTER}, + [ 98] = {"KMAC AES 256bit", KERNEL_AND_USER_COUNTER}, + [ 99] = {"KMAC AES 128bit protected key", KERNEL_AND_USER_COUNTER}, + [100] = {"KMAC AES 192bit protected key", KERNEL_AND_USER_COUNTER}, + [101] = {"KMAC AES 256bit protected key", KERNEL_AND_USER_COUNTER}, + [102] = {"PCC Last Block CMAC DES", KERNEL_AND_USER_COUNTER}, + [103] = {"PCC Last Block CMAC 2key TDES", KERNEL_AND_USER_COUNTER}, + [104] = {"PCC Last Block CMAC TDES", KERNEL_AND_USER_COUNTER}, + [105] = {"PCC Last Block CMAC DES protected key", + KERNEL_AND_USER_COUNTER}, + [106] = {"PCC Last Block CMAC 2key TDES protected key", + KERNEL_AND_USER_COUNTER}, + [107] = {"PCC Last Block CMAC TDES protected key", + KERNEL_AND_USER_COUNTER}, + [108] = {"PCC Last Block CMAC AES 128bit", KERNEL_AND_USER_COUNTER}, + [109] = {"PCC Last Block CMAC AES 192bit", KERNEL_AND_USER_COUNTER}, + [110] = {"PCC Last Block CMAC AES 256bit", KERNEL_AND_USER_COUNTER}, + [111] = {"PCC Last Block CMAC AES 128bit protected key", + KERNEL_AND_USER_COUNTER}, + [112] = {"PCC Last Block CMAC AES 192bit protected key", + KERNEL_AND_USER_COUNTER}, + [113] = {"PCC Last Block CMAC AES 256bit protected key", + KERNEL_AND_USER_COUNTER}, + [114] = {"PCC XTS Parameter AES 128bit", KERNEL_AND_USER_COUNTER}, + [115] = {"PCC XTS Parameter AES 256bit", KERNEL_AND_USER_COUNTER}, + [116] = {"PCC XTS Parameter AES 128bit protected key", + KERNEL_AND_USER_COUNTER}, + [117] = {"PCC XTS Parameter AES 256bit protected key", + KERNEL_AND_USER_COUNTER}, + [118] = {"PCC Scalar Mult P256", KERNEL_AND_USER_COUNTER}, + [119] = {"PCC Scalar Mult P384", KERNEL_AND_USER_COUNTER}, + [120] = {"PCC Scalar Mult P521", KERNEL_AND_USER_COUNTER}, + [121] = {"PCC Scalar Mult Ed25519", KERNEL_AND_USER_COUNTER}, + [122] = {"PCC Scalar Mult Ed448", KERNEL_AND_USER_COUNTER}, + [123] = {"PCC Scalar Mult X25519", KERNEL_AND_USER_COUNTER}, + [124] = {"PCC Scalar Mult X448", KERNEL_AND_USER_COUNTER}, + [125] = {"PRNO SHA512 DRNG", KERNEL_AND_USER_COUNTER}, + [126] = {"PRNO TRNG Query Ratio", KERNEL_AND_USER_COUNTER}, + [127] = {"PRNO TRNG", KERNEL_AND_USER_COUNTER}, + [128] = {"KDSA ECDSA Verify P256", KERNEL_AND_USER_COUNTER}, + [129] = {"KDSA ECDSA Verify P384", KERNEL_AND_USER_COUNTER}, + [130] = {"KDSA ECDSA Verify P521", KERNEL_AND_USER_COUNTER}, + [131] = {"KDSA ECDSA Sign P256", KERNEL_AND_USER_COUNTER}, + [132] = {"KDSA ECDSA Sign P384", KERNEL_AND_USER_COUNTER}, + [133] = {"KDSA ECDSA Sign P521", KERNEL_AND_USER_COUNTER}, + [134] = {"KDSA ECDSA Sign P256 protected key", + KERNEL_AND_USER_COUNTER}, + [135] = {"KDSA ECDSA Sign P384 protected key", + KERNEL_AND_USER_COUNTER}, + [136] = {"KDSA ECDSA Sign P521 protected key", + KERNEL_AND_USER_COUNTER}, + [137] = {"KDSA EdDSA Verify Ed25519", KERNEL_AND_USER_COUNTER}, + [138] = {"KDSA EdDSA Verify Ed448", KERNEL_AND_USER_COUNTER}, + [139] = {"KDSA EdDSA Sign Ed25519", KERNEL_AND_USER_COUNTER}, + [140] = {"KDSA EdDSA Sign Ed448", KERNEL_AND_USER_COUNTER}, + [141] = {"KDSA EdDSA Sign Ed25519 protected key", + KERNEL_AND_USER_COUNTER}, + [142] = {"KDSA EdDSA Sign Ed448 protected key", + KERNEL_AND_USER_COUNTER}, + [143] = {"PCKMO DES", KERNEL_ONLY_COUNTER}, + [144] = {"PCKMO 2key TDES", KERNEL_ONLY_COUNTER}, + [145] = {"PCKMO TDES", KERNEL_ONLY_COUNTER}, + [146] = {"PCKMO AES 128bit", KERNEL_ONLY_COUNTER}, + [147] = {"PCKMO AES 192bit", KERNEL_ONLY_COUNTER}, + [148] = {"PCKMO AES 256bit", KERNEL_ONLY_COUNTER}, + [149] = {"PCKMO ECC P256", KERNEL_ONLY_COUNTER}, + [150] = {"PCKMO ECC P384", KERNEL_ONLY_COUNTER}, + [151] = {"PCKMO ECC P521", KERNEL_ONLY_COUNTER}, + [152] = {"PCKMO ECC Ed25519", KERNEL_ONLY_COUNTER}, + [153] = {"PCKMO ECC Ed448", KERNEL_ONLY_COUNTER}, + [154] = {"Reserved 1", KERNEL_ONLY_COUNTER}, + [155] = {"Reserved 2", KERNEL_ONLY_COUNTER} +}; + +/* + * Returns counter_type of pai_counter struct + * + * SUPPRESS_COUNTER + * KERNEL_AND_USER_COUNTER + * KERNEL_ONLY_COUNTER + */ +enum counter_type is_user_space(unsigned int ctr) +{ + if (ctr >= MAX_NUM_PAI) + return SUPPRESS_COUNTER; + return pai[ctr].counter_type; +} + +const char *get_ctr_name(unsigned int ctr) +{ + if (ctr >= MAX_NUM_PAI) + return NULL; + return pai[ctr].str; +} + +/* + * Returns number of PAI counters for which no kernel space is needed + */ +unsigned int get_num_user_space_ctrs(void) +{ + unsigned int counter = 0; + unsigned int i; + + for (i = 0; i < MAX_NUM_PAI; i++) { + if (is_user_space(i) == KERNEL_AND_USER_COUNTER) + counter++; + } + + return counter; +} diff --git a/cpacfstats/cpacfstatsd.c b/cpacfstats/cpacfstatsd.c index ad864c51..ba371db1 100644 --- a/cpacfstats/cpacfstatsd.c +++ b/cpacfstats/cpacfstatsd.c @@ -24,12 +24,52 @@ #include #include #include +#include +#include +#include #include "lib/zt_common.h" +#include "lib/util_file.h" #include "cpacfstats.h" static volatile int stopsig; +/* + * This list contains the counter numbers sorted by instruction + */ +static const unsigned int pai_idx[] = { + // KM + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + // KMC + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + // KMA + 29, 30, 31, 32, 33, 34, + // KMF + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + // KMCTR + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + // KMO + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + // KIMD + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + // KLMD + 81, 82, 83, 84, 85, 86, 87, 88, 89, + // KMAC + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + // PCC + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + // PRNO + 125, 126, 127, + // KDSA + 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, + // PCKMO + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, + // Reserved + 154, 155 +}; + static const char *const name = "cpacfstatsd"; static const char *const usage = @@ -93,34 +133,35 @@ static int send_answer(int s, int ctr, int state, uint64_t value) * Note that the PAI counters are 0-based, not 1 based as in PoP! * Sending ends with the first error. */ -static int do_send_pai(int s, int user) +static int do_send_pai(int s, int user, unsigned int *counter) { - int ctr, state, i, maxctr, rc = 0; + int ctr, state, i, rc = 0; + unsigned int current_ctr; uint64_t value; - if (user) { - ctr = PAI_USER; - maxctr = NUM_PAI_USER; - } else { - ctr = PAI_KERNEL; - maxctr = NUM_PAI_KERNEL; - } + ctr = user ? PAI_USER : PAI_KERNEL; + state = perf_ctr_state(ctr); if (state != ENABLED) return rc; - for (i = 0; i < maxctr; ++i) { - rc = perf_read_pai_ctr(i, user, &value); + for (i = 0; i < MAX_NUM_PAI; ++i) { + current_ctr = pai_idx[i]; + if ((user && is_user_space(current_ctr) != KERNEL_AND_USER_COUNTER) || + (!user && is_user_space(current_ctr) == SUPPRESS_COUNTER) || + counter[current_ctr] != 1) + continue; + rc = perf_read_pai_ctr(current_ctr, user, &value); if (rc != 0) { - send_answer(s, i, rc, 0); + send_answer(s, current_ctr, rc, 0); break; } - send_answer(s, i, state, value); + send_answer(s, current_ctr, state, value); } return rc; } -static int do_enable(int s, enum ctr_e ctr) +static int do_enable(int s, enum ctr_e ctr, unsigned int *supported_counters) { uint64_t value = 0; int i, rc = 0; @@ -132,7 +173,7 @@ static int do_enable(int s, enum ctr_e ctr) if (i == (int) ctr || ctr == ALL_COUNTER) { state = perf_ctr_state(i); if (state == DISABLED) { - rc = perf_enable_ctr(i); + rc = perf_enable_ctr(i, supported_counters); if (rc != 0) { send_answer(s, i, rc, 0); break; @@ -140,7 +181,7 @@ static int do_enable(int s, enum ctr_e ctr) state = ENABLED; } if (state != UNSUPPORTED) { - rc = perf_read_ctr(i, &value); + rc = perf_read_ctr(i, &value, supported_counters); if (rc != 0) { send_answer(s, i, rc, 0); break; @@ -148,20 +189,20 @@ static int do_enable(int s, enum ctr_e ctr) } send_answer(s, i, state, value); if (i == PAI_USER) - rc = do_send_pai(s, 1); + rc = do_send_pai(s, 1, supported_counters); if (i == PAI_KERNEL) - rc = do_send_pai(s, 0); + rc = do_send_pai(s, 0, supported_counters); } } if (rc == 0) { - rc = perf_read_ctr(HOTPLUG_DETECTED, &value); + rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL); send_answer(s, HOTPLUG_DETECTED, rc, value); } return rc; } -static int do_disable(int s, enum ctr_e ctr) +static int do_disable(int s, enum ctr_e ctr, unsigned int *supported_counters) { int i, rc = 0; uint64_t value; @@ -171,7 +212,7 @@ static int do_disable(int s, enum ctr_e ctr) continue; if (i == (int) ctr || ctr == ALL_COUNTER) { if (perf_ctr_state(i) == ENABLED) { - rc = perf_disable_ctr(i); + rc = perf_disable_ctr(i, supported_counters); if (rc != 0) { send_answer(s, i, rc, 0); break; @@ -181,14 +222,14 @@ static int do_disable(int s, enum ctr_e ctr) } } if (rc == 0) { - rc = perf_read_ctr(HOTPLUG_DETECTED, &value); + rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL); send_answer(s, HOTPLUG_DETECTED, rc, value); } return rc; } -static int do_reset(int s, enum ctr_e ctr) +static int do_reset(int s, enum ctr_e ctr, unsigned int *supported_counters) { int i, rc = 0, state; uint64_t value; @@ -199,7 +240,7 @@ static int do_reset(int s, enum ctr_e ctr) if (i == (int) ctr || ctr == ALL_COUNTER) { state = perf_ctr_state(i); if (state == ENABLED) { - rc = perf_reset_ctr(i, &value); + rc = perf_reset_ctr(i, &value, supported_counters); if (rc != 0) { send_answer(s, i, rc, 0); break; @@ -207,20 +248,20 @@ static int do_reset(int s, enum ctr_e ctr) } send_answer(s, i, state, value); if (i == PAI_USER) - rc = do_send_pai(s, 1); + rc = do_send_pai(s, 1, supported_counters); if (i == PAI_KERNEL) - rc = do_send_pai(s, 0); + rc = do_send_pai(s, 0, supported_counters); } } if (rc == 0) { - rc = perf_read_ctr(HOTPLUG_DETECTED, &value); + rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL); send_answer(s, HOTPLUG_DETECTED, rc, value); } return rc; } -static int do_print(int s, enum ctr_e ctr) +static int do_print(int s, enum ctr_e ctr, unsigned int *supported_counters) { int i, rc = 0, state; uint64_t value = 0; @@ -231,7 +272,7 @@ static int do_print(int s, enum ctr_e ctr) if (i == (int) ctr || ctr == ALL_COUNTER) { state = perf_ctr_state(i); if (state == ENABLED) { - rc = perf_read_ctr(i, &value); + rc = perf_read_ctr(i, &value, supported_counters); if (rc != 0) { send_answer(s, i, rc, 0); break; @@ -239,13 +280,13 @@ static int do_print(int s, enum ctr_e ctr) } send_answer(s, i, state, value); if (i == PAI_USER) - rc = do_send_pai(s, 1); + rc = do_send_pai(s, 1, supported_counters); if (i == PAI_KERNEL) - rc = do_send_pai(s, 0); + rc = do_send_pai(s, 0, supported_counters); } } if (rc == 0) { - rc = perf_read_ctr(HOTPLUG_DETECTED, &value); + rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL); send_answer(s, HOTPLUG_DETECTED, rc, value); } return rc; @@ -436,9 +477,44 @@ int eprint(const char *format, ...) } +/* + * returns -1 on error + * returns X where X is the found counters in dir + * + * the supplied array supported_counters[] is filled in this function with the + * available PAI counters found in SYSFS_PAI_COUNTER + */ +static void supported_functions(unsigned int supported_counters[]) +{ + const char *dir = SYSFS_PAI_COUNTER; + struct dirent *dp = NULL; + char filepath[PATH_MAX]; + unsigned int num; + DIR *dfd = NULL; + + dfd = opendir(dir); + if (dfd == NULL) + return; + + while ((dp = readdir(dfd)) != NULL) { + if ((strcmp(dp->d_name, ".") != 0) && + (strcmp(dp->d_name, "..") != 0)) { + snprintf(filepath, sizeof(filepath), "%s%s", dir, dp->d_name); + if (util_file_read_va(filepath, "event=0x10%x", &num) != 1) + continue; + if (num > 0 && num <= MAX_NUM_PAI) + supported_counters[num - 1] = 1; + } + } + + closedir(dfd); + return; +} + int main(int argc, char *argv[]) { int rc, sfd, foreground = 0, startup_pipe = -1, initialized = 0; + unsigned int supported_counters[MAX_NUM_PAI] = { 0 }; struct sigaction act; if (argc > 1) { @@ -485,7 +561,9 @@ int main(int argc, char *argv[]) } } - if (perf_init() != 0) { + supported_functions(supported_counters); + + if (perf_init(supported_counters) != 0) { eprint("Couldn't initialize perf lib\n"); goto error; } @@ -548,13 +626,13 @@ int main(int argc, char *argv[]) } if (cmd == ENABLE) - rc = do_enable(s, ctr); + rc = do_enable(s, ctr, supported_counters); else if (cmd == DISABLE) - rc = do_disable(s, ctr); + rc = do_disable(s, ctr, supported_counters); else if (cmd == RESET) - rc = do_reset(s, ctr); + rc = do_reset(s, ctr, supported_counters); else if (cmd == PRINT) - rc = do_print(s, ctr); + rc = do_print(s, ctr, supported_counters); else { eprint("Received unknown command %d, ignoring\n", (int) cmd); diff --git a/cpacfstats/perf_crypto.c b/cpacfstats/perf_crypto.c index 6c1c63e8..02952170 100644 --- a/cpacfstats/perf_crypto.c +++ b/cpacfstats/perf_crypto.c @@ -52,8 +52,8 @@ static struct pmf_data { struct percpucounter { int ctr_fds[ALL_COUNTER]; - int pai_user[NUM_PAI_USER]; - int pai_kernel[NUM_PAI_KERNEL]; + int pai_user[MAX_NUM_PAI]; + int pai_kernel[MAX_NUM_PAI]; unsigned int cpunum; struct percpucounter *next; }; @@ -84,10 +84,10 @@ static struct percpucounter *allocpercpucounter(unsigned int cpunum) for (i = 0; i < ALL_COUNTER; ++i) ppc->ctr_fds[i] = -1; - for (i = 0; i < NUM_PAI_USER; ++i) + for (i = 0; i < MAX_NUM_PAI; ++i) { ppc->pai_user[i] = -1; - for (i = 0; i < NUM_PAI_KERNEL; ++i) ppc->pai_kernel[i] = -1; + } ppc->cpunum = cpunum; ppc->next = NULL; } @@ -100,10 +100,10 @@ static void freepercpucounter(struct percpucounter *pcpu) for (i = 0; i < ALL_COUNTER; ++i) (void)close(pcpu->ctr_fds[i]); - for (i = 0; i < NUM_PAI_USER; ++i) + for (i = 0; i < MAX_NUM_PAI; ++i) { (void)close(pcpu->pai_user[i]); - for (i = 0; i < NUM_PAI_KERNEL; ++i) (void)close(pcpu->pai_kernel[i]); + } free(pcpu); } @@ -225,7 +225,7 @@ static int perf_event_encode(int *pmutype, int *eventid, return 0; } -static int activatecpu(unsigned int cpu) +static int activatecpu(unsigned int cpu, unsigned int *supported_counters) { struct perf_event_attr pfm_event; struct percpucounter *ppc; @@ -273,7 +273,10 @@ static int activatecpu(unsigned int cpu) (ctr_state[PAI_USER] == UNSUPPORTED) == (ctr_state[PAI_KERNEL] == UNSUPPORTED) */ if (ctr_state[PAI_USER] != UNSUPPORTED) { - for (i = 1; i <= NUM_PAI_USER; ++i) { + for (i = 1; i <= MAX_NUM_PAI; ++i) { + if (is_user_space(i - 1) != KERNEL_AND_USER_COUNTER || + supported_counters[i - 1] != 1) + continue; memset(&pfm_event, 0, sizeof(pfm_event)); pfm_event.size = sizeof(pfm_event); pfm_event.type = paipmutype; @@ -307,7 +310,14 @@ static int activatecpu(unsigned int cpu) ppc->pai_kernel[i - 1] = fd; } } - for (; i <= NUM_PAI_KERNEL; ++i) { + /* + * i can start at the index of the first PAI counter + * for which kernel space is needed + */ + for (i = FIRST_KERNEL_ONLY_COUNTER; i <= MAX_NUM_PAI; ++i) { + if (is_user_space(i - 1) == SUPPRESS_COUNTER || + supported_counters[i - 1] != 1) + continue; memset(&pfm_event, 0, sizeof(pfm_event)); pfm_event.size = sizeof(pfm_event); pfm_event.type = paipmutype; @@ -348,10 +358,10 @@ static void deactivatecpu(unsigned int cpunum) if (pcpu != NULL) { for (i = 0; i < ALL_COUNTER; ++i) (void)close(pcpu->ctr_fds[i]); - for (i = 0; i < NUM_PAI_USER; ++i) + for (i = 0; i < MAX_NUM_PAI; ++i) { (void)close(pcpu->pai_user[i]); - for (i = 0; i < NUM_PAI_KERNEL; ++i) (void)close(pcpu->pai_kernel[i]); + } free(pcpu); if (enabledcounter) hotplugdetected = 1; @@ -359,7 +369,7 @@ static void deactivatecpu(unsigned int cpunum) pthread_mutex_unlock(&rootmux); } -static int addallcpus(void) +static int addallcpus(unsigned int *supported_counters) { unsigned int start, end; int scanned, rc = 0; @@ -379,7 +389,7 @@ static int addallcpus(void) if (scanned == 1) end = start; for (; start <= end; ++start) { - if (activatecpu(start)) { + if (activatecpu(start, supported_counters)) { rc = -1; goto out; } @@ -409,7 +419,7 @@ static int perf_load_counter_data(void) return res; } -static void *hotplughandler(void *UNUSED(unused)) +static void *hotplughandler(void *supported_counters) { struct udev *hotplug; struct udev_monitor *monitor; @@ -452,7 +462,7 @@ static void *hotplughandler(void *UNUSED(unused)) path = udev_device_get_devpath(dev); if (sscanf(path, "/devices/system/cpu/cpu%u", &cpunum) != 1) continue; - if (on && activatecpu(cpunum)) + if (on && activatecpu(cpunum, (unsigned int *) supported_counters)) eprint("Failed to attach to hotplugged CPU %u\n", cpunum); if (off) deactivatecpu(cpunum); @@ -462,11 +472,18 @@ static void *hotplughandler(void *UNUSED(unused)) return NULL; } -int perf_init(void) +int perf_init(unsigned int *supported_counters) { - int ecc_supported, i, num; + static const char *cpum_cf[] = { + "DEA_FUNCTIONS", + "AES_FUNCTIONS", + "SHA_FUNCTIONS", + "PRNG_FUNCTIONS", + "ECC_FUNCTION_COUNT" + }; unsigned long maxfd; struct rlimit rlim; + int i, num; FILE *f; /* initialize performance monitoring library */ @@ -478,16 +495,18 @@ int perf_init(void) /* We currently support all cpumf counters plus two virtual * counters for PAI. */ num = ALL_COUNTER + 2; - /* Check if ECC is supported on current hardware */ - ecc_supported = perf_counter_supported("cpum_cf", "ECC_FUNCTION_COUNT"); if (!cpumf_authorized()) { for (i = 0; i < ALL_COUNTER; ++i) ctr_state[i] = UNSUPPORTED; num -= ALL_COUNTER; - } else if (!ecc_supported) { - ctr_state[ECC_FUNCTIONS] = UNSUPPORTED; - --num; + } else { + for (i = 0; i < ALL_COUNTER; i++) { + if (!perf_counter_supported("cpum_cf", cpum_cf[i])) { + ctr_state[i] = UNSUPPORTED; + num--; + } + } } if (!perf_counter_supported("pai_crypto", "CRYPTO_ALL")) { @@ -523,11 +542,12 @@ int perf_init(void) return -1; } - if (pthread_create(&hotplugthread, NULL, hotplughandler, NULL)) { + if (pthread_create(&hotplugthread, NULL, hotplughandler, + supported_counters)) { eprint("Failed to start hotplug handler thread\n"); return -1; } - return addallcpus(); + return addallcpus(supported_counters); } @@ -552,11 +572,14 @@ void perf_close(void) } -static int enable_array(int *arr, int size) +static int enable_array(int *arr, int user, unsigned int *supported_counters) { int i, ec, rc = 0; - for (i = 0; i < size; ++i) { + for (i = 0; i < MAX_NUM_PAI; ++i) { + if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) || + supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER) + continue; ec = ioctl(arr[i], PERF_EVENT_IOC_ENABLE, 0); if (ec < 0) { eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n", @@ -568,14 +591,14 @@ static int enable_array(int *arr, int size) } -int perf_enable_ctr(enum ctr_e ctr) +int perf_enable_ctr(enum ctr_e ctr, unsigned int *supported_counters) { struct percpucounter *pcpu; int ec, rc = 0; if (ctr == ALL_COUNTER) { for (ctr = 0; ctr < ALL_COUNTER; ctr++) { - rc = perf_enable_ctr(ctr); + rc = perf_enable_ctr(ctr, supported_counters); if (rc != 0) return rc; } @@ -593,7 +616,7 @@ int perf_enable_ctr(enum ctr_e ctr) endforeachcpu(); } else if (ctr == PAI_USER) { foreachcpu(pcpu) { - ec = enable_array(pcpu->pai_user, NUM_PAI_USER); + ec = enable_array(pcpu->pai_user, 1, supported_counters); if (ec < 0) rc = -1; } @@ -602,7 +625,7 @@ int perf_enable_ctr(enum ctr_e ctr) endforeachcpu(); } else if (ctr == PAI_KERNEL) { foreachcpu(pcpu) { - ec = enable_array(pcpu->pai_kernel, NUM_PAI_KERNEL); + ec = enable_array(pcpu->pai_kernel, 0, supported_counters); if (ec < 0) rc = -1; } @@ -617,11 +640,14 @@ int perf_enable_ctr(enum ctr_e ctr) } -static int disable_array(int *arr, int size) +static int disable_array(int *arr, int user, unsigned int *supported_counters) { int i, ec, rc = 0; - for (i = 0; i < size; ++i) { + for (i = 0; i < MAX_NUM_PAI; ++i) { + if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) || + supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER) + continue; ec = ioctl(arr[i], PERF_EVENT_IOC_DISABLE, 0); if (ec < 0) { eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n", @@ -633,14 +659,14 @@ static int disable_array(int *arr, int size) } -int perf_disable_ctr(enum ctr_e ctr) +int perf_disable_ctr(enum ctr_e ctr, unsigned int *supported_counters) { struct percpucounter *pcpu; int ec, rc = 0; if (ctr == ALL_COUNTER) { for (ctr = 0; ctr < ALL_COUNTER; ctr++) { - rc = perf_disable_ctr(ctr); + rc = perf_disable_ctr(ctr, supported_counters); if (rc != 0) return rc; } @@ -660,7 +686,7 @@ int perf_disable_ctr(enum ctr_e ctr) endforeachcpu(); } else if (ctr == PAI_USER) { foreachcpu(pcpu) { - ec = disable_array(pcpu->pai_user, NUM_PAI_USER); + ec = disable_array(pcpu->pai_user, 1, supported_counters); if (ec < 0) rc = -1; } @@ -671,7 +697,7 @@ int perf_disable_ctr(enum ctr_e ctr) endforeachcpu(); } else if (ctr == PAI_KERNEL) { foreachcpu(pcpu) { - ec = disable_array(pcpu->pai_kernel, NUM_PAI_KERNEL); + ec = disable_array(pcpu->pai_kernel, 0, supported_counters); if (ec < 0) rc = -1; } @@ -688,11 +714,14 @@ int perf_disable_ctr(enum ctr_e ctr) } -static int reset_array(int *arr, int size) +static int reset_array(int *arr, int user, unsigned int *supported_counters) { int ec, rc = 0, i; - for (i = 0; i < size; ++i) { + for (i = 0; i < MAX_NUM_PAI; ++i) { + if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) || + supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER) + continue; ec = ioctl(arr[i], PERF_EVENT_IOC_RESET, 0); if (ec < 0) { eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n", @@ -704,14 +733,15 @@ static int reset_array(int *arr, int size) } -int perf_reset_ctr(enum ctr_e ctr, uint64_t *value) +int perf_reset_ctr(enum ctr_e ctr, uint64_t *value, unsigned int + *supported_counters) { struct percpucounter *pcpu; int ec, rc = 0; if (ctr == ALL_COUNTER) { for (ctr = 0; ctr < ALL_COUNTER; ctr++) { - rc = perf_reset_ctr(ctr, value); + rc = perf_reset_ctr(ctr, value, supported_counters); if (rc != 0) return rc; } @@ -727,14 +757,14 @@ int perf_reset_ctr(enum ctr_e ctr, uint64_t *value) endforeachcpu(); } else if (ctr == PAI_USER) { foreachcpu(pcpu) { - ec = reset_array(pcpu->pai_user, NUM_PAI_USER); + ec = reset_array(pcpu->pai_user, 1, supported_counters); if (ec < 0) rc = -1; } endforeachcpu(); } else if (ctr == PAI_KERNEL) { foreachcpu(pcpu) { - ec = reset_array(pcpu->pai_kernel, NUM_PAI_KERNEL); + ec = reset_array(pcpu->pai_kernel, 0, supported_counters); if (ec < 0) rc = -1; } @@ -743,12 +773,13 @@ int perf_reset_ctr(enum ctr_e ctr, uint64_t *value) rc = -1; } if (rc == 0) - rc = perf_read_ctr(ctr, value); + rc = perf_read_ctr(ctr, value, supported_counters); return rc; } -int perf_read_ctr(enum ctr_e ctr, uint64_t *value) +int perf_read_ctr(enum ctr_e ctr, uint64_t *value, unsigned int + *supported_counters) { struct percpucounter *pcpu; int ec, rc = 0; @@ -761,11 +792,26 @@ int perf_read_ctr(enum ctr_e ctr, uint64_t *value) return 0; } if (ctr == PAI_USER) { - *value = NUM_PAI_USER; + int c = 0; + + for (int i = 0; i < MAX_NUM_PAI; i++) { + if (is_user_space(i) == KERNEL_AND_USER_COUNTER && + supported_counters[i] == 1) + c++; + } + + *value = c; return 0; } if (ctr == PAI_KERNEL) { - *value = NUM_PAI_KERNEL; + int c = 0; + + for (int i = 0; i < MAX_NUM_PAI; i++) { + if (supported_counters[i] == 1) + c++; + } + + *value = c; return 0; } if (ctr >= ALL_COUNTER) @@ -802,14 +848,15 @@ int perf_ctr_state(enum ctr_e ctr) { int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value) { struct percpucounter *pcpu; - unsigned int maxctr; int *arr, ec, rc = 0; uint64_t val; *value = 0; - maxctr = user ? NUM_PAI_USER : NUM_PAI_KERNEL; - if (ctrnum >= maxctr) + + if (is_user_space(ctrnum) == SUPPRESS_COUNTER || + (user && is_user_space(ctrnum) == KERNEL_ONLY_COUNTER)) return -1; + foreachcpu(pcpu) { arr = user ? pcpu->pai_user : pcpu->pai_kernel; ec = read(arr[ctrnum], &val, sizeof(val));