mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
cpacfstats: Add PAI and hotplug support
Add virtual counters pai_user and pai_kernel to detail all Processor Activity Instrumentation (PAI) counters in user resp. kernel space. Once activated, they will show all counters for the corresponding set. Add option -n to limit the display to only non-zero counter values. Add support for cpu hotplug events based on libudev. CPU hotplug events are used to either detach from a vanishing CPU or (re-)attach to a (re-)appearing CPU. In that case, a "hotplug detected" virtual counter is set to a non-zero value to indicate possible loss of counters which happens when CPACF is used on the CPU before cpacfstatsd could attach to it. The hotplug indication is cleared once all counters are deactivated. Add support for JSON output. The JSON document is an array of JSON objects representing the counters and their values. Every object has a name (property "counter") and a value (property "value"). For PAI counters, the counters also have a space (property "space") determining the counter set pai_user or pai_kernel, and a numeric id (property "counterid") that can be used to filter the JSON document. Signed-off-by: Juergen Christ <jchrist@linux.ibm.com> Reviewed-By: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
72b5e8b313
commit
fcb1f7efd1
@@ -1,6 +1,6 @@
|
||||
.\" cpacfstats.1
|
||||
.\"
|
||||
.\" Copyright IBM Corp. 2015, 2020
|
||||
.\" Copyright IBM Corp. 2015, 2022
|
||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\"
|
||||
@@ -32,7 +32,9 @@ cpacfstats \- enable, disable and display CPACF statistical data
|
||||
.RB ]
|
||||
.RB [ \-p | \-\-print
|
||||
.I counter
|
||||
.RB [ \-n | \-\-nonzero]
|
||||
.RB ]
|
||||
.RB [ \-j | \-\-json ]
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
The cpacfstats client application interacts with the cpacfstatsd daemon and
|
||||
@@ -44,12 +46,344 @@ All counters are initially disabled and must be switched on to measure
|
||||
CPACF activities of the system. There is a slight performance penalty with
|
||||
CPACF counters enabled.
|
||||
|
||||
Note: All cryptographic counters are bound to physical CPUs. If you use
|
||||
dedicated CPUs for your LPAR, you obtain only your CPACF activities. If
|
||||
your CPUs are shared with other LPARs, their cryptographic activities might
|
||||
distort the results. CPACF performance counters are available on LPARs
|
||||
only. For security reasons only members of the group \fIcpacfstats\fR are
|
||||
allowed to run the cpacfstats client application.
|
||||
CPACF activity counters come in two flavors: CPU-MF and PAI. CPU-MF
|
||||
counters are only available on LPARs and have to be authorized. If
|
||||
they are available, the counters
|
||||
.B des,
|
||||
.B aes,
|
||||
.B sha,
|
||||
.B rng,
|
||||
and
|
||||
.B ecc
|
||||
are made available. These counters can individually be activated,
|
||||
reset, printed, or deactivated. PAI counters are a lot more detailed.
|
||||
The user interface only offers the counters
|
||||
.B pai_user
|
||||
and
|
||||
.B pai_kernel
|
||||
to count CPACF usage in user-space or kernel-space. When printing
|
||||
these counters, detailed counters are shown. The detailed names are:
|
||||
.RS
|
||||
.IP \(bu
|
||||
KM DES,
|
||||
.IP \(bu
|
||||
KM 2key TDES,
|
||||
.IP \(bu
|
||||
KM TDES,
|
||||
.IP \(bu
|
||||
KM DES protected key,
|
||||
.IP \(bu
|
||||
KM 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KM TDES protected key,
|
||||
.IP \(bu
|
||||
KM AES 128bit,
|
||||
.IP \(bu
|
||||
KM AES 192bit,
|
||||
.IP \(bu
|
||||
KM AES 256bit,
|
||||
.IP \(bu
|
||||
KM AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KM AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KM AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KM AES-XTS 128bit,
|
||||
.IP \(bu
|
||||
KM AES-XTS 256bit,
|
||||
.IP \(bu
|
||||
KM AES-XTS 128bit protected key,
|
||||
.IP \(bu
|
||||
KM AES-XTS 256bit protected key,
|
||||
.IP \(bu
|
||||
KMC DES,
|
||||
.IP \(bu
|
||||
KMC 2key TDES,
|
||||
.IP \(bu
|
||||
KMC TDES,
|
||||
.IP \(bu
|
||||
KMC DES protected key,
|
||||
.IP \(bu
|
||||
KMC 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KMC TDES protected key,
|
||||
.IP \(bu
|
||||
KMC AES 128bit,
|
||||
.IP \(bu
|
||||
KMC AES 192bit,
|
||||
.IP \(bu
|
||||
KMC AES 256bit,
|
||||
.IP \(bu
|
||||
KMC AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMC AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMC AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KMC PRNG,
|
||||
.IP \(bu
|
||||
KMA AES 128bit,
|
||||
.IP \(bu
|
||||
KMA AES 192bit,
|
||||
.IP \(bu
|
||||
KMA AES 256bit,
|
||||
.IP \(bu
|
||||
KMA AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMA AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMA AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KMF DES,
|
||||
.IP \(bu
|
||||
KMF 2key TDES,
|
||||
.IP \(bu
|
||||
KMF TDES,
|
||||
.IP \(bu
|
||||
KMF DES protected key,
|
||||
.IP \(bu
|
||||
KMF 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KMF TDES protected key,
|
||||
.IP \(bu
|
||||
KMF AES 128bit,
|
||||
.IP \(bu
|
||||
KMF AES 192bit,
|
||||
.IP \(bu
|
||||
KMF AES 256bit,
|
||||
.IP \(bu
|
||||
KMF AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMF AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMF AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KMCTR DES,
|
||||
.IP \(bu
|
||||
KMCTR 2key TDES,
|
||||
.IP \(bu
|
||||
KMCTR TDES,
|
||||
.IP \(bu
|
||||
KMCTR DES protected key,
|
||||
.IP \(bu
|
||||
KMCTR 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KMCTR TDES protected key,
|
||||
.IP \(bu
|
||||
KMCTR AES 128bit,
|
||||
.IP \(bu
|
||||
KMCTR AES 192bit,
|
||||
.IP \(bu
|
||||
KMCTR AES 256bit,
|
||||
.IP \(bu
|
||||
KMCTR AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMCTR AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMCTR AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KMO DES,
|
||||
.IP \(bu
|
||||
KMO 2key TDES,
|
||||
.IP \(bu
|
||||
KMO TDES,
|
||||
.IP \(bu
|
||||
KMO DES protected key,
|
||||
.IP \(bu
|
||||
KMO 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KMO TDES protected key,
|
||||
.IP \(bu
|
||||
KMO AES 128bit,
|
||||
.IP \(bu
|
||||
KMO AES 192bit,
|
||||
.IP \(bu
|
||||
KMO AES 256bit,
|
||||
.IP \(bu
|
||||
KMO AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMO AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMO AES 256bit protected key,
|
||||
.IP \(bu
|
||||
KIMD SHA1,
|
||||
.IP \(bu
|
||||
KIMD SHA256,
|
||||
.IP \(bu
|
||||
KIMD SHA512,
|
||||
.IP \(bu
|
||||
KIMD SHA3-224,
|
||||
.IP \(bu
|
||||
KIMD SHA3-256,
|
||||
.IP \(bu
|
||||
KIMD SHA3-384,
|
||||
.IP \(bu
|
||||
KIMD SHA3-512,
|
||||
.IP \(bu
|
||||
KIMD SHAKE 128,
|
||||
.IP \(bu
|
||||
KIMD SHAE 256,
|
||||
.IP \(bu
|
||||
KIMD GHASH,
|
||||
.IP \(bu
|
||||
KLMD SHA1,
|
||||
.IP \(bu
|
||||
KLMD SHA256,
|
||||
.IP \(bu
|
||||
KLMD SHA512,
|
||||
.IP \(bu
|
||||
KLMD SHA3-224,
|
||||
.IP \(bu
|
||||
KLMD SHA3-256,
|
||||
.IP \(bu
|
||||
KLMD SHA3-384,
|
||||
.IP \(bu
|
||||
KLMD SHA3-512,
|
||||
.IP \(bu
|
||||
KLMD SHAKE 128,
|
||||
.IP \(bu
|
||||
KLMD SHAKE 256,
|
||||
.IP \(bu
|
||||
KMAC DES,
|
||||
.IP \(bu
|
||||
KMAC 2key TDES,
|
||||
.IP \(bu
|
||||
KMAC TDES,
|
||||
.IP \(bu
|
||||
KMAC DES protected key,
|
||||
.IP \(bu
|
||||
KMAC 2key TDES protected key,
|
||||
.IP \(bu
|
||||
KMAC TDES protected key,
|
||||
.IP \(bu
|
||||
KMAC AES 128bit,
|
||||
.IP \(bu
|
||||
KMAC AES 192bit,
|
||||
.IP \(bu
|
||||
KMAC AES 256bit,
|
||||
.IP \(bu
|
||||
KMAC AES 128bit protected key,
|
||||
.IP \(bu
|
||||
KMAC AES 192bit protected key,
|
||||
.IP \(bu
|
||||
KMAC AES 256bit protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC DES,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC 2key TDES,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC TDES,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC DES protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC 2key TDES protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC TDES protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 128bit,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 192bit,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 256bit,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 128bit protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 192bit protected key,
|
||||
.IP \(bu
|
||||
PCC Last Block CMAC AES 256bit protected key,
|
||||
.IP \(bu
|
||||
PCC XTS Parameter AES 128bit,
|
||||
.IP \(bu
|
||||
PCC XTS Parameter AES 256bit,
|
||||
.IP \(bu
|
||||
PCC XTS Parameter AES 128bit protected key,
|
||||
.IP \(bu
|
||||
PCC XTS Parameter AES 256bit protected key,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult P256,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult P384,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult P521,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult Ed25519,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult Ed448,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult X25519,
|
||||
.IP \(bu
|
||||
PCC Scalar Mult X448,
|
||||
.IP \(bu
|
||||
PRNO SHA512 DRNG,
|
||||
.IP \(bu
|
||||
PRNO TRNG Query Ratio,
|
||||
.IP \(bu
|
||||
PRNO TRNG,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Verify P256,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Verify P384,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Verify P521,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P256,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P384,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P521,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P256 protected key,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P384 protected key,
|
||||
.IP \(bu
|
||||
KDSA ECDSA Sign P521 protected key,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Verify Ed25519,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Verify Ed448,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Sign Ed25519,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Sign Ed448,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Sign Ed25519 protected key,
|
||||
.IP \(bu
|
||||
KDSA EdDSA Sign Ed448 protected key,
|
||||
.IP \(bu
|
||||
PCKMO DES,
|
||||
.IP \(bu
|
||||
PCKMO 2key TDES,
|
||||
.IP \(bu
|
||||
PCMKO TDES,
|
||||
.IP \(bu
|
||||
PCKMO AES 128bit,
|
||||
.IP \(bu
|
||||
PCKMO AES 192bit,
|
||||
.IP \(bu
|
||||
PCMKO AES 256bit,
|
||||
.IP \(bu
|
||||
PCKMO ECC P256,
|
||||
.IP \(bu
|
||||
PCKMO ECC P384,
|
||||
.IP \(bu
|
||||
PCKMO ECC P521,
|
||||
.IP \(bu
|
||||
PCKMO ECC Ed25519,
|
||||
.IP \(bu
|
||||
PCKMO ECC Ed448,
|
||||
.IP \(bu
|
||||
Reserved 1, and
|
||||
.IP \(bu
|
||||
Reserved 2.
|
||||
.RE
|
||||
Note that the counters starting with PCKMO and Reserved are only
|
||||
available in the pai_kernel set.
|
||||
|
||||
Note: CPU-MF based CPACF performance counters are available on LPARs
|
||||
only. PAI counters are available on all hypervisors. For security
|
||||
reasons only members of the group \fIcpacfstats\fR are allowed to run
|
||||
the cpacfstats client application.
|
||||
|
||||
Example usage scenario:
|
||||
.P
|
||||
@@ -101,12 +435,34 @@ argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR,
|
||||
\fBecc\fR, or \fBall\fR. If the counter argument is omitted, all
|
||||
performance counters are reset to 0.
|
||||
.TP
|
||||
\fB\-p\fR or \fB\-\-print\fR [counter]
|
||||
\fB\-p\fR or \fB\-\-print\fR [\fB\-n\fR or \fB\-\-nonzero\fR] [counter]
|
||||
Display the value of one or all CPACF performance counters. The
|
||||
optional counter argument can be one of: \fBdes\fR, \fBaes\fR,
|
||||
\fBsha\fR, \fBprng\fR, \fBecc\fR, or \fBall\fR. If the counter
|
||||
argument is omitted or if there is no argument, all performance
|
||||
counters are displayed.
|
||||
\fBsha\fR, \fBprng\fR, \fBecc\fR, \fBpai_user\fR, \fBpai_kernel\fR, or
|
||||
\fBall\fR. If the counter argument is omitted or if there is no
|
||||
argument, all performance counters are displayed. If the optional
|
||||
\fB\-n\fR or \fB\-\-nonzero\fR argument is given, then only PAI
|
||||
counters that have a non-zero value are printed.
|
||||
.TP
|
||||
\fB\-j\fR or \fB\-\-json\fR
|
||||
Display all activated counters in JSON format. The JSON contains an
|
||||
array of counter objects. Each object contains the property
|
||||
.B counter
|
||||
specifying either a CPU-MF counter of one of the detailed PAI counter.
|
||||
Additional properties include
|
||||
.B error
|
||||
an error number if the counter could not be read,
|
||||
.B value
|
||||
the counter value if the counter could be read,
|
||||
.B space
|
||||
for PAI counters to specify
|
||||
.B user
|
||||
or
|
||||
.B kernel
|
||||
space counter set, and
|
||||
.B counterid
|
||||
for PAI counters to specify the PAI counter number as specified in the
|
||||
Principles of Operation.
|
||||
.TP
|
||||
The default command is --print all.
|
||||
.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* cpacfstats client implementation
|
||||
*
|
||||
* Copyright IBM Corp. 2015, 2020
|
||||
* Copyright IBM Corp. 2015, 2022
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
@@ -39,17 +39,187 @@ static const char *const usage =
|
||||
"\t-d, --disable [counter] Disable one or all counters\n"
|
||||
"\t-r, --reset [counter] Reset one or all counter values\n"
|
||||
"\t-p, --print [counter] Print one or all counter values\n"
|
||||
"\tcounter can be: 'aes' 'des' 'rng' 'sha' 'ecc' or 'all'\n";
|
||||
"\t-n, --nonzero Print all PAI counters\n"
|
||||
"\t-j, --json Print all counter values in JSON format\n"
|
||||
"\tcounter can be: 'aes' 'des' 'rng' 'sha' 'ecc'\n"
|
||||
"\t 'pai_user' 'pai_kernel' or 'all'\n";
|
||||
|
||||
static const char *const counter_str[] = {
|
||||
[DES_FUNCTIONS] = "des",
|
||||
[AES_FUNCTIONS] = "aes",
|
||||
[SHA_FUNCTIONS] = "sha",
|
||||
[PRNG_FUNCTIONS] = "rng",
|
||||
[ECC_FUNCTIONS] = "ecc",
|
||||
[ALL_COUNTER] = "all"
|
||||
[ECC_FUNCTIONS] = "ecc",
|
||||
[ALL_COUNTER] = "all",
|
||||
[PAI_USER] = "pai_user",
|
||||
[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 SHAE 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] = "PCMKO TDES",
|
||||
[146] = "PCKMO AES 128bit",
|
||||
[147] = "PCKMO AES 192bit",
|
||||
[148] = "PCMKO 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;
|
||||
|
||||
|
||||
static int send_query(int s, enum cmd_e cmd, enum ctr_e ctr)
|
||||
{
|
||||
@@ -91,21 +261,140 @@ static int recv_answer(int s, int *ctr, int *state, uint64_t *value)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void print_virtual_counter_answer(int ctr, int state, uint64_t value)
|
||||
|
||||
static void printjsonsep(void)
|
||||
{
|
||||
if (ctr == HOTPLUG_DETECTED) {
|
||||
if (state >= 0 && value > 0)
|
||||
printf(" hotplug detected\n");
|
||||
static const char *jsonsep = "";
|
||||
|
||||
fputs(jsonsep, stdout);
|
||||
jsonsep = ",";
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
const char *space;
|
||||
|
||||
switch (ctr) {
|
||||
case HOTPLUG_DETECTED:
|
||||
printjsonsep();
|
||||
printf("{\"counter\":\"hotplug detected\",");
|
||||
if (state < 0)
|
||||
printf("\"error\":%d}", state);
|
||||
else
|
||||
printf("\"value\":%d}", !!value);
|
||||
return;
|
||||
case PAI_USER:
|
||||
maxnum = NUM_PAI_USER;
|
||||
space = "user";
|
||||
break;
|
||||
case PAI_KERNEL:
|
||||
maxnum = NUM_PAI_KERNEL;
|
||||
space = "kernel";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
/* Here, we have validated the PAI counter retrieved, but not
|
||||
* yet printed. */
|
||||
if (state != ENABLED)
|
||||
return;
|
||||
if (value > maxnum) {
|
||||
eprint("Incompatible versions detected!\n");
|
||||
eprint("Expected %"PRIu64" counter space for %s, but got %"PRIu64"\n",
|
||||
maxnum, space, value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (i = 0; i < value; ++i) {
|
||||
ec = recv_answer(s, &paictr, &paistate, &paivalue);
|
||||
if (ec < 0 || paistate < 0) {
|
||||
eprint("Error on receiving answer message from daemon\n");
|
||||
/* No more data for this virtual event after error. */
|
||||
return;
|
||||
}
|
||||
if (paictr > NUM_PAI_KERNEL) {
|
||||
eprint("Pai counter number too big: %d\n", paictr);
|
||||
} else {
|
||||
printjsonsep();
|
||||
printf("{\"counter\":\"%s\",\"space\":\"%s\",\"counterid\":%d,",
|
||||
pai_str[paictr], space, paictr + 1);
|
||||
if (paistate < 0) {
|
||||
printf("\"error\":%d}", paistate);
|
||||
/* Protocol does not send furter counters. */
|
||||
return;
|
||||
}
|
||||
printf("\"value\":%"PRIu64"}", paivalue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_answer(int ctr, int state, uint64_t value)
|
||||
|
||||
static void print_virtual_counter_answer(int s,
|
||||
int ctr, int state, uint64_t value)
|
||||
{
|
||||
if (ctr > ALL_COUNTER) {
|
||||
print_virtual_counter_answer(ctr, state, value);
|
||||
static const char *const states[] = {
|
||||
[DISABLED] = "disabled",
|
||||
[ENABLED] = "enabled",
|
||||
[UNSUPPORTED] = "unsupported"
|
||||
};
|
||||
int paictr = 0, paistate = 0, ec;
|
||||
uint64_t i, paivalue = 0, maxnum;
|
||||
const char *ctrstr;
|
||||
|
||||
switch (ctr) {
|
||||
case HOTPLUG_DETECTED:
|
||||
if (state >= 0 && value > 0)
|
||||
printf(" hotplug detected\n");
|
||||
return;
|
||||
case PAI_USER:
|
||||
maxnum = NUM_PAI_USER;
|
||||
ctrstr = "pai_user";
|
||||
break;
|
||||
case PAI_KERNEL:
|
||||
maxnum = NUM_PAI_KERNEL;
|
||||
ctrstr = "pai_kernel";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (state < 0)
|
||||
/* Here, we have validated the PAI counter retrieved, but not
|
||||
* yet printed. */
|
||||
if (state < 0 || state > UNSUPPORTED) {
|
||||
printf(" %11s: error state %d\n", ctrstr, state);
|
||||
/* No details follow if counter in error state. */
|
||||
return;
|
||||
}
|
||||
printf(" %-11s: %s\n", ctrstr, states[state]);
|
||||
if (state != ENABLED)
|
||||
return;
|
||||
if (value > maxnum) {
|
||||
eprint("Incompatible versions detected!\n");
|
||||
eprint("Expected %"PRIu64" counters for %s, but got %"PRIu64"\n",
|
||||
maxnum, ctrstr, value);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
for (i = 0; i < value; ++i) {
|
||||
ec = recv_answer(s, &paictr, &paistate, &paivalue);
|
||||
if (ec < 0 || paistate < 0) {
|
||||
eprint("Error on receiving answer message from daemon\n");
|
||||
/* No more data for this virtual event after error. */
|
||||
return;
|
||||
}
|
||||
if (paictr > NUM_PAI_KERNEL)
|
||||
eprint("Pai counter number too big: %d\n", paictr);
|
||||
else if (!paiprintnonzero || paivalue > 0)
|
||||
printf(" %-45s: %"PRIu64"\n", pai_str[paictr], paivalue);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_answer(int s, int ctr, int state, uint64_t value)
|
||||
{
|
||||
if (ctr > ALL_COUNTER)
|
||||
print_virtual_counter_answer(s, ctr, state, value);
|
||||
else if (state < 0)
|
||||
printf(" %s counter: error state %d\n",
|
||||
counter_str[ctr], state);
|
||||
else if (state == DISABLED)
|
||||
@@ -117,6 +406,22 @@ static void print_answer(int ctr, int state, uint64_t value)
|
||||
}
|
||||
|
||||
|
||||
static void json_print_answer(int s, int ctr, int state, uint64_t value)
|
||||
{
|
||||
if (ctr > ALL_COUNTER) {
|
||||
json_print_virtual_counter_answer(s, ctr, state, value);
|
||||
} else if (state < 0) {
|
||||
printjsonsep();
|
||||
printf("{\"counter\":\"%s\",", counter_str[ctr]);
|
||||
printf("\"error\":%d}\n", state);
|
||||
} else if (state == ENABLED) {
|
||||
printjsonsep();
|
||||
printf("{\"counter\":\"%s\",", counter_str[ctr]);
|
||||
printf("\"value\":%"PRIu64"}", value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int eprint(const char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
@@ -139,7 +444,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
enum ctr_e ctr = ALL_COUNTER;
|
||||
enum cmd_e cmd = PRINT;
|
||||
int i, j, s, state;
|
||||
int i, j, s, state, num, json = 0;
|
||||
uint64_t value;
|
||||
|
||||
if (argc > 1) {
|
||||
@@ -151,110 +456,108 @@ int main(int argc, char *argv[])
|
||||
{ "disable", 0, NULL, 'd' },
|
||||
{ "reset", 0, NULL, 'r' },
|
||||
{ "print", 0, NULL, 'p' },
|
||||
{ "nonzero", 0, NULL, 'n' },
|
||||
{ "json", 0, NULL, 'j' },
|
||||
{ NULL, 0, NULL, 0 } };
|
||||
while (1) {
|
||||
opt = getopt_long(argc, argv,
|
||||
"hvedrp", long_opts, &idx);
|
||||
"hvedrpnj", long_opts, &idx);
|
||||
if (opt == -1)
|
||||
break; /* no more arguments */
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
printf(usage, name);
|
||||
exit(0);
|
||||
break;
|
||||
return 0;
|
||||
case 'v':
|
||||
printf("%s: Linux on System z CPACF Crypto Activity Counters Client\n"
|
||||
"Version %s\n%s\n",
|
||||
name, RELEASE_STRING, COPYRIGHT);
|
||||
exit(0);
|
||||
break;
|
||||
return 0;
|
||||
case 'e':
|
||||
cmd = ENABLE;
|
||||
json = 0;
|
||||
break;
|
||||
case 'd':
|
||||
cmd = DISABLE;
|
||||
json = 0;
|
||||
break;
|
||||
case 'r':
|
||||
cmd = RESET;
|
||||
break;
|
||||
case 'p':
|
||||
cmd = PRINT;
|
||||
json = 0;
|
||||
break;
|
||||
case 'n':
|
||||
paiprintnonzero = 1;
|
||||
break;
|
||||
case 'j':
|
||||
cmd = PRINT;
|
||||
json = 1;
|
||||
break;
|
||||
default:
|
||||
eprint("Invalid argument, try -h or --help for more information\n");
|
||||
exit(1);
|
||||
break;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
/* there may be an optional counter argument */
|
||||
if (optind > 0 && optind < argc) {
|
||||
for (i = 0; i <= ALL_COUNTER; i++)
|
||||
for (i = 0; i < NUM_COUNTER; i++)
|
||||
if (strcmp(argv[optind], counter_str[i]) == 0)
|
||||
break;
|
||||
if (i > ALL_COUNTER) {
|
||||
if (i >= NUM_COUNTER) {
|
||||
eprint("Unknown counter '%s'\n", argv[optind]);
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
ctr = (enum ctr_e) i;
|
||||
}
|
||||
}
|
||||
if (json)
|
||||
ctr = ALL_COUNTER;
|
||||
|
||||
/* try to open and connect socket to the cpacfstatsd daemon */
|
||||
s = open_socket(CLIENT);
|
||||
if (s < 0) {
|
||||
eprint("Can't connect to daemon\n");
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* send query */
|
||||
if (send_query(s, cmd, ctr) != 0) {
|
||||
eprint("Error on sending query message to daemon\n");
|
||||
close(s);
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (ctr == ALL_COUNTER) {
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
/* receive answer */
|
||||
if (recv_answer(s, &j, &state, &value) != 0) {
|
||||
eprint("Error on receiving answer message from daemon\n");
|
||||
exit(1);
|
||||
}
|
||||
if (state < 0) {
|
||||
eprint("Received bad status code %d from daemon\n",
|
||||
state);
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
print_answer(j, state, value);
|
||||
}
|
||||
/* The -1 is for ALL_COUNTER which is not sent, +1 for
|
||||
* hotplug state. */
|
||||
num = NUM_COUNTER - 1 + 1;
|
||||
} else {
|
||||
/* +1 for hotplug state */
|
||||
num = 1 + 1;
|
||||
}
|
||||
if (json)
|
||||
putchar('[');
|
||||
for (i = 0; i < num; i++) {
|
||||
/* receive answer */
|
||||
if (recv_answer(s, &j, &state, &value) != 0) {
|
||||
eprint("Error on receiving answer message from daemon\n");
|
||||
close(s);
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (state < 0) {
|
||||
eprint("Received bad status code %d from daemon\n",
|
||||
state);
|
||||
state);
|
||||
close(s);
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
print_answer(j, state, value);
|
||||
if (json)
|
||||
json_print_answer(s, j, state, value);
|
||||
else
|
||||
print_answer(s, j, state, value);
|
||||
}
|
||||
/* receive hotplug state */
|
||||
if (recv_answer(s, &j, &state, &value) != 0) {
|
||||
eprint("Error on receiving hotplug state from daemon\n");
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
if (state < 0) {
|
||||
eprint("Received bad status code %d from daemon\n", state);
|
||||
close(s);
|
||||
exit(1);
|
||||
}
|
||||
print_answer(j, state, value);
|
||||
if (json)
|
||||
putchar(']');
|
||||
|
||||
/* close connection */
|
||||
close(s);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* common function prototypes and definitions
|
||||
*
|
||||
* Copyright IBM Corp. 2015, 2020
|
||||
* Copyright IBM Corp. 2015, 2022
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
@@ -16,15 +16,25 @@
|
||||
|
||||
#define COPYRIGHT "Copyright IBM Corp. 2015, 2022"
|
||||
|
||||
#define DEFAULT_SEND_TIMEOUT (2 * 1000)
|
||||
#define DEFAULT_RECV_TIMEOUT (2 * 1000)
|
||||
#define DEFAULT_SEND_TIMEOUT (30 * 1000)
|
||||
#define DEFAULT_RECV_TIMEOUT (30 * 1000)
|
||||
|
||||
/*
|
||||
* Number of PAI counters for user space. This excludes PCKMO since
|
||||
* this instruction is privileged.
|
||||
*/
|
||||
#define NUM_PAI_USER 143
|
||||
/* Number of PAI counters for kernel space. Contains all counters. */
|
||||
#define NUM_PAI_KERNEL 156
|
||||
|
||||
int eprint(const char *format, ...);
|
||||
|
||||
/*
|
||||
* Counter names
|
||||
* ALL_COUNTER specifies the number of physical counters. Virtual
|
||||
* counters might be added afterwards.
|
||||
* counters might be added afterwards. NUM_COUNTER is the last
|
||||
* managed counter (i.e., a counter that can be activated, reset,
|
||||
* deactivated).
|
||||
*/
|
||||
enum ctr_e {
|
||||
DES_FUNCTIONS = 0,
|
||||
@@ -33,7 +43,10 @@ enum ctr_e {
|
||||
PRNG_FUNCTIONS,
|
||||
ECC_FUNCTIONS,
|
||||
ALL_COUNTER,
|
||||
HOTPLUG_DETECTED
|
||||
PAI_USER,
|
||||
PAI_KERNEL,
|
||||
NUM_COUNTER,
|
||||
HOTPLUG_DETECTED = 0xffff
|
||||
};
|
||||
|
||||
enum type_e {
|
||||
@@ -68,7 +81,7 @@ struct msg_query {
|
||||
/*
|
||||
* answer send from daemon to client
|
||||
* Consist of:
|
||||
* enum counter
|
||||
* enum counter or PAI counter number if following PAI_USER or PAI_KERNEL
|
||||
* status code: < 0 error, 0 disabled, > 0 enabled
|
||||
* counter value
|
||||
*/
|
||||
@@ -114,9 +127,10 @@ 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);
|
||||
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value);
|
||||
int perf_read_ctr(enum ctr_e ctr, uint64_t *value);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* cpacfstatsd daemon implementation
|
||||
*
|
||||
* Copyright IBM Corp. 2015, 2017
|
||||
* Copyright IBM Corp. 2015, 2022
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
@@ -85,13 +85,50 @@ static int send_answer(int s, int ctr, int state, uint64_t value)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print according to protocol for PAI:
|
||||
* - first the state and the number of PAI counters that follow
|
||||
* - if state is ENABLED:
|
||||
* - for each PAI counter the value with state ENABLED
|
||||
* 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)
|
||||
{
|
||||
int ctr, state, i, maxctr, rc = 0;
|
||||
uint64_t value;
|
||||
|
||||
if (user) {
|
||||
ctr = PAI_USER;
|
||||
maxctr = NUM_PAI_USER;
|
||||
} else {
|
||||
ctr = PAI_KERNEL;
|
||||
maxctr = NUM_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);
|
||||
if (rc != 0) {
|
||||
send_answer(s, i, rc, 0);
|
||||
break;
|
||||
}
|
||||
send_answer(s, i, state, value);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int do_enable(int s, enum ctr_e ctr)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
int i, rc = 0;
|
||||
int state;
|
||||
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
for (i = 0; i < NUM_COUNTER; i++) {
|
||||
if (i == ALL_COUNTER)
|
||||
continue;
|
||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||
state = perf_ctr_state(i);
|
||||
if (state == DISABLED) {
|
||||
@@ -110,6 +147,10 @@ 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);
|
||||
if (i == PAI_KERNEL)
|
||||
rc = do_send_pai(s, 0);
|
||||
}
|
||||
}
|
||||
if (rc == 0) {
|
||||
@@ -125,7 +166,9 @@ static int do_disable(int s, enum ctr_e ctr)
|
||||
int i, rc = 0;
|
||||
uint64_t value;
|
||||
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
for (i = 0; i < NUM_COUNTER; i++) {
|
||||
if (i == ALL_COUNTER)
|
||||
continue;
|
||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||
if (perf_ctr_state(i) == ENABLED) {
|
||||
rc = perf_disable_ctr(i);
|
||||
@@ -150,17 +193,23 @@ static int do_reset(int s, enum ctr_e ctr)
|
||||
int i, rc = 0, state;
|
||||
uint64_t value;
|
||||
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
for (i = 0; i < NUM_COUNTER; i++) {
|
||||
if (i == ALL_COUNTER)
|
||||
continue;
|
||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||
state = perf_ctr_state(i);
|
||||
if (state == ENABLED) {
|
||||
rc = perf_reset_ctr(i);
|
||||
rc = perf_reset_ctr(i, &value);
|
||||
if (rc != 0) {
|
||||
send_answer(s, i, rc, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
send_answer(s, i, state, 0);
|
||||
send_answer(s, i, state, value);
|
||||
if (i == PAI_USER)
|
||||
rc = do_send_pai(s, 1);
|
||||
if (i == PAI_KERNEL)
|
||||
rc = do_send_pai(s, 0);
|
||||
}
|
||||
}
|
||||
if (rc == 0) {
|
||||
@@ -170,12 +219,15 @@ static int do_reset(int s, enum ctr_e ctr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int do_print(int s, enum ctr_e ctr)
|
||||
{
|
||||
int i, rc = 0, state;
|
||||
uint64_t value = 0;
|
||||
|
||||
for (i = 0; i < ALL_COUNTER; i++) {
|
||||
for (i = 0; i < NUM_COUNTER; i++) {
|
||||
if (i == ALL_COUNTER)
|
||||
continue;
|
||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||
state = perf_ctr_state(i);
|
||||
if (state == ENABLED) {
|
||||
@@ -186,6 +238,10 @@ 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);
|
||||
if (i == PAI_KERNEL)
|
||||
rc = do_send_pai(s, 0);
|
||||
}
|
||||
}
|
||||
if (rc == 0) {
|
||||
@@ -380,7 +436,7 @@ int main(int argc, char *argv[])
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
printf(usage, name);
|
||||
exit(0);
|
||||
return 0;
|
||||
case 'f':
|
||||
foreground = 1;
|
||||
break;
|
||||
@@ -388,37 +444,37 @@ int main(int argc, char *argv[])
|
||||
printf("%s: Linux on System z CPACF Crypto Activity Counters Daemon\n"
|
||||
"Version %s\n%s\n",
|
||||
name, RELEASE_STRING, COPYRIGHT);
|
||||
exit(0);
|
||||
return 0;
|
||||
default:
|
||||
printf("%s: Invalid argument, try -h or --help for more information\n",
|
||||
name);
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (check_pidfile() != 0) {
|
||||
eprint("Stalled pid file or daemon allready running, terminating\n");
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!foreground) {
|
||||
if (become_daemon() != 0) {
|
||||
eprint("Couldn't daemonize\n");
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (perf_init() != 0) {
|
||||
eprint("Couldn't initialize perf lib\n");
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
atexit(perf_close);
|
||||
|
||||
sfd = open_socket(SERVER);
|
||||
if (sfd < 0) {
|
||||
eprint("Couldn't initialize server socket\n");
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
atexit(remove_sock);
|
||||
|
||||
@@ -428,13 +484,15 @@ int main(int argc, char *argv[])
|
||||
if (sigaction(SIGINT, &act, 0) != 0) {
|
||||
eprint("Couldn't establish signal handler for SIGINT, errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (sigaction(SIGTERM, &act, 0) != 0) {
|
||||
eprint("Couldn't establish signal handler for SIGTERM, errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
/* Ignore SIGPIPE such that we see EPIPE as return from write. */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
eprint("Running\n");
|
||||
|
||||
@@ -449,7 +507,7 @@ int main(int argc, char *argv[])
|
||||
continue;
|
||||
eprint("Accept() failure, errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
rc = recv_query(s, &ctr, &cmd);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* low level perf functions
|
||||
*
|
||||
* Copyright IBM Corp. 2015, 2020
|
||||
* Copyright IBM Corp. 2015, 2022
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libudev.h>
|
||||
@@ -31,14 +32,12 @@
|
||||
#include "cpacfstats.h"
|
||||
#include "../include/lib/zt_common.h"
|
||||
|
||||
#define NUM_COUNTER ALL_COUNTER
|
||||
|
||||
/* correlation between counter and perf counter string */
|
||||
static const struct {
|
||||
char pmu[20];
|
||||
char pfm_name[60];
|
||||
enum ctr_e ctr;
|
||||
} pmf_counter_name[NUM_COUNTER] = {
|
||||
} pmf_counter_name[ALL_COUNTER] = {
|
||||
{"cpum_cf", "DEA_FUNCTIONS", DES_FUNCTIONS},
|
||||
{"cpum_cf", "AES_FUNCTIONS", AES_FUNCTIONS},
|
||||
{"cpum_cf", "SHA_FUNCTIONS", SHA_FUNCTIONS},
|
||||
@@ -49,10 +48,12 @@ static const struct {
|
||||
static struct pmf_data {
|
||||
int pmutype;
|
||||
int eventid;
|
||||
} pmf_counter_data[NUM_COUNTER];
|
||||
} pmf_counter_data[ALL_COUNTER];
|
||||
|
||||
struct percpucounter {
|
||||
int ctr_fds[NUM_COUNTER];
|
||||
int ctr_fds[ALL_COUNTER];
|
||||
int pai_user[NUM_PAI_USER];
|
||||
int pai_kernel[NUM_PAI_KERNEL];
|
||||
unsigned int cpunum;
|
||||
struct percpucounter *next;
|
||||
};
|
||||
@@ -71,6 +72,8 @@ static int ctr_state[NUM_COUNTER];
|
||||
|
||||
static volatile int stoprequested;
|
||||
|
||||
static int paipmutype, paipmueventstart;
|
||||
|
||||
static struct percpucounter *allocpercpucounter(unsigned int cpunum)
|
||||
{
|
||||
struct percpucounter *ppc;
|
||||
@@ -79,8 +82,12 @@ static struct percpucounter *allocpercpucounter(unsigned int cpunum)
|
||||
if (ppc) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_COUNTER; ++i)
|
||||
for (i = 0; i < ALL_COUNTER; ++i)
|
||||
ppc->ctr_fds[i] = -1;
|
||||
for (i = 0; i < NUM_PAI_USER; ++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;
|
||||
}
|
||||
@@ -91,8 +98,12 @@ static void freepercpucounter(struct percpucounter *pcpu)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_COUNTER; ++i)
|
||||
for (i = 0; i < ALL_COUNTER; ++i)
|
||||
(void)close(pcpu->ctr_fds[i]);
|
||||
for (i = 0; i < NUM_PAI_USER; ++i)
|
||||
(void)close(pcpu->pai_user[i]);
|
||||
for (i = 0; i < NUM_PAI_KERNEL; ++i)
|
||||
(void)close(pcpu->pai_kernel[i]);
|
||||
free(pcpu);
|
||||
}
|
||||
|
||||
@@ -139,6 +150,39 @@ static int perf_counter_supported(const char *pmu, const char *counter)
|
||||
return !access(buf, R_OK);
|
||||
}
|
||||
|
||||
static int cpumf_authorized(void)
|
||||
{
|
||||
unsigned vermin, vermax, auth;
|
||||
int res = 0, found = 0;
|
||||
size_t linesize = 0;
|
||||
char *line = NULL;
|
||||
FILE *f;
|
||||
|
||||
f = fopen("/proc/service_levels", "r");
|
||||
if (f == NULL) {
|
||||
eprint("Failed to open /proc/service_levels (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
while (getline(&line, &linesize, f) >= 0) {
|
||||
if (sscanf(line,
|
||||
"CPU-MF: Counter facility: version=%d.%d authorization=%x",
|
||||
&vermin, &vermax, &auth) == 3) {
|
||||
if (auth & 0x8)
|
||||
res = 1;
|
||||
else
|
||||
eprint("CPU-MF counters not authorized.\n");
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
eprint("CPU-MF counters not available.\n");
|
||||
free(line);
|
||||
fclose(f);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int perf_event_encode(int *pmutype, int *eventid,
|
||||
const char *pmu, const char *event)
|
||||
{
|
||||
@@ -196,7 +240,8 @@ static int activatecpu(unsigned int cpu)
|
||||
freepercpucounter(ppc);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < NUM_COUNTER; ++i) {
|
||||
/* activate CPU-MF */
|
||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||
if (ctr_state[i] == UNSUPPORTED)
|
||||
continue;
|
||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||
@@ -223,6 +268,67 @@ static int activatecpu(unsigned int cpu)
|
||||
ppc->ctr_fds[i] = fd;
|
||||
}
|
||||
}
|
||||
/* activate pai_user and pai_kernel */
|
||||
/* invariant:
|
||||
(ctr_state[PAI_USER] == UNSUPPORTED) ==
|
||||
(ctr_state[PAI_KERNEL] == UNSUPPORTED) */
|
||||
if (ctr_state[PAI_USER] != UNSUPPORTED) {
|
||||
for (i = 1; i <= NUM_PAI_USER; ++i) {
|
||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||
pfm_event.size = sizeof(pfm_event);
|
||||
pfm_event.type = paipmutype;
|
||||
pfm_event.config = paipmueventstart + i;
|
||||
pfm_event.exclude_kernel = 1;
|
||||
pfm_event.exclude_user = 0;
|
||||
pfm_event.disabled = ctr_state[PAI_USER] == DISABLED;
|
||||
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
|
||||
if (fd < 0) {
|
||||
eprint("Perf_event_open() failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
ctr_state[PAI_USER] = UNSUPPORTED;
|
||||
ctr_state[PAI_KERNEL] = UNSUPPORTED;
|
||||
goto outevents;
|
||||
} else {
|
||||
ppc->pai_user[i - 1] = fd;
|
||||
}
|
||||
pfm_event.exclude_kernel = 0;
|
||||
pfm_event.exclude_user = 1;
|
||||
pfm_event.disabled = ctr_state[PAI_KERNEL] == DISABLED;
|
||||
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
|
||||
if (fd < 0) {
|
||||
eprint("Perf_event_open() failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
ctr_state[PAI_USER] = UNSUPPORTED;
|
||||
ctr_state[PAI_KERNEL] = UNSUPPORTED;
|
||||
goto outevents;
|
||||
} else {
|
||||
ppc->pai_kernel[i - 1] = fd;
|
||||
}
|
||||
}
|
||||
for (; i <= NUM_PAI_KERNEL; ++i) {
|
||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||
pfm_event.size = sizeof(pfm_event);
|
||||
pfm_event.type = paipmutype;
|
||||
pfm_event.config = paipmueventstart + i;
|
||||
pfm_event.exclude_kernel = 0;
|
||||
pfm_event.exclude_user = 1;
|
||||
pfm_event.disabled = ctr_state[PAI_KERNEL] == DISABLED;
|
||||
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
|
||||
if (fd < 0) {
|
||||
eprint("Perf_event_open() failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
ctr_state[PAI_USER] = UNSUPPORTED;
|
||||
ctr_state[PAI_KERNEL] = UNSUPPORTED;
|
||||
goto outevents;
|
||||
} else {
|
||||
ppc->pai_kernel[i - 1] = fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
outevents:
|
||||
ppc->next = root;
|
||||
root = ppc;
|
||||
if (enabledcounter)
|
||||
@@ -240,8 +346,12 @@ static void deactivatecpu(unsigned int cpunum)
|
||||
return;
|
||||
pcpu = findcpu(cpunum, 1);
|
||||
if (pcpu != NULL) {
|
||||
for (i = 0; i < NUM_COUNTER; ++i)
|
||||
for (i = 0; i < ALL_COUNTER; ++i)
|
||||
(void)close(pcpu->ctr_fds[i]);
|
||||
for (i = 0; i < NUM_PAI_USER; ++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;
|
||||
@@ -286,13 +396,16 @@ static int perf_load_counter_data(void)
|
||||
{
|
||||
int i, res = 0;
|
||||
|
||||
for (i = 0; i < NUM_COUNTER; ++i) {
|
||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||
if (ctr_state[i] != UNSUPPORTED)
|
||||
res |= perf_event_encode(&pmf_counter_data[i].pmutype,
|
||||
&pmf_counter_data[i].eventid,
|
||||
pmf_counter_name[i].pmu,
|
||||
pmf_counter_name[i].pfm_name);
|
||||
}
|
||||
if (ctr_state[PAI_USER] != UNSUPPORTED)
|
||||
res |= perf_event_encode(&paipmutype, &paipmueventstart,
|
||||
"pai_crypto", "CRYPTO_ALL");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -351,7 +464,10 @@ static void *hotplughandler(void *UNUSED(unused))
|
||||
|
||||
int perf_init(void)
|
||||
{
|
||||
int ecc_supported;
|
||||
int ecc_supported, i, num;
|
||||
unsigned long maxfd;
|
||||
struct rlimit rlim;
|
||||
FILE *f;
|
||||
|
||||
/* initialize performance monitoring library */
|
||||
if (!perf_supported()) {
|
||||
@@ -359,13 +475,56 @@ int perf_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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 (!ecc_supported)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!perf_counter_supported("pai_crypto", "CRYPTO_ALL")) {
|
||||
ctr_state[PAI_USER] = UNSUPPORTED;
|
||||
ctr_state[PAI_KERNEL] = UNSUPPORTED;
|
||||
num -= 2;
|
||||
}
|
||||
|
||||
if (num == 0) {
|
||||
eprint("No crypto counters supported!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (perf_load_counter_data())
|
||||
return -1;
|
||||
/* We have to adjust the number of FDs possible since we might
|
||||
* need more than 1024 (the typical soft limit) */
|
||||
f = fopen("/proc/sys/fs/nr_open", "r");
|
||||
if (f == NULL) {
|
||||
eprint("fopen failed for /proc/sys/fs/nr_open with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (fscanf(f, "%lu", &maxfd) != 1) {
|
||||
fclose(f);
|
||||
eprint("Failed to parse /proc/sys/fs/nr_open\n");
|
||||
return -1;
|
||||
}
|
||||
fclose(f);
|
||||
rlim.rlim_cur = maxfd;
|
||||
rlim.rlim_max = maxfd;
|
||||
if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
|
||||
eprint("setrlimit failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pthread_create(&hotplugthread, NULL, hotplughandler, NULL)) {
|
||||
eprint("Failed to start hotplug handler thread\n");
|
||||
return -1;
|
||||
@@ -395,6 +554,22 @@ void perf_close(void)
|
||||
}
|
||||
|
||||
|
||||
static int enable_array(int *arr, int size)
|
||||
{
|
||||
int i, ec, rc = 0;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
ec = ioctl(arr[i], PERF_EVENT_IOC_ENABLE, 0);
|
||||
if (ec < 0) {
|
||||
eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int perf_enable_ctr(enum ctr_e ctr)
|
||||
{
|
||||
struct percpucounter *pcpu;
|
||||
@@ -418,6 +593,24 @@ int perf_enable_ctr(enum ctr_e ctr)
|
||||
ctr_state[ctr] = ENABLED;
|
||||
++enabledcounter;
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_USER) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = enable_array(pcpu->pai_user, NUM_PAI_USER);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
ctr_state[ctr] = ENABLED;
|
||||
++enabledcounter;
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_KERNEL) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = enable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
ctr_state[ctr] = ENABLED;
|
||||
++enabledcounter;
|
||||
endforeachcpu();
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
@@ -426,6 +619,22 @@ int perf_enable_ctr(enum ctr_e ctr)
|
||||
}
|
||||
|
||||
|
||||
static int disable_array(int *arr, int size)
|
||||
{
|
||||
int i, ec, rc = 0;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
ec = ioctl(arr[i], PERF_EVENT_IOC_DISABLE, 0);
|
||||
if (ec < 0) {
|
||||
eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int perf_disable_ctr(enum ctr_e ctr)
|
||||
{
|
||||
struct percpucounter *pcpu;
|
||||
@@ -451,6 +660,28 @@ int perf_disable_ctr(enum ctr_e ctr)
|
||||
if (enabledcounter == 0)
|
||||
hotplugdetected = 0;
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_USER) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = disable_array(pcpu->pai_user, NUM_PAI_USER);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
ctr_state[ctr] = DISABLED;
|
||||
--enabledcounter;
|
||||
if (enabledcounter == 0)
|
||||
hotplugdetected = 0;
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_KERNEL) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = disable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
ctr_state[ctr] = DISABLED;
|
||||
--enabledcounter;
|
||||
if (enabledcounter == 0)
|
||||
hotplugdetected = 0;
|
||||
endforeachcpu();
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
@@ -459,14 +690,30 @@ int perf_disable_ctr(enum ctr_e ctr)
|
||||
}
|
||||
|
||||
|
||||
int perf_reset_ctr(enum ctr_e ctr)
|
||||
static int reset_array(int *arr, int size)
|
||||
{
|
||||
int ec, rc = 0, i;
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
ec = ioctl(arr[i], PERF_EVENT_IOC_RESET, 0);
|
||||
if (ec < 0) {
|
||||
eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value)
|
||||
{
|
||||
struct percpucounter *pcpu;
|
||||
int ec, rc = 0;
|
||||
|
||||
if (ctr == ALL_COUNTER) {
|
||||
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
||||
rc = perf_reset_ctr(ctr);
|
||||
rc = perf_reset_ctr(ctr, value);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
}
|
||||
@@ -480,10 +727,25 @@ int perf_reset_ctr(enum ctr_e ctr)
|
||||
}
|
||||
}
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_USER) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = reset_array(pcpu->pai_user, NUM_PAI_USER);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
endforeachcpu();
|
||||
} else if (ctr == PAI_KERNEL) {
|
||||
foreachcpu(pcpu) {
|
||||
ec = reset_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
||||
if (ec < 0)
|
||||
rc = -1;
|
||||
}
|
||||
endforeachcpu();
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
if (rc == 0)
|
||||
rc = perf_read_ctr(ctr, value);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -491,7 +753,7 @@ int perf_reset_ctr(enum ctr_e ctr)
|
||||
int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
||||
{
|
||||
struct percpucounter *pcpu;
|
||||
int ec, rc = -1;
|
||||
int ec, rc = 0;
|
||||
uint64_t val;
|
||||
|
||||
if (!value)
|
||||
@@ -500,6 +762,14 @@ int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
||||
*value = hotplugdetected;
|
||||
return 0;
|
||||
}
|
||||
if (ctr == PAI_USER) {
|
||||
*value = NUM_PAI_USER;
|
||||
return 0;
|
||||
}
|
||||
if (ctr == PAI_KERNEL) {
|
||||
*value = NUM_PAI_KERNEL;
|
||||
return 0;
|
||||
}
|
||||
if (ctr >= ALL_COUNTER)
|
||||
return -1;
|
||||
*value = 0;
|
||||
@@ -509,9 +779,9 @@ int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
||||
if (ec != sizeof(val)) {
|
||||
eprint("Read() on perf file descriptor failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
} else {
|
||||
*value += val;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
endforeachcpu();
|
||||
@@ -525,7 +795,34 @@ int perf_ecc_supported(void)
|
||||
}
|
||||
|
||||
int perf_ctr_state(enum ctr_e ctr) {
|
||||
if (ctr < ALL_COUNTER)
|
||||
if (ctr < NUM_COUNTER)
|
||||
return ctr_state[ctr];
|
||||
return UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
return -1;
|
||||
foreachcpu(pcpu) {
|
||||
arr = user ? pcpu->pai_user : pcpu->pai_kernel;
|
||||
ec = read(arr[ctrnum], &val, sizeof(val));
|
||||
if (ec != sizeof(val)) {
|
||||
eprint("Read() on perf file descriptor failed with errno=%d [%s]\n",
|
||||
errno, strerror(errno));
|
||||
rc = -1;
|
||||
} else {
|
||||
*value += val;
|
||||
}
|
||||
}
|
||||
endforeachcpu();
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user