mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a528bb41e0 | |||
| ed52031821 | |||
| 60f33fb2de | |||
| 5737a57920 | |||
| b044aec4ff | |||
| e584c88d8f | |||
| fd817280d3 | |||
| 046d27a05b | |||
| fd174cb952 | |||
| 70f1dcd770 | |||
| fcd5d64a45 | |||
| 320e11dcf9 | |||
| 34cfca722c | |||
| 2215ba672e | |||
| 1003d81412 | |||
| 943c5dc51d | |||
| c367a6bb65 | |||
| 0db89894b5 | |||
| 2f87cba1c7 | |||
| c31eba5e00 | |||
| 04b0b43739 | |||
| 798967aba3 | |||
| f2f4dc209c | |||
| d7b816ff58 | |||
| ae66f79512 | |||
| 3217e0438f | |||
| 41fae58ecd | |||
| 6dab7637fb | |||
| 53b949926f | |||
| e08e07baa9 | |||
| e679a4002e | |||
| 20b05e1f82 | |||
| ce02dd7167 | |||
| d2fc700b73 | |||
| 199b030580 | |||
| 71b36d17f0 | |||
| ca8750e820 | |||
| 0472b5ea5c | |||
| 94a3272dac | |||
| d72cf322c0 |
+2
-3
@@ -11,9 +11,8 @@
|
|||||||
cmsfs-fuse/cmsfs-fuse
|
cmsfs-fuse/cmsfs-fuse
|
||||||
cpacfstats/cpacfstats
|
cpacfstats/cpacfstats
|
||||||
cpacfstats/cpacfstatsd
|
cpacfstats/cpacfstatsd
|
||||||
cpumf/bin/chcpumf
|
cpumf/chcpumf
|
||||||
cpumf/bin/cpumf_helper
|
cpumf/lscpumf
|
||||||
cpumf/bin/lscpumf
|
|
||||||
cpuplugd/cpuplugd
|
cpuplugd/cpuplugd
|
||||||
dasdfmt/dasdfmt
|
dasdfmt/dasdfmt
|
||||||
dasdinfo/dasdinfo
|
dasdinfo/dasdinfo
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
List of all individuals having contributed content to s390-tools
|
List of all individuals having contributed content to s390-tools
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
- Alexander Egorenkov
|
||||||
- Alexey Ishchuk
|
- Alexey Ishchuk
|
||||||
- Andreas Herrmann
|
- Andreas Herrmann
|
||||||
- Andre Wild
|
- Andre Wild
|
||||||
@@ -32,6 +33,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Fritz Elfert
|
- Fritz Elfert
|
||||||
- Gerald Schaefer
|
- Gerald Schaefer
|
||||||
- Gerhard Tonn
|
- Gerhard Tonn
|
||||||
|
- Guevenc Guelce
|
||||||
- Hannes Reinecke
|
- Hannes Reinecke
|
||||||
- Hans-Joachim Picht
|
- Hans-Joachim Picht
|
||||||
- Hans Wippel
|
- Hans Wippel
|
||||||
@@ -52,6 +54,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Jean-Baptiste Joret
|
- Jean-Baptiste Joret
|
||||||
- Jens Remus
|
- Jens Remus
|
||||||
- Jochen Roehrig
|
- Jochen Roehrig
|
||||||
|
- Juergen Christ
|
||||||
- Julian Wiedmann
|
- Julian Wiedmann
|
||||||
- Karsten Graul
|
- Karsten Graul
|
||||||
- Kittipon Meesompop
|
- Kittipon Meesompop
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
* __v2.14.0 (2020-08-21)__
|
||||||
|
|
||||||
|
For Linux kernel version: 5.7 / 5.8
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- cpacfstats: Add ECC counters
|
||||||
|
- dbginfo: Added collection of /proc/softirqs
|
||||||
|
- ipl-tools: Add nvme device support to lsreipl/chreipl
|
||||||
|
- zdsfs: Add coordinated read access
|
||||||
|
- libzds: Add curl interface to access zosmf rest api
|
||||||
|
- util_opt: Change util_opt_init() to honor current command, if set
|
||||||
|
Bug Fixes:
|
||||||
|
- lsluns: Try harder to find udevadm
|
||||||
|
- mon_tools: Update udevadm location
|
||||||
|
- zipl: Fix NVMe partition and base device detection
|
||||||
|
- zipl/stage3: Correctly handle diag308 response code
|
||||||
|
- znetconf: Introduce better ways to locate udevadm
|
||||||
|
|
||||||
* __v2.13.0 (2020-05-06)__
|
* __v2.13.0 (2020-05-06)__
|
||||||
|
|
||||||
For Linux kernel version: 5.5 / 5.6
|
For Linux kernel version: 5.5 / 5.6
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
|
|||||||
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
|
||||||
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
|
||||||
VERSION = 2
|
VERSION = 2
|
||||||
RELEASE = 13
|
RELEASE = 14
|
||||||
PATCHLEVEL = 0
|
PATCHLEVEL = 0
|
||||||
DISTRELEASE = build-$(shell date +%Y%m%d)
|
DISTRELEASE = build-$(shell date +%Y%m%d)
|
||||||
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||||
|
|||||||
+2
-21
@@ -2,28 +2,10 @@ include ../common.mak
|
|||||||
|
|
||||||
ALL_CPPFLAGS += -DVERSION=$(VERSION)
|
ALL_CPPFLAGS += -DVERSION=$(VERSION)
|
||||||
|
|
||||||
|
all: cpacfstats cpacfstatsd
|
||||||
ifeq (${HAVE_PFM},0)
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(SKIP) HAVE_PFM=0
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(SKIP) HAVE_PFM=0
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
check_dep:
|
|
||||||
$(call check_dep, \
|
|
||||||
"cpacfstats", \
|
|
||||||
"perfmon/pfmlib.h", \
|
|
||||||
"libpfm-devel or libpfm4-dev", \
|
|
||||||
"HAVE_PFM=0")
|
|
||||||
|
|
||||||
all: check_dep cpacfstats cpacfstatsd
|
|
||||||
|
|
||||||
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o
|
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -lpfm -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
cpacfstats: cpacfstats.o stats_sock.o
|
cpacfstats: cpacfstats.o stats_sock.o
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
@@ -34,7 +16,6 @@ install: all
|
|||||||
$(INSTALL) -m 644 cpacfstatsd.8 $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -m 644 cpacfstatsd.8 $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -m 644 cpacfstats.1 $(DESTDIR)$(MANDIR)/man1
|
$(INSTALL) -m 644 cpacfstats.1 $(DESTDIR)$(MANDIR)/man1
|
||||||
|
|
||||||
endif
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ cpacfstatsd cpacfstats
|
rm -f *.o *~ cpacfstatsd cpacfstats
|
||||||
|
|
||||||
|
|||||||
+26
-19
@@ -1,6 +1,6 @@
|
|||||||
.\" cpacfstats.1
|
.\" cpacfstats.1
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright IBM Corp. 2015, 2017
|
.\" Copyright IBM Corp. 2015, 2020
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\"
|
.\"
|
||||||
@@ -80,31 +80,33 @@ Display help information for the command.
|
|||||||
Display version and copyright information for the command.
|
Display version and copyright information for the command.
|
||||||
.TP
|
.TP
|
||||||
\fB\-e\fR or \fB\-\-enable\fR [counter]
|
\fB\-e\fR or \fB\-\-enable\fR [counter]
|
||||||
Enable one or all CPACF performance counters. The optional counter argument
|
Enable one or all CPACF performance counters. The optional counter
|
||||||
can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR or \fBall\fR. If
|
argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR,
|
||||||
the counter argument is omitted, all performance counters are
|
\fBecc\fR, or \fBall\fR. If the counter argument is omitted, all
|
||||||
enabled. Enabling a counter does not reset it. New events are added to the
|
performance counters are enabled. Enabling a counter does not reset
|
||||||
current counter value.
|
it. New events are added to the current counter value.
|
||||||
.TP
|
.TP
|
||||||
\fB\-d\fR or \fB\-\-disable\fR [counter]
|
\fB\-d\fR or \fB\-\-disable\fR [counter]
|
||||||
Disable one or all CPACF performance counters. The optional counter
|
Disable one or all CPACF performance counters. The optional counter
|
||||||
argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR or
|
argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR,
|
||||||
\fBall\fR. If the counter argument is omitted, all performance counters
|
\fBecc\fR, or \fBall\fR. If the counter argument is omitted, all
|
||||||
are disabled. Disabling a counter does not reset it. The counter value is
|
performance counters are disabled. Disabling a counter does not reset
|
||||||
preserved when a counter is disabled, and counting will resume using the
|
it. The counter value is preserved when a counter is disabled, and
|
||||||
preserved value when the counter is re-enabled.
|
counting will resume using the preserved value when the counter is
|
||||||
|
re-enabled.
|
||||||
.TP
|
.TP
|
||||||
\fB\-r\fR or \fB\-\-reset\fR [counter]
|
\fB\-r\fR or \fB\-\-reset\fR [counter]
|
||||||
Reset one or all CPACF performance counters. The optional counter
|
Reset one or all CPACF performance counters. The optional counter
|
||||||
argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR or
|
argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR,
|
||||||
\fBall\fR. If the counter argument is omitted, all performance counters are
|
\fBecc\fR, or \fBall\fR. If the counter argument is omitted, all
|
||||||
reset to 0.
|
performance counters are reset to 0.
|
||||||
.TP
|
.TP
|
||||||
\fB\-p\fR or \fB\-\-print\fR [counter]
|
\fB\-p\fR or \fB\-\-print\fR [counter]
|
||||||
Display the value of one or all CPACF performance counters. The optional
|
Display the value of one or all CPACF performance counters. The
|
||||||
counter argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR
|
optional counter argument can be one of: \fBdes\fR, \fBaes\fR,
|
||||||
or \fBall\fR. If the counter argument is omitted or if there is no
|
\fBsha\fR, \fBprng\fR, \fBecc\fR, or \fBall\fR. If the counter
|
||||||
argument, all performance counters are displayed.
|
argument is omitted or if there is no argument, all performance
|
||||||
|
counters are displayed.
|
||||||
.TP
|
.TP
|
||||||
The default command is --print all.
|
The default command is --print all.
|
||||||
.
|
.
|
||||||
@@ -123,5 +125,10 @@ version mismatch between client and daemon, or the application is out of
|
|||||||
memory. The application prints a message with the details of the error and
|
memory. The application prints a message with the details of the error and
|
||||||
the errno value.
|
the errno value.
|
||||||
.
|
.
|
||||||
|
.SH NOTES
|
||||||
|
ECC counters are only available since z15. cpacfstats will show the
|
||||||
|
counters as \fIunsupported\fR if the hardware does not support ECC
|
||||||
|
counters.
|
||||||
|
.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
cpacfstatsd (8)
|
.BR cpacfstatsd (8)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* cpacfstats client implementation
|
* cpacfstats client implementation
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2015, 2017
|
* Copyright IBM Corp. 2015, 2020
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -39,13 +39,14 @@ static const char *const usage =
|
|||||||
"\t-d, --disable [counter] Disable one or all counters\n"
|
"\t-d, --disable [counter] Disable one or all counters\n"
|
||||||
"\t-r, --reset [counter] Reset one or all counter values\n"
|
"\t-r, --reset [counter] Reset one or all counter values\n"
|
||||||
"\t-p, --print [counter] Print one or all counter values\n"
|
"\t-p, --print [counter] Print one or all counter values\n"
|
||||||
"\tcounter can be: 'aes' 'des' 'rng' 'sha' or 'all'\n";
|
"\tcounter can be: 'aes' 'des' 'rng' 'sha' 'ecc' or 'all'\n";
|
||||||
|
|
||||||
static const char *const counter_str[] = {
|
static const char *const counter_str[] = {
|
||||||
[DES_FUNCTIONS] = "des",
|
[DES_FUNCTIONS] = "des",
|
||||||
[AES_FUNCTIONS] = "aes",
|
[AES_FUNCTIONS] = "aes",
|
||||||
[SHA_FUNCTIONS] = "sha",
|
[SHA_FUNCTIONS] = "sha",
|
||||||
[PRNG_FUNCTIONS] = "rng",
|
[PRNG_FUNCTIONS] = "rng",
|
||||||
|
[ECC_FUNCTIONS] = "ecc",
|
||||||
[ALL_COUNTER] = "all"
|
[ALL_COUNTER] = "all"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,6 +99,8 @@ static void print_answer(int ctr, int state, uint64_t value)
|
|||||||
counter_str[ctr], state);
|
counter_str[ctr], state);
|
||||||
else if (state == DISABLED)
|
else if (state == DISABLED)
|
||||||
printf(" %s counter: disabled\n", counter_str[ctr]);
|
printf(" %s counter: disabled\n", counter_str[ctr]);
|
||||||
|
else if (state == UNSUPPORTED)
|
||||||
|
printf(" %s counter: unsupported\n", counter_str[ctr]);
|
||||||
else
|
else
|
||||||
printf(" %s counter: %"PRIu64"\n", counter_str[ctr], value);
|
printf(" %s counter: %"PRIu64"\n", counter_str[ctr], value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* common function prototypes and definitions
|
* common function prototypes and definitions
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2015, 2017
|
* Copyright IBM Corp. 2015, 2020
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define COPYRIGHT "Copyright IBM Corp. 2015, 2017"
|
#define COPYRIGHT "Copyright IBM Corp. 2015, 2020"
|
||||||
|
|
||||||
int eprint(const char *format, ...);
|
int eprint(const char *format, ...);
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ enum ctr_e {
|
|||||||
AES_FUNCTIONS,
|
AES_FUNCTIONS,
|
||||||
SHA_FUNCTIONS,
|
SHA_FUNCTIONS,
|
||||||
PRNG_FUNCTIONS,
|
PRNG_FUNCTIONS,
|
||||||
|
ECC_FUNCTIONS,
|
||||||
ALL_COUNTER
|
ALL_COUNTER
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ enum cmd_e {
|
|||||||
|
|
||||||
enum state_e {
|
enum state_e {
|
||||||
DISABLED = 0,
|
DISABLED = 0,
|
||||||
ENABLED
|
ENABLED,
|
||||||
|
UNSUPPORTED
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -108,5 +110,6 @@ int perf_enable_ctr(enum ctr_e ctr);
|
|||||||
int perf_disable_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);
|
||||||
int perf_read_ctr(enum ctr_e ctr, uint64_t *value);
|
int perf_read_ctr(enum ctr_e ctr, uint64_t *value);
|
||||||
|
int perf_ecc_supported(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" cpacfstatsd.8
|
.\" cpacfstatsd.8
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright IBM Corp. 2015, 2017
|
.\" Copyright IBM Corp. 2015, 2020
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\"
|
.\"
|
||||||
@@ -37,7 +37,10 @@ config option enabled.
|
|||||||
.P
|
.P
|
||||||
- Libpfm version 4 or higher is needed to successfully run the daemon.
|
- Libpfm version 4 or higher is needed to successfully run the daemon.
|
||||||
.P
|
.P
|
||||||
- Your LPAR must be configured to enable the "Counter Facility Security Options".
|
- On the HMC or SE, authorize the LPAR for each counter set you want
|
||||||
|
to use. Customize the LPAR activation profile and modify the Counter
|
||||||
|
Facility Security Options. You need to activate the "Crypto activity
|
||||||
|
counter set authorization control" checkbox.
|
||||||
.P
|
.P
|
||||||
- The daemon requires root privileges to interact with the performance
|
- The daemon requires root privileges to interact with the performance
|
||||||
ioctls of the kernel.
|
ioctls of the kernel.
|
||||||
@@ -47,7 +50,7 @@ restart the daemon to ensure correct summing of the per-CPU performance
|
|||||||
counters.
|
counters.
|
||||||
|
|
||||||
The starting daemon first checks for any stale pid file
|
The starting daemon first checks for any stale pid file
|
||||||
/run/cpacfstatsd.pid. If this file exists, and the process ID in the
|
\%/run/cpacfstatsd.pid. If this file exists, and the process ID in the
|
||||||
file belongs to an active process, an error message is printed to the
|
file belongs to an active process, an error message is printed to the
|
||||||
console and the program terminates.
|
console and the program terminates.
|
||||||
|
|
||||||
@@ -94,4 +97,4 @@ done in the re-spawned process. Check the syslog for success or failure.
|
|||||||
The daemon could not be set to run in the background.
|
The daemon could not be set to run in the background.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
cpacfstats (1)
|
.BR cpacfstats (1)
|
||||||
|
|||||||
+20
-13
@@ -94,20 +94,24 @@ static int do_enable(int s, enum ctr_e ctr)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; i++) {
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
if (!ctr_state[i]) {
|
if (ctr_state[i] == DISABLED) {
|
||||||
rc = perf_enable_ctr(i);
|
rc = perf_enable_ctr(i);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ctr_state[i] = 1;
|
ctr_state[i] = ENABLED;
|
||||||
}
|
}
|
||||||
rc = perf_read_ctr(i, &value);
|
if (ctr_state[i] == UNSUPPORTED) {
|
||||||
if (rc != 0) {
|
send_answer(s, i, UNSUPPORTED, 0);
|
||||||
send_answer(s, i, rc, 0);
|
} else {
|
||||||
break;
|
rc = perf_read_ctr(i, &value);
|
||||||
|
if (rc != 0) {
|
||||||
|
send_answer(s, i, rc, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
send_answer(s, i, ENABLED, value);
|
||||||
}
|
}
|
||||||
send_answer(s, i, ENABLED, value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +125,7 @@ static int do_disable(int s, enum ctr_e ctr)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; i++) {
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
if (ctr_state[i]) {
|
if (ctr_state[i] == ENABLED) {
|
||||||
rc = perf_disable_ctr(i);
|
rc = perf_disable_ctr(i);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
@@ -129,7 +133,7 @@ static int do_disable(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
ctr_state[i] = 0;
|
ctr_state[i] = 0;
|
||||||
}
|
}
|
||||||
send_answer(s, i, DISABLED, 0);
|
send_answer(s, i, ctr_state[i], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +147,7 @@ static int do_reset(int s, enum ctr_e ctr)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; i++) {
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
if (ctr_state[i]) {
|
if (ctr_state[i] == ENABLED) {
|
||||||
rc = perf_reset_ctr(i);
|
rc = perf_reset_ctr(i);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
@@ -151,7 +155,7 @@ static int do_reset(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
send_answer(s, i, ENABLED, 0);
|
send_answer(s, i, ENABLED, 0);
|
||||||
} else {
|
} else {
|
||||||
send_answer(s, i, DISABLED, 0);
|
send_answer(s, i, ctr_state[i], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,7 +170,7 @@ static int do_print(int s, enum ctr_e ctr)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; i++) {
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
if (ctr_state[i]) {
|
if (ctr_state[i] == ENABLED) {
|
||||||
rc = perf_read_ctr(i, &value);
|
rc = perf_read_ctr(i, &value);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
@@ -174,7 +178,7 @@ static int do_print(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
send_answer(s, i, ENABLED, value);
|
send_answer(s, i, ENABLED, value);
|
||||||
} else {
|
} else {
|
||||||
send_answer(s, i, DISABLED, 0);
|
send_answer(s, i, ctr_state[i], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,6 +416,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
atexit(perf_close);
|
atexit(perf_close);
|
||||||
|
|
||||||
|
if (!perf_ecc_supported())
|
||||||
|
ctr_state[ECC_FUNCTIONS] = UNSUPPORTED;
|
||||||
|
|
||||||
sfd = open_socket(SERVER);
|
sfd = open_socket(SERVER);
|
||||||
if (sfd < 0) {
|
if (sfd < 0) {
|
||||||
eprint("Couldn't initialize server socket\n");
|
eprint("Couldn't initialize server socket\n");
|
||||||
|
|||||||
+116
-38
@@ -3,36 +3,39 @@
|
|||||||
*
|
*
|
||||||
* low level perf functions
|
* low level perf functions
|
||||||
*
|
*
|
||||||
* Copyright IBM Corp. 2015, 2017
|
* Copyright IBM Corp. 2015, 2020
|
||||||
*
|
*
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <asm/unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#define __STDC_FORMAT_MACROS
|
#define __STDC_FORMAT_MACROS
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <perfmon/perf_event.h>
|
#include <limits.h>
|
||||||
#include <perfmon/pfmlib.h>
|
#include <linux/perf_event.h>
|
||||||
#include <perfmon/pfmlib_perf_event.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cpacfstats.h"
|
#include "cpacfstats.h"
|
||||||
|
|
||||||
/* correlation between counter and perf counter string */
|
/* correlation between counter and perf counter string */
|
||||||
static const struct {
|
static const struct {
|
||||||
char pfm_name[80];
|
char pmu[20];
|
||||||
|
char pfm_name[60];
|
||||||
enum ctr_e ctr;
|
enum ctr_e ctr;
|
||||||
} pmf_counter_name[ALL_COUNTER] = {
|
} pmf_counter_name[ALL_COUNTER] = {
|
||||||
{"cpum_cf::DEA_FUNCTIONS", DES_FUNCTIONS},
|
{"cpum_cf", "DEA_FUNCTIONS", DES_FUNCTIONS},
|
||||||
{"cpum_cf::AES_FUNCTIONS", AES_FUNCTIONS},
|
{"cpum_cf", "AES_FUNCTIONS", AES_FUNCTIONS},
|
||||||
{"cpum_cf::SHA_FUNCTIONS", SHA_FUNCTIONS},
|
{"cpum_cf", "SHA_FUNCTIONS", SHA_FUNCTIONS},
|
||||||
{"cpum_cf::PRNG_FUNCTIONS", PRNG_FUNCTIONS}
|
{"cpum_cf", "PRNG_FUNCTIONS", PRNG_FUNCTIONS},
|
||||||
|
{"cpum_cf", "ECC_FUNCTION_COUNT", ECC_FUNCTIONS}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -53,27 +56,106 @@ static const struct {
|
|||||||
*/
|
*/
|
||||||
static int *ctr_fds[ALL_COUNTER];
|
static int *ctr_fds[ALL_COUNTER];
|
||||||
|
|
||||||
|
static int ecc_supported;
|
||||||
|
|
||||||
|
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
|
||||||
|
int cpu, int group_fd, unsigned long flags)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
|
||||||
|
group_fd, flags);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perf_supported(void)
|
||||||
|
{
|
||||||
|
return !access("/proc/sys/kernel/perf_event_paranoid", R_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perf_counter_supported(const char *pmu, const char *counter)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
|
||||||
|
if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/events/%s",
|
||||||
|
pmu, counter) >= PATH_MAX) {
|
||||||
|
eprint("overflow in path name");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return !access(buf, R_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perf_event_encode(struct perf_event_attr *attr,
|
||||||
|
const char *pmu, const char *event)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int eventid;
|
||||||
|
int pmutype;
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
|
||||||
|
if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/events/%s",
|
||||||
|
pmu, event) >= PATH_MAX) {
|
||||||
|
eprint("overflow in path name");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
f = fopen(buf, "r");
|
||||||
|
if (!f) {
|
||||||
|
eprint("Event %s for pmu %s not found (%d:%s)\n", event, pmu,
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fscanf(f, "event=0x%x\n", &eventid) != 1) {
|
||||||
|
fclose(f);
|
||||||
|
eprint("Event file %s has invalid format\n", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/type",
|
||||||
|
pmu) >= PATH_MAX) {
|
||||||
|
eprint("overflow in path name");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
f = fopen(buf, "r");
|
||||||
|
if (!f) {
|
||||||
|
eprint("Event %s for pmu %s not found (%d:%s)\n", event, pmu,
|
||||||
|
errno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fscanf(f, "%d\n", &pmutype) != 1) {
|
||||||
|
fclose(f);
|
||||||
|
eprint("Type file %s has invalid format\n", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
attr->type = pmutype;
|
||||||
|
attr->config = eventid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int perf_init(void)
|
int perf_init(void)
|
||||||
{
|
{
|
||||||
int i, cpus, ctr, cpu, ec, *fds;
|
int i, cpus, ctr, cpu, *fds;
|
||||||
|
|
||||||
memset(ctr_fds, 0, sizeof(ctr_fds));
|
memset(ctr_fds, 0, sizeof(ctr_fds));
|
||||||
|
|
||||||
/* initialize performance monitoring library */
|
/* initialize performance monitoring library */
|
||||||
ec = pfm_initialize();
|
if (!perf_supported()) {
|
||||||
if (ec != PFM_SUCCESS) {
|
eprint("Performance counter not supported");
|
||||||
eprint("Pfm_initialize() returned with failure (%d:%s)\n",
|
|
||||||
ec, pfm_strerror(ec));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if ECC is supported on current hardware */
|
||||||
|
ecc_supported = perf_counter_supported("cpum_cf", "ECC_FUNCTION_COUNT");
|
||||||
|
|
||||||
/* get number of logical processors */
|
/* get number of logical processors */
|
||||||
cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
|
||||||
/* for each counter */
|
/* for each counter */
|
||||||
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
||||||
|
|
||||||
|
/* Skip ECC counters completely if unsupported */
|
||||||
|
if (ctr == ECC_FUNCTIONS && !ecc_supported)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate an array of ints to store for each CPU
|
* allocate an array of ints to store for each CPU
|
||||||
* one filedescriptor + a terminating 0
|
* one filedescriptor + a terminating 0
|
||||||
@@ -88,37 +170,28 @@ int perf_init(void)
|
|||||||
|
|
||||||
ctr_fds[ctr] = fds;
|
ctr_fds[ctr] = fds;
|
||||||
|
|
||||||
|
/* search for the counter's corresponding pfm name */
|
||||||
|
for (i = ALL_COUNTER-1; i >= 0; i--)
|
||||||
|
if ((int) pmf_counter_name[i].ctr == ctr)
|
||||||
|
break;
|
||||||
|
if (i < 0) {
|
||||||
|
eprint("Pfm ctr name not found for counter %d, please adjust pmf_counter_name[] in %s\n",
|
||||||
|
ctr, __FILE__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (cpu = 0; cpu < cpus; cpu++) {
|
for (cpu = 0; cpu < cpus; cpu++) {
|
||||||
pfm_perf_encode_arg_t pfm_arg;
|
|
||||||
struct perf_event_attr pfm_event;
|
struct perf_event_attr pfm_event;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
memset(&pfm_arg, 0, sizeof(pfm_arg));
|
|
||||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||||
pfm_arg.attr = &pfm_event;
|
|
||||||
pfm_arg.size = sizeof(pfm_arg);
|
|
||||||
pfm_event.size = sizeof(pfm_event);
|
pfm_event.size = sizeof(pfm_event);
|
||||||
|
if (perf_event_encode(&pfm_event,
|
||||||
/* search for the counter's corresponding pfm name */
|
pmf_counter_name[i].pmu,
|
||||||
for (i = ALL_COUNTER-1; i >= 0; i--)
|
pmf_counter_name[i].pfm_name)) {
|
||||||
if ((int) pmf_counter_name[i].ctr == ctr)
|
eprint("Failed to initialize counter %s for pmu %s\n",
|
||||||
break;
|
|
||||||
if (i < 0) {
|
|
||||||
eprint("Pfm ctr name not found for counter %d, please adjust pmf_counter_name[] in %s\n",
|
|
||||||
ctr, __FILE__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* encode the counters perf event into pfm_arg.attr */
|
|
||||||
ec = pfm_get_os_event_encoding(
|
|
||||||
pmf_counter_name[i].pfm_name,
|
|
||||||
PFM_PLM0,
|
|
||||||
PFM_OS_PERF_EVENT,
|
|
||||||
&pfm_arg);
|
|
||||||
if (ec != PFM_SUCCESS) {
|
|
||||||
eprint("Pfm_initialize() for %s failed (%d:%s)\n",
|
|
||||||
pmf_counter_name[i].pfm_name,
|
pmf_counter_name[i].pfm_name,
|
||||||
ec, pfm_strerror(ec));
|
pmf_counter_name[i].pmu);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,3 +330,8 @@ int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
|||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int perf_ecc_supported(void)
|
||||||
|
{
|
||||||
|
return ecc_supported;
|
||||||
|
}
|
||||||
|
|||||||
+13
-52
@@ -1,67 +1,28 @@
|
|||||||
#!/usr/bin/make -f
|
|
||||||
|
|
||||||
include ../common.mak
|
include ../common.mak
|
||||||
|
|
||||||
|
BIN_FILES = lscpumf chcpumf
|
||||||
CPUMF_DATADIR = $(TOOLS_DATADIR)/cpumf
|
|
||||||
DATA_FILES = cpum-cf-hw-counter.map \
|
|
||||||
cpum-cf-cfvn-1.ctr cpum-cf-cfvn-3.ctr \
|
|
||||||
cpum-cf-csvn-12345.ctr cpum-cf-csvn-6.ctr \
|
|
||||||
cpum-cf-extended-z10.ctr cpum-cf-extended-z196.ctr \
|
|
||||||
cpum-cf-extended-zEC12.ctr cpum-sf-modes.ctr \
|
|
||||||
cpum-cf-extended-z13.ctr cpum-cf-extended-z14.ctr \
|
|
||||||
cpum-cf-extended-z15.ctr
|
|
||||||
LIB_FILES = bin/cpumf_helper
|
|
||||||
USRBIN_SCRIPTS = bin/lscpumf
|
|
||||||
USRSBIN_SCRIPTS = bin/chcpumf
|
|
||||||
MAN_FILES = lscpumf.1 chcpumf.8
|
MAN_FILES = lscpumf.1 chcpumf.8
|
||||||
|
|
||||||
all:
|
all: $(BIN_FILES)
|
||||||
|
|
||||||
scripts: $(USRBIN_SCRIPTS) $(USRSBIN_SCRIPTS) $(LIB_FILES)
|
libs = $(rootdir)/libutil/libutil.a
|
||||||
chmod +x $(USRBIN_SCRIPTS) $(USRSBIN_SCRIPTS) $(LIB_FILES)
|
|
||||||
|
|
||||||
check:
|
lscpumf: lscpumf.o $(libs)
|
||||||
|
chcpumf: chcpumf.o $(libs)
|
||||||
|
|
||||||
install: scripts install-man
|
install: all install-man
|
||||||
for prg in $(USRBIN_SCRIPTS); do \
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $$prg $(DESTDIR)$(USRBINDIR) ; \
|
for binf in $(BIN_FILES); do \
|
||||||
done
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $$binf $(DESTDIR)$(BINDIR); \
|
||||||
for prg in $(USRSBIN_SCRIPTS); do \
|
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $$prg $(DESTDIR)$(USRSBINDIR) ; \
|
|
||||||
done
|
|
||||||
test -d $(DESTDIR)$(CPUMF_DATADIR) || mkdir -p $(DESTDIR)$(CPUMF_DATADIR)
|
|
||||||
for lib in $(LIB_FILES); do \
|
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $$lib $(DESTDIR)$(TOOLS_LIBDIR) ; \
|
|
||||||
done
|
|
||||||
for data in $(DATA_FILES); do \
|
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 data/$$data $(DESTDIR)$(CPUMF_DATADIR) ; \
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o *~ $(BIN_FILES) core
|
||||||
|
|
||||||
install-man:
|
install-man:
|
||||||
for man in $(MAN_FILES); do \
|
for man in $(MAN_FILES); do \
|
||||||
msection=`echo $$man |sed 's/.*\.\([1-9]\)$$/man\1/'` ; \
|
msection=`echo $$man |sed 's/.*\.\([1-9]\)$$/man\1/'` ; \
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 -D man/$$man $(DESTDIR)$(MANDIR)/$$msection/$$man ; \
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 -D man/$$man $(DESTDIR)$(MANDIR)/$$msection/$$man ; \
|
||||||
done
|
done
|
||||||
|
|
||||||
man2pdf:
|
.PHONY: all install clean
|
||||||
for man in $(MAN_FILES); do \
|
|
||||||
man -t man/$$man |ps2pdf -sPAPERSIZE=a4 - man/$${man}.pdf ; \
|
|
||||||
done
|
|
||||||
man2text:
|
|
||||||
for man in $(MAN_FILES); do \
|
|
||||||
MANWIDTH=80 LANG=C man man/$$man |col -b |expand > man/$${man}.txt ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(LIB_FILES) $(USRBIN_SCRIPTS) $(USRSBIN_SCRIPTS)
|
|
||||||
|
|
||||||
%: %.in
|
|
||||||
real_libdir=$(TOOLS_LIBDIR); \
|
|
||||||
real_cpumfdatadir=$(CPUMF_DATADIR); \
|
|
||||||
$(SED) -e "s#@lib_path@#$$real_libdir#g" \
|
|
||||||
-e "s#@cpumfdata_path@#$$real_cpumfdatadir#g" \
|
|
||||||
-e 's#@S390_TOOLS_RELEASE@#$(S390_TOOLS_RELEASE)#g' \
|
|
||||||
< $< > $@
|
|
||||||
|
|
||||||
.PHONY: all scripts install install-man man2pdf man2text clean
|
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
#!/usr/bin/perl -W
|
|
||||||
#
|
|
||||||
# chcpumf - Control CPU-measurement facilities
|
|
||||||
#
|
|
||||||
# Copyright IBM Corp. 2014, 2017
|
|
||||||
#
|
|
||||||
# s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
#
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use File::Basename qw/fileparse/;
|
|
||||||
use Data::Dumper;
|
|
||||||
use Getopt::Long qw/:config no_ignore_case/;
|
|
||||||
|
|
||||||
# Global constants
|
|
||||||
my $CPUMF_HELPER = '@lib_path@/cpumf_helper';
|
|
||||||
my $CPUM_SFB_SIZE = '/sys/module/kernel/parameters/cpum_sfb_size';
|
|
||||||
|
|
||||||
# Prototypes
|
|
||||||
sub main();
|
|
||||||
sub show_help();
|
|
||||||
sub show_version();
|
|
||||||
sub do_set_sfb_size($);
|
|
||||||
sub cpumf_set_sfb_size($);
|
|
||||||
sub invoke_cpumf_helper($);
|
|
||||||
|
|
||||||
sub main()
|
|
||||||
{
|
|
||||||
my $config = {
|
|
||||||
# Internal data
|
|
||||||
cpumf => {}, # CPU-MF information hash
|
|
||||||
};
|
|
||||||
|
|
||||||
unless (GetOptions(
|
|
||||||
# General options for help, version, verbose,...
|
|
||||||
"h|help" => \&show_help,
|
|
||||||
"v|version" => \&show_version,
|
|
||||||
"V|verbose+" => \$config->{verbose},
|
|
||||||
# Change specific options
|
|
||||||
"m|min=i" => \$config->{min},
|
|
||||||
"x|max=i" => \$config->{max},
|
|
||||||
)) {
|
|
||||||
print STDERR "One or more options are not valid\n";
|
|
||||||
print STDERR "Try '" . fileparse($0) .
|
|
||||||
" --help' for more information\n";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Collect CPU-MF information
|
|
||||||
$config->{cpumf} = invoke_cpumf_helper("-i");
|
|
||||||
die "Failed to collect CPU-MF information: $!\n" unless $config->{cpumf};
|
|
||||||
|
|
||||||
# Process parameters
|
|
||||||
my $exitval = 5;
|
|
||||||
if (defined($config->{min}) || defined($config->{max})) {
|
|
||||||
$exitval = do_set_sfb_size($config);
|
|
||||||
} else {
|
|
||||||
print STDERR "You must specify a valid option\n";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($exitval);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub show_help()
|
|
||||||
{
|
|
||||||
my $prog = fileparse($0);
|
|
||||||
|
|
||||||
print <<"EoHelp";
|
|
||||||
Usage: chcpumf -h|-v
|
|
||||||
chcpumf -m <num_sdb>
|
|
||||||
chcpumf -x <num_sdb>
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-m <num_sdb> Specifies the initial size of the sampling buffer.
|
|
||||||
A sample-data-block (SDB) consumes about 4 kilobytes.
|
|
||||||
-x <num_sdb> Specifies the maximum size of the sampling buffer.
|
|
||||||
A sample-data-block (SDB) consumes about 4 kilobytes.
|
|
||||||
-h Displays help information, then exits.
|
|
||||||
-v Displays version information, then exits.
|
|
||||||
|
|
||||||
For more help information, issue 'man $prog'.
|
|
||||||
EoHelp
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub show_version()
|
|
||||||
{
|
|
||||||
print <<'EoVersion';
|
|
||||||
CPU-measurement facility utilities, version @S390_TOOLS_RELEASE@
|
|
||||||
Copyright IBM Corp. 2014, 2017
|
|
||||||
|
|
||||||
EoVersion
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_set_sfb_size($)
|
|
||||||
{
|
|
||||||
my @size = @{shift()};
|
|
||||||
my $val = join ',', @size[0,1];
|
|
||||||
my ($SFBSIZE, $rc);
|
|
||||||
|
|
||||||
return undef unless open($SFBSIZE, '>', $CPUM_SFB_SIZE);
|
|
||||||
# Check the return code of print and close to detect error conditions
|
|
||||||
# reported by the device driver. Because perl might buffer data, print
|
|
||||||
# might be successful, but close might then report the error condition.
|
|
||||||
# So check the return code of both functions and always close the file
|
|
||||||
# handle.
|
|
||||||
$rc = print { $SFBSIZE } "$val\n";
|
|
||||||
unless ($rc) {
|
|
||||||
close($SFBSIZE);
|
|
||||||
return $rc;
|
|
||||||
}
|
|
||||||
return close($SFBSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_set_sfb_size($)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
my $size;
|
|
||||||
|
|
||||||
# Check if sampling facility is available
|
|
||||||
unless (exists $c->{cpumf}->{sf}) {
|
|
||||||
print STDERR "No CPU-measurement sampling facility detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
# Check if perf support is available
|
|
||||||
unless (exists $c->{cpumf}->{sf}->{perf}) {
|
|
||||||
print STDERR "No perf support for the CPU-measurement" .
|
|
||||||
" sampling facility availalble\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Optionally, change the sampling buffer sizes
|
|
||||||
if (defined($c->{min}) || defined($c->{max})) {
|
|
||||||
$size = invoke_cpumf_helper("--sfb-size");
|
|
||||||
# Use current size value for zero min/max specifications
|
|
||||||
$size->[0] = $c->{min} if defined($c->{min});
|
|
||||||
$size->[1] = $c->{max} if defined($c->{max});
|
|
||||||
# Validate new settings
|
|
||||||
if ($size->[0] < 1 || $size->[1] < 1) {
|
|
||||||
die "The specified number(s) are not valid\n";
|
|
||||||
}
|
|
||||||
if ($size->[0] >= $size->[1]) {
|
|
||||||
die "The specified maximum must be greater " .
|
|
||||||
"than the minimum\n";
|
|
||||||
}
|
|
||||||
# Set new sampling buffer sizes
|
|
||||||
unless (cpumf_set_sfb_size($size)) {
|
|
||||||
die "Failed to change sampling buffer size: $!\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Finally, show sampling buffer sizes
|
|
||||||
if ($c->{verbose}) {
|
|
||||||
$size = invoke_cpumf_helper("--sfb-size");
|
|
||||||
print "Sampling buffer sizes:\n";
|
|
||||||
printf " Minimum: %6u sample-data-blocks\n", $size->[0];
|
|
||||||
printf " Maximum: %6u sample-data-blocks\n", $size->[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub invoke_cpumf_helper($)
|
|
||||||
{
|
|
||||||
my $parms = shift();
|
|
||||||
my $result;
|
|
||||||
|
|
||||||
# Call helper module
|
|
||||||
my $output = qx"$CPUMF_HELPER $parms";
|
|
||||||
die "Failed to run helper module for '$parms'\n" if $? >> 8;
|
|
||||||
$result = eval "$output";
|
|
||||||
die "Failed to parse helper module data\n" if $@;
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
&main();
|
|
||||||
__DATA__
|
|
||||||
__END__
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
#!/usr/bin/perl -W
|
|
||||||
#
|
|
||||||
# cpumf_helper - Helper module for managing CPU-measurement facilities (CPU-MF)
|
|
||||||
#
|
|
||||||
# Copyright IBM Corp. 2014, 2017
|
|
||||||
#
|
|
||||||
# s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
#
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use Carp qw/croak/;
|
|
||||||
use Data::Dumper;
|
|
||||||
use Getopt::Long qw/:config no_ignore_case/;
|
|
||||||
|
|
||||||
# Global constants
|
|
||||||
my $SERVICE_LEVELS = '/proc/service_levels';
|
|
||||||
my $CPUMF_DATA_DIR = '@cpumfdata_path@';
|
|
||||||
my $CPUM_SFB_SIZE = '/sys/module/kernel/parameters/cpum_sfb_size';
|
|
||||||
my $CPUM_SF_DBF='/sys/kernel/debug/s390dbf/cpum_sf';
|
|
||||||
|
|
||||||
# Counter set bits (according to QUERY COUNTER INFORMATION)
|
|
||||||
my $BASIC_SET = 0x0002;
|
|
||||||
my $PROBLEM_STATE_SET = 0x0004;
|
|
||||||
my $CRYPTO_SET = 0x0008;
|
|
||||||
my $EXTENTED_SET = 0x0001;
|
|
||||||
my $MT_DIAG_SET = 0x0020;
|
|
||||||
my $COPROC_GRP_SET = 0x8000;
|
|
||||||
|
|
||||||
|
|
||||||
# Public prototypes
|
|
||||||
sub cpumf_collect_data();
|
|
||||||
sub cpumf_get_sfb_size();
|
|
||||||
sub cpumf_set_sfb_size($);
|
|
||||||
sub cpumf_parse_ctrdef($;$);
|
|
||||||
sub cpumf_load_ctrdef($;$);
|
|
||||||
sub cpumf_get_counter_set($);
|
|
||||||
sub cpumf_counter_set_names();
|
|
||||||
sub cpumf_counter_set_ids();
|
|
||||||
sub cpumf_hardware_counter_map();
|
|
||||||
|
|
||||||
# Internal prototypes
|
|
||||||
sub cpumf_parse_cf($$);
|
|
||||||
sub cpumf_parse_sf($$);
|
|
||||||
|
|
||||||
|
|
||||||
sub cpumf_get_sfb_size()
|
|
||||||
{
|
|
||||||
my $val = "0,0";
|
|
||||||
my $SFBSIZE;
|
|
||||||
|
|
||||||
if (open($SFBSIZE, '<', $CPUM_SFB_SIZE)) {
|
|
||||||
$val = <$SFBSIZE>;
|
|
||||||
chomp($val);
|
|
||||||
close($SFBSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [split /,/, $val];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_set_sfb_size($)
|
|
||||||
{
|
|
||||||
my @size = @{shift()};
|
|
||||||
my $val = join ',', @size[0,1];
|
|
||||||
my ($SFBSIZE, $rc);
|
|
||||||
|
|
||||||
return undef unless open($SFBSIZE, '>', $CPUM_SFB_SIZE);
|
|
||||||
# Check the return code of print and close to detect error conditions
|
|
||||||
# reported by the device driver. Because perl might buffer data, print
|
|
||||||
# might be successful, but close might then report the error condition.
|
|
||||||
# So check the return code of both functions and always close the file
|
|
||||||
# handle.
|
|
||||||
$rc = print { $SFBSIZE } "$val\n";
|
|
||||||
unless ($rc) {
|
|
||||||
close($SFBSIZE);
|
|
||||||
return $rc;
|
|
||||||
}
|
|
||||||
return close($SFBSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sub cpumf_parse_cf($$)
|
|
||||||
{
|
|
||||||
my ($ent, $data) = @_;
|
|
||||||
|
|
||||||
if ($ent =~ /version=([0-9.]+) authorization=([[:xdigit:]]+)/) {
|
|
||||||
$data->{cf} = { version => $1, auth => hex($2) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_parse_sf($$)
|
|
||||||
{
|
|
||||||
my ($ent, $data) = @_;
|
|
||||||
|
|
||||||
# Parse common sampling facility entry
|
|
||||||
if ($ent =~ /min_rate=(\d+) max_rate=(\d+) cpu_speed=(\d+)/) {
|
|
||||||
$data->{sf} = {
|
|
||||||
min_sampl_interval => $1,
|
|
||||||
max_sampl_interval => $2,
|
|
||||||
cpu_speed => $3,
|
|
||||||
# This contains a list of authorized sampling modes, for
|
|
||||||
# example, basic
|
|
||||||
modes => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parse sampling facility mode entries
|
|
||||||
if ($ent =~ /mode=(\w+) sample_size=(\d+)/) {
|
|
||||||
$data->{sf}->{modes}->{$1}->{sample_size} = $2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_collect_data()
|
|
||||||
{
|
|
||||||
my $SL;
|
|
||||||
|
|
||||||
# Collect CPU-MF information from /proc/service_levels
|
|
||||||
return undef unless open($SL, '<', $SERVICE_LEVELS);
|
|
||||||
my @sl = <$SL>;
|
|
||||||
chomp(@sl);
|
|
||||||
close($SL);
|
|
||||||
|
|
||||||
# Process CPU-MF information and build data hash
|
|
||||||
my $data = {};
|
|
||||||
foreach my $ent (@sl) {
|
|
||||||
$ent =~ s/^CPU-MF: // or next;
|
|
||||||
cpumf_parse_cf($ent, $data) if $ent =~ s/Counter facility: //;
|
|
||||||
cpumf_parse_sf($ent, $data) if $ent =~ s/Sampling facility: //;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Collect perf support for available facilities
|
|
||||||
if (-e '/sys/bus/event_source/devices/cpum_cf') {
|
|
||||||
$data->{cf}->{perf} = "cpum_cf" if exists $data->{cf};
|
|
||||||
}
|
|
||||||
if (-e '/sys/bus/event_source/devices/cpum_sf') {
|
|
||||||
$data->{sf}->{perf} = "cpum_sf" if exists $data->{sf};
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Parse the specified counter definition file and returns a hash containing
|
|
||||||
# the parsed counter definition. The optional argument specifies a hash
|
|
||||||
# reference to which the new definitions are added. This reference is returned.
|
|
||||||
sub cpumf_parse_ctrdef($;$)
|
|
||||||
{
|
|
||||||
my $ctrdef = shift();
|
|
||||||
my $h = @_ ? shift() : {};
|
|
||||||
my $CTRDEF;
|
|
||||||
|
|
||||||
return undef unless open($CTRDEF, '<', "$CPUMF_DATA_DIR/$ctrdef");
|
|
||||||
my ($ctr, $name);
|
|
||||||
while (my $line = <$CTRDEF>) {
|
|
||||||
next if $line =~ /^#/;
|
|
||||||
chomp($line);
|
|
||||||
|
|
||||||
# Parse start of counter definition entry
|
|
||||||
if ($line =~ m/^Counter:\s*(0x[[:xdigit:]]+|\d+)
|
|
||||||
\s+Name:\s*([[:alnum:]_]+)$/x) {
|
|
||||||
($ctr, $name) = ($1, $2);
|
|
||||||
$ctr = hex($ctr) if $ctr =~ /^0x/;
|
|
||||||
unless (length($ctr)) {
|
|
||||||
print STDERR "Found invalid entry in counter " .
|
|
||||||
"definition: line $.\n";
|
|
||||||
}
|
|
||||||
$h->{$ctr} = { name => $name || "" };
|
|
||||||
}
|
|
||||||
|
|
||||||
# At this point, a counter must be defined
|
|
||||||
next unless defined($ctr);
|
|
||||||
|
|
||||||
# Parse short description (optional)
|
|
||||||
if ($line =~ m/^Short-Description:\s*(\S.*)?$/) {
|
|
||||||
$h->{$ctr}->{shortdesc} = $1 || "";
|
|
||||||
|
|
||||||
# Parse start of counter description
|
|
||||||
} elsif ($line =~ m/^Description:\s*(\S.*)?$/) {
|
|
||||||
$h->{$ctr}->{desc} = $1 || "";
|
|
||||||
|
|
||||||
# Parse end of counter description
|
|
||||||
} elsif ($line =~ m/^\.$/) {
|
|
||||||
# Complete the counter definition
|
|
||||||
$h->{$ctr}->{set} = cpumf_get_counter_set($ctr);
|
|
||||||
# Trim whitespaces
|
|
||||||
$h->{$ctr}->{shortdesc} =~ s/^\s+|\s+$//g if $h->{$ctr}->{shortdesc};
|
|
||||||
$h->{$ctr}->{desc} =~ s/^\s+|\s+$//g if $h->{$ctr}->{desc};
|
|
||||||
# Finally, reset counter for next entry
|
|
||||||
$ctr = undef;
|
|
||||||
|
|
||||||
# Line is part of counter description (if $ctr_num is set)
|
|
||||||
} else {
|
|
||||||
$h->{$ctr}->{desc} .= " $line";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close($CTRDEF);
|
|
||||||
|
|
||||||
return $h;
|
|
||||||
}
|
|
||||||
|
|
||||||
# IBM System z hardware with CPU-M counter facility support
|
|
||||||
my $system_z_hwtype_map = {
|
|
||||||
# Machine type Description
|
|
||||||
'' => 'Unknown hardware model',
|
|
||||||
2097 => 'IBM System z10 EC',
|
|
||||||
2098 => 'IBM System z10 BC',
|
|
||||||
2817 => 'IBM zEnterprise 196',
|
|
||||||
2818 => 'IBM zEnterprise 114',
|
|
||||||
2827 => 'IBM zEnterprise EC12',
|
|
||||||
2828 => 'IBM zEnterprise BC12',
|
|
||||||
2964 => 'IBM z13',
|
|
||||||
2965 => 'IBM z13s',
|
|
||||||
3906 => 'IBM z14',
|
|
||||||
3907 => 'IBM z14 ZR1',
|
|
||||||
8561 => 'IBM z15',
|
|
||||||
};
|
|
||||||
|
|
||||||
sub get_hardware_type()
|
|
||||||
{
|
|
||||||
my $type = "";
|
|
||||||
my $SYSINFO;
|
|
||||||
|
|
||||||
return undef unless open($SYSINFO, '<', '/proc/sysinfo');
|
|
||||||
while (my $line = <$SYSINFO>) {
|
|
||||||
if ($line =~ m/^Type:\s*(\d+)\s*$/) {
|
|
||||||
$type = $1;
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close($SYSINFO);
|
|
||||||
return $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_cpum_cf_version()
|
|
||||||
{
|
|
||||||
my $SL;
|
|
||||||
|
|
||||||
my $v = {
|
|
||||||
cfvn => 0,
|
|
||||||
csvn => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
return $v unless open($SL, '<', $SERVICE_LEVELS);
|
|
||||||
while (my $line = <$SL>) {
|
|
||||||
# CPU-MF: Counter facility: version=3.5
|
|
||||||
if ($line =~ m/^CPU-MF: Counter facility: version=(\d+)\.(\d+)/) {
|
|
||||||
$v->{cfvn} = $1; # Counter First Version Number
|
|
||||||
$v->{csvn} = $2; # Counter Second Version Number
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close($SL);
|
|
||||||
return $v
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_load_ctrdef($;$)
|
|
||||||
{
|
|
||||||
my $hw_type = shift();
|
|
||||||
my $authorized = @_ ? shift() : 0xffff; # Counter Set authorization
|
|
||||||
|
|
||||||
my $ctrmap = cpumf_hardware_counter_map();
|
|
||||||
return unless $ctrmap;
|
|
||||||
|
|
||||||
# Obtain CPU-MF counter facility versions
|
|
||||||
my $version = get_cpum_cf_version();
|
|
||||||
|
|
||||||
# List of "generic" counter sets
|
|
||||||
my @def = ();
|
|
||||||
push @def, "cfvn-" . $version->{cfvn};
|
|
||||||
if ($version->{csvn} >= 1 && $version->{csvn} <= 6) {
|
|
||||||
push @def, "csvn-12345";
|
|
||||||
}
|
|
||||||
if ($version->{csvn} == 6) {
|
|
||||||
push @def, "csvn-6";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $h = {};
|
|
||||||
# Load counter set definition
|
|
||||||
foreach my $ent (@def) {
|
|
||||||
cpumf_parse_ctrdef($ctrmap->{$ent}, $h) or
|
|
||||||
croak "Failed to read counter definition for $ent: $!\n";
|
|
||||||
}
|
|
||||||
# Load hardware model specific counter set(s)
|
|
||||||
if ($hw_type && $ctrmap->{$hw_type}) {
|
|
||||||
# Hardware-model specific counter sets are:
|
|
||||||
# - Extended Counter Set
|
|
||||||
# - MT-diagnostic Counter Set
|
|
||||||
cpumf_parse_ctrdef($ctrmap->{$hw_type}, $h) or
|
|
||||||
croak "Failed to read hardware-model counter definition: $!\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove counter sets that miss authorizations
|
|
||||||
my @no_auth_list = ();
|
|
||||||
foreach my $ctr (sort keys %$h) {
|
|
||||||
push @no_auth_list, $ctr unless $h->{$ctr}->{set} & $authorized;
|
|
||||||
}
|
|
||||||
delete $h->{$_} foreach (@no_auth_list);
|
|
||||||
|
|
||||||
return $h;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sub cpumf_get_counter_set($)
|
|
||||||
{
|
|
||||||
my $ctr = shift();
|
|
||||||
|
|
||||||
return $BASIC_SET if $ctr < 32;
|
|
||||||
return $PROBLEM_STATE_SET if $ctr < 64;
|
|
||||||
return $CRYPTO_SET if $ctr < 128;
|
|
||||||
#
|
|
||||||
# The extended counter set ranges from
|
|
||||||
# 128 to
|
|
||||||
# 159 for csvn == 1
|
|
||||||
# 175 for csvn == 2
|
|
||||||
# 255 for csvn > 2
|
|
||||||
# Tolerate any future counters up to
|
|
||||||
# the MT-diagnostic counter set.
|
|
||||||
return $EXTENTED_SET if $ctr < 448;
|
|
||||||
#
|
|
||||||
# The MT-diagnostic counter set ranges from
|
|
||||||
# 448 to
|
|
||||||
# 495 for cvsn > 3
|
|
||||||
return $MT_DIAG_SET if $ctr <= 495;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_counter_set_names()
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
# Identifier Name
|
|
||||||
$BASIC_SET => 'Basic Counter Set',
|
|
||||||
$PROBLEM_STATE_SET => 'Problem-State Counter Set',
|
|
||||||
$CRYPTO_SET => 'Crypto-Activity Counter Set',
|
|
||||||
$EXTENTED_SET => 'Extended Counter Set',
|
|
||||||
$MT_DIAG_SET => 'MT-diagnostic Counter Set',
|
|
||||||
$COPROC_GRP_SET => 'Coprocessor Group Counter Set',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_counter_set_ids()
|
|
||||||
{
|
|
||||||
return [$BASIC_SET, $PROBLEM_STATE_SET, $CRYPTO_SET, $EXTENTED_SET,
|
|
||||||
$MT_DIAG_SET, $COPROC_GRP_SET];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cpumf_hardware_counter_map()
|
|
||||||
{
|
|
||||||
my $map = do "$CPUMF_DATA_DIR/cpum-cf-hw-counter.map";
|
|
||||||
croak "Failed to parse mapfile: $@" if $@;
|
|
||||||
croak "Failed to read mapfile: $!" unless defined $map;
|
|
||||||
return $map;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $cpumf_helper_str = <<'END_MESSAGE';
|
|
||||||
|
|
||||||
cpumf_helper - Helper module for managing CPU-Measurement Facilities (CPU-MF)
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-i, --info:
|
|
||||||
Displays detailed information about installed and available
|
|
||||||
CPU-measurement facilities and the related Linux support.
|
|
||||||
|
|
||||||
-c, --counter authorization_value
|
|
||||||
Displays counter information for the current System z hardware.
|
|
||||||
The authorization value provides information about the authorized
|
|
||||||
counter sets. The value must be specified in decimal format.
|
|
||||||
|
|
||||||
To display all supported counters, specify C<65535> (FFFF hex).
|
|
||||||
|
|
||||||
To display supported counters for a particular System z hardware,
|
|
||||||
use the --ctr-def option and specify the System z hardware type.
|
|
||||||
|
|
||||||
--hardware-type
|
|
||||||
Displays the System z hardware type.
|
|
||||||
|
|
||||||
--ctr-def ctr-definition
|
|
||||||
Displays detailed information about the specified counter definition.
|
|
||||||
Valid counter definitions start with C<cfvn-> or <csvn-> followed by
|
|
||||||
the counter first/second version number of the CPU-Measurement Counter
|
|
||||||
Facility. To display counter information of model-specific counter
|
|
||||||
sets, specify the System z hardware type for I<ctr-definition>.
|
|
||||||
|
|
||||||
--ctr-set-names
|
|
||||||
Displays the mapping of counter set IDs to counter set names.
|
|
||||||
The counter set IDs are numbers that are used in counter definitions.
|
|
||||||
|
|
||||||
--ctr-set-ids
|
|
||||||
Displays the counter set IDs. The counter set IDs are numbers that
|
|
||||||
match the authorization bits (see QUERY COUNTER INFORMATION).
|
|
||||||
The output format is a list. To get the ID for a particular counter
|
|
||||||
set, use an index number as follows:
|
|
||||||
|
|
||||||
0: Basic Counter Set
|
|
||||||
1: Problem-State Counter Set
|
|
||||||
2: Crypto-Activity Counter Set
|
|
||||||
3: Extended Counter Set
|
|
||||||
4: MT-diagnostic Counter Set
|
|
||||||
5: Coprocessor Group Counter Set
|
|
||||||
|
|
||||||
--ctr-sf
|
|
||||||
Displays the counter definitions for the sampling facility support.
|
|
||||||
These counter definitions are specific to Linux perf infrastructure.
|
|
||||||
|
|
||||||
--sfb-size
|
|
||||||
Displays the size of the sampling facility buffer (SFB). The minimum
|
|
||||||
and maximum numbers are measured in units of sample-data-blocks. A
|
|
||||||
sample-data-block uses about 4 kilobytes.
|
|
||||||
|
|
||||||
END_MESSAGE
|
|
||||||
|
|
||||||
sub cpumf_helper_main()
|
|
||||||
{
|
|
||||||
# Configuration settings and options
|
|
||||||
my $conf = {
|
|
||||||
};
|
|
||||||
|
|
||||||
# Parse command line option
|
|
||||||
GetOptions(
|
|
||||||
"i|info" => \$conf->{opt_info},
|
|
||||||
"c|counter=i" => \$conf->{opt_ctr},
|
|
||||||
"ctr-def=s" => \$conf->{opt_ctrdef},
|
|
||||||
"hardware-type" => \$conf->{opt_hwtype},
|
|
||||||
"ctr-set-names" => \$conf->{opt_ctrset_names},
|
|
||||||
"ctr-set-ids" => \$conf->{opt_ctrset_ids},
|
|
||||||
"sfb-size" => \$conf->{opt_sfb_size},
|
|
||||||
"ctr-sf" => \$conf->{opt_sf_ctr},
|
|
||||||
) or die("One or more options are not valid\n" . $cpumf_helper_str);
|
|
||||||
|
|
||||||
|
|
||||||
# Setting up Data::Dumper to create parseable Perl output
|
|
||||||
local $Data::Dumper::Purity = 1;
|
|
||||||
local $Data::Dumper::Sortkeys = 1;
|
|
||||||
local $Data::Dumper::Terse = 1;
|
|
||||||
|
|
||||||
###print STDERR "CONF: " . Dumper($conf) . "\n";
|
|
||||||
|
|
||||||
# Process command line options
|
|
||||||
my $exitval = 0;
|
|
||||||
my $result;
|
|
||||||
if (defined($conf->{opt_info})) {
|
|
||||||
$result = cpumf_collect_data();
|
|
||||||
|
|
||||||
# Display System z hardware type
|
|
||||||
} elsif (defined($conf->{opt_hwtype})) {
|
|
||||||
my $type = get_hardware_type();
|
|
||||||
$result = [$type, $system_z_hwtype_map->{$type} || ""];
|
|
||||||
|
|
||||||
# Display counters for current System z hardware
|
|
||||||
} elsif (defined($conf->{opt_ctr})) {
|
|
||||||
my $type = get_hardware_type();
|
|
||||||
$type = 0 unless $type;
|
|
||||||
$result = cpumf_load_ctrdef($type, $conf->{opt_ctr});
|
|
||||||
|
|
||||||
# Display counters for a particular System z hardware type
|
|
||||||
} elsif (defined($conf->{opt_ctrdef})) {
|
|
||||||
my $m = cpumf_hardware_counter_map();
|
|
||||||
if (exists $m->{$conf->{opt_ctrdef}}) {
|
|
||||||
$result = cpumf_parse_ctrdef($m->{$conf->{opt_ctrdef}});
|
|
||||||
} else {
|
|
||||||
printf STDERR "Invalid counter definition\n";
|
|
||||||
$exitval = 2;
|
|
||||||
}
|
|
||||||
# Display the size of the sampling facility buffer (sfb)
|
|
||||||
} elsif (defined($conf->{opt_sfb_size})) {
|
|
||||||
$result = cpumf_get_sfb_size();
|
|
||||||
|
|
||||||
# Display counter definitions for the sampling facility support (perf)
|
|
||||||
} elsif (defined($conf->{opt_sf_ctr})) {
|
|
||||||
$result = cpumf_parse_ctrdef('cpum-sf-modes.ctr');
|
|
||||||
|
|
||||||
# Display mapping of counter set IDs to counter set names
|
|
||||||
} elsif (defined($conf->{opt_ctrset_names})) {
|
|
||||||
$result = cpumf_counter_set_names();
|
|
||||||
|
|
||||||
# Display counter set IDs
|
|
||||||
} elsif (defined($conf->{opt_ctrset_ids})) {
|
|
||||||
$result = cpumf_counter_set_ids();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
die("No option specified\n" . $cpumf_helper_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display result
|
|
||||||
print Dumper($result) if $result;
|
|
||||||
exit $exitval;
|
|
||||||
}
|
|
||||||
|
|
||||||
&cpumf_helper_main();
|
|
||||||
__DATA__
|
|
||||||
__END__
|
|
||||||
@@ -1,387 +0,0 @@
|
|||||||
#!/usr/bin/perl -W
|
|
||||||
#
|
|
||||||
# lscpumf - Display information about CPU-measurement facilities
|
|
||||||
#
|
|
||||||
# Copyright IBM Corp. 2014, 2017
|
|
||||||
#
|
|
||||||
# s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
#
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use Data::Dumper;
|
|
||||||
use File::Basename qw/fileparse/;
|
|
||||||
use Getopt::Long qw/:config no_ignore_case/;
|
|
||||||
|
|
||||||
# Global constants
|
|
||||||
my $CPUMF_HELPER = '@lib_path@/cpumf_helper';
|
|
||||||
|
|
||||||
# Prototypes
|
|
||||||
sub main();
|
|
||||||
sub show_help();
|
|
||||||
sub show_version();
|
|
||||||
sub do_show_info($);
|
|
||||||
sub do_show_cf($);
|
|
||||||
sub do_show_sf($);
|
|
||||||
sub do_show_ctr($;$);
|
|
||||||
sub do_show_sf_events($);
|
|
||||||
sub invoke_cpumf_helper($);
|
|
||||||
|
|
||||||
|
|
||||||
sub main()
|
|
||||||
{
|
|
||||||
my $config = {
|
|
||||||
# Internal data
|
|
||||||
cpumf => {}, # CPU-MF information hash
|
|
||||||
};
|
|
||||||
|
|
||||||
unless (GetOptions(
|
|
||||||
# General options for help, version,...
|
|
||||||
"h|help" => \&show_help,
|
|
||||||
"v|version" => \&show_version,
|
|
||||||
# Display options
|
|
||||||
"i|info" => \$config->{opt_info},
|
|
||||||
"c|list-counters" => \$config->{opt_ctr},
|
|
||||||
"C|list-all-counters" => \$config->{opt_ctr_all},
|
|
||||||
"s|list-sampling-events" => \$config->{opt_ctr_sf},
|
|
||||||
)) {
|
|
||||||
print STDERR "One or more options are not valid\n";
|
|
||||||
print STDERR "Try '" . fileparse($0) .
|
|
||||||
" --help' for more information\n";
|
|
||||||
exit 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Collect CPU-MF information
|
|
||||||
$config->{cpumf} = invoke_cpumf_helper("-i");
|
|
||||||
die "Failed to collect CPU-MF information: $!\n" unless $config->{cpumf};
|
|
||||||
|
|
||||||
# Process parameters
|
|
||||||
my $exitval = 5;
|
|
||||||
if (defined($config->{opt_info})) {
|
|
||||||
do_show_cf($config);
|
|
||||||
do_show_sf($config);
|
|
||||||
$exitval = 0;
|
|
||||||
|
|
||||||
} elsif (defined($config->{opt_ctr})) {
|
|
||||||
$exitval = do_show_ctr($config);
|
|
||||||
} elsif (defined($config->{opt_ctr_all})) {
|
|
||||||
$exitval = do_show_ctr($config, "all")
|
|
||||||
} elsif (defined($config->{opt_ctr_sf})) {
|
|
||||||
$exitval = do_show_sf_events($config);
|
|
||||||
} else {
|
|
||||||
$exitval = do_show_info($config);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit($exitval);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub show_help()
|
|
||||||
{
|
|
||||||
my $prog = fileparse($0);
|
|
||||||
|
|
||||||
print <<"EoHelp";
|
|
||||||
Usage: lscpumf -h|-v
|
|
||||||
lscpumf [-i]
|
|
||||||
lscpumf -c|-C
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-i Displays detailed information.
|
|
||||||
-c Lists counters for which the LPAR is authorized.
|
|
||||||
-C Lists counters regardless of LPAR authorization.
|
|
||||||
-s Lists perf raw events that activate the sampling facility.
|
|
||||||
-h Displays help information, then exits.
|
|
||||||
-v Displays version information, then exits.
|
|
||||||
|
|
||||||
For more help information, issue 'man $prog'.
|
|
||||||
EoHelp
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub show_version()
|
|
||||||
{
|
|
||||||
print <<'EoVersion';
|
|
||||||
CPU-measurement facility utilities, version @S390_TOOLS_RELEASE@
|
|
||||||
Copyright IBM Corp. 2014, 2017
|
|
||||||
|
|
||||||
EoVersion
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_show_info($)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
my $cpumf = $c->{cpumf};
|
|
||||||
my @f = ();
|
|
||||||
|
|
||||||
push @f, "CPU-measurement Counter Facility" if exists $cpumf->{cf};
|
|
||||||
push @f, "CPU-measurement Sampling Facility" if exists $cpumf->{sf};
|
|
||||||
|
|
||||||
if (@f) {
|
|
||||||
print((join "\n", @f) . "\n");
|
|
||||||
} else {
|
|
||||||
print STDERR "No CPU-measurement facilities detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_show_cf($)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
|
|
||||||
# Check if counter facility is available
|
|
||||||
unless (exists $c->{cpumf}->{cf}) {
|
|
||||||
print STDERR "No CPU-measurement counter facility detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Retrieve counter facility information
|
|
||||||
my $cf = $c->{cpumf}->{cf};
|
|
||||||
|
|
||||||
# Create list of authorized counter sets
|
|
||||||
my @sets = ();
|
|
||||||
push @sets, "None" unless $cf->{auth};
|
|
||||||
push @sets, "Crypto-Activity counter set" if $cf->{auth} & 0x8;
|
|
||||||
push @sets, "Problem-State counter set" if $cf->{auth} & 0x4;
|
|
||||||
push @sets, "Basic counter set" if $cf->{auth} & 0x2;
|
|
||||||
push @sets, "Extented counter set" if $cf->{auth} & 0x1;
|
|
||||||
push @sets, "MT-diagnostic counter set" if $cf->{auth} & 0x20;
|
|
||||||
|
|
||||||
print "CPU-measurement counter facility\n";
|
|
||||||
print "-" x 74 . "\n";
|
|
||||||
# TODO Display additional information about available conters depending
|
|
||||||
# on the version information
|
|
||||||
print "Version: " . $cf->{version} . "\n";
|
|
||||||
print "\n";
|
|
||||||
print "Authorized counter sets:\n";
|
|
||||||
print " $_\n" foreach (sort @sets);
|
|
||||||
printf "\nLinux perf event support: %s\n\n",
|
|
||||||
exists $cf->{perf} ? "Yes (PMU: $cf->{perf})" : "No";
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub div_ceil($$)
|
|
||||||
{
|
|
||||||
my ($a, $b) = @_;
|
|
||||||
return int(($a + $b - 1) / $b);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub humanize_bytes($;$)
|
|
||||||
{
|
|
||||||
my $bytes = shift();
|
|
||||||
my @units = split //, " KMGTPEZY";
|
|
||||||
|
|
||||||
my $u = @_ ? shift() : 0;
|
|
||||||
while ($bytes >= 1024 && $u <= $#units) {
|
|
||||||
$bytes /= 1024;
|
|
||||||
$u++;
|
|
||||||
}
|
|
||||||
return sprintf "%.f%sB", $bytes, $units[$u];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub get_sfb_details($)
|
|
||||||
{
|
|
||||||
my $n_sdb = shift();
|
|
||||||
|
|
||||||
# Calculate sampling buffer structure
|
|
||||||
my $n_sdbt = div_ceil($n_sdb, 511);
|
|
||||||
my $n_pages = $n_sdb + $n_sdbt;
|
|
||||||
return [
|
|
||||||
$n_sdb, # number of sample-data-blocks
|
|
||||||
$n_sdbt, # number of sample-data-block-tables
|
|
||||||
$n_pages, # number of 4K pages
|
|
||||||
$n_pages * 4096, # size in bytes
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_show_sf($)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
|
|
||||||
# Check if sampling facility is available
|
|
||||||
unless (exists $c->{cpumf}->{sf}) {
|
|
||||||
print STDERR "No CPU-measurement sampling facility detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
my $sf = $c->{cpumf}->{sf};
|
|
||||||
my $size = invoke_cpumf_helper("--sfb-size");
|
|
||||||
|
|
||||||
# Sampling facility information
|
|
||||||
print "CPU-measurement sampling facility\n";
|
|
||||||
print "-" x 74 . "\n";
|
|
||||||
print "Sampling Interval:\n";
|
|
||||||
printf " Minimum: %10u cycles (approx. %8u Hz)\n",
|
|
||||||
$sf->{min_sampl_interval},
|
|
||||||
1000000 * $sf->{cpu_speed} / $sf->{min_sampl_interval};
|
|
||||||
printf " Maximum: %10u cycles (approx. %8u Hz)\n",
|
|
||||||
$sf->{max_sampl_interval},
|
|
||||||
1000000 * $sf->{cpu_speed} / $sf->{max_sampl_interval};
|
|
||||||
print "\n";
|
|
||||||
print "Authorized sampling modes:\n";
|
|
||||||
foreach my $m (sort keys %{$sf->{modes}}) {
|
|
||||||
printf " %-10s (sample size: %3u bytes)\n", $m,
|
|
||||||
$sf->{modes}->{$m}->{sample_size};
|
|
||||||
}
|
|
||||||
print "\n";
|
|
||||||
printf "\nLinux perf event support: %s\n\n",
|
|
||||||
exists $sf->{perf} ? "Yes (PMU: $sf->{perf})" : "No";
|
|
||||||
|
|
||||||
# Sampling buffer settings for cpum_sf
|
|
||||||
goto out unless exists $sf->{perf};
|
|
||||||
|
|
||||||
print "Current sampling buffer settings for $sf->{perf}:\n";
|
|
||||||
printf " Basic-sampling mode\n";
|
|
||||||
my $s = get_sfb_details($size->[0]);
|
|
||||||
printf " Minimum: %6u sample-data-blocks (%6s)\n",
|
|
||||||
$s->[0], humanize_bytes($s->[3]);
|
|
||||||
$s = get_sfb_details($size->[1]);
|
|
||||||
printf " Maximum: %6u sample-data-blocks (%6s)\n",
|
|
||||||
$s->[0], humanize_bytes($s->[3]);
|
|
||||||
unless (exists $sf->{modes}->{diagnostic}) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sampling buffer setting specific to diagnostic-sampling mode
|
|
||||||
my $f_diag = div_ceil($sf->{modes}->{diagnostic}->{sample_size},
|
|
||||||
$sf->{modes}->{basic}->{sample_size});
|
|
||||||
print "\n";
|
|
||||||
printf " Diagnostic-sampling mode (including basic-sampling)\n";
|
|
||||||
$s = get_sfb_details($size->[0] * $f_diag);
|
|
||||||
printf " Minimum: %6u sample-data-blocks (%6s)\n",
|
|
||||||
$s->[0], humanize_bytes($s->[3]);
|
|
||||||
$s = get_sfb_details($size->[1] * $f_diag);
|
|
||||||
printf " Maximum: %6u sample-data-blocks (%6s)\n",
|
|
||||||
$s->[0], humanize_bytes($s->[3]);
|
|
||||||
printf " Size factor: %2u\n", $f_diag;
|
|
||||||
out:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub print_counters($$)
|
|
||||||
{
|
|
||||||
my ($ctrdef, $header) = @_;
|
|
||||||
my $set_name_map = invoke_cpumf_helper('--ctr-set-names');
|
|
||||||
my $out = [];
|
|
||||||
|
|
||||||
my ($ctr_perf, $ctr_num, $set, $name, $desc);
|
|
||||||
format PERF_CTR_FORM =
|
|
||||||
r@<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
||||||
$ctr_perf, $name
|
|
||||||
|
|
||||||
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
||||||
$desc
|
|
||||||
^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~
|
|
||||||
$desc
|
|
||||||
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
||||||
$set
|
|
||||||
|
|
||||||
.
|
|
||||||
print $header;
|
|
||||||
$~ = "PERF_CTR_FORM";
|
|
||||||
foreach my $ctr (sort { $a <=> $b } keys %$ctrdef) {
|
|
||||||
$ctr_perf = sprintf "%x", $ctr;
|
|
||||||
$ctr_num = $ctr < (1 << 16) ? $ctr : "";
|
|
||||||
$name = $ctrdef->{$ctr}->{name};
|
|
||||||
$desc = $ctrdef->{$ctr}->{shortdesc} ?
|
|
||||||
$ctrdef->{$ctr}->{shortdesc}
|
|
||||||
: $ctrdef->{$ctr}->{desc};
|
|
||||||
$desc .= ".";
|
|
||||||
$set = $set_name_map->{$ctrdef->{$ctr}->{set}};
|
|
||||||
if ($set) {
|
|
||||||
$set = "Counter $ctr_num / $set.";
|
|
||||||
} else {
|
|
||||||
$set = "This event is not associated with a counter set.";
|
|
||||||
}
|
|
||||||
write;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_show_ctr($;$)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
|
|
||||||
# Check if counter facility is available
|
|
||||||
unless (exists $c->{cpumf}->{cf}) {
|
|
||||||
print STDERR "No CPU-measurement counter facility detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Retrieve counter authorization ("all" or authorized counters only)
|
|
||||||
my $auth = @_ ? hex("0xFFFF") : $c->{cpumf}->{cf}->{auth};
|
|
||||||
|
|
||||||
# Retrieve counter information
|
|
||||||
my $ctrs = invoke_cpumf_helper("-c $auth");
|
|
||||||
unless ($ctrs) {
|
|
||||||
print STDERR "No counters are available or authorized\n";
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Retrieve hardware type
|
|
||||||
my $hwtype = invoke_cpumf_helper("--hardware-type");
|
|
||||||
my $model = length $hwtype->[1] ? "for $hwtype->[1]" : "";
|
|
||||||
my $header = <<"EoHeader";
|
|
||||||
Perf event counter list $model
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Raw
|
|
||||||
event Name Description
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
EoHeader
|
|
||||||
print_counters($ctrs, $header);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub do_show_sf_events($)
|
|
||||||
{
|
|
||||||
my $c = shift();
|
|
||||||
|
|
||||||
# Check if sampling facility is available
|
|
||||||
unless (exists $c->{cpumf}->{sf}) {
|
|
||||||
print STDERR "No CPU-measurement sampling facility detected\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
my $sf = $c->{cpumf}->{sf};
|
|
||||||
my $events = invoke_cpumf_helper("--ctr-sf");
|
|
||||||
|
|
||||||
# Remove events with missing authorization
|
|
||||||
delete $events->{0xB0000} unless exists $sf->{modes}->{basic};
|
|
||||||
delete $events->{0xBD000} unless exists $sf->{modes}->{diagnostic};
|
|
||||||
|
|
||||||
unless ($events) {
|
|
||||||
print STDERR "Sampling facility is not authorized\n";
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Display sampling facility events (aka. counters)
|
|
||||||
my $header = <<"EoHeader";
|
|
||||||
Perf events for activating the sampling facility
|
|
||||||
==============================================================================
|
|
||||||
|
|
||||||
Raw
|
|
||||||
event Name Description
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
EoHeader
|
|
||||||
print_counters($events, $header);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub invoke_cpumf_helper($)
|
|
||||||
{
|
|
||||||
my $parms = shift();
|
|
||||||
my $result;
|
|
||||||
|
|
||||||
# Call helper module
|
|
||||||
my $output = qx"$CPUMF_HELPER $parms";
|
|
||||||
die "Failed to run helper module for '$parms'\n" if $? >> 8;
|
|
||||||
$result = eval "$output";
|
|
||||||
die "Failed to parse helper module data\n" if $@;
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
&main();
|
|
||||||
__DATA__
|
|
||||||
__END__
|
|
||||||
+214
@@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* chcpumf - Change CPU Measurement Facility Characteristics
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2020
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
#include "lib/util_prg.h"
|
||||||
|
#include "lib/util_base.h"
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
static int verbose;
|
||||||
|
static unsigned long min_sdb, max_sdb;
|
||||||
|
|
||||||
|
static struct util_opt opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "min", required_argument, NULL, 'm' },
|
||||||
|
.argument = "num_sdb",
|
||||||
|
.desc = "Specifies the initial size of the sampling buffer.\n"
|
||||||
|
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "max", required_argument, NULL, 'x' },
|
||||||
|
.argument = "num_sdb",
|
||||||
|
.desc = "Specifies the maximum size of the sampling buffer.\n"
|
||||||
|
"A sample-data-block (SDB) consumes about 4 kilobytes.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "verbose", no_argument, NULL, 'V' },
|
||||||
|
.desc = "Verbose, display new sample-data-block values.",
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
UTIL_OPT_VERSION,
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct util_prg prg = {
|
||||||
|
.desc = "Change CPU Measurement facility charactertics",
|
||||||
|
.copyright_vec = {
|
||||||
|
{
|
||||||
|
.owner = "IBM Corp.",
|
||||||
|
.pub_first = 2020,
|
||||||
|
.pub_last = 2020,
|
||||||
|
},
|
||||||
|
UTIL_PRG_COPYRIGHT_END
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse tool parameters. Fill in global variables keep_case, buffersize and
|
||||||
|
* command according to parameters. Return VMCP_OK on success, VMCP_OPT
|
||||||
|
* in case of parameter errors. In case of --help or --version, print
|
||||||
|
* respective text to stdout and exit. */
|
||||||
|
static long parse_buffersize(char *string)
|
||||||
|
{
|
||||||
|
char *suffix;
|
||||||
|
long bytes;
|
||||||
|
|
||||||
|
bytes = strtol(string, &suffix, 10);
|
||||||
|
if (strlen(suffix) > 1)
|
||||||
|
return -1;
|
||||||
|
switch (*suffix) {
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
bytes *= 1024;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
bytes *= 1048576;
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_sfb(unsigned long *min, unsigned long *max)
|
||||||
|
{
|
||||||
|
int rc = EXIT_SUCCESS;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(PERF_SFB_SIZE, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
linux_error(PERF_SFB_SIZE);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (fscanf(fp, "%ld,%ld", min, max) != 2) {
|
||||||
|
fprintf(stderr, "Error: Can not parse file " PERF_SFB_SIZE);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_sfb(unsigned long min, unsigned long max)
|
||||||
|
{
|
||||||
|
int rc = EXIT_SUCCESS;
|
||||||
|
char text[64];
|
||||||
|
size_t len;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(PERF_SFB_SIZE, "w");
|
||||||
|
if (fp == NULL) {
|
||||||
|
linux_error(PERF_SFB_SIZE);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
snprintf(text, sizeof text, "%ld,%ld", min, max);
|
||||||
|
len = strlen(text) + 1;
|
||||||
|
if (fwrite(text, 1, len, fp) != len) {
|
||||||
|
linux_error(PERF_SFB_SIZE);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (fclose(fp)) {
|
||||||
|
linux_error(PERF_SFB_SIZE);
|
||||||
|
rc = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (verbose && rc != EXIT_FAILURE)
|
||||||
|
fprintf(stderr, "Sampling buffer sizes:\n"
|
||||||
|
" Minimum:%7ld sample-data-blocks\n"
|
||||||
|
" Maximum:%7ld sample-data-blocks\n",
|
||||||
|
min, max);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_args(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt, action = 0;
|
||||||
|
long new;
|
||||||
|
|
||||||
|
while ((opt = util_opt_getopt_long(argc, argv)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
util_prg_print_help();
|
||||||
|
util_opt_print_help();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'v':
|
||||||
|
util_prg_print_version();
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'x':
|
||||||
|
new = parse_buffersize(optarg);
|
||||||
|
if (new < 1) {
|
||||||
|
fprintf(stderr, "The specified number(s)"
|
||||||
|
" are not valid\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
max_sdb = new;
|
||||||
|
action = 1;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
new = parse_buffersize(optarg);
|
||||||
|
if (new < 1) {
|
||||||
|
fprintf(stderr, "The specified number(s)"
|
||||||
|
" are not valid\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
min_sdb = new;
|
||||||
|
action = 1;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
verbose = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
fprintf(stderr, "One or more options are not valid\n");
|
||||||
|
fprintf(stderr, "Try 'chcpumf --help' for more"
|
||||||
|
" information\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!action) {
|
||||||
|
fprintf(stderr, "You must specify a valid option\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ret = EXIT_FAILURE;
|
||||||
|
struct stat sbuf;
|
||||||
|
|
||||||
|
util_prg_init(&prg);
|
||||||
|
util_opt_init(opt_vec, NULL);
|
||||||
|
|
||||||
|
if (stat(PERF_PATH PERF_SF, &sbuf) != 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"No CPU-measurement sampling facility detected\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (read_sfb(&min_sdb, &max_sdb))
|
||||||
|
return ret;
|
||||||
|
/* Overwrite min_sdb and/or max_sdb */
|
||||||
|
parse_args(argc, argv);
|
||||||
|
if (min_sdb >= max_sdb) {
|
||||||
|
fprintf(stderr, "The specified maximum must be greater "
|
||||||
|
"than the minimum\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return write_sfb(min_sdb, max_sdb);
|
||||||
|
}
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
Counter: 0 Name:CPU_CYCLES
|
|
||||||
Short-Description:CPU Cycles
|
|
||||||
Description:
|
|
||||||
Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 1 Name:INSTRUCTIONS
|
|
||||||
Short-Description:Instructions
|
|
||||||
Description:
|
|
||||||
Instruction Count
|
|
||||||
.
|
|
||||||
Counter: 2 Name:L1I_DIR_WRITES
|
|
||||||
Short-Description:L1I Directory Writes
|
|
||||||
Description:
|
|
||||||
Level-1 I-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 3 Name:L1I_PENALTY_CYCLES
|
|
||||||
Short-Description:L1I Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Level-1 I-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 4 Name:L1D_DIR_WRITES
|
|
||||||
Short-Description:L1D Directory Writes
|
|
||||||
Description:
|
|
||||||
Level-1 D-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 5 Name:L1D_PENALTY_CYCLES
|
|
||||||
Short-Description:L1D Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Level-1 D-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 32 Name:PROBLEM_STATE_CPU_CYCLES
|
|
||||||
Short-Description:Problem-State CPU Cycles
|
|
||||||
Description:
|
|
||||||
Problem-State Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 33 Name:PROBLEM_STATE_INSTRUCTIONS
|
|
||||||
Short-Description:Problem-State Instructions
|
|
||||||
Description:
|
|
||||||
Problem-State Instruction Count
|
|
||||||
.
|
|
||||||
Counter: 34 Name:PROBLEM_STATE_L1I_DIR_WRITES
|
|
||||||
Short-Description:Problem-State L1I Directory Writes
|
|
||||||
Description:
|
|
||||||
Problem-State Level-1 I-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 35 Name:PROBLEM_STATE_L1I_PENALTY_CYCLES
|
|
||||||
Short-Description:Problem-State L1I Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Problem-State Level-1 I-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 36 Name:PROBLEM_STATE_L1D_DIR_WRITES
|
|
||||||
Short-Description:Problem-State L1D Directory Writes
|
|
||||||
Description:
|
|
||||||
Problem-State Level-1 D-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 37 Name:PROBLEM_STATE_L1D_PENALTY_CYCLES
|
|
||||||
Short-Description:Problem-State L1D Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Problem-State Level-1 D-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
Counter: 0 Name:CPU_CYCLES
|
|
||||||
Short-Description:CPU Cycles
|
|
||||||
Description:
|
|
||||||
Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 1 Name:INSTRUCTIONS
|
|
||||||
Short-Description:Instructions
|
|
||||||
Description:
|
|
||||||
Instruction Count
|
|
||||||
.
|
|
||||||
Counter: 2 Name:L1I_DIR_WRITES
|
|
||||||
Short-Description:L1I Directory Writes
|
|
||||||
Description:
|
|
||||||
Level-1 I-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 3 Name:L1I_PENALTY_CYCLES
|
|
||||||
Short-Description:L1I Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Level-1 I-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 4 Name:L1D_DIR_WRITES
|
|
||||||
Short-Description:L1D Directory Writes
|
|
||||||
Description:
|
|
||||||
Level-1 D-Cache Directory Write Count
|
|
||||||
.
|
|
||||||
Counter: 5 Name:L1D_PENALTY_CYCLES
|
|
||||||
Short-Description:L1D Penalty Cycles
|
|
||||||
Description:
|
|
||||||
Level-1 D-Cache Penalty Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 32 Name:PROBLEM_STATE_CPU_CYCLES
|
|
||||||
Short-Description:Problem-State CPU Cycles
|
|
||||||
Description:
|
|
||||||
Problem-State Cycle Count
|
|
||||||
.
|
|
||||||
Counter: 33 Name:PROBLEM_STATE_INSTRUCTIONS
|
|
||||||
Short-Description:Problem-State Instructions
|
|
||||||
Description:
|
|
||||||
Problem-State Instruction Count
|
|
||||||
.
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
Counter: 64 Name:PRNG_FUNCTIONS
|
|
||||||
Short-Description:PRNG Functions
|
|
||||||
Description:
|
|
||||||
Total number of the PRNG functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 65 Name:PRNG_CYCLES
|
|
||||||
Short-Description:PRNG Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles when the DEA/AES coprocessor is busy
|
|
||||||
performing PRNG functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 66 Name:PRNG_BLOCKED_FUNCTIONS
|
|
||||||
Short-Description:PRNG Blocked Functions
|
|
||||||
Description:
|
|
||||||
Total number of the PRNG functions that are issued by the CPU and are
|
|
||||||
blocked because the DEA/AES coprocessor is busy performing a function
|
|
||||||
issued by another CPU
|
|
||||||
.
|
|
||||||
Counter: 67 Name:PRNG_BLOCKED_CYCLES
|
|
||||||
Short-Description:PRNG Blocked Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles blocked for the PRNG functions issued by
|
|
||||||
the CPU because the DEA/AES coprocessor is busy performing a function
|
|
||||||
issued by another CPU
|
|
||||||
.
|
|
||||||
Counter: 68 Name:SHA_FUNCTIONS
|
|
||||||
Short-Description:SHA Functions
|
|
||||||
Description:
|
|
||||||
Total number of SHA functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 69 Name:SHA_CYCLES
|
|
||||||
Short-Description:SHA Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles when the SHA coprocessor is busy performing
|
|
||||||
the SHA functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 70 Name:SHA_BLOCKED_FUNCTIONS
|
|
||||||
Short-Description:SHA Blocked Functions
|
|
||||||
Description:
|
|
||||||
Total number of the SHA functions that are issued by the CPU and are
|
|
||||||
blocked because the SHA coprocessor is busy performing a function issued
|
|
||||||
by another CPU
|
|
||||||
.
|
|
||||||
Counter: 71 Name:SHA_BLOCKED_CYCLES
|
|
||||||
Short-Description:SHA Bloced Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles blocked for the SHA functions issued by the
|
|
||||||
CPU because the SHA coprocessor is busy performing a function issued
|
|
||||||
by another CPU
|
|
||||||
.
|
|
||||||
Counter: 72 Name:DEA_FUNCTIONS
|
|
||||||
Short-Description:DEA Functions
|
|
||||||
Description:
|
|
||||||
Total number of the DEA functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 73 Name:DEA_CYCLES
|
|
||||||
Short-Description:DEA Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles when the DEA/AES coprocessor is busy
|
|
||||||
performing the DEA functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 74 Name:DEA_BLOCKED_FUNCTIONS
|
|
||||||
Short-Description:DEA Blocked Functions
|
|
||||||
Description:
|
|
||||||
Total number of the DEA functions that are issued by the CPU and are
|
|
||||||
blocked because the DEA/AES coprocessor is busy performing a function
|
|
||||||
issued by another CPU
|
|
||||||
.
|
|
||||||
Counter: 75 Name:DEA_BLOCKED_CYCLES
|
|
||||||
Short-Description:DEA Blocked Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles blocked for the DEA functions issued by the
|
|
||||||
CPU because the DEA/AES coprocessor is busy performing a function issued
|
|
||||||
by another CPU
|
|
||||||
.
|
|
||||||
Counter: 76 Name:AES_FUNCTIONS
|
|
||||||
Short-Description:AES Functions
|
|
||||||
Description:
|
|
||||||
Total number of AES functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 77 Name:AES_CYCLES
|
|
||||||
Short-Description:AES Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles when the DEA/AES coprocessor is busy
|
|
||||||
performing the AES functions issued by the CPU
|
|
||||||
.
|
|
||||||
Counter: 78 Name:AES_BLOCKED_FUNCTIONS
|
|
||||||
Short-Description:AES Blocked Functions
|
|
||||||
Description:
|
|
||||||
Total number of AES functions that are issued by the CPU and are blocked
|
|
||||||
because the DEA/AES coprocessor is busy performing a function issued
|
|
||||||
by another CPU
|
|
||||||
.
|
|
||||||
Counter: 79 Name:AES_BLOCKED_CYCLES
|
|
||||||
Short-Description:AES Blocked Cycles
|
|
||||||
Description:
|
|
||||||
Total number of CPU cycles blocked for the AES functions issued by the
|
|
||||||
CPU because the DEA/AES coprocessor is busy performing a function issued
|
|
||||||
by another CPU
|
|
||||||
.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
Counter: 80 Name:ECC_FUNCTION_COUNT
|
|
||||||
Short-Description:ECC Function Count
|
|
||||||
Description:
|
|
||||||
This counter counts the
|
|
||||||
total number of the elliptic-curve cryptography (ECC)
|
|
||||||
functions issued by the CPU.
|
|
||||||
.
|
|
||||||
Counter: 81 Name:ECC_CYCLES_COUNT
|
|
||||||
Short-Description:ECC Cycles Count
|
|
||||||
Description:
|
|
||||||
This counter counts the total
|
|
||||||
number of CPU cycles when the ECC coprocessor is
|
|
||||||
busy performing the elliptic-curve cryptography
|
|
||||||
(ECC) functions issued by the CPU.
|
|
||||||
.
|
|
||||||
Counter: 82 Name:ECC_BLOCKED_FUNCTION_COUNT
|
|
||||||
Short-Description:Ecc Blocked Function Count
|
|
||||||
Description:
|
|
||||||
This counter
|
|
||||||
counts the total number of the elliptic-curve
|
|
||||||
cryptography (ECC) functions that are issued by the CPU
|
|
||||||
and are blocked because the ECC coprocessor is
|
|
||||||
busy performing a function issued by another CPU.
|
|
||||||
.
|
|
||||||
Counter: 83 Name:ECC_BLOCKED_CYCLES_COUNT
|
|
||||||
Short-Description:ECC Blocked Cycles Count
|
|
||||||
Description:
|
|
||||||
This counter counts
|
|
||||||
the total number of CPU cycles blocked for the elliptic-curve
|
|
||||||
cryptography (ECC) functions issued by the
|
|
||||||
CPU because the ECC coprocessor is busy perform-
|
|
||||||
ing a function issued by another CPU.
|
|
||||||
.
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
Counter: 128 Name:L1I_L2_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 (L1.5) cache
|
|
||||||
.
|
|
||||||
Counter: 129 Name:L1D_L2_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the installed
|
|
||||||
cache line was sourced from the Level-2 (L1.5) cache
|
|
||||||
.
|
|
||||||
Counter: 130 Name:L1I_L3_LOCAL_WRITES
|
|
||||||
Short-Description:L1I L3 Local Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the installed
|
|
||||||
cache line was sourced from the Level-3 cache that is on the same book
|
|
||||||
as the Instruction cache (Local L2 cache)
|
|
||||||
.
|
|
||||||
Counter: 131 Name:L1D_L3_LOCAL_WRITES
|
|
||||||
Short-Description:L1D L3 Local Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the installtion
|
|
||||||
cache line was source from the Level-3 cache that is on the same book
|
|
||||||
as the Data cache (Local L2 cache)
|
|
||||||
.
|
|
||||||
Counter: 132 Name:L1I_L3_REMOTE_WRITES
|
|
||||||
Short-Description:L1I L3 Remote Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the installed
|
|
||||||
cache line was sourced from a Level-3 cache that is not on the same
|
|
||||||
book as the Instruction cache (Remote L2 cache)
|
|
||||||
.
|
|
||||||
Counter: 133 Name:L1D_L3_REMOTE_WRITES
|
|
||||||
Short-Description:L1D L3 Remote Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the installed
|
|
||||||
cache line was sourced from a Level-3 cache that is not on the same
|
|
||||||
book as the Data cache (Remote L2 cache)
|
|
||||||
.
|
|
||||||
Counter: 134 Name:L1D_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the installed
|
|
||||||
cache line was sourced from memory that is attached to the same book
|
|
||||||
as the Data cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter: 135 Name:L1I_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache where the installed cache
|
|
||||||
line was sourced from memory that is attached to the s ame book as the
|
|
||||||
Instruction cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter: 136 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache where the line was originally
|
|
||||||
in a Read-Only state in the cache but has been updated to be in the
|
|
||||||
Exclusive state that allows stores to the cache line
|
|
||||||
.
|
|
||||||
Counter: 137 Name:L1I_CACHELINE_INVALIDATES
|
|
||||||
Short-Description:L1I Cacheline Invalidates
|
|
||||||
Description:
|
|
||||||
A cache line in the Level-1 I-Cache has been invalidated by a store on
|
|
||||||
the same CPU as the Level-1 I-Cache
|
|
||||||
.
|
|
||||||
Counter: 138 Name:ITLB1_WRITES
|
|
||||||
Short-Description:ITLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written into the Level-1 Instruction
|
|
||||||
Translation Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter: 139 Name:DTLB1_WRITES
|
|
||||||
Short-Description:DTLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter: 140 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Page Table
|
|
||||||
Entry arrays
|
|
||||||
.
|
|
||||||
Counter: 141 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays
|
|
||||||
.
|
|
||||||
Counter: 142 Name:TLB2_CRSTE_HPAGE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays for a one-megabyte large page translation
|
|
||||||
.
|
|
||||||
Counter: 145 Name:ITLB1_MISSES
|
|
||||||
Short-Description:ITLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Instruction TLB miss in progress. Incremented by one for every
|
|
||||||
cycle an ITLB1 miss is in progress
|
|
||||||
.
|
|
||||||
Counter: 146 Name:DTLB1_MISSES
|
|
||||||
Short-Description:DTLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Data TLB miss in progress. Incremented by one for every cycle
|
|
||||||
an DTLB1 miss is in progress
|
|
||||||
.
|
|
||||||
Counter: 147 Name:L2C_STORES_SENT
|
|
||||||
Short-Description:L2C Stores Sent
|
|
||||||
Description:
|
|
||||||
Incremented by one for every store sent to Level-2 (L1.5) cache
|
|
||||||
.
|
|
||||||
@@ -1,373 +0,0 @@
|
|||||||
# Counter decriptions for the
|
|
||||||
# IBM z13 extended counter and MT-diagnostic counter set
|
|
||||||
#
|
|
||||||
# Notes for transactional-execution mode symbolic names:
|
|
||||||
# TX .. transactional-execution mode
|
|
||||||
# NC .. nonconstrained
|
|
||||||
# C .. constrained
|
|
||||||
#
|
|
||||||
# Undefined counters in the extended counter set:
|
|
||||||
# 142
|
|
||||||
# 180-217
|
|
||||||
# 221-225
|
|
||||||
# Undefined counters in the MT-diagnostic counter set:
|
|
||||||
# 450-495
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Extended Counter Set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:128 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache where the line was
|
|
||||||
originally in a Read-Only state in the cache but has been updated
|
|
||||||
to be in the Exclusive state that allows stores to the cache line.
|
|
||||||
.
|
|
||||||
Counter:129 Name:DTLB1_WRITES
|
|
||||||
Short-Description:DTLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter:130 Name:DTLB1_MISSES
|
|
||||||
Short-Description:DTLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Data TLB miss in progress. Incremented by one for every cycle
|
|
||||||
a DTLB1 miss is in progress.
|
|
||||||
.
|
|
||||||
Counter:131 Name:DTLB1_HPAGE_WRITES
|
|
||||||
Short-Description:DTLB1 One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer for a one-megabyte page
|
|
||||||
.
|
|
||||||
Counter:132 Name:DTLB1_GPAGE_WRITES
|
|
||||||
Short-Description:DTLB1 Two-Gigabyte Page Writes
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer for a two-gigabyte page.
|
|
||||||
.
|
|
||||||
Counter:133 Name:L1D_L2D_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2D Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 Data cache
|
|
||||||
.
|
|
||||||
Counter:134 Name:ITLB1_WRITES
|
|
||||||
Short-Description:ITLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Instruction
|
|
||||||
Translation Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter:135 Name:ITLB1_MISSES
|
|
||||||
Short-Description:ITLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Instruction TLB miss in progress. Incremented by one for every
|
|
||||||
cycle an ITLB1 miss is in progress
|
|
||||||
.
|
|
||||||
Counter:136 Name:L1I_L2I_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2I Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Instruction cache
|
|
||||||
.
|
|
||||||
Counter:137 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Page Table
|
|
||||||
Entry arrays
|
|
||||||
.
|
|
||||||
Counter:138 Name:TLB2_CRSTE_HPAGE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Combined Region
|
|
||||||
Segment Table Entry arrays for a one-megabyte large page translation
|
|
||||||
.
|
|
||||||
Counter:139 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Combined Region
|
|
||||||
Segment Table Entry arrays
|
|
||||||
.
|
|
||||||
Counter:140 Name:TX_C_TEND
|
|
||||||
Short-Description:Completed TEND instructions in constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a constrained transactional-execution
|
|
||||||
mode
|
|
||||||
.
|
|
||||||
Counter:141 Name:TX_NC_TEND
|
|
||||||
Short-Description:Completed TEND instructions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:143 Name:L1C_TLB1_MISSES
|
|
||||||
Short-Description:L1C TLB1 Misses
|
|
||||||
Description:
|
|
||||||
Increments by one for any cycle where a Level-1 cache or Level-1 TLB miss
|
|
||||||
is in progress.
|
|
||||||
.
|
|
||||||
Counter:144 Name:L1D_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:145 Name:L1D_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:146 Name:L1D_ONNODE_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Node L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Node Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:147 Name:L1D_ONNODE_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Node L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Node Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:148 Name:L1D_ONNODE_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Node L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Node Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:149 Name:L1D_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:150 Name:L1D_ONDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Drawer Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:151 Name:L1D_ONDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Drawer Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:152 Name:L1D_OFFDRAWER_SCOL_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Same-Column L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Same-Column Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:153 Name:L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Drawer Same-Column L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Same-Column Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:154 Name:L1D_OFFDRAWER_SCOL_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Same-Column L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Same-Column Level-3 cache
|
|
||||||
without intervention
|
|
||||||
.
|
|
||||||
Counter:155 Name:L1D_OFFDRAWER_FCOL_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Far-Column L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Far-Column Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:156 Name:L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Drawer Far-Column L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Far-Column Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:157 Name:L1D_OFFDRAWER_FCOL_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Far-Column L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Far-Column Level-3 cache
|
|
||||||
without intervention
|
|
||||||
.
|
|
||||||
Counter:158 Name:L1D_ONNODE_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Node Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Node memory
|
|
||||||
.
|
|
||||||
Counter:159 Name:L1D_ONDRAWER_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:160 Name:L1D_OFFDRAWER_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:161 Name:L1D_ONCHIP_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:162 Name:L1I_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Chip Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:163 Name:L1I_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On Chip Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:164 Name:L1I_ONNODE_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Node Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:165 Name:L1I_ONNODE_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Node L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an On-Node Level-3 cache
|
|
||||||
with intervention
|
|
||||||
.
|
|
||||||
Counter:166 Name:L1I_ONNODE_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Node L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an On-Node Level-3 cache
|
|
||||||
without intervention
|
|
||||||
.
|
|
||||||
Counter:167 Name:L1I_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:168 Name:L1I_ONDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an On-Drawer Level-3 cache
|
|
||||||
with intervention
|
|
||||||
.
|
|
||||||
Counter:169 Name:L1I_ONDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an On-Drawer Level-3 cache
|
|
||||||
without intervention
|
|
||||||
.
|
|
||||||
Counter:170 Name:L1I_OFFDRAWER_SCOL_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Same-Column L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Same-Column
|
|
||||||
Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:171 Name:L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Drawer Same-Column L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Same-Column
|
|
||||||
Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:172 Name:L1I_OFFDRAWER_SCOL_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Same-Column L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Same-Column
|
|
||||||
Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:173 Name:L1I_OFFDRAWER_FCOL_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Far-Column L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Far-Column
|
|
||||||
Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:174 Name:L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Drawer Far-Column L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Far-Column
|
|
||||||
Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:175 Name:L1I_OFFDRAWER_FCOL_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Far-Column L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from an Off-Drawer Far-Column
|
|
||||||
Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:176 Name:L1I_ONNODE_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Node Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from On-Node memory
|
|
||||||
.
|
|
||||||
Counter:177 Name:L1I_ONDRAWER_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from On-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:178 Name:L1I_OFFDRAWER_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from On-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:179 Name:L1I_ONCHIP_MEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where
|
|
||||||
the returned cache line was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:218 Name:TX_NC_TABORT
|
|
||||||
Short-Description:Aborted transactions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:219 Name:TX_C_TABORT_NO_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode not using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is not using any special logic to allow the transaction
|
|
||||||
to complete
|
|
||||||
.
|
|
||||||
Counter:220 Name:TX_C_TABORT_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is using special logic to allow the transaction to
|
|
||||||
complete
|
|
||||||
.
|
|
||||||
#
|
|
||||||
# MT-diagnostic counter set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:448 Name:MT_DIAG_CYCLES_ONE_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with one thread active
|
|
||||||
Description:
|
|
||||||
Cycle count with one thread active
|
|
||||||
.
|
|
||||||
Counter:449 Name:MT_DIAG_CYCLES_TWO_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with two threads active
|
|
||||||
Description:
|
|
||||||
Cycle count with two threads active
|
|
||||||
.
|
|
||||||
@@ -1,357 +0,0 @@
|
|||||||
# Counter decriptions for the
|
|
||||||
# IBM z14 extended counter and MT-diagnostic counter set
|
|
||||||
#
|
|
||||||
# Notes for transactional-execution mode symbolic names:
|
|
||||||
# TX .. transactional-execution mode
|
|
||||||
# NC .. nonconstrained
|
|
||||||
# C .. constrained
|
|
||||||
#
|
|
||||||
# Undefined counters in the extended counter set:
|
|
||||||
# 142
|
|
||||||
# 158-161
|
|
||||||
# 176-223
|
|
||||||
# 227-231
|
|
||||||
# 233-242
|
|
||||||
# 246-255
|
|
||||||
# Undefined counters in the MT-diagnostic counter set:
|
|
||||||
# 450-495
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Extended Counter Set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:128 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache where the line was
|
|
||||||
originally in a Read-Only state in the cache but has been updated
|
|
||||||
to be in the Exclusive state that allows stores to the cache line
|
|
||||||
.
|
|
||||||
Counter:129 Name:DTLB2_WRITES
|
|
||||||
Short-Description:DTLB2 Writes
|
|
||||||
Description:
|
|
||||||
A translation has been written into The Translation Lookaside
|
|
||||||
Buffer 2 (TLB2) and the request was made by the data cache
|
|
||||||
.
|
|
||||||
Counter:130 Name:DTLB2_MISSES
|
|
||||||
Short-Description:DTLB2 Misses
|
|
||||||
Description:
|
|
||||||
A TLB2 miss is in progress for a request made by the data cache.
|
|
||||||
Incremented by one for every TLB2 miss in progress for the Level-1
|
|
||||||
Data cache on this cycle
|
|
||||||
.
|
|
||||||
Counter:131 Name:DTLB2_HPAGE_WRITES
|
|
||||||
Short-Description:DTLB2 One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry was written into the Combined Region and Segment
|
|
||||||
Table Entry array in the Level-2 TLB for a one-megabyte page or a
|
|
||||||
Last Host Translation was done
|
|
||||||
.
|
|
||||||
Counter:132 Name:DTLB2_GPAGE_WRITES
|
|
||||||
Short-Description:DTLB2 Two-Gigabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry for a two-gigabyte page was written into the
|
|
||||||
Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:133 Name:L1D_L2D_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2D Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Data cache
|
|
||||||
.
|
|
||||||
Counter:134 Name:ITLB2_WRITES
|
|
||||||
Short-Description:ITLB2 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written into the Translation Lookaside
|
|
||||||
Buffer 2 (TLB2) and the request was made by the instruction cache
|
|
||||||
.
|
|
||||||
Counter:135 Name:ITLB2_MISSES
|
|
||||||
Short-Description:ITLB2 Misses
|
|
||||||
Description:
|
|
||||||
A TLB2 miss is in progress for a request made by the instruction cache.
|
|
||||||
Incremented by one for every TLB2 miss in progress for the Level-1
|
|
||||||
Instruction cache in a cycle
|
|
||||||
.
|
|
||||||
Counter:136 Name:L1I_L2I_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2I Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Instruction cache
|
|
||||||
.
|
|
||||||
Counter:137 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry was written into the Page Table Entry array in the
|
|
||||||
Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:138 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
Translation entries were written into the Combined Region and Segment
|
|
||||||
Table Entry array and the Page Table Entry array in the Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:139 Name:TLB2_ENGINES_BUSY
|
|
||||||
Short-Description:TLB2 Engines Busy
|
|
||||||
Description:
|
|
||||||
The number of Level-2 TLB translation engines busy in a cycle
|
|
||||||
.
|
|
||||||
Counter:140 Name:TX_C_TEND
|
|
||||||
Short-Description:Completed TEND instructions in constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a constrained transactional-execution
|
|
||||||
mode
|
|
||||||
.
|
|
||||||
Counter:141 Name:TX_NC_TEND
|
|
||||||
Short-Description:Completed TEND instructions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:143 Name:L1C_TLB2_MISSES
|
|
||||||
Short-Description:L1C TLB2 Misses
|
|
||||||
Description:
|
|
||||||
Increments by one for any cycle where a level-1 cache or level-2 TLB miss
|
|
||||||
is in progress
|
|
||||||
.
|
|
||||||
Counter:144 Name:L1D_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:145 Name:L1D_ONCHIP_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:146 Name:L1D_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:147 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Cluster Level-3 cache withountervention
|
|
||||||
.
|
|
||||||
Counter:148 Name:L1D_ONCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:149 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Cluster Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:150 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:151 Name:L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:152 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Cluster Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:153 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:154 Name:L1D_OFFDRAWER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:155 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:156 Name:L1D_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:157 Name:L1D_OFFDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:158 Name:L1D_ONCHIP_L3_SOURCED_WRITES_RO
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes read-only
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Chip L3 but a read-only invalidate was
|
|
||||||
done to remove other copies of the cache line
|
|
||||||
.
|
|
||||||
Counter:162 Name:L1I_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from an On-Chip Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:163 Name:L1I_ONCHIP_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:164 Name:L1I_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from an On-Chip Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:165 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:166 Name:L1I_ONCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:167 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from On-Cluster Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:168 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:169 Name:L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:170 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Cluster Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:171 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Drawer Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:172 Name:L1I_OFFDRAWER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:173 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Drawer Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:174 Name:L1I_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:175 Name:L1I_OFFDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:224 Name:BCD_DFP_EXECUTION_SLOTS
|
|
||||||
Short-Description:BCD DFP Execution Slots
|
|
||||||
Description:
|
|
||||||
Count of floating point execution slots used for finished Binary Coded
|
|
||||||
Decimal to Decimal Floating Point conversions. Instructions: CDZT,
|
|
||||||
CXZT, CZDT, CZXT
|
|
||||||
.
|
|
||||||
Counter:225 Name:VX_BCD_EXECUTION_SLOTS
|
|
||||||
Short-Description:VX BCD Execution Slots
|
|
||||||
Description:
|
|
||||||
Count of floating point execution slots used for finished vector arithmetic
|
|
||||||
Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP,
|
|
||||||
VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG
|
|
||||||
.
|
|
||||||
Counter:226 Name:DECIMAL_INSTRUCTIONS
|
|
||||||
Short-Description:Decimal Instructions
|
|
||||||
Description:
|
|
||||||
Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED,
|
|
||||||
EDMK, MP, SRP, SP, ZAP
|
|
||||||
.
|
|
||||||
Counter:232 Name:LAST_HOST_TRANSLATIONS
|
|
||||||
Short-Description:Last host translation done
|
|
||||||
Description:
|
|
||||||
Last Host Translation done
|
|
||||||
.
|
|
||||||
Counter:243 Name:TX_NC_TABORT
|
|
||||||
Short-Description:Aborted transactions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:244 Name:TX_C_TABORT_NO_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode not using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is not using any special logic to allow the transaction
|
|
||||||
to complete
|
|
||||||
.
|
|
||||||
Counter:245 Name:TX_C_TABORT_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is using special logic to allow the transaction to
|
|
||||||
complete
|
|
||||||
.
|
|
||||||
#
|
|
||||||
# MT-diagnostic counter set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:448 Name:MT_DIAG_CYCLES_ONE_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with one thread active
|
|
||||||
Description:
|
|
||||||
Cycle count with one thread active
|
|
||||||
.
|
|
||||||
Counter:449 Name:MT_DIAG_CYCLES_TWO_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with two threads active
|
|
||||||
Description:
|
|
||||||
Cycle count with two threads active
|
|
||||||
.
|
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
# Counter decriptions for the
|
|
||||||
# IBM z14 extended counter and MT-diagnostic counter set
|
|
||||||
#
|
|
||||||
# Notes for transactional-execution mode symbolic names:
|
|
||||||
# TX .. transactional-execution mode
|
|
||||||
# NC .. nonconstrained
|
|
||||||
# C .. constrained
|
|
||||||
#
|
|
||||||
# Undefined counters in the extended counter set:
|
|
||||||
# 142
|
|
||||||
# 158-161
|
|
||||||
# 176-223
|
|
||||||
# 227-231
|
|
||||||
# 233-242
|
|
||||||
# 246-255
|
|
||||||
# Undefined counters in the MT-diagnostic counter set:
|
|
||||||
# 450-495
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Extended Counter Set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:128 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache where the line was
|
|
||||||
originally in a Read-Only state in the cache but has been updated
|
|
||||||
to be in the Exclusive state that allows stores to the cache line
|
|
||||||
.
|
|
||||||
Counter:129 Name:DTLB2_WRITES
|
|
||||||
Short-Description:DTLB2 Writes
|
|
||||||
Description:
|
|
||||||
A translation has been written into The Translation Lookaside
|
|
||||||
Buffer 2 (TLB2) and the request was made by the data cache
|
|
||||||
.
|
|
||||||
Counter:130 Name:DTLB2_MISSES
|
|
||||||
Short-Description:DTLB2 Misses
|
|
||||||
Description:
|
|
||||||
A TLB2 miss is in progress for a request made by the data cache.
|
|
||||||
Incremented by one for every TLB2 miss in progress for the Level-1
|
|
||||||
Data cache on this cycle
|
|
||||||
.
|
|
||||||
Counter:131 Name:DTLB2_HPAGE_WRITES
|
|
||||||
Short-Description:DTLB2 One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry was written into the Combined Region and Segment
|
|
||||||
Table Entry array in the Level-2 TLB for a one-megabyte page
|
|
||||||
.
|
|
||||||
Counter:132 Name:DTLB2_GPAGE_WRITES
|
|
||||||
Short-Description:DTLB2 Two-Gigabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry for a two-gigabyte page was written into the
|
|
||||||
Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:133 Name:L1D_L2D_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2D Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Data cache
|
|
||||||
.
|
|
||||||
Counter:134 Name:ITLB2_WRITES
|
|
||||||
Short-Description:ITLB2 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written into the Translation Lookaside
|
|
||||||
Buffer 2 (TLB2) and the request was made by the instruction cache
|
|
||||||
.
|
|
||||||
Counter:135 Name:ITLB2_MISSES
|
|
||||||
Short-Description:ITLB2 Misses
|
|
||||||
Description:
|
|
||||||
A TLB2 miss is in progress for a request made by the instruction cache.
|
|
||||||
Incremented by one for every TLB2 miss in progress for the Level-1
|
|
||||||
Instruction cache in a cycle
|
|
||||||
.
|
|
||||||
Counter:136 Name:L1I_L2I_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2I Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Instruction cache
|
|
||||||
.
|
|
||||||
Counter:137 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry was written into the Page Table Entry array in the
|
|
||||||
Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:138 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
Translation entries were written into the Combined Region and Segment
|
|
||||||
Table Entry array and the Page Table Entry array in the Level-2 TLB
|
|
||||||
.
|
|
||||||
Counter:139 Name:TLB2_ENGINES_BUSY
|
|
||||||
Short-Description:TLB2 Engines Busy
|
|
||||||
Description:
|
|
||||||
The number of Level-2 TLB translation engines busy in a cycle
|
|
||||||
.
|
|
||||||
Counter:140 Name:TX_C_TEND
|
|
||||||
Short-Description:Completed TEND instructions in constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a constrained transactional-execution
|
|
||||||
mode
|
|
||||||
.
|
|
||||||
Counter:141 Name:TX_NC_TEND
|
|
||||||
Short-Description:Completed TEND instructions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:143 Name:L1C_TLB2_MISSES
|
|
||||||
Short-Description:L1C TLB2 Misses
|
|
||||||
Description:
|
|
||||||
Increments by one for any cycle where a level-1 cache or level-2 TLB miss
|
|
||||||
is in progress
|
|
||||||
.
|
|
||||||
Counter:144 Name:L1D_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:145 Name:L1D_ONCHIP_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:146 Name:L1D_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Chip Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:147 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Cluster Level-3 cache withountervention
|
|
||||||
.
|
|
||||||
Counter:148 Name:L1D_ONCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:149 Name:L1D_ONCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On-Cluster Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:150 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:151 Name:L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:152 Name:L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Cluster Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:153 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:154 Name:L1D_OFFDRAWER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:155 Name:L1D_OFFDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off-Drawer Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:156 Name:L1D_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:157 Name:L1D_OFFDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from Off-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:158 Name:L1D_ONCHIP_L3_SOURCED_WRITES_RO
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes read-only
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from On-Chip L3 but a read-only invalidate was
|
|
||||||
done to remove other copies of the cache line
|
|
||||||
.
|
|
||||||
Counter:162 Name:L1I_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from an On-Chip Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:163 Name:L1I_ONCHIP_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from On-Chip memory
|
|
||||||
.
|
|
||||||
Counter:164 Name:L1I_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache ine was sourced from an On-Chip Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:165 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:166 Name:L1I_ONCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:167 Name:L1I_ONCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from On-Cluster Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:168 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Cluster L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Cluster Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:169 Name:L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Cluster Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Cluster memory
|
|
||||||
.
|
|
||||||
Counter:170 Name:L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Cluster L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Cluster Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:171 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Drawer Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:172 Name:L1I_OFFDRAWER_MEMORY_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Drawer memory
|
|
||||||
.
|
|
||||||
Counter:173 Name:L1I_OFFDRAWER_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Drawer L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off-Drawer Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:174 Name:L1I_ONDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from On-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:175 Name:L1I_OFFDRAWER_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Drawer L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from Off-Drawer Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:224 Name:BCD_DFP_EXECUTION_SLOTS
|
|
||||||
Short-Description:BCD DFP Execution Slots
|
|
||||||
Description:
|
|
||||||
Count of floating point execution slots used for finished Binary Coded
|
|
||||||
Decimal to Decimal Floating Point conversions. Instructions: CDZT,
|
|
||||||
CXZT, CZDT, CZXT
|
|
||||||
.
|
|
||||||
Counter:225 Name:VX_BCD_EXECUTION_SLOTS
|
|
||||||
Short-Description:VX BCD Execution Slots
|
|
||||||
Description:
|
|
||||||
Count of floating point execution slots used for finished vector arithmetic
|
|
||||||
Binary Coded Decimal instructions. Instructions: VAP, VSP, VMPVMSP, VDP,
|
|
||||||
VSDP, VRP, VLIP, VSRP, VPSOPVCP, VTP, VPKZ, VUPKZ, VCVB, VCVBG, VCVDVCVDG
|
|
||||||
.
|
|
||||||
Counter:226 Name:DECIMAL_INSTRUCTIONS
|
|
||||||
Short-Description:Decimal Instructions
|
|
||||||
Description:
|
|
||||||
Decimal instructions dispatched. Instructions: CVB, CVD, AP, CP, DP, ED,
|
|
||||||
EDMK, MP, SRP, SP, ZAP
|
|
||||||
.
|
|
||||||
Counter:232 Name:LAST_HOST_TRANSLATIONS
|
|
||||||
Short-Description:Last host translation done
|
|
||||||
Description:
|
|
||||||
Last Host Translation done
|
|
||||||
.
|
|
||||||
Counter:243 Name:TX_NC_TABORT
|
|
||||||
Short-Description:Aborted transactions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a non-constrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:244 Name:TX_C_TABORT_NO_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode not using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is not using any special logic to allow the transaction
|
|
||||||
to complete
|
|
||||||
.
|
|
||||||
Counter:245 Name:TX_C_TABORT_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is using special logic to allow the transaction to
|
|
||||||
complete
|
|
||||||
.
|
|
||||||
Counter:247 Name:DFLT_ACCESS
|
|
||||||
Short-Description:Cycles CPU spent obtaining access to Deflate unit
|
|
||||||
Description:
|
|
||||||
Cycles CPU spent obtaining access to Deflate unit
|
|
||||||
.
|
|
||||||
Counter:252 Name:DFLT_CYCLES
|
|
||||||
Short-Description:Cycles CPU is using Deflate unit
|
|
||||||
Description:
|
|
||||||
Cycles CPU is using Deflate unit
|
|
||||||
.
|
|
||||||
Counter:264 Name:DFLT_CC
|
|
||||||
Short-Description:Increments by one for every DEFLATE CONVERSION CALL instruction executed
|
|
||||||
Description:
|
|
||||||
Increments by one for every DEFLATE CONVERSION CALL instruction executed
|
|
||||||
.
|
|
||||||
Counter:265 Name:DFLT_CCERROR
|
|
||||||
Short-Description:Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2
|
|
||||||
Description:
|
|
||||||
Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2
|
|
||||||
.
|
|
||||||
#
|
|
||||||
# MT-diagnostic counter set
|
|
||||||
# ---------------------------------------------------------------------
|
|
||||||
Counter:448 Name:MT_DIAG_CYCLES_ONE_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with one thread active
|
|
||||||
Description:
|
|
||||||
Cycle count with one thread active
|
|
||||||
.
|
|
||||||
Counter:449 Name:MT_DIAG_CYCLES_TWO_THR_ACTIVE
|
|
||||||
Short-Description:Cycle count with two threads active
|
|
||||||
Description:
|
|
||||||
Cycle count with two threads active
|
|
||||||
.
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
Counter: 128 Name:L1D_L2_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 cache
|
|
||||||
.
|
|
||||||
Counter: 129 Name:L1I_L2_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 cache
|
|
||||||
.
|
|
||||||
Counter: 130 Name:DTLB1_MISSES
|
|
||||||
Short-Description:DTLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Data TLB miss in progress. Incremented by one for every cycle
|
|
||||||
a DTLB1 miss is in progress.
|
|
||||||
.
|
|
||||||
Counter: 131 Name:ITLB1_MISSES
|
|
||||||
Short-Description:ITLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Instruction TLB miss in progress. Incremented by one for every
|
|
||||||
cycle a ITLB1 miss is in progress.
|
|
||||||
.
|
|
||||||
Counter: 133 Name:L2C_STORES_SENT
|
|
||||||
Short-Description:L2C Stores Sent
|
|
||||||
Description:
|
|
||||||
Incremented by one for every store sent to Level-2 cache
|
|
||||||
.
|
|
||||||
Counter: 134 Name:L1D_OFFBOOK_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Book L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-3 cache
|
|
||||||
.
|
|
||||||
Counter: 135 Name:L1D_ONBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from an On Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter: 136 Name:L1I_ONBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from an On Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter: 137 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache where the line was originally
|
|
||||||
in a Read-Only state in the cache but has been updated to be in the
|
|
||||||
Exclusive state that allows stores to the cache line
|
|
||||||
.
|
|
||||||
Counter: 138 Name:L1D_OFFBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter: 139 Name:L1I_OFFBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter: 140 Name:DTLB1_HPAGE_WRITES
|
|
||||||
Short-Description:DTLB1 One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer for a one-megabyte page
|
|
||||||
.
|
|
||||||
Counter: 141 Name:L1D_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache where the installed cache line
|
|
||||||
was sourced from memory that is attached to the same book as the Data
|
|
||||||
cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter: 142 Name:L1I_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache where the installed cache
|
|
||||||
line was sourced from memory that is attached to the same book as the
|
|
||||||
Instruction cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter: 143 Name:L1I_OFFBOOK_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Book L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-3 cache
|
|
||||||
.
|
|
||||||
Counter: 144 Name:DTLB1_WRITES
|
|
||||||
Short-Description:DTLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter: 145 Name:ITLB1_WRITES
|
|
||||||
Short-Description:ITLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Instruction
|
|
||||||
Translation Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter: 146 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Page Table
|
|
||||||
Entry arrays
|
|
||||||
.
|
|
||||||
Counter: 147 Name:TLB2_CRSTE_HPAGE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays for a one-megabyte large page translation
|
|
||||||
.
|
|
||||||
Counter: 148 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays
|
|
||||||
.
|
|
||||||
Counter: 150 Name:L1D_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from an On Chip Level-3 cache
|
|
||||||
.
|
|
||||||
Counter: 152 Name:L1D_OFFCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Chip/On Book Level-3 cache
|
|
||||||
.
|
|
||||||
Counter: 153 Name:L1I_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from an On Chip Level-3 cache
|
|
||||||
.
|
|
||||||
Counter: 155 Name:L1I_OFFCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 I-Cache directory where the returned
|
|
||||||
cache line was sourced from an Off Chip/On Book Level-3 cache
|
|
||||||
.
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
Counter: 128 Name:DTLB1_MISSES
|
|
||||||
Short-Description:DTLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Data TLB miss in progress. Incremented by one for every cycle
|
|
||||||
a DTLB1 miss is in progress.
|
|
||||||
.
|
|
||||||
Counter:129 Name:ITLB1_MISSES
|
|
||||||
Short-Description:ITLB1 Misses
|
|
||||||
Description:
|
|
||||||
Level-1 Instruction TLB miss in progress. Incremented by one for every
|
|
||||||
cycle a ITLB1 miss is in progress.
|
|
||||||
.
|
|
||||||
Counter:130 Name:L1D_L2I_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2I Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 Instruction cache
|
|
||||||
.
|
|
||||||
Counter:131 Name:L1I_L2I_SOURCED_WRITES
|
|
||||||
Short-Description:L1I L2I Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from the Level-2 Instruction cache
|
|
||||||
.
|
|
||||||
Counter:132 Name:L1D_L2D_SOURCED_WRITES
|
|
||||||
Short-Description:L1D L2D Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from the Level-2 Data cache
|
|
||||||
.
|
|
||||||
Counter:133 Name:DTLB1_WRITES
|
|
||||||
Short-Description:DTLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter:135 Name:L1D_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache where the installed cache line
|
|
||||||
was sourced from memory that is attached to the same book as the Data
|
|
||||||
cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter:137 Name:L1I_LMEM_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Local Memory Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache where the installed cache
|
|
||||||
line was sourced from memory that is attached to the same book as the
|
|
||||||
Instruction cache (Local Memory)
|
|
||||||
.
|
|
||||||
Counter:138 Name:L1D_RO_EXCL_WRITES
|
|
||||||
Short-Description:L1D Read-only Exclusive Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 D-Cache where the line was originally
|
|
||||||
in a Read-Only state in the cache but has been updated to be in the
|
|
||||||
Exclusive state that allows stores to the cache line
|
|
||||||
.
|
|
||||||
Counter:139 Name:DTLB1_HPAGE_WRITES
|
|
||||||
Short-Description:DTLB1 One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Data Translation
|
|
||||||
Lookaside Buffer for a one-megabyte page
|
|
||||||
.
|
|
||||||
Counter:140 Name:ITLB1_WRITES
|
|
||||||
Short-Description:ITLB1 Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-1 Instruction
|
|
||||||
Translation Lookaside Buffer
|
|
||||||
.
|
|
||||||
Counter:141 Name:TLB2_PTE_WRITES
|
|
||||||
Short-Description:TLB2 PTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Page Table
|
|
||||||
Entry arrays
|
|
||||||
.
|
|
||||||
Counter:142 Name:TLB2_CRSTE_HPAGE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE One-Megabyte Page Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays for a one-megabyte large page translation
|
|
||||||
.
|
|
||||||
Counter:143 Name:TLB2_CRSTE_WRITES
|
|
||||||
Short-Description:TLB2 CRSTE Writes
|
|
||||||
Description:
|
|
||||||
A translation entry has been written to the Level-2 TLB Common Region
|
|
||||||
Segment Table Entry arrays
|
|
||||||
.
|
|
||||||
Counter:144 Name:L1D_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On Chip Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:145 Name:L1D_OFFCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off Chip/On Book Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:146 Name:L1D_OFFBOOK_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Book L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-3 cache without intervention
|
|
||||||
.
|
|
||||||
Counter:147 Name:L1D_ONBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D On-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an On Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:148 Name:L1D_OFFBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1D Off-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-4 cache
|
|
||||||
.
|
|
||||||
#
|
|
||||||
# Notes for the transactional-execution mode notations:
|
|
||||||
# TX .. transactional-execution mode
|
|
||||||
# NC .. nonconstrained
|
|
||||||
# C .. constrained
|
|
||||||
#
|
|
||||||
Counter:149 Name:TX_NC_TEND
|
|
||||||
Short-Description:Completed TEND instructions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a nonconstrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:150 Name:L1D_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from a On Chip Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:151 Name:L1D_OFFCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off Chip/On Book Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
# XXX Remove SOURCED from L1D_OFFBOOK_L3_SOURCED_WRITES...
|
|
||||||
Counter:152 Name:L1D_OFFBOOK_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1D Off-Book L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Data cache directory where the returned
|
|
||||||
cache line was sourced from an Off Book Level-3 cache with intervention
|
|
||||||
.
|
|
||||||
Counter:153 Name:L1I_ONCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On Chip Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:154 Name:L1I_OFFCHIP_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Chip L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off Chip/On Book Level-3 cache
|
|
||||||
without intervention
|
|
||||||
.
|
|
||||||
Counter:155 Name:L1I_OFFBOOK_L3_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Book L3 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off Book Level-3 cache without
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:156 Name:L1I_ONBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I On-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:157 Name:L1I_OFFBOOK_L4_SOURCED_WRITES
|
|
||||||
Short-Description:L1I Off-Book L4 Sourced Writes
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off Book Level-4 cache
|
|
||||||
.
|
|
||||||
Counter:158 Name:TX_C_TEND
|
|
||||||
Short-Description:Completed TEND instructions in constrained TX mode
|
|
||||||
Description:
|
|
||||||
A TEND instruction has completed in a constrained transactional-execution
|
|
||||||
mode
|
|
||||||
.
|
|
||||||
Counter:159 Name:L1I_ONCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I On-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an On Chip Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:160 Name:L1I_OFFCHIP_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Chip L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off Chip/On Book Level-3 cache
|
|
||||||
with intervention
|
|
||||||
.
|
|
||||||
Counter:161 Name:L1I_OFFBOOK_L3_SOURCED_WRITES_IV
|
|
||||||
Short-Description:L1I Off-Book L3 Sourced Writes with Intervention
|
|
||||||
Description:
|
|
||||||
A directory write to the Level-1 Instruction cache directory where the
|
|
||||||
returned cache line was sourced from an Off Book Level-3 cache with
|
|
||||||
intervention
|
|
||||||
.
|
|
||||||
Counter:177 Name:TX_NC_TABORT
|
|
||||||
Short-Description:Aborted transactions in non-constrained TX mode
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a nonconstrained
|
|
||||||
transactional-execution mode
|
|
||||||
.
|
|
||||||
Counter:178 Name:TX_C_TABORT_NO_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode not using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is not using any special logic to allow the transaction
|
|
||||||
to complete
|
|
||||||
.
|
|
||||||
Counter:179 Name:TX_C_TABORT_SPECIAL
|
|
||||||
Short-Description:Aborted transactions in constrained TX mode using special completion logic
|
|
||||||
Description:
|
|
||||||
A transaction abort has occurred in a constrained transactional-execution
|
|
||||||
mode and the CPU is using special logic to allow the transaction to
|
|
||||||
complete
|
|
||||||
.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# CPU-measurement facilities
|
|
||||||
#
|
|
||||||
# Mapping of:
|
|
||||||
# 1. CPU-MF counter first/second version numbers to "generic" counter
|
|
||||||
# definitions
|
|
||||||
# 2. IBM z Systems hardware to respective extended counter set definitions
|
|
||||||
#
|
|
||||||
#
|
|
||||||
{
|
|
||||||
# Definition # File name
|
|
||||||
|
|
||||||
# CFVN
|
|
||||||
'cfvn-1' => 'cpum-cf-cfvn-1.ctr',
|
|
||||||
'cfvn-3' => 'cpum-cf-cfvn-3.ctr',
|
|
||||||
|
|
||||||
# CSVN
|
|
||||||
'csvn-12345' => 'cpum-cf-csvn-12345.ctr',
|
|
||||||
'csvn-6' => 'cpum-cf-csvn-6.ctr',
|
|
||||||
|
|
||||||
# Extended counters
|
|
||||||
2097 => 'cpum-cf-extended-z10.ctr',
|
|
||||||
2098 => 'cpum-cf-extended-z10.ctr',
|
|
||||||
2817 => 'cpum-cf-extended-z196.ctr',
|
|
||||||
2818 => 'cpum-cf-extended-z196.ctr',
|
|
||||||
2827 => 'cpum-cf-extended-zEC12.ctr',
|
|
||||||
2828 => 'cpum-cf-extended-zEC12.ctr',
|
|
||||||
2964 => 'cpum-cf-extended-z13.ctr',
|
|
||||||
2965 => 'cpum-cf-extended-z13.ctr',
|
|
||||||
3906 => 'cpum-cf-extended-z14.ctr',
|
|
||||||
3907 => 'cpum-cf-extended-z14.ctr',
|
|
||||||
8561 => 'cpum-cf-extended-z15.ctr',
|
|
||||||
8562 => 'cpum-cf-extended-z15.ctr',
|
|
||||||
};
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Perf raw event counter definitions for the
|
|
||||||
# CPU-measurment sampling facility
|
|
||||||
#
|
|
||||||
# Basic-sampling mode
|
|
||||||
Counter: 0xB0000 Name:SF_CYCLES_BASIC
|
|
||||||
Short-Description:Sample CPU Cycles Using Basic-sampling Mode
|
|
||||||
Description:
|
|
||||||
Sample CPU cycles using basic-sampling mode
|
|
||||||
.
|
|
||||||
# Diagnostic-sampling mode (includes basic-sampling)
|
|
||||||
Counter: 0xBD000 Name:SF_CYCLES_BASIC_DIAG
|
|
||||||
Short-Description:Sample CPU Cycle Using Diagnostic-sampling Mode (not for ordinary use)
|
|
||||||
Description:
|
|
||||||
Sample CPU cycle using diagnostic-sampling mode (not for ordinary use)
|
|
||||||
.
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Defines for CPU Measurement Facility Characteristics
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2020
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEFINES_H
|
||||||
|
#define DEFINES_H
|
||||||
|
|
||||||
|
#define PERF_SFB_SIZE "/sys/module/kernel/parameters/cpum_sfb_size"
|
||||||
|
#define PERF_PATH "/sys/bus/event_source/devices/"
|
||||||
|
#define PERF_SF "cpum_sf"
|
||||||
|
#define PERF_CF "cpum_cf"
|
||||||
|
|
||||||
|
static inline void linux_error(const char *message)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: %s: %s\n", message, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+3120
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@ chcpumf \- manage the CPU-measurement facilities support
|
|||||||
.IR num_sdb ]
|
.IR num_sdb ]
|
||||||
.RB [ \-x | \-\-max
|
.RB [ \-x | \-\-max
|
||||||
.IR num_sdb ]
|
.IR num_sdb ]
|
||||||
|
.RB [ \-V | \-\-verbose ]
|
||||||
.br
|
.br
|
||||||
.B chcpumf
|
.B chcpumf
|
||||||
.BR \-h | \-\-help
|
.BR \-h | \-\-help
|
||||||
|
|||||||
+17
-4
@@ -1,11 +1,11 @@
|
|||||||
\" lscpumf.1
|
\" lscpumf.1
|
||||||
.\"
|
.\"
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright IBM Corp. 2014, 2017
|
.\" Copyright IBM Corp. 2014, 2020
|
||||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
.\" ----------------------------------------------------------------------
|
.\" ----------------------------------------------------------------------
|
||||||
.TH lscpumf "1" "February 2014" "s390-tools" "CPU-MF management programs"
|
.TH lscpumf "1" "May 2020" "s390-tools" "CPU-MF management programs"
|
||||||
.
|
.
|
||||||
.ds c \fBlscpumf\fP
|
.ds c \fBlscpumf\fP
|
||||||
.
|
.
|
||||||
@@ -19,8 +19,8 @@ lscpumf \- display information about CPU-measurement facilities
|
|||||||
.RB [ \-i | \-\-info ]
|
.RB [ \-i | \-\-info ]
|
||||||
.br
|
.br
|
||||||
.B lscpumf
|
.B lscpumf
|
||||||
.RB [ \-c | \-\-list\-counters ]
|
.RB [ \-c | \-\-list\-counters ] [ \-n ]
|
||||||
.RB [ \-C | \-\-list\-all\-counters ]
|
.RB [ \-C | \-\-list\-all\-counters ] [ \-n ]
|
||||||
.RB [ \-s | \-\-list\-sampling\-events ]
|
.RB [ \-s | \-\-list\-sampling\-events ]
|
||||||
.br
|
.br
|
||||||
.B lscpumf
|
.B lscpumf
|
||||||
@@ -46,12 +46,25 @@ facilities.
|
|||||||
Lists counters that are provided by the CPU-measurement facility, omitting
|
Lists counters that are provided by the CPU-measurement facility, omitting
|
||||||
counters for which the LPAR is not authorized. For counter measurements with
|
counters for which the LPAR is not authorized. For counter measurements with
|
||||||
the perf program, the raw event identifier is displayed.
|
the perf program, the raw event identifier is displayed.
|
||||||
|
For Linux version 5.5 and later, the raw event identifier is
|
||||||
|
displayed as <type>:<number>, where type is an integer that the kernel
|
||||||
|
assignes to the CPU Measurement counter facility device driver.
|
||||||
|
For earlier Linux versions the raw event identifier is displayed as r<number>.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-C ", " \-\-list\-all\-counters
|
.BR \-C ", " \-\-list\-all\-counters
|
||||||
Lists all counters that are provided by the CPU-measurement counter facility,
|
Lists all counters that are provided by the CPU-measurement counter facility,
|
||||||
regardless of LPAR authorization. To list only those counters for which the
|
regardless of LPAR authorization. To list only those counters for which the
|
||||||
LPAR is authorized, use the -c option.
|
LPAR is authorized, use the -c option.
|
||||||
|
For linux version 5.5 and later the raw event identifier is
|
||||||
|
displayed as <type>:<number>, where type is the number the CPU Measurement
|
||||||
|
counter facility device driver was assigned to by the kernel.
|
||||||
|
For earlier linux versions the raw event identifier is displayed as r<number>.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-n ", " \-\-name
|
||||||
|
.
|
||||||
|
Display the counter name together with the raw event identifier.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-s ", " \-\-list\-sampling\-events
|
.BR \-s ", " \-\-list\-sampling\-events
|
||||||
|
|||||||
+29
-4
@@ -1,14 +1,39 @@
|
|||||||
include ../common.mak
|
include ../common.mak
|
||||||
|
|
||||||
ALL_CPPFLAGS += -DSYSFS
|
|
||||||
|
|
||||||
all: dasdview
|
|
||||||
|
|
||||||
libs = $(rootdir)/libdasd/libdasd.a \
|
libs = $(rootdir)/libdasd/libdasd.a \
|
||||||
$(rootdir)/libzds/libzds.a \
|
$(rootdir)/libzds/libzds.a \
|
||||||
$(rootdir)/libvtoc/libvtoc.a \
|
$(rootdir)/libvtoc/libvtoc.a \
|
||||||
$(rootdir)/libutil/libutil.a
|
$(rootdir)/libutil/libutil.a
|
||||||
|
|
||||||
|
ifneq (${HAVE_CURL},0)
|
||||||
|
|
||||||
|
check_dep:
|
||||||
|
$(call check_dep, \
|
||||||
|
"dasdview", \
|
||||||
|
"curl/curl.h", \
|
||||||
|
"curl-devel or libcurl-dev", \
|
||||||
|
"HAVE_CURL=0")
|
||||||
|
|
||||||
|
BUILDTARGET = check_dep
|
||||||
|
|
||||||
|
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
||||||
|
CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl)
|
||||||
|
CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl)
|
||||||
|
else
|
||||||
|
CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl
|
||||||
|
CURL_LDLIBS = -lcurl
|
||||||
|
endif # shell
|
||||||
|
|
||||||
|
endif # HAVE_CURL
|
||||||
|
|
||||||
|
BUILDTARGET += dasdview
|
||||||
|
|
||||||
|
ALL_CPPFLAGS += -DSYSFS
|
||||||
|
ALL_CFLAGS += $(CURL_CFLAGS)
|
||||||
|
LDLIBS += $(CURL_LDLIBS)
|
||||||
|
|
||||||
|
all: $(BUILDTARGET)
|
||||||
|
|
||||||
dasdview: dasdview.o $(libs)
|
dasdview: dasdview.o $(libs)
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ if [ -f $CONFIG_FILE ]; then
|
|||||||
. $CONFIG_FILE
|
. $CONFIG_FILE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
UDEVSETTLE=/sbin/udevadm
|
UDEVSETTLE=/usr/bin/udevadm
|
||||||
if [ ! -e $UDEVSETTLE ]
|
if [ ! -e $UDEVSETTLE ]
|
||||||
then
|
then
|
||||||
UDEVSETTLE=/sbin/udevsettle
|
UDEVSETTLE=/sbin/udevsettle
|
||||||
|
|||||||
@@ -6,11 +6,9 @@
|
|||||||
# verifying the issuer, the validity date and the signature.
|
# verifying the issuer, the validity date and the signature.
|
||||||
# Optionally verify the full trust chain using a CA certficate.
|
# Optionally verify the full trust chain using a CA certficate.
|
||||||
#
|
#
|
||||||
# Revocation list checking not yet implemented.
|
|
||||||
#
|
|
||||||
# Sample invocation:
|
# Sample invocation:
|
||||||
#
|
#
|
||||||
# ./check_hostkeydoc HKD1234.crt signing-key.crt
|
# ./check_hostkeydoc HKD1234.crt ibm-z-host-key-signing.crt -c DigiCertCA.crt -r ibm-z-host-key.crl
|
||||||
#
|
#
|
||||||
# Copyright IBM Corp. 2020
|
# Copyright IBM Corp. 2020
|
||||||
#
|
#
|
||||||
@@ -37,8 +35,9 @@ cleanup()
|
|||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
# Enhanced error checking for bash
|
# Enhanced error checking for bash
|
||||||
if echo $SHELL | grep /bin/bash > /dev/null
|
if [ -n "${BASH}" ]
|
||||||
then
|
then
|
||||||
|
set -o posix
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
set -o nounset
|
set -o nounset
|
||||||
fi
|
fi
|
||||||
@@ -101,7 +100,7 @@ extract_body()
|
|||||||
|
|
||||||
verify_signature()
|
verify_signature()
|
||||||
{
|
{
|
||||||
# Assuming that the signature algorith is SHA512 with RSA
|
# Assuming that the signature algorithm is SHA512 with RSA
|
||||||
openssl sha512 -verify $1 -signature $2 $3
|
openssl sha512 -verify $1 -signature $2 $3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ enum diag308_subcode {
|
|||||||
|
|
||||||
enum diag308_rc {
|
enum diag308_rc {
|
||||||
DIAG308_RC_OK = 0x0001,
|
DIAG308_RC_OK = 0x0001,
|
||||||
|
DIAG308_RC_NO_CONF = 0x0102,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
|
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
|
||||||
|
|||||||
@@ -191,6 +191,8 @@
|
|||||||
#define ENDTOKEN 0xFFFFFFFFFFFFFFFFULL
|
#define ENDTOKEN 0xFFFFFFFFFFFFFFFFULL
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_LINE_LENGTH 512
|
||||||
|
#define MAX_SERVER 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This structure represents the count field in an ECKD record.
|
* @brief This structure represents the count field in an ECKD record.
|
||||||
@@ -854,6 +856,7 @@ int lzds_zdsroot_extract_datasets_from_dasd(struct zdsroot *root,
|
|||||||
|
|
||||||
void lzds_dslist_free(struct zdsroot *root);
|
void lzds_dslist_free(struct zdsroot *root);
|
||||||
|
|
||||||
|
int lzds_ping_rest(struct dshandle *dsh, char *server);
|
||||||
|
|
||||||
/** @} */ /* end of group libzds_functions_high */
|
/** @} */ /* end of group libzds_functions_high */
|
||||||
|
|
||||||
@@ -878,6 +881,8 @@ int lzds_analyse_open_count(struct zdsroot *root, int warn);
|
|||||||
/** @} */ /* end of group libzds_functions_helper */
|
/** @} */ /* end of group libzds_functions_helper */
|
||||||
|
|
||||||
|
|
||||||
|
int lzds_rest_get_enq(struct dshandle *dsh, char *server);
|
||||||
|
int lzds_rest_release_enq(struct dshandle *dsh, char *server);
|
||||||
|
int lzds_rest_ping(struct dshandle *dsh, char *server);
|
||||||
|
|
||||||
#endif /* LIB_LIBZDS_H */
|
#endif /* LIB_LIBZDS_H */
|
||||||
|
|||||||
+1
-3
@@ -4,9 +4,7 @@ libs = $(rootdir)/libutil/libutil.a
|
|||||||
|
|
||||||
all: chreipl lsreipl chshut lsshut
|
all: chreipl lsreipl chshut lsshut
|
||||||
|
|
||||||
libs = $(rootdir)/libutil/libutil.a
|
objects = main.o ccw.o fcp.o nvme.o system.o shutdown.o \
|
||||||
|
|
||||||
objects = main.o ccw.o fcp.o system.o shutdown.o \
|
|
||||||
cmd_lsshut.o cmd_chshut.o cmd_lsreipl.o cmd_chreipl.o proc.o
|
cmd_lsshut.o cmd_chshut.o cmd_lsreipl.o cmd_chreipl.o proc.o
|
||||||
|
|
||||||
chreipl: $(objects) $(libs)
|
chreipl: $(objects) $(libs)
|
||||||
|
|||||||
+148
-5
@@ -28,12 +28,14 @@ enum target_type {
|
|||||||
TT_FCP,
|
TT_FCP,
|
||||||
TT_NSS,
|
TT_NSS,
|
||||||
TT_NODE,
|
TT_NODE,
|
||||||
|
TT_NVME,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum reipl_type {
|
enum reipl_type {
|
||||||
REIPL_FCP,
|
REIPL_FCP,
|
||||||
REIPL_CCW,
|
REIPL_CCW,
|
||||||
REIPL_NSS
|
REIPL_NSS,
|
||||||
|
REIPL_NVME,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *const usage_chreipl =
|
static const char *const usage_chreipl =
|
||||||
@@ -41,6 +43,7 @@ static const char *const usage_chreipl =
|
|||||||
"\n"
|
"\n"
|
||||||
" chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n"
|
" chreipl [ccw] [-d] <DEVICE> [OPTIONS]\n"
|
||||||
" chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n"
|
" chreipl [fcp] [-d] <DEVICE> [-w] <WWPN> [-l] <LUN> [OPTIONS]\n"
|
||||||
|
" chreipl nvme [-i] <FID> [-s] <NSID> [OPTIONS]\n"
|
||||||
" chreipl [node] <NODE|DIR> [OPTIONS]\n"
|
" chreipl [node] <NODE|DIR> [OPTIONS]\n"
|
||||||
" chreipl nss [-n] <NAME> [OPTIONS]\n"
|
" chreipl nss [-n] <NAME> [OPTIONS]\n"
|
||||||
" chreipl [-h] [-v]\n"
|
" chreipl [-h] [-v]\n"
|
||||||
@@ -48,6 +51,7 @@ static const char *const usage_chreipl =
|
|||||||
"The following re-IPL targets are supported:\n"
|
"The following re-IPL targets are supported:\n"
|
||||||
" ccw IPL from CCW device\n"
|
" ccw IPL from CCW device\n"
|
||||||
" fcp IPL from FCP device\n"
|
" fcp IPL from FCP device\n"
|
||||||
|
" nvme IPL from NVME device\n"
|
||||||
" nss IPL from NSS\n"
|
" nss IPL from NSS\n"
|
||||||
" node IPL from device specified by device node or directory\n"
|
" node IPL from device specified by device node or directory\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -70,6 +74,12 @@ static const char *const usage_chreipl =
|
|||||||
" -L, --loadparm <PARM> Loadparm specification\n"
|
" -L, --loadparm <PARM> Loadparm specification\n"
|
||||||
" -c, --clear 0|1 Control if memory is cleared on re-IPL\n"
|
" -c, --clear 0|1 Control if memory is cleared on re-IPL\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"Options for nvme target:\n"
|
||||||
|
" -i, --fid <FUNCTION_ID> PCI Function ID of NVME IPL device (hex)\n"
|
||||||
|
" -s --nsid <NAMESPACE_ID> Namespace ID of NVME IPL device (decimal, default 1)\n"
|
||||||
|
" -b, --bootprog <BPROG> Bootprog specification\n"
|
||||||
|
" -L, --loadparm <PARM> Loadparm specification\n"
|
||||||
|
"\n"
|
||||||
"Options for nss target:\n"
|
"Options for nss target:\n"
|
||||||
" -n, --name <NAME> Identifier of the NSS\n"
|
" -n, --name <NAME> Identifier of the NSS\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -86,6 +96,10 @@ static struct locals {
|
|||||||
char lun[20]; /* 18 character +0x" */
|
char lun[20]; /* 18 character +0x" */
|
||||||
int lun_set;
|
int lun_set;
|
||||||
char busid[10]; /* Bus ID e.g. 0.0.4711 */
|
char busid[10]; /* Bus ID e.g. 0.0.4711 */
|
||||||
|
int fid_set;
|
||||||
|
char fid[FID_MAX_LEN];
|
||||||
|
int nsid_set;
|
||||||
|
char nsid[11]; /* 10 decimal chars + null */
|
||||||
int busid_set;
|
int busid_set;
|
||||||
char dev[15]; /* Device (e.g. dasda) */
|
char dev[15]; /* Device (e.g. dasda) */
|
||||||
int dev_set;
|
int dev_set;
|
||||||
@@ -94,10 +108,10 @@ static struct locals {
|
|||||||
char bootparms[4096];
|
char bootparms[4096];
|
||||||
int bootparms_set;
|
int bootparms_set;
|
||||||
int force_set;
|
int force_set;
|
||||||
enum target_type target_type; /* CCW, FCP, NSS or NODE */
|
enum target_type target_type; /* CCW,FCP,NVME,NSS or NODE */
|
||||||
int target_type_set;
|
int target_type_set;
|
||||||
int target_type_auto_mode;
|
int target_type_auto_mode;
|
||||||
enum reipl_type reipl_type; /* CCW, FCP, NSS */
|
enum reipl_type reipl_type; /* CCW, FCP, NVME, NSS */
|
||||||
int reipl_clear;
|
int reipl_clear;
|
||||||
} l;
|
} l;
|
||||||
|
|
||||||
@@ -229,6 +243,34 @@ static void set_wwpn(const char *wwpn)
|
|||||||
l.wwpn_set = 1;
|
l.wwpn_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_nvme_nsid(const char *nsid)
|
||||||
|
{
|
||||||
|
unsigned long long nsid_tmp;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
nsid_tmp = strtoull(nsid, &endptr, 10);
|
||||||
|
if (*endptr)
|
||||||
|
ERR_EXIT("NSID \"%s\" is not a decimal number", nsid);
|
||||||
|
snprintf(l.nsid, sizeof(l.nsid), "%08llu", nsid_tmp);
|
||||||
|
l.nsid_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_nvme_fid(const char *fid)
|
||||||
|
{
|
||||||
|
unsigned long long fid_tmp;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
fid_tmp = strtoull(fid, &endptr, 16);
|
||||||
|
if (*endptr)
|
||||||
|
ERR_EXIT("FID \"%s\" is not a hexadecimal number", fid);
|
||||||
|
snprintf(l.fid, sizeof(l.fid), "0x%08llx", fid_tmp);
|
||||||
|
l.fid_set = 1;
|
||||||
|
|
||||||
|
/* nsid defaults to 1, if not already set */
|
||||||
|
if (!l.nsid_set)
|
||||||
|
set_nvme_nsid("1");
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_fcp_args(char *nargv[], int nargc)
|
static void parse_fcp_args(char *nargv[], int nargc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -248,6 +290,28 @@ static void parse_fcp_args(char *nargv[], int nargc)
|
|||||||
set_lun(nargv[2]);
|
set_lun(nargv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_nvme_args(char *nargv[], int nargc)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* we might be called like this:
|
||||||
|
* chreipl nvme 0x13 1
|
||||||
|
*/
|
||||||
|
if (l.busid_set || l.fid_set || l.nsid_set || l.dev_set)
|
||||||
|
ERR_EXIT("Use either options or positional parameters");
|
||||||
|
if (nargc > 2)
|
||||||
|
ERR_EXIT("Too many arguments specified for \"nvme\" re-IPL "
|
||||||
|
"type");
|
||||||
|
else if (nargc < 1)
|
||||||
|
ERR_EXIT("The \"nvme\" re-IPL type requires function id, and "
|
||||||
|
"optional namespace id");
|
||||||
|
set_nvme_fid(nargv[0]);
|
||||||
|
|
||||||
|
if (nargc == 2)
|
||||||
|
set_nvme_nsid(nargv[1]);
|
||||||
|
else
|
||||||
|
set_nvme_nsid("1");
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_ccw_args(char *nargv[], int nargc)
|
static void parse_ccw_args(char *nargv[], int nargc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -288,6 +352,13 @@ static void dev_from_part(char *dev_name)
|
|||||||
dev_name[i] = 0;
|
dev_name[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dev_from_part_nvme(char *dev_name)
|
||||||
|
{
|
||||||
|
char *delim = strrchr(dev_name, 'p');
|
||||||
|
if (delim)
|
||||||
|
*delim = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int set_reipl_type(const char *dev_name)
|
static int set_reipl_type(const char *dev_name)
|
||||||
{
|
{
|
||||||
if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 ||
|
if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 ||
|
||||||
@@ -295,11 +366,18 @@ static int set_reipl_type(const char *dev_name)
|
|||||||
l.reipl_type = REIPL_CCW;
|
l.reipl_type = REIPL_CCW;
|
||||||
else if (strncmp(dev_name, "sd", strlen("sd")) == 0)
|
else if (strncmp(dev_name, "sd", strlen("sd")) == 0)
|
||||||
l.reipl_type = REIPL_FCP;
|
l.reipl_type = REIPL_FCP;
|
||||||
|
else if (strncmp(dev_name, "nvme", strlen("nvme")) == 0)
|
||||||
|
l.reipl_type = REIPL_NVME;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
util_strlcpy(l.dev, dev_name, sizeof(l.dev));
|
util_strlcpy(l.dev, dev_name, sizeof(l.dev));
|
||||||
dev_from_part(l.dev);
|
|
||||||
|
if (l.reipl_type == REIPL_NVME)
|
||||||
|
dev_from_part_nvme(l.dev);
|
||||||
|
else
|
||||||
|
dev_from_part(l.dev);
|
||||||
|
|
||||||
l.dev_set = 1;
|
l.dev_set = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -402,6 +480,9 @@ static void parse_pos_args(char *nargv[], int nargc)
|
|||||||
case TT_FCP:
|
case TT_FCP:
|
||||||
parse_fcp_args(nargv, nargc);
|
parse_fcp_args(nargv, nargc);
|
||||||
break;
|
break;
|
||||||
|
case TT_NVME:
|
||||||
|
parse_nvme_args(nargv, nargc);
|
||||||
|
break;
|
||||||
case TT_CCW:
|
case TT_CCW:
|
||||||
parse_ccw_args(nargv, nargc);
|
parse_ccw_args(nargv, nargc);
|
||||||
break;
|
break;
|
||||||
@@ -423,6 +504,14 @@ static void check_fcp_opts(void)
|
|||||||
"and LUN");
|
"and LUN");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_nvme_opts(void)
|
||||||
|
{
|
||||||
|
if (l.nss_name_set || l.wwpn_set || l.lun_set || l.busid_set)
|
||||||
|
ERR_EXIT("Invalid option for \"nvme\" target specified");
|
||||||
|
if (!(l.fid_set && l.nsid_set))
|
||||||
|
ERR_EXIT("The \"nvme\" target requires FID, and optional NSID");
|
||||||
|
}
|
||||||
|
|
||||||
static void check_ccw_opts(void)
|
static void check_ccw_opts(void)
|
||||||
{
|
{
|
||||||
if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set)
|
if (l.bootprog_set || l.lun_set || l.wwpn_set || l.nss_name_set)
|
||||||
@@ -482,6 +571,8 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
{ "device", required_argument, NULL, 'd' },
|
{ "device", required_argument, NULL, 'd' },
|
||||||
{ "lun", required_argument, NULL, 'l' },
|
{ "lun", required_argument, NULL, 'l' },
|
||||||
{ "wwpn", required_argument, NULL, 'w' },
|
{ "wwpn", required_argument, NULL, 'w' },
|
||||||
|
{ "fid", required_argument, NULL, 'i' },
|
||||||
|
{ "nsid", required_argument, NULL, 's' },
|
||||||
{ "loadparm", required_argument, NULL, 'L' },
|
{ "loadparm", required_argument, NULL, 'L' },
|
||||||
{ "name", required_argument, NULL, 'n' },
|
{ "name", required_argument, NULL, 'n' },
|
||||||
{ "bootparms", required_argument, NULL, 'p' },
|
{ "bootparms", required_argument, NULL, 'p' },
|
||||||
@@ -490,7 +581,7 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
{ "clear", required_argument, NULL, 'c' },
|
{ "clear", required_argument, NULL, 'c' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
static const char optstr[] = "hd:vw:l:fL:b:n:p:c:";
|
static const char optstr[] = "hd:vw:l:fL:b:n:p:c:i:s:";
|
||||||
|
|
||||||
/* dont run without any argument */
|
/* dont run without any argument */
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
@@ -502,6 +593,8 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
set_target_type(TT_CCW, 0);
|
set_target_type(TT_CCW, 0);
|
||||||
else if (strcmp(argv[1], "nss") == 0)
|
else if (strcmp(argv[1], "nss") == 0)
|
||||||
set_target_type(TT_NSS, 0);
|
set_target_type(TT_NSS, 0);
|
||||||
|
else if (strcmp(argv[1], "nvme") == 0)
|
||||||
|
set_target_type(TT_NVME, 0);
|
||||||
else if (strcmp(argv[1], "node") == 0)
|
else if (strcmp(argv[1], "node") == 0)
|
||||||
set_target_type(TT_NODE, 0);
|
set_target_type(TT_NODE, 0);
|
||||||
else
|
else
|
||||||
@@ -516,9 +609,15 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
case 'd':
|
case 'd':
|
||||||
set_device(optarg);
|
set_device(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'i':
|
||||||
|
set_nvme_fid(optarg);
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
set_lun(optarg);
|
set_lun(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
set_nvme_nsid(optarg);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
set_wwpn(optarg);
|
set_wwpn(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -680,6 +779,40 @@ static void chreipl_fcp(void)
|
|||||||
print_fcp(0, 0);
|
print_fcp(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void chreipl_nvme(void)
|
||||||
|
{
|
||||||
|
check_nvme_opts();
|
||||||
|
|
||||||
|
if (!nvme_is_device(l.fid, l.nsid) && !l.force_set) {
|
||||||
|
ERR_EXIT("Could not find NVME device with fid %s and nsid %s",
|
||||||
|
l.fid, l.nsid);
|
||||||
|
}
|
||||||
|
check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target");
|
||||||
|
|
||||||
|
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
|
||||||
|
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||||
|
strlen(l.bootparms), BOOTPARMS_FCP_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_str_optional(l.loadparm, "reipl/nvme/loadparm", l.loadparm_set,
|
||||||
|
"loadparm");
|
||||||
|
write_str_optional(l.bootparms, "reipl/nvme/scp_data", l.bootparms_set,
|
||||||
|
"boot parameters");
|
||||||
|
write_str(l.fid, "reipl/nvme/fid");
|
||||||
|
write_str(l.nsid, "reipl/nvme/nsid");
|
||||||
|
/*
|
||||||
|
* set the boot record logical block address. Master boot
|
||||||
|
* record. It is always 0 for Linux
|
||||||
|
*/
|
||||||
|
write_str("0", "reipl/nvme/br_lba");
|
||||||
|
if (!l.bootprog_set)
|
||||||
|
sprintf(l.bootprog, "0");
|
||||||
|
write_str(l.bootprog, "reipl/nvme/bootprog");
|
||||||
|
write_str("nvme", "reipl/reipl_type");
|
||||||
|
|
||||||
|
print_nvme(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void chreipl_nss(void)
|
static void chreipl_nss(void)
|
||||||
{
|
{
|
||||||
check_nss_opts();
|
check_nss_opts();
|
||||||
@@ -720,6 +853,13 @@ static void chreipl_node(void)
|
|||||||
l.busid_set = 1;
|
l.busid_set = 1;
|
||||||
chreipl_fcp();
|
chreipl_fcp();
|
||||||
break;
|
break;
|
||||||
|
case REIPL_NVME:
|
||||||
|
nvme_fid_get(l.dev, l.fid);
|
||||||
|
l.fid_set = 1;
|
||||||
|
nvme_nsid_get(l.dev, l.nsid);
|
||||||
|
l.nsid_set = 1;
|
||||||
|
chreipl_nvme();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ERR_EXIT("Internal error: chreipl_node");
|
ERR_EXIT("Internal error: chreipl_node");
|
||||||
}
|
}
|
||||||
@@ -735,6 +875,9 @@ void cmd_chreipl(int argc, char *argv[])
|
|||||||
case TT_FCP:
|
case TT_FCP:
|
||||||
chreipl_fcp();
|
chreipl_fcp();
|
||||||
break;
|
break;
|
||||||
|
case TT_NVME:
|
||||||
|
chreipl_nvme();
|
||||||
|
break;
|
||||||
case TT_NSS:
|
case TT_NSS:
|
||||||
chreipl_nss();
|
chreipl_nss();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -84,6 +84,35 @@ void print_fcp(int show_ipl, int dump)
|
|||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_nvme(int show_ipl, int dump)
|
||||||
|
{
|
||||||
|
char *dir = show_ipl ? "ipl" : "reipl/nvme";
|
||||||
|
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
|
||||||
|
"/sys/firmware/reipl/nvme/scp_data";
|
||||||
|
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
||||||
|
"/sys/firmware/reipl/nvme/loadparm";
|
||||||
|
char loadparm[9], loadparm_path[PATH_MAX];
|
||||||
|
|
||||||
|
if (dump)
|
||||||
|
printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
|
||||||
|
else
|
||||||
|
printf("%-12s nvme\n", get_ipl_banner(show_ipl));
|
||||||
|
|
||||||
|
print_fw_str("FID: %s\n", dir, "fid");
|
||||||
|
print_fw_str("NSID: %s\n", dir, "nsid");
|
||||||
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
||||||
|
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
||||||
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
|
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
||||||
|
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
||||||
|
if (strcmp(loadparm, " ") == 0)
|
||||||
|
loadparm[0] = 0;
|
||||||
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
}
|
||||||
|
if (access(path_bootparms, R_OK) == 0)
|
||||||
|
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
||||||
|
}
|
||||||
|
|
||||||
void print_ccw(int show_ipl)
|
void print_ccw(int show_ipl)
|
||||||
{
|
{
|
||||||
char loadparm[9], loadparm_path[PATH_MAX];
|
char loadparm[9], loadparm_path[PATH_MAX];
|
||||||
@@ -155,6 +184,10 @@ void cmd_lsreipl(int argc, char *argv[])
|
|||||||
print_fcp(l.ipl_set, 0);
|
print_fcp(l.ipl_set, 0);
|
||||||
else if (strcmp(reipl_type_str, "fcp_dump") == 0)
|
else if (strcmp(reipl_type_str, "fcp_dump") == 0)
|
||||||
print_fcp(l.ipl_set, 1);
|
print_fcp(l.ipl_set, 1);
|
||||||
|
else if (strcmp(reipl_type_str, "nvme") == 0)
|
||||||
|
print_nvme(l.ipl_set, 0);
|
||||||
|
else if (strcmp(reipl_type_str, "nvme_dump") == 0)
|
||||||
|
print_nvme(l.ipl_set, 1);
|
||||||
else if (strcmp(reipl_type_str, "ccw") == 0)
|
else if (strcmp(reipl_type_str, "ccw") == 0)
|
||||||
print_ccw(l.ipl_set);
|
print_ccw(l.ipl_set);
|
||||||
else if (strcmp(reipl_type_str, "nss") == 0)
|
else if (strcmp(reipl_type_str, "nss") == 0)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ extern void cmd_chreipl(int argc, char *argv[]);
|
|||||||
|
|
||||||
extern void print_ccw(int show_ipl);
|
extern void print_ccw(int show_ipl);
|
||||||
extern void print_fcp(int show_ipl, int dump);
|
extern void print_fcp(int show_ipl, int dump);
|
||||||
|
extern void print_nvme(int show_ipl, int dump);
|
||||||
extern void print_nss(int show_ipl);
|
extern void print_nss(int show_ipl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -70,6 +71,16 @@ extern void fcp_lun_get(const char *device, char *lun);
|
|||||||
extern void fcp_wwpn_get(const char *device, char *wwpn);
|
extern void fcp_wwpn_get(const char *device, char *wwpn);
|
||||||
extern void fcp_busid_get(const char *device, char *devno);
|
extern void fcp_busid_get(const char *device, char *devno);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NVME
|
||||||
|
*/
|
||||||
|
#define FID_MAX_LEN 11 /* 8 characters + 0x + null */
|
||||||
|
#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
|
||||||
|
|
||||||
|
extern void nvme_fid_get(const char *device, char *fid);
|
||||||
|
extern void nvme_nsid_get(const char *device, char *nsid);
|
||||||
|
int nvme_is_device(char *fid_str, char *nsid_str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CCW
|
* CCW
|
||||||
*/
|
*/
|
||||||
|
|||||||
+52
-1
@@ -39,6 +39,9 @@ Specify a DASD CCW device for reboot
|
|||||||
.RB "- " fcp :
|
.RB "- " fcp :
|
||||||
Specify a FCP device for reboot
|
Specify a FCP device for reboot
|
||||||
.TP
|
.TP
|
||||||
|
.RB "- " nvme :
|
||||||
|
Specify an NVMe device for reboot
|
||||||
|
.TP
|
||||||
.RB "- " nss :
|
.RB "- " nss :
|
||||||
Specify a named saved system (NSS) for reboot
|
Specify a named saved system (NSS) for reboot
|
||||||
.TP
|
.TP
|
||||||
@@ -118,6 +121,11 @@ WWPN 0x500507630300c562, and LUN 0x401040b300000000. In addition to that
|
|||||||
append kernel parameter "mem=" to restrict memory to 512 MB:
|
append kernel parameter "mem=" to restrict memory to 512 MB:
|
||||||
|
|
||||||
\fB# chreipl 0.0.1700 0x500507630300c562 0x401040b300000000 -p "mem=512M"\fP
|
\fB# chreipl 0.0.1700 0x500507630300c562 0x401040b300000000 -p "mem=512M"\fP
|
||||||
|
|
||||||
|
4. Next time reboot from the NVMe device with function id 0x13, namespace 1:
|
||||||
|
|
||||||
|
\fB# chreipl nvme 0x13 1
|
||||||
|
|
||||||
.SH ccw
|
.SH ccw
|
||||||
Use the ccw re-IPL target for DASD devices that are accessed by the hardware
|
Use the ccw re-IPL target for DASD devices that are accessed by the hardware
|
||||||
using channel command word (CCW) channels.
|
using channel command word (CCW) channels.
|
||||||
@@ -207,6 +215,44 @@ use options instead of positional parameters:
|
|||||||
.br
|
.br
|
||||||
|
|
||||||
\fB# chreipl fcp -d 0.0.1700 -w 0x5005076... -l 0x401040b3... -b 2\fP
|
\fB# chreipl fcp -d 0.0.1700 -w 0x5005076... -l 0x401040b3... -b 2\fP
|
||||||
|
.SH nvme
|
||||||
|
Use the nvme re-IPL target for specifying an NVMe disk for reboot.
|
||||||
|
.TP
|
||||||
|
.BR "\-i" " or " "\-\-fid"
|
||||||
|
PCI Function ID of NVME IPL device (hex).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-s" " or " "\-\-nsid"
|
||||||
|
Namespace ID of the NVME IPL device (decimal, default 1).
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-b" " or " "\-\-bootprog"
|
||||||
|
Specifies an entry in the boot configuration by defining the IPL boot
|
||||||
|
program selector. If omitted, '0' will be used.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-L" " or " "\-\-loadparm"
|
||||||
|
The loadparm for the nvme re-IPL target is not used to control the boot
|
||||||
|
configuration that is defined by the
|
||||||
|
.BR zipl (8)
|
||||||
|
boot menu. Instead it can be used to control higher level boot loaders
|
||||||
|
like GRUB. For more details refer to distribution specific documentation.
|
||||||
|
|
||||||
|
.PP
|
||||||
|
\fBExamples:\fP
|
||||||
|
.br
|
||||||
|
|
||||||
|
1. Next time reboot from the NVMe disk with function-id 0x13 and namespace 1:
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB# chreipl nvme 0x13 1\fP
|
||||||
|
.br
|
||||||
|
|
||||||
|
2. Use same configuration as (1) but choose boot program selector 2 and
|
||||||
|
use options instead of positional parameters:
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB# chreipl nvme -i 0x13 -s 1 -b 2\fP
|
||||||
.SH nss
|
.SH nss
|
||||||
Use the nss re-IPL target to specify z/VM named saved systems (NSS) for
|
Use the nss re-IPL target to specify z/VM named saved systems (NSS) for
|
||||||
reboot.
|
reboot.
|
||||||
@@ -221,7 +267,7 @@ Use the NSS named LINUX1 for the next reboot:
|
|||||||
|
|
||||||
\fB# chreipl nss LINUX1\fP
|
\fB# chreipl nss LINUX1\fP
|
||||||
.SH node
|
.SH node
|
||||||
You can identify DASD or SCSI re-IPL devices indirectly through a device
|
You can identify DASD, SCSI, or NVMe re-IPL devices indirectly through a device
|
||||||
node or directory. The chreipl tool then determines the information
|
node or directory. The chreipl tool then determines the information
|
||||||
that you would otherwise have to specify with the ccw or fcp target.
|
that you would otherwise have to specify with the ccw or fcp target.
|
||||||
.PP
|
.PP
|
||||||
@@ -244,6 +290,11 @@ that you would otherwise have to specify with the ccw or fcp target.
|
|||||||
|
|
||||||
\fB# chreipl node /mnt/boot\fP
|
\fB# chreipl node /mnt/boot\fP
|
||||||
|
|
||||||
|
4. Next time reboot from the NVMe device represented by /dev/nvme0n1
|
||||||
|
.br
|
||||||
|
|
||||||
|
\fB# chreipl node /dev/nvme0n1\fP
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR lsreipl (8),
|
.BR lsreipl (8),
|
||||||
.BR zipl (8),
|
.BR zipl (8),
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* ipl_tools - Linux for System z reipl and shutdown tools
|
||||||
|
*
|
||||||
|
* NVMe device functions
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2020
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lib/util_libc.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the fid of a device
|
||||||
|
*/
|
||||||
|
void nvme_fid_get(const char *device, char *fid)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX], buf[FID_MAX_LEN];
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "/sys/block/%s/device/device/function_id",
|
||||||
|
device);
|
||||||
|
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
||||||
|
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
||||||
|
|
||||||
|
util_strlcpy(fid, buf, FID_MAX_LEN);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Return the nsid of a device
|
||||||
|
*/
|
||||||
|
void nvme_nsid_get(const char *device, char *nsid)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX], buf[FID_MAX_LEN];
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "/sys/block/%s/nsid", device);
|
||||||
|
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
||||||
|
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
||||||
|
|
||||||
|
util_strlcpy(nsid, buf, FID_MAX_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int next_entry(DIR *dir, char *in_path, char *out_path,
|
||||||
|
unsigned char entry_type)
|
||||||
|
{
|
||||||
|
struct dirent *dirent;
|
||||||
|
char temp_path[NVME_PATH_MAX];
|
||||||
|
|
||||||
|
while ((dirent = readdir(dir)) != NULL) {
|
||||||
|
if (strcmp(dirent->d_name, ".") == 0 ||
|
||||||
|
strcmp(dirent->d_name, "..") == 0 ||
|
||||||
|
dirent->d_type != entry_type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Resolve the symlink, if needed */
|
||||||
|
if (dirent->d_type == DT_LNK) {
|
||||||
|
snprintf(temp_path, sizeof(temp_path), "%s/%s", in_path,
|
||||||
|
dirent->d_name);
|
||||||
|
if (!realpath(temp_path, out_path))
|
||||||
|
ERR_EXIT_ERRNO("Could not resolve link %s",
|
||||||
|
temp_path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(out_path, NVME_PATH_MAX, "%s/%s", in_path,
|
||||||
|
dirent->d_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvme_getdev_by_fid(char *fidstr, char *devpath)
|
||||||
|
{
|
||||||
|
char temp_path[PATH_MAX+19], real_path[PATH_MAX];
|
||||||
|
char *sys_path = "/sys/class/nvme";
|
||||||
|
u_int64_t target_fid, curfid;
|
||||||
|
DIR *dir;
|
||||||
|
char *end;
|
||||||
|
int rc = -1;
|
||||||
|
|
||||||
|
target_fid = strtoul(fidstr, &end, 16);
|
||||||
|
if (*end)
|
||||||
|
ERR_EXIT("Invalid function_id given %s", fidstr);
|
||||||
|
|
||||||
|
dir = opendir(sys_path);
|
||||||
|
if (!dir)
|
||||||
|
ERR_EXIT("Could not open %s", sys_path);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
while (next_entry(dir, sys_path, real_path, DT_LNK)) {
|
||||||
|
snprintf(temp_path, sizeof(temp_path), "%s/%s", real_path,
|
||||||
|
"device/function_id");
|
||||||
|
if (access(temp_path, F_OK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (util_file_read_ul(&curfid, 16, temp_path))
|
||||||
|
ERR_EXIT("Invalid function_id found in %s", temp_path);
|
||||||
|
|
||||||
|
if (curfid == target_fid) {
|
||||||
|
strncpy(devpath, real_path, PATH_MAX);
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvme_getdev_by_nsid(char *nsid_str, char *path, char *dev_path)
|
||||||
|
{
|
||||||
|
char full_path[NVME_PATH_MAX+1], nsid_path[sizeof(full_path)+5];
|
||||||
|
char *end;
|
||||||
|
u_int64_t nsid, curnsid;
|
||||||
|
DIR *dir;
|
||||||
|
|
||||||
|
nsid = strtoul(nsid_str, &end, 10);
|
||||||
|
if (*end)
|
||||||
|
ERR_EXIT_ERRNO("Invalid namespace id given %s", nsid_str);
|
||||||
|
|
||||||
|
dir = opendir(path);
|
||||||
|
if (!dir)
|
||||||
|
ERR_EXIT_ERRNO("Could not open %s", path);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
while (next_entry(dir, path, full_path, DT_DIR)) {
|
||||||
|
snprintf(nsid_path, sizeof(nsid_path), "%s/%s", full_path,
|
||||||
|
"nsid");
|
||||||
|
if (access(nsid_path, F_OK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (util_file_read_ul(&curnsid, 10, nsid_path))
|
||||||
|
ERR_EXIT("Invalid namespace id found in %s", nsid_path);
|
||||||
|
|
||||||
|
if (curnsid == nsid) {
|
||||||
|
strncpy(dev_path, full_path, NVME_PATH_MAX+1);
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvme_getdev(char *fid_str, char *nsid_str, char *dev_path)
|
||||||
|
{
|
||||||
|
char path_tmp[NVME_PATH_MAX];
|
||||||
|
|
||||||
|
if (nvme_getdev_by_fid(fid_str, path_tmp))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return nvme_getdev_by_nsid(nsid_str, path_tmp, dev_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the specified fid and nsid leads to a valid nvme device
|
||||||
|
*/
|
||||||
|
int nvme_is_device(char *fid_str, char *nsid_str)
|
||||||
|
{
|
||||||
|
char path_tmp[NVME_PATH_MAX+1];
|
||||||
|
|
||||||
|
return !(nvme_getdev(fid_str, nsid_str, path_tmp));
|
||||||
|
}
|
||||||
+7
-2
@@ -49,6 +49,7 @@ struct util_opt_l *util_opt_l = &l;
|
|||||||
#define MAX_OPTLEN 256
|
#define MAX_OPTLEN 256
|
||||||
|
|
||||||
static int opt_max_len(void);
|
static int opt_max_len(void);
|
||||||
|
static bool opt_is_active(struct util_opt *opt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the command line options
|
* Initialize the command line options
|
||||||
@@ -68,7 +69,9 @@ void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix)
|
|||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
/* Get number of options */
|
/* Get number of options */
|
||||||
for (count = 0; opt_vec[count].desc != NULL; count++);
|
for (i = 0, count = 0; opt_vec[i].desc != NULL; i++)
|
||||||
|
if (opt_is_active(&opt_vec[i]))
|
||||||
|
count++;
|
||||||
/*
|
/*
|
||||||
* Allocate short option string for worst case when all options have
|
* Allocate short option string for worst case when all options have
|
||||||
* optional parameters e.g "x::" and long option string.
|
* optional parameters e.g "x::" and long option string.
|
||||||
@@ -85,7 +88,9 @@ void util_opt_init(struct util_opt *opt_vec, const char *opt_prefix)
|
|||||||
/* Force getopt_long() to return ':' for missing required arguments */
|
/* Force getopt_long() to return ':' for missing required arguments */
|
||||||
*str++ = ':';
|
*str++ = ':';
|
||||||
/* Construction of input structures for getopt_long() function. */
|
/* Construction of input structures for getopt_long() function. */
|
||||||
for (i = 0, j = 0; i < count; i++) {
|
for (i = 0, j = 0; opt_vec[i].desc != NULL; i++) {
|
||||||
|
if (!opt_is_active(&opt_vec[i]))
|
||||||
|
continue;
|
||||||
if (opt_vec[i].flags & UTIL_OPT_FLAG_SECTION)
|
if (opt_vec[i].flags & UTIL_OPT_FLAG_SECTION)
|
||||||
continue;
|
continue;
|
||||||
if (!(opt_vec[i].flags & UTIL_OPT_FLAG_NOLONG)) {
|
if (!(opt_vec[i].flags & UTIL_OPT_FLAG_NOLONG)) {
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ static struct util_opt opt_vec[] = {
|
|||||||
.desc = "Option with a required argument REQ_ARG",
|
.desc = "Option with a required argument REQ_ARG",
|
||||||
.command = COMMAND_PULL,
|
.command = COMMAND_PULL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.option = { "test", required_argument, NULL, 't'},
|
||||||
|
.argument = "TEST",
|
||||||
|
.desc = "Option 'test' with a required argument TEST for pull",
|
||||||
|
.command = COMMAND_PULL,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.desc = "OPTIONS",
|
.desc = "OPTIONS",
|
||||||
.flags = UTIL_OPT_FLAG_SECTION,
|
.flags = UTIL_OPT_FLAG_SECTION,
|
||||||
@@ -57,7 +63,12 @@ static struct util_opt opt_vec[] = {
|
|||||||
.option = { NULL, no_argument, NULL, 'l'},
|
.option = { NULL, no_argument, NULL, 'l'},
|
||||||
.desc = "Option with only a short name",
|
.desc = "Option with only a short name",
|
||||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||||
.command = "push",
|
.command = COMMAND_PUSH,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "test", no_argument, NULL, 't'},
|
||||||
|
.desc = "Option 'test' without an argument for push",
|
||||||
|
.command = COMMAND_PUSH,
|
||||||
},
|
},
|
||||||
UTIL_OPT_SECTION("COMMON OPTIONS"),
|
UTIL_OPT_SECTION("COMMON OPTIONS"),
|
||||||
/* Standard option: -h,--help */
|
/* Standard option: -h,--help */
|
||||||
@@ -122,9 +133,6 @@ int main(int argc, char *argv[])
|
|||||||
char **my_argv = argv;
|
char **my_argv = argv;
|
||||||
char *command = NULL;
|
char *command = NULL;
|
||||||
|
|
||||||
/* Install option vector */
|
|
||||||
util_opt_init(opt_vec, NULL);
|
|
||||||
|
|
||||||
/* The command name is the very first argument */
|
/* The command name is the very first argument */
|
||||||
if (argc >= 2 && strncmp(argv[1], "-", 1) != 0) {
|
if (argc >= 2 && strncmp(argv[1], "-", 1) != 0) {
|
||||||
command = argv[1];
|
command = argv[1];
|
||||||
@@ -144,6 +152,9 @@ int main(int argc, char *argv[])
|
|||||||
util_opt_set_command(command);
|
util_opt_set_command(command);
|
||||||
util_prg_set_command(command);
|
util_prg_set_command(command);
|
||||||
|
|
||||||
|
/* Install option vector */
|
||||||
|
util_opt_init(opt_vec, NULL);
|
||||||
|
|
||||||
/* Parse all options specified in my_argv[] */
|
/* Parse all options specified in my_argv[] */
|
||||||
while (1) {
|
while (1) {
|
||||||
/* Get the next option 'c' from my_argv[] */
|
/* Get the next option 'c' from my_argv[] */
|
||||||
@@ -173,6 +184,9 @@ int main(int argc, char *argv[])
|
|||||||
case 'l':
|
case 'l':
|
||||||
printf("Specified: -l\n");
|
printf("Specified: -l\n");
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
printf("Specified: --test %s\n", optarg ? optarg : "");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
util_opt_print_parse_error(c, my_argv);
|
util_opt_print_parse_error(c, my_argv);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|||||||
@@ -2,6 +2,10 @@ include ../common.mak
|
|||||||
|
|
||||||
ALL_CFLAGS += -D_FILE_OFFSET_BITS=64
|
ALL_CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||||
|
|
||||||
|
ifneq (${HAVE_CURL},0)
|
||||||
|
ALL_CFLAGS += -DHAVE_CURL
|
||||||
|
endif
|
||||||
|
|
||||||
lib = libzds.a
|
lib = libzds.a
|
||||||
|
|
||||||
all: $(lib)
|
all: $(lib)
|
||||||
|
|||||||
+281
@@ -18,7 +18,12 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_CURL
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#endif /* HAVE_CURL */
|
||||||
|
|
||||||
|
#include "lib/util_libc.h"
|
||||||
#include "lib/dasd_base.h"
|
#include "lib/dasd_base.h"
|
||||||
#include "lib/dasd_sys.h"
|
#include "lib/dasd_sys.h"
|
||||||
#include "lib/libzds.h"
|
#include "lib/libzds.h"
|
||||||
@@ -300,6 +305,8 @@ struct dshandle {
|
|||||||
unsigned long long skip;
|
unsigned long long skip;
|
||||||
/** @brief Detailed error messages in case of a problem */
|
/** @brief Detailed error messages in case of a problem */
|
||||||
struct errorlog *log;
|
struct errorlog *log;
|
||||||
|
|
||||||
|
char *session_ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
@@ -2942,6 +2949,280 @@ void lzds_dshandle_close(struct dshandle *dsh)
|
|||||||
dsh->is_open = 0;
|
dsh->is_open = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CURL
|
||||||
|
|
||||||
|
struct response_data {
|
||||||
|
char *session_ref;
|
||||||
|
unsigned long statuscode;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
parse_response_callback(void *data, size_t size, size_t member, void *target)
|
||||||
|
{
|
||||||
|
struct response_data *response = target;
|
||||||
|
|
||||||
|
if (strstr(data, "HTTP/1.1 500 Internal Server Error")) {
|
||||||
|
response->statuscode = 500;
|
||||||
|
} else if (strstr(data, "HTTP/1.1 200 OK")) {
|
||||||
|
response->statuscode = 200;
|
||||||
|
} else
|
||||||
|
sscanf(data, "X-IBM-Session-Ref: %m[^\n]\n",
|
||||||
|
&response->session_ref);
|
||||||
|
|
||||||
|
return size*member;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t write_discard_callback(void *UNUSED(data), size_t size, size_t member,
|
||||||
|
void *UNUSED(target))
|
||||||
|
{
|
||||||
|
/* do nothing just pretend all data has been processed */
|
||||||
|
return size*member;
|
||||||
|
}
|
||||||
|
|
||||||
|
CURL *lzds_prepare_curl(char *url)
|
||||||
|
{
|
||||||
|
CURL *curl;
|
||||||
|
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if (!curl)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 0L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_discard_callback);
|
||||||
|
|
||||||
|
return curl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ping the z/OSMS REST server.
|
||||||
|
* Used to check if the server is responding and accessible and to prevent
|
||||||
|
* the ENQ from timing out. If not used it would be automatically released
|
||||||
|
* after 10 minutes.
|
||||||
|
*
|
||||||
|
* @param[in] dsh The dshandle that keeps track of the I/O operations.
|
||||||
|
* server The URL to the z/OSMF REST services
|
||||||
|
* @return 1 on success, 0 otherwise
|
||||||
|
*/
|
||||||
|
int lzds_rest_ping(struct dshandle *dsh, char *server)
|
||||||
|
{
|
||||||
|
struct curl_slist *list = NULL;
|
||||||
|
char *release;
|
||||||
|
CURLcode res;
|
||||||
|
size_t size;
|
||||||
|
CURL *curl;
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
url = util_strcat_realloc(NULL, server);
|
||||||
|
url = util_strcat_realloc(url, "restfiles/ping");
|
||||||
|
|
||||||
|
curl = lzds_prepare_curl(url);
|
||||||
|
if (!curl) {
|
||||||
|
free(url);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = curl_slist_append(list, "X-CSRF-ZOSMF-HEADER: none");
|
||||||
|
if (dsh && dsh->session_ref) {
|
||||||
|
size = sizeof("X-IBM-Session-Ref: ") + strlen(dsh->session_ref);
|
||||||
|
release = util_zalloc(size);
|
||||||
|
snprintf(release, size, "X-IBM-Session-Ref: %s",
|
||||||
|
dsh->session_ref);
|
||||||
|
list = curl_slist_append(list, release);
|
||||||
|
}
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
if (res == CURLE_OK) {
|
||||||
|
free(url);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "URL: %s\n", url);
|
||||||
|
fprintf(stderr, "Error: %s\n", curl_easy_strerror(res));
|
||||||
|
free(url);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the dataset as in use for z/OS.
|
||||||
|
* Use z/OSMF REST services to read a small amount of data and get an exclusive
|
||||||
|
* ENQ that prevents z/OS applications from writing to the dataset in parallel
|
||||||
|
* until the ENQ is released.
|
||||||
|
*
|
||||||
|
* @param[in] dsh The dshandle that keeps track of the I/O operations.
|
||||||
|
* server The URL to the z/OSMF REST services
|
||||||
|
* @return 0 on success, otherwise one of the following error codes:
|
||||||
|
* - ENOTSUP Unable to setup curl and therefore no further access possible.
|
||||||
|
* - EPERM ENQ not obtained and therefore access is not allowed.
|
||||||
|
*/
|
||||||
|
int lzds_rest_get_enq(struct dshandle *dsh, char *server)
|
||||||
|
{
|
||||||
|
struct curl_slist *list = NULL;
|
||||||
|
struct response_data response;
|
||||||
|
int first_run;
|
||||||
|
CURLcode res;
|
||||||
|
CURL *curl;
|
||||||
|
char *url;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
url = util_strcat_realloc(NULL, server);
|
||||||
|
url = util_strcat_realloc(url, "restfiles/ds/");
|
||||||
|
url = util_strcat_realloc(url, dsh->ds->name);
|
||||||
|
|
||||||
|
memset(&response, 0, sizeof(response));
|
||||||
|
/*
|
||||||
|
* in the first run provide a range statement to read only 1 record of
|
||||||
|
* the dataset to get an ENQ.
|
||||||
|
* For the unlikely case that the dataset is empty
|
||||||
|
* "500 Internal Server Error" will be returned.
|
||||||
|
* If this is the case give it a second try without a range statement
|
||||||
|
*/
|
||||||
|
first_run = 1;
|
||||||
|
list = curl_slist_append(list, "X-IBM-Record-Range: 0-1");
|
||||||
|
retry:
|
||||||
|
rc = 1;
|
||||||
|
curl = lzds_prepare_curl(url);
|
||||||
|
if (!curl) {
|
||||||
|
free(url);
|
||||||
|
return errorlog_add_message(
|
||||||
|
&dsh->log,
|
||||||
|
NULL, ENOTSUP,
|
||||||
|
"curl handle not established for dataset %s\n",
|
||||||
|
dsh->ds->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_response_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response);
|
||||||
|
list = curl_slist_append(list, "X-CSRF-ZOSMF-HEADER: none");
|
||||||
|
list = curl_slist_append(list, "X-IBM-Obtain-ENQ: EXCLU");
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
rc = errorlog_add_message(&dsh->log, NULL, ECONNREFUSED,
|
||||||
|
"Error: %s\n",
|
||||||
|
curl_easy_strerror(res));
|
||||||
|
} else {
|
||||||
|
if (first_run && response.statuscode == 500) {
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
first_run = 0;
|
||||||
|
list = NULL;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
/* expect that the callback function found a reference string, double check */
|
||||||
|
if (response.statuscode == 200 && response.session_ref) {
|
||||||
|
dsh->session_ref = response.session_ref;
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
rc = errorlog_add_message(
|
||||||
|
&dsh->log,
|
||||||
|
NULL, EPERM,
|
||||||
|
"no session ref obtained for dataset %s rest rc %ld\n",
|
||||||
|
dsh->ds->name, response.statuscode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(url);
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the dataset as no longer in use for z/OS.
|
||||||
|
* Use z/OSMF REST services to read a small amount of data and release the exclusive
|
||||||
|
* ENQ that was previously obtained.
|
||||||
|
*
|
||||||
|
* @param[in] dsh The dshandle that keeps track of the I/O operations.
|
||||||
|
* server The URL to the z/OSMF REST services
|
||||||
|
* @return 0 on success, otherwise one of the following error codes:
|
||||||
|
* - ENOTSUP Unable to release the ENQ.
|
||||||
|
*/
|
||||||
|
int lzds_rest_release_enq(struct dshandle *dsh, char *server)
|
||||||
|
{
|
||||||
|
struct curl_slist *list = NULL;
|
||||||
|
struct response_data response;
|
||||||
|
char *release;
|
||||||
|
int first_run;
|
||||||
|
CURLcode res;
|
||||||
|
CURL *curl;
|
||||||
|
char *url;
|
||||||
|
|
||||||
|
|
||||||
|
if (!dsh->session_ref) {
|
||||||
|
fprintf(stderr, "No ENQ to release.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = util_strcat_realloc(NULL, server);
|
||||||
|
url = util_strcat_realloc(url, "restfiles/ds/");
|
||||||
|
url = util_strcat_realloc(url, dsh->ds->name);
|
||||||
|
|
||||||
|
release = util_strcat_realloc(NULL, "X-IBM-Session-Ref: ");
|
||||||
|
release = util_strcat_realloc(release, dsh->session_ref);
|
||||||
|
|
||||||
|
memset(&response, 0, sizeof(response));
|
||||||
|
/*
|
||||||
|
* in the first run provide a range statement to read only 1 record of
|
||||||
|
* the dataset to release the ENQ.
|
||||||
|
* For the unlikely case that the dataset is empty
|
||||||
|
* "500 Internal Server Error" will be returned.
|
||||||
|
* If this is the case give it a second try without a range statement
|
||||||
|
*/
|
||||||
|
first_run = 1;
|
||||||
|
list = curl_slist_append(list, "X-IBM-Record-Range: 0-1");
|
||||||
|
retry:
|
||||||
|
curl = lzds_prepare_curl(url);
|
||||||
|
if (!curl) {
|
||||||
|
free(url);
|
||||||
|
free(release);
|
||||||
|
return errorlog_add_message(
|
||||||
|
&dsh->log,
|
||||||
|
NULL, ENOTSUP,
|
||||||
|
"curl handle not established for dataset %s\n",
|
||||||
|
dsh->ds->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
list = curl_slist_append(list, "X-CSRF-ZOSMF-HEADER: none");
|
||||||
|
list = curl_slist_append(list, "X-IBM-Release-ENQ: true");
|
||||||
|
list = curl_slist_append(list, release);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, parse_response_callback);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response);
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
errorlog_add_message(&dsh->log, NULL, ENOTSUP, "Error: %s\n",
|
||||||
|
curl_easy_strerror(res));
|
||||||
|
} else if (first_run && response.statuscode == 500) {
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
first_run = 0;
|
||||||
|
list = NULL;
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_slist_free_all(list);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
free(dsh->session_ref);
|
||||||
|
free(release);
|
||||||
|
free(url);
|
||||||
|
dsh->session_ref = NULL;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_CURL */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This makes the data set context ready for read operations.
|
* This makes the data set context ready for read operations.
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ PROCFILES="\
|
|||||||
/proc/schedstat\
|
/proc/schedstat\
|
||||||
/proc/service_levels\
|
/proc/service_levels\
|
||||||
/proc/slabinfo\
|
/proc/slabinfo\
|
||||||
|
/proc/softirqs\
|
||||||
/proc/stat\
|
/proc/stat\
|
||||||
/proc/swaps\
|
/proc/swaps\
|
||||||
/proc/sys/kernel\
|
/proc/sys/kernel\
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ EnvironmentFile=@sysconf_path@/sysconfig/mon_fsstatd
|
|||||||
#Environment=FSSTAT_INTERVAL=30
|
#Environment=FSSTAT_INTERVAL=30
|
||||||
|
|
||||||
ExecStartPre=-/sbin/modprobe monwriter
|
ExecStartPre=-/sbin/modprobe monwriter
|
||||||
ExecStartPre=/sbin/udevadm settle --timeout=10
|
ExecStartPre=/usr/bin/udevadm settle --timeout=10
|
||||||
ExecStart=@usrsbin_path@/mon_fsstatd -i $FSSTAT_INTERVAL
|
ExecStart=@usrsbin_path@/mon_fsstatd -i $FSSTAT_INTERVAL
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
KillMode=process
|
KillMode=process
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ EnvironmentFile=@sysconf_path@/sysconfig/mon_procd
|
|||||||
#Environment=PROC_INTERVAL=30
|
#Environment=PROC_INTERVAL=30
|
||||||
|
|
||||||
ExecStartPre=-/sbin/modprobe monwriter
|
ExecStartPre=-/sbin/modprobe monwriter
|
||||||
ExecStartPre=/sbin/udevadm settle --timeout=10
|
ExecStartPre=/usr/bin/udevadm settle --timeout=10
|
||||||
ExecStart=@usrsbin_path@/mon_procd -i $PROC_INTERVAL
|
ExecStart=@usrsbin_path@/mon_procd -i $PROC_INTERVAL
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
KillMode=process
|
KillMode=process
|
||||||
|
|||||||
+5
-5
@@ -235,15 +235,15 @@ int main(int argc, char **argv)
|
|||||||
write_buffer(STDOUT_FILENO, cp.response,
|
write_buffer(STDOUT_FILENO, cp.response,
|
||||||
MIN(cp.response_size, cp.buffer_size));
|
MIN(cp.response_size, cp.buffer_size));
|
||||||
free(cp.response);
|
free(cp.response);
|
||||||
if (ret == VMCP_ERR_TOOSMALL) {
|
|
||||||
fprintf(stderr, "Error: output (%d bytes) was truncated, try "
|
|
||||||
"--buffer to increase size\n", cp.response_size);
|
|
||||||
return VMCP_BUF;
|
|
||||||
}
|
|
||||||
if (cp.cprc > 0) {
|
if (cp.cprc > 0) {
|
||||||
fprintf(stderr, "Error: non-zero CP response for command '%s': "
|
fprintf(stderr, "Error: non-zero CP response for command '%s': "
|
||||||
"#%d\n", command, cp.cprc);
|
"#%d\n", command, cp.cprc);
|
||||||
return VMCP_CP;
|
return VMCP_CP;
|
||||||
}
|
}
|
||||||
|
if (ret == VMCP_ERR_TOOSMALL) {
|
||||||
|
fprintf(stderr, "Error: output (%d bytes) was truncated, try "
|
||||||
|
"--buffer to increase size\n", cp.response_size);
|
||||||
|
return VMCP_BUF;
|
||||||
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-4
@@ -24,13 +24,22 @@ my $wlun = "0xc101000000000000";
|
|||||||
my $lun0 = "0x0000000000000000";
|
my $lun0 = "0x0000000000000000";
|
||||||
my $sg_dir = "/sys/class/scsi_generic";
|
my $sg_dir = "/sys/class/scsi_generic";
|
||||||
my $udevsettle_call;
|
my $udevsettle_call;
|
||||||
my $udevadm = "/sbin/udevadm";
|
|
||||||
|
|
||||||
|
|
||||||
if (! -e $udevadm) {
|
# See if we can find udevadm through $PATH:
|
||||||
$udevsettle_call = "/sbin/udevsettle";
|
if (!system("udevadm --version > /dev/null 2>&1")) {
|
||||||
|
$udevsettle_call = "udevadm settle";
|
||||||
|
# Search udevadm in well-known locations:
|
||||||
|
} elsif (-e "/sbin/udevadm") {
|
||||||
|
$udevsettle_call = "/sbin/udevadm settle";
|
||||||
|
} elsif (-e "/usr/bin/udevadm") {
|
||||||
|
$udevsettle_call = "/usr/bin/udevadm settle";
|
||||||
|
# Fall back to udevsettle:
|
||||||
|
} elsif (-e "/sbin/udevsettle") {
|
||||||
|
$udevsettle_call = "/sbin/udevsettle";
|
||||||
} else {
|
} else {
|
||||||
$udevsettle_call = "$udevadm settle";
|
$udevsettle_call = "";
|
||||||
|
print "Failed to find any candidate for udevsettle.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
# read the first line of a sysfs-entry and compare it to a given string
|
# read the first line of a sysfs-entry and compare it to a given string
|
||||||
|
|||||||
+33
-9
@@ -63,14 +63,8 @@ CMD=$(basename $0)
|
|||||||
LSZNET=/lib/s390-tools/lsznet.raw
|
LSZNET=/lib/s390-tools/lsznet.raw
|
||||||
LSZNET_ARGS=-a
|
LSZNET_ARGS=-a
|
||||||
LSZNET_CALL="$LSZNET $LSZNET_ARGS"
|
LSZNET_CALL="$LSZNET $LSZNET_ARGS"
|
||||||
UDEVSETTLE=/sbin/udevadm
|
UDEVSETTLE=udevadm
|
||||||
if [ ! -e $UDEVSETTLE ]
|
UDEVSETTLE_CALL="$UDEVSETTLE settle --timeout=10"
|
||||||
then
|
|
||||||
UDEVSETTLE=/sbin/udevsettle
|
|
||||||
UDEVSETTLE_CALL="$UDEVSETTLE --timeout=10"
|
|
||||||
else
|
|
||||||
UDEVSETTLE_CALL="$UDEVSETTLE settle --timeout=10"
|
|
||||||
fi
|
|
||||||
SYSFSDIR=$(cat /proc/mounts|awk '$3=="sysfs"{print $2; exit}')
|
SYSFSDIR=$(cat /proc/mounts|awk '$3=="sysfs"{print $2; exit}')
|
||||||
CCWGROUPBUS_DIR=$SYSFSDIR/bus/ccwgroup
|
CCWGROUPBUS_DIR=$SYSFSDIR/bus/ccwgroup
|
||||||
CCWDEV_DIR=$SYSFSDIR/bus/ccw/devices
|
CCWDEV_DIR=$SYSFSDIR/bus/ccw/devices
|
||||||
@@ -261,6 +255,35 @@ function lookup_lan_layer()
|
|||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
|
||||||
|
function prepare_udevsettle_cmd()
|
||||||
|
{
|
||||||
|
# is the command available in $PATH
|
||||||
|
if ! [ -x "$(command -v $UDEVSETTLE)" ]
|
||||||
|
then
|
||||||
|
# check the well known locations.
|
||||||
|
if [ -e "/sbin/udevadm" ]
|
||||||
|
then
|
||||||
|
UDEVSETTLE=/sbin/udevadm
|
||||||
|
UDEVSETTLE_CALL="$UDEVSETTLE settle --timeout=10"
|
||||||
|
elif [ -e "/usr/bin/udevadm" ]
|
||||||
|
then
|
||||||
|
UDEVSETTLE=/usr/bin/udevadm
|
||||||
|
UDEVSETTLE_CALL="$UDEVSETTLE settle --timeout=10"
|
||||||
|
elif [ -e "/sbin/udevsettle" ]
|
||||||
|
then
|
||||||
|
# Fallback to udevsettle
|
||||||
|
UDEVSETTLE=/sbin/udevsettle
|
||||||
|
UDEVSETTLE_CALL="$UDEVSETTLE --timeout=10"
|
||||||
|
else
|
||||||
|
UDEVSETTLE=""
|
||||||
|
UDEVSETTLE_CALL=""
|
||||||
|
echo "Failed to find any candidate for udevsettle"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#==============================================================================
|
||||||
|
|
||||||
function lookup_type_and_lan_or_vswitch_name()
|
function lookup_type_and_lan_or_vswitch_name()
|
||||||
{
|
{
|
||||||
local DEVNO="$1"
|
local DEVNO="$1"
|
||||||
@@ -506,8 +529,9 @@ function wait_for_net_device()
|
|||||||
local CMD_FINDNETLINK="find $CCWGROUPBUS_DEVICEDIR/$CCWGROUPDEVNO/ -type l -name net*"
|
local CMD_FINDNETLINK="find $CCWGROUPBUS_DEVICEDIR/$CCWGROUPDEVNO/ -type l -name net*"
|
||||||
local LINKNAME=""
|
local LINKNAME=""
|
||||||
|
|
||||||
|
prepare_udevsettle_cmd
|
||||||
# polling loop to wait for net device to become available
|
# polling loop to wait for net device to become available
|
||||||
if [ -e $UDEVSETTLE ]
|
if [ "$UDEVSETTLE" != "" ]
|
||||||
then
|
then
|
||||||
$UDEVSETTLE_CALL
|
$UDEVSETTLE_CALL
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -511,20 +511,6 @@ static struct attrib qeth_attr_route6 = {
|
|||||||
.st_data = QETH_DATA(layer_3, group_none),
|
.st_data = QETH_DATA(layer_3, group_none),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attrib qeth_attr_fake_broadcast = {
|
|
||||||
.name = "fake_broadcast",
|
|
||||||
.title = "Enable simulation of broadcast capability",
|
|
||||||
.desc =
|
|
||||||
"Control whether a QETH device that doesn't support broadcast should\n"
|
|
||||||
"fake the broadcast capability.\n"
|
|
||||||
" 0: Fake broadcasting depending on hardware capabilities\n"
|
|
||||||
" 1: No faked broadcasting\n",
|
|
||||||
.defval = "0",
|
|
||||||
.order_cmp = after_layer2_order_cmp,
|
|
||||||
.accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)),
|
|
||||||
.st_data = QETH_DATA(layer_3, group_none),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct attrib qeth_attr_ipa_takeover_enable = {
|
static struct attrib qeth_attr_ipa_takeover_enable = {
|
||||||
.name = "ipa_takeover/enable",
|
.name = "ipa_takeover/enable",
|
||||||
.title = "Control IP address takeover",
|
.title = "Control IP address takeover",
|
||||||
@@ -1451,7 +1437,6 @@ struct subtype qeth_subtype_qeth = {
|
|||||||
&qeth_attr_hw_trap,
|
&qeth_attr_hw_trap,
|
||||||
&qeth_attr_route4,
|
&qeth_attr_route4,
|
||||||
&qeth_attr_route6,
|
&qeth_attr_route6,
|
||||||
&qeth_attr_fake_broadcast,
|
|
||||||
&qeth_attr_ipa_takeover_enable,
|
&qeth_attr_ipa_takeover_enable,
|
||||||
&qeth_attr_ipa_takeover_add4,
|
&qeth_attr_ipa_takeover_add4,
|
||||||
&qeth_attr_ipa_takeover_add6,
|
&qeth_attr_ipa_takeover_add6,
|
||||||
|
|||||||
+24
-2
@@ -13,6 +13,17 @@ all:
|
|||||||
install:
|
install:
|
||||||
$(SKIP) HAVE_FUSE=0
|
$(SKIP) HAVE_FUSE=0
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
ifeq (${HAVE_CURL},0)
|
||||||
|
|
||||||
|
all:
|
||||||
|
$(SKIP) HAVE_CURL=0
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(SKIP) HAVE_CURL=0
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
check_dep:
|
check_dep:
|
||||||
@@ -21,17 +32,26 @@ check_dep:
|
|||||||
"fuse.h", \
|
"fuse.h", \
|
||||||
"fuse-devel or libfuse-dev", \
|
"fuse-devel or libfuse-dev", \
|
||||||
"HAVE_FUSE=0")
|
"HAVE_FUSE=0")
|
||||||
|
$(call check_dep, \
|
||||||
|
"zdsfs", \
|
||||||
|
"curl/curl.h", \
|
||||||
|
"curl-devel or libcurl-dev", \
|
||||||
|
"HAVE_CURL=0")
|
||||||
|
|
||||||
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
ifneq ($(shell sh -c 'command -v pkg-config'),)
|
||||||
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse)
|
FUSE_CFLAGS = $(shell pkg-config --silence-errors --cflags fuse)
|
||||||
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse)
|
FUSE_LDLIBS = $(shell pkg-config --silence-errors --libs fuse)
|
||||||
|
CURL_CFLAGS = $(shell pkg-config --silence-errors --cflags libcurl)
|
||||||
|
CURL_LDLIBS = $(shell pkg-config --silence-errors --libs libcurl)
|
||||||
else
|
else
|
||||||
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
|
FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
|
||||||
FUSE_LDLIBS = -lfuse
|
FUSE_LDLIBS = -lfuse
|
||||||
|
CURL_CFLAGS = -I/usr/include/s390x-linux-gnu/curl
|
||||||
|
CURL_LDLIBS = -lcurl
|
||||||
endif
|
endif
|
||||||
ALL_CPPFLAGS += -DSYSFS
|
ALL_CPPFLAGS += -DSYSFS
|
||||||
ALL_CFLAGS += -DHAVE_SETXATTR -pthread $(FUSE_CFLAGS)
|
ALL_CFLAGS += -DHAVE_SETXATTR -pthread $(FUSE_CFLAGS) $(CURL_CFLAGS)
|
||||||
LDLIBS += $(FUSE_LDLIBS) -lpthread -lrt -lm
|
LDLIBS += $(FUSE_LDLIBS) $(CURL_LDLIBS) -lpthread -lrt -lm
|
||||||
|
|
||||||
all: check_dep zdsfs
|
all: check_dep zdsfs
|
||||||
|
|
||||||
@@ -45,6 +65,8 @@ install: all
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ zdsfs core
|
rm -f *.o *~ zdsfs core
|
||||||
|
|
||||||
|
|||||||
+96
-22
@@ -34,21 +34,33 @@ Data sets on tape devices are not supported.
|
|||||||
|
|
||||||
To maintain data consistency, a DASD must not be modified while it is
|
To maintain data consistency, a DASD must not be modified while it is
|
||||||
in use by zdsfs. This can be assured by varying the device offline
|
in use by zdsfs. This can be assured by varying the device offline
|
||||||
in z/OS before setting it online in Linux.
|
in z/OS before setting it online in Linux or by using z/OSMF REST
|
||||||
|
services to notify z/OS about access to data sets.
|
||||||
|
|
||||||
The access to the device by Linux is not subject to RACF or any other
|
Device access by Linux is not subject to RACF or other
|
||||||
z/OS auditing mechanism. The safety of the data on the device must be
|
z/OS auditing mechanisms unless the z/OSMF REST services are used for
|
||||||
established by the respective Linux mechanisms. The default behavior
|
a coordinated read access.
|
||||||
of zdsfs is to grant access to the files in the fuse file system only
|
The safety of the data on the device must be established by
|
||||||
to the user who has started the tool. This behavior can be
|
therespective Linux mechanisms. By default, zdsfs grants access to the
|
||||||
configured by using the options `allow_other', `default_permissions',
|
files in the fuse file system only to the user who started the
|
||||||
`umask', `uid', and `gid'.
|
tool. This behavior can be changed by using the options `allow_other',
|
||||||
|
`default_permissions', `umask', `uid', and `gid'.
|
||||||
|
|
||||||
|
When using the z/OSMF REST services for coordinated read access, a
|
||||||
|
connection is established for every opened file. The z/OSMF REST
|
||||||
|
services confirm that the z/OS userid that is specified in the .netrc
|
||||||
|
configuration file has the required access rights for the data set.
|
||||||
|
Using this mechanism also an exclusive ENQ is obtained to mark the
|
||||||
|
data set as in use to z/OS. The ENQ prevents z/OS applications from
|
||||||
|
modifying the data set during zdsfs access.
|
||||||
|
If the ENQ cannot be obtained, the access from Linux fails with an
|
||||||
|
error.
|
||||||
|
|
||||||
Only physical sequential (PS) and partitioned data sets (PDS) are
|
Only physical sequential (PS) and partitioned data sets (PDS) are
|
||||||
supported. Supported record formats are: V, F, U, B, S, A, and M.
|
supported. Supported record formats are: V, F, U, B, S, A, and M.
|
||||||
|
|
||||||
The file system is limited to basic operations (readdir, stat, open,
|
The file system is limited to basic operations: readdir, stat, open,
|
||||||
read, seek). Because the actual size of the data in each track is not
|
read, and seek. Because the actual size of the data in each track is not
|
||||||
always known, zdsfs does not support mmap. Seek operations read the
|
always known, zdsfs does not support mmap. Seek operations read the
|
||||||
whole data set to the given offset. The performance of seek
|
whole data set to the given offset. The performance of seek
|
||||||
operations to previous offsets can be improved by buffering seek
|
operations to previous offsets can be improved by buffering seek
|
||||||
@@ -59,11 +71,11 @@ cannot provide exact file sizes. As a heuristic, the given file sizes
|
|||||||
are the maximum possible data sizes, based on the number and size of
|
are the maximum possible data sizes, based on the number and size of
|
||||||
the extents that belong to each data set. When the actual end of the
|
the extents that belong to each data set. When the actual end of the
|
||||||
data is reached during read, the usual end of file (EOF) is returned.
|
data is reached during read, the usual end of file (EOF) is returned.
|
||||||
To make sure that the EOF is passed to the user correctly, the option
|
To ensure that the EOF is passed to the user correctly, the option
|
||||||
`-o direct_io' is set by zdsfs implicitly.
|
`-o direct_io' is set by zdsfs implicitly.
|
||||||
|
|
||||||
The detection of incomplete multi volume data sets does not work for
|
Incomplete multi-volume data sets are not detected if only the first
|
||||||
data sets for which only the first volume (device) is present.
|
volume (device) of the data set is present.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.SS "general options:"
|
.SS "general options:"
|
||||||
@@ -89,7 +101,7 @@ Print version information, then exit.
|
|||||||
\fB\-l\fR \fI<device_list>\fR
|
\fB\-l\fR \fI<device_list>\fR
|
||||||
The specified file \fI<device_list>\fR contains a list of device
|
The specified file \fI<device_list>\fR contains a list of device
|
||||||
nodes, separated by white space (space, tab or new line). All device
|
nodes, separated by white space (space, tab or new line). All device
|
||||||
nodes in this file are mounted as if given directly via the command
|
nodes in this file are mounted as if specified directly via the command
|
||||||
line.
|
line.
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR rdw
|
\fB\-o\fR rdw
|
||||||
@@ -119,9 +131,9 @@ standard error stream.
|
|||||||
\fB\-o\fR tracks=\fI<n>\fR
|
\fB\-o\fR tracks=\fI<n>\fR
|
||||||
Size of the track buffer in tracks. The default for \fI<n>\fR is 128.
|
Size of the track buffer in tracks. The default for \fI<n>\fR is 128.
|
||||||
|
|
||||||
The data that is read from the DASD has to be stored in a buffer, because
|
The data that is read from the DASD must be stored in a buffer, because
|
||||||
the minimum size for a read operation in raw access mode is one track,
|
the minimum size for a read operation in raw access mode is one track,
|
||||||
and the user data has to be extracted from the track images. Reading
|
and the user data must be extracted from the track images. Reading
|
||||||
more than one track at a time improves the overall performance, but
|
more than one track at a time improves the overall performance, but
|
||||||
requires larger buffers.
|
requires larger buffers.
|
||||||
|
|
||||||
@@ -154,7 +166,25 @@ read from the beginning of the data set.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-o\fR check_host_count
|
\fB\-o\fR check_host_count
|
||||||
Stop processing if the device is used by another operating system instance.
|
Stop processing if the device is used by another operating system
|
||||||
|
instance.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-c\fR \fI<config_file>\fR
|
||||||
|
zdsfs configuration file. The default is /etc/zdsfs.conf.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-o\fR restapi
|
||||||
|
Make zdsfs use z/OSMF REST services for coordinated read access to
|
||||||
|
data sets. The user credentials are taken from .netrc file in the
|
||||||
|
user's home directory or where the NETRC environment variable points
|
||||||
|
to.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-o\fR restserver=<server_URL>
|
||||||
|
Specify up to 3 server URLs to z/OSMF REST services.
|
||||||
|
For multiple specifications, the URLs are tried sequentially, and the
|
||||||
|
first functioning URL is used.
|
||||||
|
|
||||||
.SS "Applicable FUSE options (version 2.8):"
|
.SS "Applicable FUSE options (version 2.8):"
|
||||||
This is a selected subset of all FUSE options. Use the zdsfs
|
This is a selected subset of all FUSE options. Use the zdsfs
|
||||||
@@ -220,11 +250,10 @@ by z/OS.
|
|||||||
dsn=<data set name>,recfm=<fmt>,lrecl=<size>,dsorg=<org>
|
dsn=<data set name>,recfm=<fmt>,lrecl=<size>,dsorg=<org>
|
||||||
|
|
||||||
\fBdsn\fR: The data set name.
|
\fBdsn\fR: The data set name.
|
||||||
For physical sequential data sets this is the
|
For physical sequential data sets, this is the same as the file name in the mount directory. For partitioned
|
||||||
same name as the file name in the mount directory. For partitioned
|
data sets (PDS), this is the same as the directory name in the mount
|
||||||
data sets (PDS) this is the same as the directory name in the mount
|
directory. For PDS members, the member name is placed after the PDS
|
||||||
directory. For PDS members the member name is placed in parentheses
|
name, in parentheses.
|
||||||
after the PDS name.
|
|
||||||
|
|
||||||
\fBrecfm\fR: The record format.
|
\fBrecfm\fR: The record format.
|
||||||
|
|
||||||
@@ -244,6 +273,44 @@ directory:
|
|||||||
|
|
||||||
\fBuser.dsorg\fR: The data set organization of a file.
|
\fBuser.dsorg\fR: The data set organization of a file.
|
||||||
|
|
||||||
|
.SH zdsfs configuration file
|
||||||
|
|
||||||
|
The default search path is /etc/zdsfs.conf.
|
||||||
|
Use the \fB\-c\fR \fI<config_file>\fR option to specify other zdsfs
|
||||||
|
configuration file locations.
|
||||||
|
|
||||||
|
.br
|
||||||
|
|
||||||
|
The configuration file can contain the following options:
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.B restapi
|
||||||
|
=
|
||||||
|
.IR 0 / 1
|
||||||
|
.IP
|
||||||
|
Setting this option to 1 enables the z/OSMF REST services.
|
||||||
|
The z/OSMF REST services require a valid URL specification for a REST
|
||||||
|
server, and a .netrc file with a valid z/OS user ID and password.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.B restserver
|
||||||
|
=
|
||||||
|
.IR URL
|
||||||
|
.IP
|
||||||
|
Specifies the URL of the z/OSMF REST server that is
|
||||||
|
used for coordinated read access. For failover, up to 3 different
|
||||||
|
server addresses can be provided.
|
||||||
|
.PP
|
||||||
|
|
||||||
|
.B keepalive
|
||||||
|
=
|
||||||
|
.I timeout
|
||||||
|
(in seconds)
|
||||||
|
.IP
|
||||||
|
Specifies the keepalive timer for ENQs.
|
||||||
|
By default the timer is set to 540 seconds to prevent the ENQ from a
|
||||||
|
timeout after 10 minutes in case access to the data set takes longer
|
||||||
|
than this.
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
To mount the z/OS disk with the name dasde enter:
|
To mount the z/OS disk with the name dasde enter:
|
||||||
@@ -270,6 +337,13 @@ To list all extended attributes of file FOOBAR.TEST.TXT
|
|||||||
assuming the z/OS disk was mounted on /mnt:
|
assuming the z/OS disk was mounted on /mnt:
|
||||||
|
|
||||||
# getfattr -d /mnt/FOOBAR.TEST.TXT
|
# getfattr -d /mnt/FOOBAR.TEST.TXT
|
||||||
|
.br
|
||||||
|
|
||||||
|
To mount the z/OS disk using the z/OSMF REST services for coordinated
|
||||||
|
read access:
|
||||||
|
.br
|
||||||
|
|
||||||
|
# ./zdsfs -o restapi -o restserver=zos1.server.tld/zosmf /dev/dasde /mnt/
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
getfattr(1), fuse(8), z/OS DFSMS Using Data Sets,
|
getfattr(1), fuse(8), z/OS DFSMS Using Data Sets,
|
||||||
|
|||||||
+283
-1
@@ -21,6 +21,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef HAVE_SETXATTR
|
#ifdef HAVE_SETXATTR
|
||||||
#include <linux/xattr.h>
|
#include <linux/xattr.h>
|
||||||
@@ -36,6 +39,8 @@
|
|||||||
/* defaults for file and directory permissions (octal) */
|
/* defaults for file and directory permissions (octal) */
|
||||||
#define DEF_FILE_PERM 0440
|
#define DEF_FILE_PERM 0440
|
||||||
#define DEF_DIR_PERM 0550
|
#define DEF_DIR_PERM 0550
|
||||||
|
/* default timer interval 9 minutes, enq times out after 10 minutes */
|
||||||
|
#define DEFAULT_KEEPALIVE_SEC 540
|
||||||
|
|
||||||
struct zdsfs_info {
|
struct zdsfs_info {
|
||||||
int devcount;
|
int devcount;
|
||||||
@@ -50,11 +55,24 @@ struct zdsfs_info {
|
|||||||
size_t metasize; /* total size of meta data buffer */
|
size_t metasize; /* total size of meta data buffer */
|
||||||
size_t metaused; /* how many bytes of buffer are already filled */
|
size_t metaused; /* how many bytes of buffer are already filled */
|
||||||
time_t metatime; /* when did we create this meta data */
|
time_t metatime; /* when did we create this meta data */
|
||||||
|
char *configfile;
|
||||||
|
int restapi;
|
||||||
|
unsigned int nr_server;
|
||||||
|
int active_server;
|
||||||
|
char *server[MAX_SERVER];
|
||||||
|
long keepalive;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct zdsfs_info zdsfsinfo;
|
static struct zdsfs_info zdsfsinfo;
|
||||||
static int zdsfs_create_meta_data_buffer(struct zdsfs_info *);
|
static int zdsfs_create_meta_data_buffer(struct zdsfs_info *);
|
||||||
static int zdsfs_verify_datasets(void);
|
static int zdsfs_verify_datasets(void);
|
||||||
|
static struct util_list *open_dsh;
|
||||||
|
static int timer_running;
|
||||||
|
|
||||||
|
struct dsh_node {
|
||||||
|
struct util_list_node node;
|
||||||
|
struct dshandle *dsh;
|
||||||
|
};
|
||||||
|
|
||||||
struct zdsfs_file_info {
|
struct zdsfs_file_info {
|
||||||
struct dshandle *dsh;
|
struct dshandle *dsh;
|
||||||
@@ -64,6 +82,67 @@ struct zdsfs_file_info {
|
|||||||
size_t metaread; /* how many bytes have already been read */
|
size_t metaread; /* how many bytes have already been read */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Allocate and initialize a new list of struct dsh_node. */
|
||||||
|
static struct util_list *dshlist_alloc(void)
|
||||||
|
{
|
||||||
|
struct util_list *list;
|
||||||
|
|
||||||
|
list = util_malloc(sizeof(struct util_list));
|
||||||
|
util_list_init(list, struct dsh_node, node);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free list of struct dsh_node. */
|
||||||
|
static void dshlist_free(struct util_list *list)
|
||||||
|
{
|
||||||
|
struct dsh_node *s, *n;
|
||||||
|
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
util_list_iterate_safe(list, s, n) {
|
||||||
|
util_list_remove(list, s);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add dsh to list */
|
||||||
|
static void dshlist_add(struct util_list *list, struct dshandle *dsh)
|
||||||
|
{
|
||||||
|
struct dsh_node *s;
|
||||||
|
|
||||||
|
s = util_malloc(sizeof(struct dsh_node));
|
||||||
|
s->dsh = dsh;
|
||||||
|
util_list_add_tail(list, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find a dsh_node. */
|
||||||
|
static struct dsh_node *dshlist_find(struct util_list *list, struct dshandle *dsh)
|
||||||
|
{
|
||||||
|
struct dsh_node *s;
|
||||||
|
|
||||||
|
util_list_iterate(list, s) {
|
||||||
|
if (s->dsh == dsh)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove a dsh_node from the list. */
|
||||||
|
void dshlist_remove(struct util_list *list, struct dshandle *dsh)
|
||||||
|
{
|
||||||
|
struct dsh_node *p;
|
||||||
|
|
||||||
|
p = dshlist_find(list, dsh);
|
||||||
|
if (p) {
|
||||||
|
util_list_remove(list, p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* normalize the given path name to a dataset name
|
/* normalize the given path name to a dataset name
|
||||||
@@ -97,7 +176,47 @@ static void path_to_member_name(const char *path, char *normds, size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setup_timer(long sec)
|
||||||
|
{
|
||||||
|
static struct itimerval timer;
|
||||||
|
|
||||||
|
memset(&timer, 0, sizeof(struct itimerval));
|
||||||
|
timer.it_value.tv_sec = sec;
|
||||||
|
setitimer(ITIMER_REAL, &timer, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keep_alive(int UNUSED(signal))
|
||||||
|
{
|
||||||
|
struct dsh_node *s;
|
||||||
|
|
||||||
|
if (!open_dsh) {
|
||||||
|
timer_running = 0;
|
||||||
|
setup_timer(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
util_list_iterate(open_dsh, s) {
|
||||||
|
lzds_rest_ping(s->dsh,
|
||||||
|
zdsfsinfo.server[zdsfsinfo.active_server]);
|
||||||
|
}
|
||||||
|
timer_running = 1;
|
||||||
|
setup_timer(zdsfsinfo.keepalive);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keepalive_start(void)
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
|
||||||
|
if (!open_dsh || timer_running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
timer_running = 1;
|
||||||
|
/* Setup timer for periodic ping. */
|
||||||
|
memset(&act, 0, sizeof(struct sigaction));
|
||||||
|
act.sa_handler = &keep_alive;
|
||||||
|
sigaction(SIGALRM, &act, NULL);
|
||||||
|
setup_timer(zdsfsinfo.keepalive);
|
||||||
|
}
|
||||||
|
|
||||||
static int zdsfs_getattr(const char *path, struct stat *stbuf)
|
static int zdsfs_getattr(const char *path, struct stat *stbuf)
|
||||||
{
|
{
|
||||||
@@ -375,6 +494,43 @@ static int zdsfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* walk through the serverlist and check if the URLs start with http or https
|
||||||
|
* if not attach a https:// prefix
|
||||||
|
* also check if they end with / and if not attach it
|
||||||
|
*
|
||||||
|
* afterwards ping the z/OSMF server and use the first working one
|
||||||
|
*
|
||||||
|
* return 1 if working server found 0 otherwise
|
||||||
|
*/
|
||||||
|
static int zdsfs_test_restserver(void)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
char *server;
|
||||||
|
char *prefix;
|
||||||
|
|
||||||
|
for (i = 0; i < zdsfsinfo.nr_server; i++) {
|
||||||
|
server = zdsfsinfo.server[i];
|
||||||
|
if (strncmp(server, "http", 4)) {
|
||||||
|
prefix = util_strdup("https://");
|
||||||
|
server = util_strcat_realloc(prefix, server);
|
||||||
|
free(zdsfsinfo.server[i]);
|
||||||
|
zdsfsinfo.server[i] = server;
|
||||||
|
}
|
||||||
|
if (strncmp(server + strlen(server) - 1, "/", 1)) {
|
||||||
|
server = util_strcat_realloc(server, "/");
|
||||||
|
zdsfsinfo.server[i] = server;
|
||||||
|
}
|
||||||
|
if (lzds_rest_ping(NULL, zdsfsinfo.server[i])) {
|
||||||
|
zdsfsinfo.active_server = i;
|
||||||
|
fprintf(stdout, "Using z/OSMF REST services on %s\n",
|
||||||
|
zdsfsinfo.server[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int zdsfs_open(const char *path, struct fuse_file_info *fi)
|
static int zdsfs_open(const char *path, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
@@ -464,13 +620,32 @@ static int zdsfs_open(const char *path, struct fuse_file_info *fi)
|
|||||||
rc = -rc;
|
rc = -rc;
|
||||||
goto error2;
|
goto error2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry:
|
||||||
|
if (zdsfsinfo.restapi && zdsfsinfo.active_server >= 0) {
|
||||||
|
rc = lzds_rest_get_enq(dsh,
|
||||||
|
zdsfsinfo.server[zdsfsinfo.active_server]);
|
||||||
|
/* if the REST server is not responding try the other */
|
||||||
|
if (rc == ECONNREFUSED && zdsfs_test_restserver()) {
|
||||||
|
goto retry;
|
||||||
|
} else if (rc) {
|
||||||
|
lzds_dshandle_get_errorlog(dsh, &log);
|
||||||
|
lzds_errorlog_fprint(log, stderr);
|
||||||
|
rc = -rc;
|
||||||
|
goto error2;
|
||||||
|
} else {
|
||||||
|
dshlist_add(open_dsh, dsh);
|
||||||
|
/* add to open dsh list */
|
||||||
|
keepalive_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
rc = lzds_dshandle_open(dsh);
|
rc = lzds_dshandle_open(dsh);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
fprintf(stderr, "Error when opening data set:\n");
|
fprintf(stderr, "Error when opening data set:\n");
|
||||||
lzds_dshandle_get_errorlog(dsh, &log);
|
lzds_dshandle_get_errorlog(dsh, &log);
|
||||||
lzds_errorlog_fprint(log, stderr);
|
lzds_errorlog_fprint(log, stderr);
|
||||||
rc = -rc;
|
rc = -rc;
|
||||||
goto error2;
|
goto error3;
|
||||||
}
|
}
|
||||||
zfi->is_metadata_file = 0;
|
zfi->is_metadata_file = 0;
|
||||||
zfi->metaread = 0;
|
zfi->metaread = 0;
|
||||||
@@ -478,6 +653,8 @@ static int zdsfs_open(const char *path, struct fuse_file_info *fi)
|
|||||||
fi->fh = (uint64_t)(unsigned long)zfi;
|
fi->fh = (uint64_t)(unsigned long)zfi;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error3:
|
||||||
|
dshlist_remove(open_dsh, dsh);
|
||||||
error2:
|
error2:
|
||||||
lzds_dshandle_free(dsh);
|
lzds_dshandle_free(dsh);
|
||||||
error1:
|
error1:
|
||||||
@@ -495,7 +672,10 @@ static int zdsfs_release(const char *UNUSED(path), struct fuse_file_info *fi)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
zfi = (struct zdsfs_file_info *)(unsigned long)fi->fh;
|
zfi = (struct zdsfs_file_info *)(unsigned long)fi->fh;
|
||||||
if (zfi->dsh) {
|
if (zfi->dsh) {
|
||||||
|
lzds_rest_release_enq(zfi->dsh,
|
||||||
|
zdsfsinfo.server[zdsfsinfo.active_server]);
|
||||||
lzds_dshandle_close(zfi->dsh);
|
lzds_dshandle_close(zfi->dsh);
|
||||||
|
dshlist_remove(open_dsh, zfi->dsh);
|
||||||
lzds_dshandle_free(zfi->dsh);
|
lzds_dshandle_free(zfi->dsh);
|
||||||
}
|
}
|
||||||
rc = pthread_mutex_destroy(&zfi->mutex);
|
rc = pthread_mutex_destroy(&zfi->mutex);
|
||||||
@@ -831,6 +1011,8 @@ enum {
|
|||||||
KEY_DEVFILE,
|
KEY_DEVFILE,
|
||||||
KEY_TRACKS,
|
KEY_TRACKS,
|
||||||
KEY_SEEKBUFFER,
|
KEY_SEEKBUFFER,
|
||||||
|
KEY_CONFIG,
|
||||||
|
KEY_SERVER,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ZDSFS_OPT(t, p, v) { t, offsetof(struct zdsfs_info, p), v }
|
#define ZDSFS_OPT(t, p, v) { t, offsetof(struct zdsfs_info, p), v }
|
||||||
@@ -843,9 +1025,12 @@ static const struct fuse_opt zdsfs_opts[] = {
|
|||||||
FUSE_OPT_KEY("-l %s", KEY_DEVFILE),
|
FUSE_OPT_KEY("-l %s", KEY_DEVFILE),
|
||||||
FUSE_OPT_KEY("tracks=", KEY_TRACKS),
|
FUSE_OPT_KEY("tracks=", KEY_TRACKS),
|
||||||
FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER),
|
FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER),
|
||||||
|
FUSE_OPT_KEY("-c %s", KEY_CONFIG),
|
||||||
|
FUSE_OPT_KEY("restserver=", KEY_SERVER),
|
||||||
ZDSFS_OPT("rdw", keepRDW, 1),
|
ZDSFS_OPT("rdw", keepRDW, 1),
|
||||||
ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1),
|
ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1),
|
||||||
ZDSFS_OPT("check_host_count", host_count, 1),
|
ZDSFS_OPT("check_host_count", host_count, 1),
|
||||||
|
ZDSFS_OPT("restapi", restapi, 1),
|
||||||
FUSE_OPT_END
|
FUSE_OPT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -865,6 +1050,8 @@ static void usage(const char *progname)
|
|||||||
"ZDSFS options:\n"
|
"ZDSFS options:\n"
|
||||||
" -l list_file Text file that contains a list of DASD device"
|
" -l list_file Text file that contains a list of DASD device"
|
||||||
" nodes\n"
|
" nodes\n"
|
||||||
|
" -c config_file Text file that contains configuration options\n"
|
||||||
|
" for zdsfs\n"
|
||||||
" -o rdw Keep record descriptor words in byte stream\n"
|
" -o rdw Keep record descriptor words in byte stream\n"
|
||||||
" -o ignore_incomplete Continue processing even if parts of a multi"
|
" -o ignore_incomplete Continue processing even if parts of a multi"
|
||||||
" volume\n"
|
" volume\n"
|
||||||
@@ -874,6 +1061,10 @@ static void usage(const char *progname)
|
|||||||
" size (default 1048576)\n"
|
" size (default 1048576)\n"
|
||||||
" -o check_host_count Stop processing if the device is used by another\n"
|
" -o check_host_count Stop processing if the device is used by another\n"
|
||||||
" operating system instance\n"
|
" operating system instance\n"
|
||||||
|
" -o restapi Enable using z/OSMF REST services for coordinated\n"
|
||||||
|
" access to datasets\n"
|
||||||
|
" -o restserver=URL The URL of the z/OSMF REST server to be used for\n"
|
||||||
|
" coordinated access to datasets\n"
|
||||||
, progname);
|
, progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,6 +1164,67 @@ static void zdsfs_process_device_file(const char *devfile)
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove_whitespace(const char *s, char *t)
|
||||||
|
{
|
||||||
|
while (*s != '\0') {
|
||||||
|
if (!isspace(*s)) {
|
||||||
|
*t = *s;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*t = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void zdsfs_process_config_file(const char *config)
|
||||||
|
{
|
||||||
|
char line[MAX_LINE_LENGTH];
|
||||||
|
char *tmp, *key, *value;
|
||||||
|
FILE *fd;
|
||||||
|
char delimiter[] = " =#\n";
|
||||||
|
unsigned long enabled;
|
||||||
|
|
||||||
|
fd = fopen(config, "r");
|
||||||
|
if (!fd) {
|
||||||
|
fprintf(stderr, "could not open file %s: %s\n",
|
||||||
|
config, strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), fd)) {
|
||||||
|
/* skip empty lines */
|
||||||
|
if (*line == '\n' || *line == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* remove all whitespaces */
|
||||||
|
tmp = util_malloc(strlen(line));
|
||||||
|
remove_whitespace(line, tmp);
|
||||||
|
|
||||||
|
key = strtok(tmp, delimiter);
|
||||||
|
if (strcmp(key, "restserver") == 0) {
|
||||||
|
if (zdsfsinfo.nr_server >= MAX_SERVER) {
|
||||||
|
free(tmp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
value = strtok(NULL, delimiter);
|
||||||
|
zdsfsinfo.server[zdsfsinfo.nr_server] =
|
||||||
|
util_strdup(value);
|
||||||
|
zdsfsinfo.nr_server++;
|
||||||
|
} else if (strcmp(key, "restapi") == 0) {
|
||||||
|
value = strtok(NULL, delimiter);
|
||||||
|
enabled = strtoul(value, NULL, 0);
|
||||||
|
if (enabled == 1)
|
||||||
|
zdsfsinfo.restapi = true;
|
||||||
|
} else if (strcmp(key, "keepalive") == 0) {
|
||||||
|
value = strtok(NULL, delimiter);
|
||||||
|
zdsfsinfo.keepalive = strtoul(value, NULL, 0);
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
|
||||||
static int zdsfs_process_args(void *UNUSED(data), const char *arg, int key,
|
static int zdsfs_process_args(void *UNUSED(data), const char *arg, int key,
|
||||||
struct fuse_args *outargs)
|
struct fuse_args *outargs)
|
||||||
{
|
{
|
||||||
@@ -1057,6 +1309,18 @@ static int zdsfs_process_args(void *UNUSED(data), const char *arg, int key,
|
|||||||
", program version %s\n", RELEASE_STRING);
|
", program version %s\n", RELEASE_STRING);
|
||||||
fprintf(stdout, "Copyright IBM Corp. 2013, 2017\n");
|
fprintf(stdout, "Copyright IBM Corp. 2013, 2017\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
|
case KEY_CONFIG:
|
||||||
|
/* note that arg starts with "-c" */
|
||||||
|
zdsfsinfo.configfile = util_strdup(arg + 2);
|
||||||
|
return 0;
|
||||||
|
case KEY_SERVER:
|
||||||
|
if (zdsfsinfo.nr_server >= MAX_SERVER)
|
||||||
|
return 0;
|
||||||
|
value = arg + strlen("restserver=");
|
||||||
|
zdsfsinfo.server[zdsfsinfo.nr_server] =
|
||||||
|
util_strdup(value);
|
||||||
|
zdsfsinfo.nr_server++;
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown argument key %x\n", key);
|
fprintf(stderr, "Unknown argument key %x\n", key);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -1069,13 +1333,18 @@ int main(int argc, char *argv[])
|
|||||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
timer_running = 0;
|
||||||
bzero(&zdsfsinfo, sizeof(zdsfsinfo));
|
bzero(&zdsfsinfo, sizeof(zdsfsinfo));
|
||||||
zdsfsinfo.keepRDW = 0;
|
zdsfsinfo.keepRDW = 0;
|
||||||
zdsfsinfo.allow_inclomplete_multi_volume = 0;
|
zdsfsinfo.allow_inclomplete_multi_volume = 0;
|
||||||
zdsfsinfo.tracks_per_frame = 128;
|
zdsfsinfo.tracks_per_frame = 128;
|
||||||
zdsfsinfo.seek_buffer_size = 1048576;
|
zdsfsinfo.seek_buffer_size = 1048576;
|
||||||
|
zdsfsinfo.configfile = "/etc/zdsfs.conf";
|
||||||
|
zdsfsinfo.keepalive = DEFAULT_KEEPALIVE_SEC;
|
||||||
|
zdsfsinfo.active_server = -1;
|
||||||
|
|
||||||
rc = lzds_zdsroot_alloc(&zdsfsinfo.zdsroot);
|
rc = lzds_zdsroot_alloc(&zdsfsinfo.zdsroot);
|
||||||
|
open_dsh = dshlist_alloc();
|
||||||
if (rc) {
|
if (rc) {
|
||||||
fprintf(stderr, "Could not allocate internal structures\n");
|
fprintf(stderr, "Could not allocate internal structures\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -1085,6 +1354,7 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "Failed to parse option\n");
|
fprintf(stderr, "Failed to parse option\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
zdsfs_process_config_file(zdsfsinfo.configfile);
|
||||||
|
|
||||||
if (!zdsfsinfo.devcount) {
|
if (!zdsfsinfo.devcount) {
|
||||||
fprintf(stderr, "Please specify a block device\n");
|
fprintf(stderr, "Please specify a block device\n");
|
||||||
@@ -1111,9 +1381,21 @@ int main(int argc, char *argv[])
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (zdsfsinfo.restapi) {
|
||||||
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
zdsfs_test_restserver();
|
||||||
|
if (zdsfsinfo.active_server < 0) {
|
||||||
|
fprintf(stderr, "Error: No z/OSMF REST Server reachable\n");
|
||||||
|
rc = -EACCES;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rc = fuse_main(args.argc, args.argv, &rdf_oper, NULL);
|
rc = fuse_main(args.argc, args.argv, &rdf_oper, NULL);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
curl_global_cleanup();
|
||||||
|
dshlist_free(open_dsh);
|
||||||
lzds_zdsroot_free(zdsfsinfo.zdsroot);
|
lzds_zdsroot_free(zdsfsinfo.zdsroot);
|
||||||
|
|
||||||
fuse_opt_free_args(&args);
|
fuse_opt_free_args(&args);
|
||||||
|
|||||||
@@ -69,8 +69,6 @@ struct globals {
|
|||||||
extern struct globals g;
|
extern struct globals g;
|
||||||
|
|
||||||
#define PROC_CMDLINE "/proc/cmdline"
|
#define PROC_CMDLINE "/proc/cmdline"
|
||||||
#define DEV_ZCORE "/sys/kernel/debug/zcore/mem"
|
|
||||||
#define DEV_ZCORE_MAP "/sys/kernel/debug/zcore/memmap"
|
|
||||||
#define DEV_ZCORE_REIPL "/sys/kernel/debug/zcore/reipl"
|
#define DEV_ZCORE_REIPL "/sys/kernel/debug/zcore/reipl"
|
||||||
#define DEV_ZCORE_HSA "/sys/kernel/debug/zcore/hsa"
|
#define DEV_ZCORE_HSA "/sys/kernel/debug/zcore/hsa"
|
||||||
#define REIPL "1"
|
#define REIPL "1"
|
||||||
|
|||||||
+1
-2
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "lib/zt_common.h"
|
|
||||||
#include "boot/s390.h"
|
#include "boot/s390.h"
|
||||||
|
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@@ -501,7 +500,7 @@ void initialize(void)
|
|||||||
/*
|
/*
|
||||||
* Load disabled wait PSW with reason code in address field
|
* Load disabled wait PSW with reason code in address field
|
||||||
*/
|
*/
|
||||||
void __noreturn libc_stop(unsigned long reason)
|
void libc_stop(unsigned long reason)
|
||||||
{
|
{
|
||||||
struct psw_t psw;
|
struct psw_t psw;
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -14,6 +14,8 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define EPERM 1 /* Operation not permitted */
|
#define EPERM 1 /* Operation not permitted */
|
||||||
#define ENOENT 2 /* No such file or directory */
|
#define ENOENT 2 /* No such file or directory */
|
||||||
#define ESRCH 3 /* No such process */
|
#define ESRCH 3 /* No such process */
|
||||||
@@ -55,7 +57,7 @@ char *strcpy(char *, const char *);
|
|||||||
unsigned long get_zeroed_page(void);
|
unsigned long get_zeroed_page(void);
|
||||||
void free_page(unsigned long);
|
void free_page(unsigned long);
|
||||||
void initialize(void);
|
void initialize(void);
|
||||||
void libc_stop(unsigned long);
|
void libc_stop(unsigned long) __noreturn;
|
||||||
void start(void);
|
void start(void);
|
||||||
void pgm_check_handler(void);
|
void pgm_check_handler(void);
|
||||||
void pgm_check_handler_fn(void);
|
void pgm_check_handler_fn(void);
|
||||||
|
|||||||
+11
-14
@@ -57,18 +57,6 @@ static inline void __noreturn start_kernel(void)
|
|||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int store_ipl_parmblock(struct ipl_pl_hdr *pl_hdr)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = diag308(DIAG308_STORE, pl_hdr);
|
|
||||||
if (rc == DIAG308_RC_OK &&
|
|
||||||
pl_hdr->version <= IPL_MAX_SUPPORTED_VERSION)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
is_verified_address(unsigned long image_addr)
|
is_verified_address(unsigned long image_addr)
|
||||||
{
|
{
|
||||||
@@ -126,9 +114,18 @@ secure_boot_enabled()
|
|||||||
unsigned int rc;
|
unsigned int rc;
|
||||||
|
|
||||||
pl_hdr = (void *)get_zeroed_page();
|
pl_hdr = (void *)get_zeroed_page();
|
||||||
if (!pl_hdr || store_ipl_parmblock(pl_hdr))
|
switch (diag308(DIAG308_STORE, pl_hdr)) {
|
||||||
|
case DIAG308_RC_OK:
|
||||||
|
rc = pl_hdr->version <= IPL_MAX_SUPPORTED_VERSION &&
|
||||||
|
!!(pl_hdr->flags & IPL_FLAG_SECURE);
|
||||||
|
break;
|
||||||
|
case DIAG308_RC_NO_CONF:
|
||||||
|
rc = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
panic(ESECUREBOOT, "%s", msg_sipl_noparm);
|
panic(ESECUREBOOT, "%s", msg_sipl_noparm);
|
||||||
rc = !!(pl_hdr->flags & IPL_FLAG_SECURE);
|
break;
|
||||||
|
}
|
||||||
free_page((unsigned long) pl_hdr);
|
free_page((unsigned long) pl_hdr);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
+1
-1
@@ -126,7 +126,7 @@ char* scan_keyword_name(enum scan_keyword_id id);
|
|||||||
int scan_check_defaultboot(struct scan_token* scan);
|
int scan_check_defaultboot(struct scan_token* scan);
|
||||||
struct scan_token* scan_build_automenu(struct scan_token* scan);
|
struct scan_token* scan_build_automenu(struct scan_token* scan);
|
||||||
int scan_check(struct scan_token* scan);
|
int scan_check(struct scan_token* scan);
|
||||||
int scan_check_bls(struct scan_token *scan);
|
void scan_update_bls_path(struct scan_token *scan);
|
||||||
int scan_find_section(struct scan_token* scan, char* name, enum scan_id type,
|
int scan_find_section(struct scan_token* scan, char* name, enum scan_id type,
|
||||||
int offset);
|
int offset);
|
||||||
int scan_check_section_data(char* keyword[], int* line, char* name,
|
int scan_check_section_data(char* keyword[], int* line, char* name,
|
||||||
|
|||||||
+2
-1
@@ -509,7 +509,8 @@ add_ipl_program(int fd, struct job_ipl_data* ipl, disk_blockptr_t* program,
|
|||||||
size_t stage3_params_size;
|
size_t stage3_params_size;
|
||||||
const char *comp_name[10];
|
const char *comp_name[10];
|
||||||
size_t signature_size;
|
size_t signature_size;
|
||||||
int offset, flags = 0;
|
int offset;
|
||||||
|
uint64_t flags = 0;
|
||||||
void *stage3_params;
|
void *stage3_params;
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
void *signature;
|
void *signature;
|
||||||
|
|||||||
+93
-2
@@ -89,6 +89,88 @@ disk_determine_dasd_type(struct disk_info *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int blkext_get_partnum(dev_t dev)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX], *buf;
|
||||||
|
int dev_major, dev_minor, partnum = -1;
|
||||||
|
|
||||||
|
dev_major = major(dev);
|
||||||
|
dev_minor = minor(dev);
|
||||||
|
snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
|
||||||
|
dev_major, dev_minor);
|
||||||
|
|
||||||
|
if (misc_read_special_file(path, &buf, NULL, 1)) {
|
||||||
|
error_text("Could not read from path '%s'", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
partnum = atoi(buf);
|
||||||
|
free(buf);
|
||||||
|
if (partnum < 0) {
|
||||||
|
error_text("Bad partition number in '%s'", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return partnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int blkext_is_base_device(dev_t dev)
|
||||||
|
{
|
||||||
|
int dev_major, dev_minor;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
struct stat stats;
|
||||||
|
|
||||||
|
dev_major = major(dev);
|
||||||
|
dev_minor = minor(dev);
|
||||||
|
|
||||||
|
snprintf(path, PATH_MAX, "/sys/dev/block/%d:%d/partition",
|
||||||
|
dev_major, dev_minor);
|
||||||
|
return (stat(path, &stats));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int blkext_get_base_dev(dev_t dev, dev_t *base_dev)
|
||||||
|
{
|
||||||
|
int base_major, base_minor;
|
||||||
|
char dev_path[PATH_MAX], base_path[PATH_MAX];
|
||||||
|
char *temp_path, *buf;
|
||||||
|
|
||||||
|
misc_asprintf(&temp_path, "/sys/dev/block/%d:%d", major(dev), minor(dev));
|
||||||
|
if (!realpath(temp_path, dev_path)) {
|
||||||
|
error_reason(strerror(errno));
|
||||||
|
error_text("Could not resolve link %s", temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(temp_path);
|
||||||
|
|
||||||
|
misc_asprintf(&temp_path, "%s/..", dev_path);
|
||||||
|
if (!realpath(temp_path, base_path)) {
|
||||||
|
error_reason(strerror(errno));
|
||||||
|
error_text("Could not resolve path %s", temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(temp_path);
|
||||||
|
|
||||||
|
misc_asprintf(&temp_path, "%s/dev", base_path);
|
||||||
|
if (misc_read_special_file(temp_path, &buf, NULL, 1)) {
|
||||||
|
error_text("Could not read from path '%s'", temp_path);
|
||||||
|
free(temp_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(temp_path);
|
||||||
|
|
||||||
|
if (sscanf(buf, "%i:%i", &base_major, &base_minor) != 2) {
|
||||||
|
error_text("Could not parse major:minor from string '%s'", buf);
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
*base_dev = makedev(base_major, base_minor);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return non-zero for ECKD type. */
|
/* Return non-zero for ECKD type. */
|
||||||
int
|
int
|
||||||
disk_is_eckd(disk_type_t type)
|
disk_is_eckd(disk_type_t type)
|
||||||
@@ -409,8 +491,17 @@ disk_get_info(const char* device, struct job_target_data* target,
|
|||||||
} else if (strcmp(data->drv_name, "blkext") == 0) {
|
} else if (strcmp(data->drv_name, "blkext") == 0) {
|
||||||
data->devno = -1;
|
data->devno = -1;
|
||||||
data->type = disk_type_scsi;
|
data->type = disk_type_scsi;
|
||||||
data->partnum = stats.st_rdev & SCSI_PARTN_MASK;
|
|
||||||
data->device = stats.st_rdev & ~SCSI_PARTN_MASK;
|
if (blkext_is_base_device(stats.st_rdev)) {
|
||||||
|
data->device = stats.st_rdev;
|
||||||
|
data->partnum = 0;
|
||||||
|
} else {
|
||||||
|
if (blkext_get_base_dev(stats.st_rdev, &data->device))
|
||||||
|
goto out_close;
|
||||||
|
data->partnum = blkext_get_partnum(stats.st_rdev);
|
||||||
|
if (data->partnum == -1)
|
||||||
|
goto out_close;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Driver name is unknown */
|
/* Driver name is unknown */
|
||||||
error_reason("Unsupported device driver '%s'", data->drv_name);
|
error_reason("Unsupported device driver '%s'", data->drv_name);
|
||||||
|
|||||||
+2
-6
@@ -1874,12 +1874,8 @@ get_job_from_config_file(struct command_line* cmdline, struct job_data* job)
|
|||||||
scan_free(scan);
|
scan_free(scan);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = scan_check_bls(scan);
|
/* maybe we need to update bls search path with target path */
|
||||||
if (rc) {
|
scan_update_bls_path(scan);
|
||||||
error_text("BLS parsing '%s'", blsdir);
|
|
||||||
scan_free(scan);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
/* Get job from config file data */
|
/* Get job from config file data */
|
||||||
if (cmdline->menu != NULL)
|
if (cmdline->menu != NULL)
|
||||||
rc = get_menu_job(scan, cmdline->menu, job);
|
rc = get_menu_job(scan, cmdline->menu, job);
|
||||||
|
|||||||
+35
-25
@@ -1567,15 +1567,17 @@ scan_check(struct scan_token* scan)
|
|||||||
/*
|
/*
|
||||||
* Check if kernel and initrd image paths provided by BLS files are readable.
|
* Check if kernel and initrd image paths provided by BLS files are readable.
|
||||||
* If not, add value of 'scan_keyword_target' into search path and silently
|
* If not, add value of 'scan_keyword_target' into search path and silently
|
||||||
* update scan list.
|
* update scan list if the file exists.
|
||||||
|
* In case neither path works the scan_check code will correctly handle missing
|
||||||
|
* files
|
||||||
*/
|
*/
|
||||||
int
|
void scan_update_bls_path(struct scan_token *scan)
|
||||||
scan_check_bls(struct scan_token *scan)
|
|
||||||
{
|
{
|
||||||
int i, rc;
|
|
||||||
char *target_value = NULL;
|
char *target_value = NULL;
|
||||||
char *img_value = NULL;
|
char *img_value = NULL;
|
||||||
char *buffer = NULL;
|
char *file = NULL;
|
||||||
|
char *tmp, *value;
|
||||||
|
int i;
|
||||||
/*
|
/*
|
||||||
* In the BLS case, each BLS section heading inherits a keyword
|
* In the BLS case, each BLS section heading inherits a keyword
|
||||||
* assignment target= from zipl.conf, and they are all the same.
|
* assignment target= from zipl.conf, and they are all the same.
|
||||||
@@ -1589,38 +1591,46 @@ scan_check_bls(struct scan_token *scan)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!target_value)
|
if (!target_value)
|
||||||
return -1;
|
return;
|
||||||
for (i = 0 ; scan[i].id != scan_id_empty; i++) {
|
for (i = 0 ; scan[i].id != scan_id_empty; i++) {
|
||||||
if (scan[i].id != scan_id_keyword_assignment)
|
if (scan[i].id != scan_id_keyword_assignment)
|
||||||
continue;
|
continue;
|
||||||
if (scan[i].content.keyword.keyword == scan_keyword_image ||
|
if (scan[i].content.keyword.keyword == scan_keyword_image ||
|
||||||
scan[i].content.keyword.keyword == scan_keyword_ramdisk) {
|
scan[i].content.keyword.keyword == scan_keyword_ramdisk) {
|
||||||
|
|
||||||
rc = misc_check_readable_file(
|
value = scan[i].content.keyword.value;
|
||||||
scan[i].content.keyword.value);
|
/*
|
||||||
if (rc) {
|
* put the filename only into the file var before
|
||||||
|
* checking its presence
|
||||||
|
*/
|
||||||
|
if (contains_address(value)) {
|
||||||
|
tmp = strrchr(value, ',');
|
||||||
|
file = strndup(value, tmp - value);
|
||||||
|
} else {
|
||||||
|
file = value;
|
||||||
|
}
|
||||||
|
if (misc_check_readable_file(file)) {
|
||||||
misc_asprintf(&img_value, "%s%s",
|
misc_asprintf(&img_value, "%s%s",
|
||||||
target_value,
|
target_value, file);
|
||||||
scan[i].content.keyword.value);
|
if (misc_check_readable_file(img_value))
|
||||||
rc = misc_check_readable_file(img_value);
|
continue;
|
||||||
if (rc) {
|
|
||||||
error_text(
|
/*
|
||||||
"Image file '%s' is not accessible",
|
* when file has stripped the load address part,
|
||||||
scan[i].content.keyword.value);
|
* do generate a prefixed value
|
||||||
return rc;
|
*/
|
||||||
|
if (file != value) {
|
||||||
|
free(file);
|
||||||
|
free(img_value);
|
||||||
|
misc_asprintf(&img_value, "%s%s",
|
||||||
|
target_value, value);
|
||||||
}
|
}
|
||||||
buffer = (char *)
|
|
||||||
misc_malloc(strlen(img_value) + 1);
|
|
||||||
if (buffer == NULL)
|
|
||||||
return -1;
|
|
||||||
memcpy(buffer, img_value, strlen(img_value));
|
|
||||||
buffer[strlen(img_value)] = 0;
|
|
||||||
free(scan[i].content.keyword.value);
|
free(scan[i].content.keyword.value);
|
||||||
scan[i].content.keyword.value = buffer;
|
scan[i].content.keyword.value = img_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
+1
-3
@@ -2454,7 +2454,6 @@ static int _keystore_display_apqn_status(struct keystore *keystore,
|
|||||||
if (apqns == NULL)
|
if (apqns == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
apqns = properties_get(properties, PROP_NAME_APQNS);
|
|
||||||
key_type = properties_get(properties, PROP_NAME_KEY_TYPE);
|
key_type = properties_get(properties, PROP_NAME_KEY_TYPE);
|
||||||
rc = cross_check_apqns(apqns, mkvp,
|
rc = cross_check_apqns(apqns, mkvp,
|
||||||
get_min_card_level_for_keytype(key_type),
|
get_min_card_level_for_keytype(key_type),
|
||||||
@@ -2867,8 +2866,7 @@ static int _keystore_process_reencipher(struct keystore *keystore,
|
|||||||
rc = _keystore_perform_reencipher(keystore, name, info->lib,
|
rc = _keystore_perform_reencipher(keystore, name, info->lib,
|
||||||
¶ms, secure_key,
|
¶ms, secure_key,
|
||||||
secure_key_size, is_old_mk,
|
secure_key_size, is_old_mk,
|
||||||
properties_get(properties,
|
apqns);
|
||||||
PROP_NAME_APQNS));
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ function used to encrypt the volume key in the LUKS key slots is of less
|
|||||||
relevance.
|
relevance.
|
||||||
.PP
|
.PP
|
||||||
.B Note:
|
.B Note:
|
||||||
The \fBreencipher\fP command requires the CCA host library (libcsulcca.so, for)
|
The \fBreencipher\fP command requires the CCA host library (libcsulcca.so)
|
||||||
for secure volume keys of type CCA-AESDATA or CCA-AESCIPHER, or the IBM Z
|
for secure volume keys of type CCA-AESDATA or CCA-AESCIPHER, or the IBM Z
|
||||||
Enterprise PKCS #11 (EP11) Support Program (EP11 host library) for secure volume
|
Enterprise PKCS #11 (EP11) Support Program (EP11 host library) for secure volume
|
||||||
keys of type EP11-AES to be installed. For the supported environments and
|
keys of type EP11-AES to be installed. For the supported environments and
|
||||||
|
|||||||
@@ -650,10 +650,10 @@ static int get_password_file(char **pwd, size_t *pwd_size, const char *key_file,
|
|||||||
size_t file_read_size;
|
size_t file_read_size;
|
||||||
int regular_file = 0;
|
int regular_file = 0;
|
||||||
int char_to_read = 0;
|
int char_to_read = 0;
|
||||||
|
size_t buflen = 0, i;
|
||||||
int fd, rc, newline;
|
int fd, rc, newline;
|
||||||
char *pass = NULL;
|
char *pass = NULL;
|
||||||
int char_read = 0;
|
int char_read = 0;
|
||||||
size_t buflen, i;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
fd = key_file ? open(key_file, O_RDONLY) : STDIN_FILENO;
|
fd = key_file ? open(key_file, O_RDONLY) : STDIN_FILENO;
|
||||||
@@ -712,6 +712,7 @@ static int get_password_file(char **pwd, size_t *pwd_size, const char *key_file,
|
|||||||
if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
|
if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
|
||||||
warnx("Cannot seek to requested key file offset %lu",
|
warnx("Cannot seek to requested key file offset %lu",
|
||||||
keyfile_offset);
|
keyfile_offset);
|
||||||
|
rc = -EIO;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-6
@@ -36,7 +36,7 @@ location. Keys stored in a secure key repository inherit the permissions from
|
|||||||
the repository directory (except write access for other users, which is always
|
the repository directory (except write access for other users, which is always
|
||||||
denied). The default repository location \fB/etc/zkey/repository\fP is created
|
denied). The default repository location \fB/etc/zkey/repository\fP is created
|
||||||
with group \fBzkeyadm\fP as owner and mode \fB770\fP. Thus all secure keys
|
with group \fBzkeyadm\fP as owner and mode \fB770\fP. Thus all secure keys
|
||||||
created in that repository are owned by group \fBzkeyadm\fP. Anyone that
|
created in that repository are owned by group \fBzkeyadm\fP. Anyone who
|
||||||
is supposed to access secure keys in the secure key repository must be part of
|
is supposed to access secure keys in the secure key repository must be part of
|
||||||
group \fBzkeyadm\fP.
|
group \fBzkeyadm\fP.
|
||||||
.PP
|
.PP
|
||||||
@@ -50,11 +50,12 @@ volume association also contains the device-mapper name, separated by a colon,
|
|||||||
used with dm-crypt. A specific volume can only be associated with one secure
|
used with dm-crypt. A specific volume can only be associated with one secure
|
||||||
key.
|
key.
|
||||||
.PP
|
.PP
|
||||||
The generated secure key is saved in a file with a size of 64 or 128 bytes.
|
The generated secure key is saved in a file, and contains an AES secure key with
|
||||||
The file contains an AES key with a length of 128, 192, or 256 bits. The key is
|
a length of 128, 192, or 256 bits, or two concatenated AES secure keys with a
|
||||||
enciphered with the master key of the CCA or EP11 cryptographic adapter.
|
length of 128, or 256 bits each, for keys that are used for the XTS cipher mode.
|
||||||
Secure keys that are used for the XTS cipher mode can be 128 or 256 bits
|
Note that the file size is not related to the key bit size, but is specific for
|
||||||
in size.
|
the secure key type. The key is enciphered with the master key of the CCA or
|
||||||
|
EP11 cryptographic adapter.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
.
|
.
|
||||||
|
|||||||
Reference in New Issue
Block a user