mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
409 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e07b30bdf | ||
|
|
35596e1dd7 | ||
|
|
0311cf7c5e | ||
|
|
78fdf56d38 | ||
|
|
b5c4ff68d7 | ||
|
|
3b0fc8cfda | ||
|
|
8d40b5c97a | ||
|
|
ad4075804f | ||
|
|
126ba7e336 | ||
|
|
1d2a89b387 | ||
|
|
7c4b029020 | ||
|
|
b5a750c2cc | ||
|
|
893667e73e | ||
|
|
95fb1e2b03 | ||
|
|
87966251c4 | ||
|
|
012025595f | ||
|
|
48c8fc8321 | ||
|
|
19995638e9 | ||
|
|
91ee8e0593 | ||
|
|
238ca83b99 | ||
|
|
df8aac7084 | ||
|
|
8ad28f7856 | ||
|
|
dd818ccc15 | ||
|
|
e7203069cc | ||
|
|
d4ee1ff01f | ||
|
|
9c60ceccd4 | ||
|
|
6da56acf4b | ||
|
|
365be71dfc | ||
|
|
789b097d3a | ||
|
|
06df08ae49 | ||
|
|
56a656f1c9 | ||
|
|
8efd4da53b | ||
|
|
d2efda1ac2 | ||
|
|
aa29a5f1f9 | ||
|
|
28815d3928 | ||
|
|
65a891fa35 | ||
|
|
5dc39e87e7 | ||
|
|
3358a30dae | ||
|
|
d7ba322d69 | ||
|
|
3123f56765 | ||
|
|
eb881c2a39 | ||
|
|
5c2e6fd730 | ||
|
|
47cac92ca2 | ||
|
|
11f2ccb957 | ||
|
|
5b909a40cb | ||
|
|
591eb30854 | ||
|
|
3083f5dc85 | ||
|
|
2325d94453 | ||
|
|
fef70e3e95 | ||
|
|
808b766407 | ||
|
|
346a69e5a9 | ||
|
|
52ddd291d4 | ||
|
|
4cf239b8b6 | ||
|
|
b292ce565f | ||
|
|
75ab455cf6 | ||
|
|
25088b340b | ||
|
|
8edc5558b5 | ||
|
|
cd93949d17 | ||
|
|
97136585da | ||
|
|
96d5b0bb02 | ||
|
|
771c794580 | ||
|
|
f11c71237e | ||
|
|
8dd5758341 | ||
|
|
20cc99feb7 | ||
|
|
9fa165de7a | ||
|
|
103a99fa34 | ||
|
|
c161c04392 | ||
|
|
8e74293c2d | ||
|
|
e14e0aa858 | ||
|
|
355700d606 | ||
|
|
ddf30feb89 | ||
|
|
0047fc162e | ||
|
|
d9eee82ab0 | ||
|
|
a9059449b9 | ||
|
|
c3d8208a57 | ||
|
|
a2663ec8d3 | ||
|
|
12d9d24437 | ||
|
|
aca6704cfa | ||
|
|
3a85d1ebe6 | ||
|
|
e8f9244224 | ||
|
|
a49887de1f | ||
|
|
4e61b4c9f4 | ||
|
|
d884cc27c1 | ||
|
|
bf3810ea6a | ||
|
|
99d7ec51a7 | ||
|
|
327d132aac | ||
|
|
fcb89662e0 | ||
|
|
a52243ea04 | ||
|
|
805a4d4408 | ||
|
|
b1e4f6f331 | ||
|
|
10d72caac0 | ||
|
|
0ea693d95c | ||
|
|
0ff130ed84 | ||
|
|
8a57017af3 | ||
|
|
41ec030db1 | ||
|
|
34aff761d0 | ||
|
|
01cb8c4085 | ||
|
|
8d58a9abb0 | ||
|
|
ce82010827 | ||
|
|
c0d8034962 | ||
|
|
95290562e0 | ||
|
|
638cbbe332 | ||
|
|
70157462d8 | ||
|
|
40bc181f31 | ||
|
|
a2eb03660d | ||
|
|
f4c4c40b78 | ||
|
|
fe78faa8ae | ||
|
|
617a8248e8 | ||
|
|
c5695e43c4 | ||
|
|
7b3add9389 | ||
|
|
44fdf586e1 | ||
|
|
0d6e63abdc | ||
|
|
1771e7f2f3 | ||
|
|
c403208332 | ||
|
|
2a99007a6e | ||
|
|
994269c278 | ||
|
|
ae5687f1d1 | ||
|
|
b856ae62a7 | ||
|
|
7b4be02441 | ||
|
|
2403d1e166 | ||
|
|
3f03ceb007 | ||
|
|
150ae08678 | ||
|
|
43a10f4806 | ||
|
|
4e08c5fcd8 | ||
|
|
6532bf02c2 | ||
|
|
3f7b459606 | ||
|
|
14830b1ead | ||
|
|
1dae9b4f49 | ||
|
|
b58414d7dc | ||
|
|
64524f17fa | ||
|
|
1b87b016d4 | ||
|
|
94bdb17d01 | ||
|
|
2625cd704f | ||
|
|
59df2c6d02 | ||
|
|
8ba03642b7 | ||
|
|
1956e7abc5 | ||
|
|
d76cb1d53a | ||
|
|
7d5f2ba038 | ||
|
|
8bbf1d5bea | ||
|
|
b2fcb608d5 | ||
|
|
76b7928592 | ||
|
|
339b69cf3b | ||
|
|
419f042f55 | ||
|
|
128e5f86fe | ||
|
|
b29e824923 | ||
|
|
3175d52ce7 | ||
|
|
17024c02af | ||
|
|
5cd680c0be | ||
|
|
c333f91d4c | ||
|
|
095e5ee226 | ||
|
|
6ee5ffef91 | ||
|
|
82f8c137e1 | ||
|
|
b21a824fda | ||
|
|
f74b8d7d6f | ||
|
|
b766d4a53c | ||
|
|
a1126352ec | ||
|
|
35e539a428 | ||
|
|
99100b3f99 | ||
|
|
49faa1d7fd | ||
|
|
86ce85b3a6 | ||
|
|
b1c1bea4e2 | ||
|
|
e68547f06f | ||
|
|
95d784d866 | ||
|
|
783ae9735e | ||
|
|
5a78c7f45d | ||
|
|
586040a0ad | ||
|
|
deb61b5cd9 | ||
|
|
8be51ad454 | ||
|
|
cef50c2140 | ||
|
|
33bd112e2f | ||
|
|
2c31ed6f14 | ||
|
|
771623832b | ||
|
|
b8060baf44 | ||
|
|
76a0401deb | ||
|
|
e6ac87d7a2 | ||
|
|
0a711d4934 | ||
|
|
f90e913806 | ||
|
|
94a7ec22f2 | ||
|
|
940ce67900 | ||
|
|
c12faf0128 | ||
|
|
a3d50487ed | ||
|
|
b1d8e40bfe | ||
|
|
8d3949f77b | ||
|
|
2f49025d49 | ||
|
|
4c9ceeeb64 | ||
|
|
3a0c394fa2 | ||
|
|
20a4ebd83c | ||
|
|
4a9f66fc31 | ||
|
|
35d68b2101 | ||
|
|
522c67a2c3 | ||
|
|
f4ee6c2c8d | ||
|
|
377f2a59f5 | ||
|
|
176f0405b8 | ||
|
|
839d34e758 | ||
|
|
a68d1e323b | ||
|
|
549c7ef9e7 | ||
|
|
103c9444c9 | ||
|
|
fe7bef3f09 | ||
|
|
8a88ada9c5 | ||
|
|
538bc7b4e8 | ||
|
|
b56451e5a4 | ||
|
|
63f9a672d0 | ||
|
|
2c5c5ef4b4 | ||
|
|
5a3ffc2036 | ||
|
|
e576443859 | ||
|
|
43067df78e | ||
|
|
973059438f | ||
|
|
9d3567d9ce | ||
|
|
7687b0fcda | ||
|
|
6f70f34b79 | ||
|
|
37aed81745 | ||
|
|
5aa1824eef | ||
|
|
82603e589a | ||
|
|
3ba897a1be | ||
|
|
fa92a7f7c9 | ||
|
|
f569849e57 | ||
|
|
458c27a0e1 | ||
|
|
e4dcf084c5 | ||
|
|
bed1bc8676 | ||
|
|
8e315c4401 | ||
|
|
ae8fa4371f | ||
|
|
29ff9408e0 | ||
|
|
a24be25779 | ||
|
|
58337d7f90 | ||
|
|
fcaad5a8e2 | ||
|
|
4d598ade86 | ||
|
|
b455ee9a31 | ||
|
|
82b9328e48 | ||
|
|
f45a45c38c | ||
|
|
d1bf9e68c6 | ||
|
|
0356d78bc2 | ||
|
|
a4f48415a0 | ||
|
|
c9f0e3accf | ||
|
|
9dd432ca94 | ||
|
|
179bc57cdf | ||
|
|
e1d1c6df9c | ||
|
|
e894fb61d8 | ||
|
|
c3a84109b7 | ||
|
|
1ca5f63dee | ||
|
|
60bc1e38d0 | ||
|
|
431e4542ca | ||
|
|
731f00202c | ||
|
|
2945593991 | ||
|
|
f375327085 | ||
|
|
338bea49c2 | ||
|
|
d15e36cf24 | ||
|
|
4b76530788 | ||
|
|
cb1c002bed | ||
|
|
d6f7eff5b5 | ||
|
|
e1692b7079 | ||
|
|
54b3c9ef24 | ||
|
|
48743aa28b | ||
|
|
7ce988ac59 | ||
|
|
f4fec5f120 | ||
|
|
2739b8a488 | ||
|
|
ce9c518b97 | ||
|
|
bd2a2cc6a1 | ||
|
|
6547d1ae4c | ||
|
|
650265e296 | ||
|
|
b122acb422 | ||
|
|
9710f29770 | ||
|
|
ed01bac8e2 | ||
|
|
66d3aa849a | ||
|
|
95e4b3413a | ||
|
|
06e0d569f1 | ||
|
|
660bab6e68 | ||
|
|
3dd91bb84e | ||
|
|
8fadcd9fe5 | ||
|
|
e8237e6ae0 | ||
|
|
c746c5c267 | ||
|
|
b69b750ef5 | ||
|
|
120ad30f1e | ||
|
|
bfc9854eb5 | ||
|
|
619c466275 | ||
|
|
017377c093 | ||
|
|
7e38c7106b | ||
|
|
8dc06d14d7 | ||
|
|
f07504d92e | ||
|
|
02554fa6d8 | ||
|
|
3eb09e8842 | ||
|
|
3eb9711021 | ||
|
|
2349236bb4 | ||
|
|
2d86117167 | ||
|
|
a0265d1069 | ||
|
|
084792bdc6 | ||
|
|
5ece6a3373 | ||
|
|
14c977768e | ||
|
|
5bedcff65c | ||
|
|
479820528c | ||
|
|
486882a4df | ||
|
|
ce997c6d01 | ||
|
|
b9d1c86613 | ||
|
|
f9337f0576 | ||
|
|
a06302e7f0 | ||
|
|
7bc0fb809d | ||
|
|
bc511f84fe | ||
|
|
3a3cea0061 | ||
|
|
616d2f52f9 | ||
|
|
6dd671f24e | ||
|
|
443652dcd2 | ||
|
|
b11bb64732 | ||
|
|
2cd7c7a875 | ||
|
|
8929d21948 | ||
|
|
f7bba3a687 | ||
|
|
5d2c93bc7a | ||
|
|
f1055a62e3 | ||
|
|
4c4ab4fd70 | ||
|
|
34a5e47508 | ||
|
|
6d7cdb9e10 | ||
|
|
1fefdecbe7 | ||
|
|
e62cdf9a6e | ||
|
|
fa00d1eac1 | ||
|
|
0eac97542d | ||
|
|
b3db52fd16 | ||
|
|
a9eb80b1a2 | ||
|
|
e93668ae5b | ||
|
|
c68c3cb8b2 | ||
|
|
f63c548c2a | ||
|
|
1ab2fbb482 | ||
|
|
fed79474e4 | ||
|
|
8c1ffd8989 | ||
|
|
33fc534a81 | ||
|
|
7e832ead9e | ||
|
|
7f0f765bb4 | ||
|
|
69c7f45bb7 | ||
|
|
d843e08828 | ||
|
|
055c455571 | ||
|
|
ba387af804 | ||
|
|
8b9960abe9 | ||
|
|
efdadfcdb9 | ||
|
|
ec10654c35 | ||
|
|
76bddf9715 | ||
|
|
b4cc30ac10 | ||
|
|
9f9dddddd4 | ||
|
|
f821a3c174 | ||
|
|
ee4cb78dc2 | ||
|
|
6f82c5792a | ||
|
|
2c5d4073a7 | ||
|
|
9efd1df31d | ||
|
|
6f53d7d3cd | ||
|
|
92486dfcaf | ||
|
|
29007541e8 | ||
|
|
2278f112ba | ||
|
|
c39722aff2 | ||
|
|
1e8edb6524 | ||
|
|
bd5f03d1c4 | ||
|
|
f8ccd56bf1 | ||
|
|
72218c5bc3 | ||
|
|
b94566048b | ||
|
|
85a232a711 | ||
|
|
931c61f141 | ||
|
|
253ca8a30e | ||
|
|
829fc3b294 | ||
|
|
3c5fb0f885 | ||
|
|
9df45d4256 | ||
|
|
283ae4dd2f | ||
|
|
718907d9ba | ||
|
|
26cf3ec769 | ||
|
|
7150da3e4f | ||
|
|
f946ce27f7 | ||
|
|
4942504a9a | ||
|
|
e1245ed4e5 | ||
|
|
272eb5ad8c | ||
|
|
543d41cb59 | ||
|
|
8619f14c0a | ||
|
|
56aa3e2d26 | ||
|
|
a9fbfcc7ae | ||
|
|
a32adbf5d8 | ||
|
|
f9050799bb | ||
|
|
66a10d5e3e | ||
|
|
152f446d76 | ||
|
|
646e080217 | ||
|
|
3fd8c48245 | ||
|
|
c93b74b527 | ||
|
|
4fe6025b18 | ||
|
|
73b6a684ec | ||
|
|
40d9df5cc8 | ||
|
|
9ebb8da624 | ||
|
|
589ce29d41 | ||
|
|
b343672eb8 | ||
|
|
df47036f01 | ||
|
|
5febec5f44 | ||
|
|
84f44dd20f | ||
|
|
d86dd0658f | ||
|
|
00c36baee0 | ||
|
|
a40519fd16 | ||
|
|
b836b4fb83 | ||
|
|
1ab819cd81 | ||
|
|
ee50f20c11 | ||
|
|
0f17fe5183 | ||
|
|
650e2da843 | ||
|
|
426311f440 | ||
|
|
5333085c55 | ||
|
|
4c301d47dd | ||
|
|
aea2ba8728 | ||
|
|
594a554e56 | ||
|
|
a0c3a74019 | ||
|
|
efdd34a56c | ||
|
|
c80a0c8af0 | ||
|
|
d98a10f67f | ||
|
|
fb6e7e70c6 | ||
|
|
e49569db60 | ||
|
|
b3055154db | ||
|
|
6718c0edc9 | ||
|
|
28d9405f73 | ||
|
|
05f0aeb61e | ||
|
|
6004a7029c | ||
|
|
16add4a4ae | ||
|
|
ef752d1f45 |
@@ -10,3 +10,4 @@
|
|||||||
--ignore FILE_PATH_CHANGES
|
--ignore FILE_PATH_CHANGES
|
||||||
--ignore NEW_TYPEDEFS
|
--ignore NEW_TYPEDEFS
|
||||||
--ignore SPDX_LICENSE_TAG
|
--ignore SPDX_LICENSE_TAG
|
||||||
|
--ignore STRNCPY
|
||||||
|
|||||||
37
.clang-tidy
Normal file
37
.clang-tidy
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
Checks: >
|
||||||
|
bugprone-*,
|
||||||
|
clang-analyzer-*,
|
||||||
|
misc-*,
|
||||||
|
performance-*,
|
||||||
|
portability-*,
|
||||||
|
readability-*,
|
||||||
|
-bugprone-easily-swappable-parameters,
|
||||||
|
-misc-include-cleaner,
|
||||||
|
-readability-braces-around-statements,
|
||||||
|
-readability-identifier-length,
|
||||||
|
-readability-isolate-declaration,
|
||||||
|
-modernize-*,
|
||||||
|
-performance-*,
|
||||||
|
-portability-*,
|
||||||
|
-readability-implicit-bool-conversion
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
- key: readability-identifier-naming.VariableCase
|
||||||
|
value: lower_case
|
||||||
|
- key: readability-identifier-naming.FunctionCase
|
||||||
|
value: lower_case
|
||||||
|
- key: readability-identifier-naming.StructCase
|
||||||
|
value: lower_case
|
||||||
|
- key: readability-identifier-naming.EnumCase
|
||||||
|
value: lower_case
|
||||||
|
- key: readability-identifier-naming.EnumConstantCase
|
||||||
|
value: UPPER_CASE
|
||||||
|
- key: readability-identifier-naming.MacroDefinitionCase
|
||||||
|
value: UPPER_CASE
|
||||||
|
- key: bugprone-sizeof-expression.WarnOnSizeOfPointer
|
||||||
|
value: true
|
||||||
|
- key: misc-unused-parameters.StrictMode
|
||||||
|
value: true
|
||||||
|
|
||||||
|
FormatStyle: file
|
||||||
|
UseColor: true
|
||||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -25,6 +25,7 @@ compile_commands.json
|
|||||||
#
|
#
|
||||||
**/.detect-openssl.dep.c
|
**/.detect-openssl.dep.c
|
||||||
*.debug
|
*.debug
|
||||||
|
*/autocompletion_generator_host
|
||||||
ap_tools/ap-check
|
ap_tools/ap-check
|
||||||
cmsfs-fuse/cmsfs-fuse
|
cmsfs-fuse/cmsfs-fuse
|
||||||
cpacfstats/cpacfstats
|
cpacfstats/cpacfstats
|
||||||
@@ -34,8 +35,20 @@ cpumf/lscpumf
|
|||||||
cpumf/lshwc
|
cpumf/lshwc
|
||||||
cpumf/lspai
|
cpumf/lspai
|
||||||
cpumf/pai
|
cpumf/pai
|
||||||
|
cpumf/_chcpumf
|
||||||
|
cpumf/_lscpumf
|
||||||
|
cpumf/_lshwc
|
||||||
|
cpumf/_lspai
|
||||||
|
cpumf/_pai
|
||||||
|
cpumf/chcpumf.bash
|
||||||
|
cpumf/lscpumf.bash
|
||||||
|
cpumf/lshwc.bash
|
||||||
|
cpumf/lspai.bash
|
||||||
|
cpumf/pai.bash
|
||||||
cpuplugd/cpuplugd
|
cpuplugd/cpuplugd
|
||||||
dasdfmt/dasdfmt
|
dasdfmt/dasdfmt
|
||||||
|
dasdfmt/_dasdfmt
|
||||||
|
dasdfmt/dasdfmt.bash
|
||||||
dasdinfo/dasdinfo
|
dasdinfo/dasdinfo
|
||||||
dasdview/dasdview
|
dasdview/dasdview
|
||||||
dump2tar/src/dump2tar
|
dump2tar/src/dump2tar
|
||||||
@@ -63,7 +76,7 @@ libekmfweb/check-dep-libekmfweb
|
|||||||
libekmfweb/detect-openssl-version.dep
|
libekmfweb/detect-openssl-version.dep
|
||||||
libekmfweb/libekmfweb.so
|
libekmfweb/libekmfweb.so
|
||||||
libekmfweb/libekmfweb.so.1
|
libekmfweb/libekmfweb.so.1
|
||||||
libekmfweb/libekmfweb.so.1.0
|
libekmfweb/libekmfweb.so.1.1
|
||||||
libkmipclient/check-dep-libkmipclient
|
libkmipclient/check-dep-libkmipclient
|
||||||
libkmipclient/detect-openssl-version.dep
|
libkmipclient/detect-openssl-version.dep
|
||||||
libkmipclient/libkmipclient.so
|
libkmipclient/libkmipclient.so
|
||||||
@@ -119,7 +132,7 @@ ziomon/ziomon_zfcpdd
|
|||||||
ziomon/ziorep_traffic
|
ziomon/ziorep_traffic
|
||||||
ziomon/ziorep_utilization
|
ziomon/ziorep_utilization
|
||||||
zipl/boot/*.bin
|
zipl/boot/*.bin
|
||||||
zipl/boot/*.exec
|
zipl/boot/*.elf
|
||||||
zipl/boot/.loaders
|
zipl/boot/.loaders
|
||||||
zipl/boot/data.h
|
zipl/boot/data.h
|
||||||
zipl/src/chreipl_helper.device-mapper
|
zipl/src/chreipl_helper.device-mapper
|
||||||
@@ -137,4 +150,6 @@ zkey/kmip/libkmipclient.dep
|
|||||||
zkey/kmip/zkey-kmip.so
|
zkey/kmip/zkey-kmip.so
|
||||||
zkey/zkey
|
zkey/zkey
|
||||||
zkey/zkey-cryptsetup
|
zkey/zkey-cryptsetup
|
||||||
|
zmemtopo/zmemtopo
|
||||||
zpcictl/zpcictl
|
zpcictl/zpcictl
|
||||||
|
zpwr/zpwr
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
exclude: \.(bin|crl|crt|key)$
|
exclude: \.(bin|crl|crt|key)$
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.1.0
|
rev: v6.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
@@ -11,6 +11,9 @@ repos:
|
|||||||
- id: check-executables-have-shebangs
|
- id: check-executables-have-shebangs
|
||||||
- id: check-shebang-scripts-are-executable
|
- id: check-shebang-scripts-are-executable
|
||||||
exclude_types: ['rust']
|
exclude_types: ['rust']
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-json
|
||||||
|
- id: check-toml
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
- id: git-clang-format
|
- id: git-clang-format
|
||||||
@@ -24,7 +27,7 @@ repos:
|
|||||||
minimum_pre_commit_version: "2.9.0"
|
minimum_pre_commit_version: "2.9.0"
|
||||||
types_or: [c++, c]
|
types_or: [c++, c]
|
||||||
- repo: https://github.com/codespell-project/codespell
|
- repo: https://github.com/codespell-project/codespell
|
||||||
rev: v2.2.1
|
rev: v2.4.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
exclude_types: ['rust']
|
exclude_types: ['rust']
|
||||||
|
|||||||
19
AUTHORS.md
19
AUTHORS.md
@@ -1,13 +1,16 @@
|
|||||||
List of all individuals having contributed content to s390-tools
|
List of all individuals having contributed content to s390-tools
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
- Ajaykumar Rajappa
|
||||||
- Alexander Egorenkov
|
- Alexander Egorenkov
|
||||||
- Alexandra Winter
|
- Alexandra Winter
|
||||||
- Alexey Ishchuk
|
- Alexey Ishchuk
|
||||||
- Andreas Herrmann
|
- Andreas Herrmann
|
||||||
- André Wild
|
- André Wild
|
||||||
|
- Annu Sharma
|
||||||
- Antoinette Kaschner
|
- Antoinette Kaschner
|
||||||
- Arnd Bergmann
|
- Arnd Bergmann
|
||||||
|
- Aswin Karuvally
|
||||||
- Axel Wirbser
|
- Axel Wirbser
|
||||||
- Balint Reczey
|
- Balint Reczey
|
||||||
- Benjamin Block
|
- Benjamin Block
|
||||||
@@ -23,11 +26,13 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Dan Horak
|
- Dan Horak
|
||||||
- Dan Horák
|
- Dan Horák
|
||||||
- Daniel S. Haischt
|
- Daniel S. Haischt
|
||||||
|
- Dean Doyle
|
||||||
- Despina Papadopoulou
|
- Despina Papadopoulou
|
||||||
- Dimitri John Ledkov
|
- Dimitri John Ledkov
|
||||||
- Eberhard Pasch
|
- Eberhard Pasch
|
||||||
- Eduard Shishkin
|
- Eduard Shishkin
|
||||||
- Einar Lueck
|
- Einar Lueck
|
||||||
|
- Ellen McIntyre
|
||||||
- Eric Farman
|
- Eric Farman
|
||||||
- Eric Sandeen
|
- Eric Sandeen
|
||||||
- Erwin Vicari
|
- Erwin Vicari
|
||||||
@@ -43,13 +48,14 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Frank Munzert
|
- Frank Munzert
|
||||||
- Frank Pavlic
|
- Frank Pavlic
|
||||||
- Fritz Elfert
|
- Fritz Elfert
|
||||||
|
- Gautam Gala
|
||||||
- Gerald Schaefer
|
- Gerald Schaefer
|
||||||
- Gerhard Tonn
|
- Gerhard Tonn
|
||||||
- Graham Inggs
|
- Graham Inggs
|
||||||
- Guevenc Guelce
|
- Guevenc Guelce
|
||||||
- Hannes Reinecke
|
- Hannes Reinecke
|
||||||
- Hans-Joachim Picht
|
|
||||||
- Hans Wippel
|
- Hans Wippel
|
||||||
|
- Hans-Joachim Picht
|
||||||
- Harald Freudenberger
|
- Harald Freudenberger
|
||||||
- Heiko Carstens
|
- Heiko Carstens
|
||||||
- Hendrik Brueckner
|
- Hendrik Brueckner
|
||||||
@@ -63,6 +69,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Jakub Čajka
|
- Jakub Čajka
|
||||||
- Jan Glauber
|
- Jan Glauber
|
||||||
- Jan Höppner
|
- Jan Höppner
|
||||||
|
- Jan Polensky
|
||||||
- Jan Willeke
|
- Jan Willeke
|
||||||
- Jason J. Herne
|
- Jason J. Herne
|
||||||
- Javier Martinez Canillas
|
- Javier Martinez Canillas
|
||||||
@@ -72,9 +79,11 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Joern Siglen
|
- Joern Siglen
|
||||||
- Juergen Christ
|
- Juergen Christ
|
||||||
- Julian Wiedmann
|
- Julian Wiedmann
|
||||||
|
- Jörn Siglen
|
||||||
- Karsten Graul
|
- Karsten Graul
|
||||||
- Kittipon Meesompop
|
- Kittipon Meesompop
|
||||||
- Klaus-Dieter Wacker
|
- Klaus-Dieter Wacker
|
||||||
|
- L. E. Segovia
|
||||||
- Lakhvich Dmitriy
|
- Lakhvich Dmitriy
|
||||||
- Marc Hartmayer
|
- Marc Hartmayer
|
||||||
- Mario Held
|
- Mario Held
|
||||||
@@ -97,6 +106,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Nikita Dubrovskii
|
- Nikita Dubrovskii
|
||||||
- Niklas Schnelle
|
- Niklas Schnelle
|
||||||
- Nikolay Gueorguiev
|
- Nikolay Gueorguiev
|
||||||
|
- Peter Jin
|
||||||
- Peter Oberparleiter
|
- Peter Oberparleiter
|
||||||
- Peter Tiedemann
|
- Peter Tiedemann
|
||||||
- Philipp Kern
|
- Philipp Kern
|
||||||
@@ -106,12 +116,15 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Raimund Schroeder
|
- Raimund Schroeder
|
||||||
- Ralph Wuerthner
|
- Ralph Wuerthner
|
||||||
- Rene Trumpp
|
- Rene Trumpp
|
||||||
|
- Richie Buturla
|
||||||
- Rolf Schaefer
|
- Rolf Schaefer
|
||||||
- Sa Liu
|
- Sa Liu
|
||||||
- Sascha Silbe
|
- Sascha Silbe
|
||||||
- Sebastian Ott
|
- Sebastian Ott
|
||||||
- Sertonix
|
- Sertonix
|
||||||
- Seshagiri N. Ippili
|
- Seshagiri N. Ippili
|
||||||
|
- Shalini Chellathurai Saroja
|
||||||
|
- Siglen
|
||||||
- Simon Sturm
|
- Simon Sturm
|
||||||
- Stefan Bader
|
- Stefan Bader
|
||||||
- Stefan Haberland
|
- Stefan Haberland
|
||||||
@@ -121,10 +134,12 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Steffen Eiden
|
- Steffen Eiden
|
||||||
- Steffen Maier
|
- Steffen Maier
|
||||||
- Steffen Thoss
|
- Steffen Thoss
|
||||||
|
- Sumanth Korikkar
|
||||||
- Susanne Wintenberger
|
- Susanne Wintenberger
|
||||||
- Sven Schnelle
|
- Sven Schnelle
|
||||||
- Sven Schuetz
|
- Sven Schuetz
|
||||||
- Swen Schillig
|
- Swen Schillig
|
||||||
|
- Szabina Korbai
|
||||||
- Taraka R. Bodireddy
|
- Taraka R. Bodireddy
|
||||||
- Thomas Heidrich
|
- Thomas Heidrich
|
||||||
- Thomas Huth
|
- Thomas Huth
|
||||||
@@ -141,7 +156,9 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Vasily Gorbik
|
- Vasily Gorbik
|
||||||
- Viktor Mihajlovski
|
- Viktor Mihajlovski
|
||||||
- Vineeth Vijayan
|
- Vineeth Vijayan
|
||||||
|
- Volkan Unal
|
||||||
- Volker Sameske
|
- Volker Sameske
|
||||||
- Wenjia Zhang
|
- Wenjia Zhang
|
||||||
|
- Wisdom Erhimwionsobo
|
||||||
- Wolfgang Taphorn
|
- Wolfgang Taphorn
|
||||||
- Yaakov Selkowitz
|
- Yaakov Selkowitz
|
||||||
|
|||||||
166
CHANGELOG.md
166
CHANGELOG.md
@@ -1,6 +1,164 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
* __v2.41.0 (2026-02-16)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.19
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- chreipl: Make --bootparms work for ECKD re-IPL
|
||||||
|
- cpacfstats: Add 'unauthorized' state to CPU-MF counters
|
||||||
|
- cpictl: Detect RHCOS using VARIANT_ID
|
||||||
|
- hsci: Automatically set appropriate MTU for HSCI
|
||||||
|
- libutil: Add util_readlink() and util_readlinkat() helpers
|
||||||
|
- libutil: Add util_startswith() to util_str
|
||||||
|
- libutil: Add utility parsing functions
|
||||||
|
- lschp: Add support for structured output (--format)
|
||||||
|
- lsreipl: Suppress 'clear' output if not supported
|
||||||
|
- pvimg: Add '--format text' support to 'pvimg info'
|
||||||
|
- pvimg: Add '--print-schema <FORMAT>' option to 'pvimg info'
|
||||||
|
- pvimg: Add '--show-secrets' flag to 'pvimg info'
|
||||||
|
- pvimg: Provide improved JSON output to 'pvimg info --format json'
|
||||||
|
- pvinfo: Improve User experience on non-SE enabled systems
|
||||||
|
- zipl/ngdump: Ensure ext4 file system is used on dump partition
|
||||||
|
- zkey: Add support for integrity protected disks using HMAC keys
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- cpumf/pai: Handle different size of perf_event_attr
|
||||||
|
- lscss: Fix memory leak
|
||||||
|
- zipl: Fix dump job on tape devices
|
||||||
|
|
||||||
|
* __v2.40.0 (2025-12-11)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.18
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
- Add project-wide .clang-tidy configuration
|
||||||
|
- libutil: Introduce util_time for time related functionality
|
||||||
|
- libutil: Introduce zsh/bash autocompletion tooling based on util_opt
|
||||||
|
- pvinfo: Tool to display Secure Execution system information
|
||||||
|
- pvverify: Tool to verify host-key documents
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- cpumf: Implement zsh and bash autocompletion
|
||||||
|
- dasdfmt: Implement zsh and bash autocompletion
|
||||||
|
- dbginfo.sh: Add NetworkManager and netplan
|
||||||
|
- dbginfo.sh: Add kvm_stat
|
||||||
|
- dbginfo.sh: Adding stp time information
|
||||||
|
- dbginfo.sh: Simplify procfs collection
|
||||||
|
- hyptop: Add physical information row
|
||||||
|
- hyptop: Calculate sample time delta for physical partition
|
||||||
|
- hyptop: Replace long option names using _ with - for consistency
|
||||||
|
For example: --cpu_types -> --cpu-types
|
||||||
|
(Options with _ are still supported for backward compatibility)
|
||||||
|
- libekmfweb: Add function to validate a certificate against the identity key
|
||||||
|
- netboot: Add longer kernel command lines support
|
||||||
|
- udev/rules.d: Make virtio-blk devices non-rotational
|
||||||
|
- udev/rules.d: Set default io scheduler to 'none' for virtio-blk
|
||||||
|
- ziomon: Add support to sample device symlinks (/dev/disk/...)
|
||||||
|
- ziorep_config: Add fcp-lun details to -M option output
|
||||||
|
- ziorep_config: Add port_id and failed attributes to -A option output
|
||||||
|
- netboot: Install on non-s390 architectures
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- lib(ekmfweb|kmipclient): Use ln without -r
|
||||||
|
- s390-tools: Fix various compilation issues with musl libc
|
||||||
|
- zipl/boot: Fix unused loadparm when SCLP line-mode console is absent
|
||||||
|
|
||||||
|
* __v2.39.0 (2025-10-14)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.16 / 6.17
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- chpstat: Add options to select IEC units for scaling (SI units are default)
|
||||||
|
- chzdev: Introduce --no-module-load option
|
||||||
|
- cpi: Disable CPI for SEL guests by default
|
||||||
|
- dbginfo.sh: Enhance logging on timeout triggered
|
||||||
|
- iucvterm: Install symlink for lsiucvallow.8 man page
|
||||||
|
- lshwc: Add command line flag to specify individual counters
|
||||||
|
- lspai: Add command line flag for delta values
|
||||||
|
- lspai: Add command line flag for short counter names
|
||||||
|
- lspai: Add command line flag to specify individual counters
|
||||||
|
- lspai: Add command line flags for all cpus
|
||||||
|
- lspai: Add command line flags for hexadecimal output
|
||||||
|
- man: Use CR for constant width font
|
||||||
|
- pvimg: Add '--image-key' option
|
||||||
|
- zdev: Allow dynamic control of module load
|
||||||
|
- zipl/boot: Fix EBCDIC code page 500 conversion and decrease size by 200 bytes
|
||||||
|
- zipl: Add support of heterogeneous mirrors (remove technical limitations
|
||||||
|
on mirrored targets, thus allowing mirrored devices consist of partitions
|
||||||
|
at different offsets on disks of different types and geometry).
|
||||||
|
- zkey: Add support for generating and importing exportable secure keys
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- chpstat: Fix scaling of DPU utilization calculation
|
||||||
|
- zdev/dracut: Prevent loading of unused kernel modules
|
||||||
|
- zdev: Fix double device configuration on DPM systems
|
||||||
|
- zdev: Fix double device configuration with rd.dasd
|
||||||
|
- zipl_helper.device-mapper: Fix segfault in an error path
|
||||||
|
|
||||||
|
* __v2.38.0 (2025-06-25)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.14 / 6.15
|
||||||
|
|
||||||
|
Add new tools:
|
||||||
|
- udev: New rule to set newly hotplugged CPUs online
|
||||||
|
- zmemtopo: Display memory topology information
|
||||||
|
- zpwr: Display power readings of a partition and CPC
|
||||||
|
|
||||||
|
Removed tools / features:
|
||||||
|
- check_hostkeydoc: Remove installation target
|
||||||
|
- scsi_logging_level: Delete SCSI logging script (available in sg3_utils)
|
||||||
|
- zdump: Drop build_arch for s390 DASD dumps
|
||||||
|
- zdump: Drop non-extended multi-volume DASD dump support
|
||||||
|
- zdump: Drop support of 32-bit dump architecture
|
||||||
|
- zdump: Drop support of non-extended single volume DASD dumpers
|
||||||
|
- zdump: Drop support of obsolete dumps and dumpers
|
||||||
|
|
||||||
|
Changes of existing tools / libraries:
|
||||||
|
- Various man-pages fixes
|
||||||
|
- check_hostkeydoc: Add deprecation warning
|
||||||
|
- check_hostkeydoc: Move to scripts directory
|
||||||
|
- cpuplugd: Allow cpu hotplugging on systems without polarization
|
||||||
|
- dbginfo.sh: Add Ubuntu snap tool
|
||||||
|
- dbginfo.sh: Add missing config data and logs
|
||||||
|
- dbginfo.sh: Reworking the container section
|
||||||
|
- dbginfo.sh: Update for network commands
|
||||||
|
- dbginfo.sh: Updating info for disks and lvm
|
||||||
|
- libutil: Add machine type definition for machines 9175 and 9176
|
||||||
|
- lscpumf: Add support for IBM z17 counter sets
|
||||||
|
- lshwc: Add command line flag for run time
|
||||||
|
- lshwc: Add flags to display counter values in hex
|
||||||
|
- lshwc: Add output '--format' option
|
||||||
|
- lshwc: Add support for delta counter value display
|
||||||
|
- lspai: Add output '--format' option
|
||||||
|
- lsreipl: Add secure boot state to output
|
||||||
|
- lswhc: Add short names to lshwc output
|
||||||
|
- pv_tools: Add Bash and Zsh completions
|
||||||
|
- pvapconfig: Add '--unbind' option
|
||||||
|
- pvimg/boot: Print error messages from stage3a bootloader
|
||||||
|
- pvimg: Add support for CCK update
|
||||||
|
- pvsecret: Add support for CCK update
|
||||||
|
- pvsecret: Allow retrieving secrets by index & warn for duplicated entries
|
||||||
|
- pvsecret: Deny adding secrets with duplicated secret IDs
|
||||||
|
- zdev: Add support for virtio devices
|
||||||
|
- zipl: Enhance mirror support
|
||||||
|
- zipl: Implement '--dry-run' option for all dump jobs
|
||||||
|
- zipl_helper.device-mapper: Support mirrors over NVMe devices
|
||||||
|
- zkey/dracut: Add a dracut config file for zkey
|
||||||
|
- zkey/initramfs: Update initramfs hook to correct drivers and include zkey plugins
|
||||||
|
- zkey: Add support for converting a clear-key LUKS2 volume to use a secure key
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- chpstat: Add missing CMG 5 data fields
|
||||||
|
- chpstat: Fix DPU utilization calculation
|
||||||
|
- libutil/util_file: Handle over-read in util_file_read_fd()
|
||||||
|
- pvattest: Fix successful 'check' evaluation
|
||||||
|
- pvsecret: Fix some edge cases for plaintext keys
|
||||||
|
- zipl_helper.device-mapper: Fix imprecise is_device_mapper() predicate
|
||||||
|
- zkey: Fix EP11 secure key reencipher function
|
||||||
|
- zpcictl: Fix command line parsing for invalid options
|
||||||
|
|
||||||
* __v2.37.0 (2025-02-07)__
|
* __v2.37.0 (2025-02-07)__
|
||||||
|
|
||||||
For Linux kernel version: 6.13
|
For Linux kernel version: 6.13
|
||||||
@@ -49,6 +207,14 @@ Release history for s390-tools (MIT version)
|
|||||||
- chpstat: Add support for full CMCB
|
- chpstat: Add support for full CMCB
|
||||||
- chpstat: Add support for new CMG types
|
- chpstat: Add support for new CMG types
|
||||||
- dbginfo.sh: add overview commands and crypto update
|
- dbginfo.sh: add overview commands and crypto update
|
||||||
|
- genprotimg:
|
||||||
|
1. genprotimg is now a symbolic link to the new tool `pvimg create`
|
||||||
|
2. Breaking API changes in genprotimg:
|
||||||
|
1. An existing output file is no longer silently overwritten; to revert
|
||||||
|
to the old behavior use the `--overwrite` option.
|
||||||
|
2. The Linux kernel component is now checked to determine whether it is a
|
||||||
|
binary s390x kernel. To disable this behavior use the
|
||||||
|
`--no-component-check` option.
|
||||||
- hyptop: Support for structured output (json, json-seq, csv)
|
- hyptop: Support for structured output (json, json-seq, csv)
|
||||||
- lszfcp: Add missing fallback marker for non-good fc_host port_state
|
- lszfcp: Add missing fallback marker for non-good fc_host port_state
|
||||||
- lszfcp: Improve speed with many SCSI devices
|
- lszfcp: Improve speed with many SCSI devices
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -15,12 +15,13 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
|||||||
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||||
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
||||||
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
||||||
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust opticsmon
|
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust opticsmon \
|
||||||
|
zpwr zmemtopo
|
||||||
|
|
||||||
else
|
else
|
||||||
BASELIB_DIRS =
|
BASELIB_DIRS =
|
||||||
LIB_DIRS = libpv
|
LIB_DIRS = libpv
|
||||||
TOOL_DIRS = rust
|
TOOL_DIRS = netboot rust
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS)
|
SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS)
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -128,9 +128,6 @@ Package contents
|
|||||||
* sclpdbf:
|
* sclpdbf:
|
||||||
Display debug data for the sclp kernel component.
|
Display debug data for the sclp kernel component.
|
||||||
|
|
||||||
* scsi_logging_level:
|
|
||||||
Create, get or set the logging level for the SCSI logging facility.
|
|
||||||
|
|
||||||
* zconf:
|
* zconf:
|
||||||
Set of scripts to configure and list status information of Linux on s390
|
Set of scripts to configure and list status information of Linux on s390
|
||||||
devices.
|
devices.
|
||||||
@@ -417,6 +414,19 @@ the different tools are provided:
|
|||||||
dumping).
|
dumping).
|
||||||
Removing the inflate modules and function prototypes are the only major
|
Removing the inflate modules and function prototypes are the only major
|
||||||
modifications made to the kernel version of zlib.
|
modifications made to the kernel version of zlib.
|
||||||
|
For stand-alone NVMe and list-directed DASD dump, the following tools/packages
|
||||||
|
are required to populate dumper's initramfs and prepare a dump partition:
|
||||||
|
- cat
|
||||||
|
- cut
|
||||||
|
- findmnt
|
||||||
|
- logsave
|
||||||
|
- makedumpfile
|
||||||
|
- mount
|
||||||
|
- poweroff
|
||||||
|
- sha256sum
|
||||||
|
- sync
|
||||||
|
- umount
|
||||||
|
- mkfs.ext4
|
||||||
|
|
||||||
* zgetdump
|
* zgetdump
|
||||||
For building zgetdump you need OpenSSL version 1.1.0 or newer
|
For building zgetdump you need OpenSSL version 1.1.0 or newer
|
||||||
@@ -508,11 +518,11 @@ the different tools are provided:
|
|||||||
|
|
||||||
* zkey:
|
* zkey:
|
||||||
For building the zkey tools you need openssl version 0.9.7 or newer installed
|
For building the zkey tools you need openssl version 0.9.7 or newer installed
|
||||||
(openssl-devel.rpm). Also required are cryptsetup version 2.0.3 or newer
|
(openssl-devel.rpm). Also required are cryptsetup version 2.8.2 or newer
|
||||||
(cryptsetup-devel.rpm), and json-c version 0.12 or newer (json-c-devel.rpm).
|
(cryptsetup-devel.rpm), and json-c version 0.12 or newer (json-c-devel.rpm).
|
||||||
Tip: you may skip the zkey build by adding `HAVE_OPENSSL=0`, and you may
|
Tip: you may skip the zkey build by adding `HAVE_OPENSSL=0` or
|
||||||
may skip the zkey-cryptsetup build by adding `HAVE_CRYPTSETUP2=0`, or
|
`HAVE_CRYPTSETUP2=0`, and you may skip the zkey-cryptsetup build
|
||||||
`HAVE_JSONC=0` to the make invocation.
|
by adding `HAVE_JSONC=0` to the make invocation.
|
||||||
A new group 'zkeyadm' needs to be created and all users intending to use the
|
A new group 'zkeyadm' needs to be created and all users intending to use the
|
||||||
tool must be added to this group. The owner of the default key repository
|
tool must be added to this group. The owner of the default key repository
|
||||||
'/etc/zkey/repository' must be set to group 'zkeyadm' with write permission
|
'/etc/zkey/repository' must be set to group 'zkeyadm' with write permission
|
||||||
|
|||||||
@@ -303,11 +303,11 @@ static void conflict_error(const char *uuid, unsigned int a, unsigned int d,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (persistent) {
|
if (persistent) {
|
||||||
fprintf(stderr, "AQPN %u.%u is not defined for "
|
fprintf(stderr, "APQN %u.%u is not defined for "
|
||||||
"vfio_ap-passthrough use by the persistent "
|
"vfio_ap-passthrough use by the persistent "
|
||||||
"ap bus mask settings\n", a, d);
|
"ap bus mask settings\n", a, d);
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "AQPN %u.%u is not allowed for "
|
fprintf(stderr, "APQN %u.%u is not allowed for "
|
||||||
"vfio_ap-passthrough use by the active ap "
|
"vfio_ap-passthrough use by the active ap "
|
||||||
"bus mask settings\n", a, d);
|
"bus mask settings\n", a, d);
|
||||||
}
|
}
|
||||||
@@ -531,7 +531,7 @@ out:
|
|||||||
* Determine if there are any conflicts between the specified device and
|
* Determine if there are any conflicts between the specified device and
|
||||||
* the apmask/aqmask settings stored in udev. This is done by treating
|
* the apmask/aqmask settings stored in udev. This is done by treating
|
||||||
* the masks as a temporary vfio_ap_device with all of the associated
|
* the masks as a temporary vfio_ap_device with all of the associated
|
||||||
* AQPNs owned by the system.
|
* APQNs owned by the system.
|
||||||
*/
|
*/
|
||||||
static int check_cfg_mask_conflicts(struct ap_check_anchor *anc)
|
static int check_cfg_mask_conflicts(struct ap_check_anchor *anc)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ else # $(ENABLE_DOC) != 1
|
|||||||
# freshness of the man page can be checked, even if `pandoc` is not available,
|
# freshness of the man page can be checked, even if `pandoc` is not available,
|
||||||
# or ENABLE_DOC disabled.
|
# or ENABLE_DOC disabled.
|
||||||
|
|
||||||
MANPAGE_FRESH := $(shell sha256sum --check .chreipl-fcp-mpath.7.cksum >/dev/null && echo 1 || echo 0)
|
MANPAGE_FRESH := $(shell sha256sum -c .chreipl-fcp-mpath.7.cksum >/dev/null && echo 1 || echo 0)
|
||||||
ifeq ($(MANPAGE_FRESH),0)
|
ifeq ($(MANPAGE_FRESH),0)
|
||||||
$(warning chreipl-fcp-mpath.7 is outdated, please regenerate it by calling `make ENABLE_DOC=1`)
|
$(warning chreipl-fcp-mpath.7 is outdated, please regenerate it by calling `make ENABLE_DOC=1`)
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -1,182 +1,170 @@
|
|||||||
.\" Automatically generated by Pandoc 2.16.1
|
.\" Automatically generated by Pandoc 3.1.11.1
|
||||||
.\"
|
.\"
|
||||||
.TH "CHREIPL-FCP-MPATH" "7" "2022-02-24" "s390-tools 2.20.0-build-20220224" "Administrator Manual"
|
.TH "CHREIPL\-FCP\-MPATH" "7" "2025\-03\-12" "s390-tools 2.37.0-build-20250312" "Administrator Manual"
|
||||||
.hy
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
chreipl\-fcp\-mpath \- use multipath information for re\-IPL path
|
||||||
chreipl-fcp-mpath - use multipath information for re-IPL path failover
|
failover on a running Linux instance
|
||||||
on a running Linux instance
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.PP
|
The IPL process of Linux on Z or LinuxONE from an FCP\-attached SCSI
|
||||||
The IPL process of Linux on Z or LinuxONE from an FCP-attached SCSI
|
|
||||||
volume uses exactly one path to the volume.
|
volume uses exactly one path to the volume.
|
||||||
If this path is unavailable, the IPL fails.
|
If this path is unavailable, the IPL fails.
|
||||||
.PP
|
.PP
|
||||||
The \f[B]chreipl-fcp-mpath\f[R] toolset monitors \f[B]udev\f[R] events
|
The \f[B]chreipl\-fcp\-mpath\f[R] toolset monitors \f[B]udev\f[R] events
|
||||||
about paths to the re-IPL volume.
|
about paths to the re\-IPL volume.
|
||||||
If the currently configured re-IPL path becomes unavailable, the toolset
|
If the currently configured re\-IPL path becomes unavailable, the
|
||||||
checks for operational paths to the same volume.
|
toolset checks for operational paths to the same volume.
|
||||||
If available, it reconfigures the re-IPL settings to use an operational
|
If available, it reconfigures the re\-IPL settings to use an operational
|
||||||
path.
|
path.
|
||||||
.PP
|
.PP
|
||||||
Thus, re-IPL from an FCP-attached SCSI volume can be successful despite
|
Thus, re\-IPL from an FCP\-attached SCSI volume can be successful
|
||||||
path failures on a running Linux instance if at least one path to the
|
despite path failures on a running Linux instance if at least one path
|
||||||
re-IPL volume remains operational.
|
to the re\-IPL volume remains operational.
|
||||||
.PP
|
.PP
|
||||||
\f[B]Chreipl-fcp-mpath\f[R] requires \f[B]udev\f[R],
|
\f[B]Chreipl\-fcp\-mpath\f[R] requires \f[B]udev\f[R],
|
||||||
\f[B]multipathd\f[R] and \f[B]dm-multipath\f[R].
|
\f[B]multipathd\f[R] and \f[B]dm\-multipath\f[R].
|
||||||
Once installed, the toolset runs automatically and autonomously.
|
Once installed, the toolset runs automatically and autonomously.
|
||||||
No user intervention is possible or required.
|
No user intervention is possible or required.
|
||||||
.PP
|
.PP
|
||||||
Other than installing the toolset, there is no user interface for
|
Other than installing the toolset, there is no user interface for
|
||||||
\f[B]chreipl-fcp-mpath\f[R].
|
\f[B]chreipl\-fcp\-mpath\f[R].
|
||||||
.SS Requirements
|
.SS Requirements
|
||||||
.PP
|
The \f[B]chreipl\-fcp\-mpath\f[R] tool has the following requirements on
|
||||||
The \f[B]chreipl-fcp-mpath\f[R] tool has the following requirements on
|
|
||||||
the Linux instance that is being monitored:
|
the Linux instance that is being monitored:
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The Linux instance must have started successfully, during IPL.
|
The Linux instance must have started successfully, during IPL.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The running Linux instance must use \f[B]dm-multipath\f[R] and
|
The running Linux instance must use \f[B]dm\-multipath\f[R] and
|
||||||
\f[B]multipathd\f[R] for the configured re-IPL volume - a volume that
|
\f[B]multipathd\f[R] for the configured re\-IPL volume \- a volume that
|
||||||
contains a zipl boot record and has one of its paths used in the re-IPL
|
contains a zipl boot record and has one of its paths used in the re\-IPL
|
||||||
configuration.
|
configuration.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[B]udev\f[R] must run.
|
\f[B]udev\f[R] must run.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The toolset must observe at least one event about the configured re-IPL
|
The toolset must observe at least one event about the configured re\-IPL
|
||||||
path.
|
path.
|
||||||
Examples for such events are: the SCSI disk comes online, or a path of
|
Examples for such events are: the SCSI disk comes online, or a path of
|
||||||
the corresponding multipath device goes down or comes back online.
|
the corresponding multipath device goes down or comes back online.
|
||||||
.RS 2
|
.RS 2
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The WWID of the re-IPL volume must not change while the Linux instance
|
The WWID of the re\-IPL volume must not change while the Linux instance
|
||||||
is running.
|
is running.
|
||||||
.RE
|
.RE
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
When the configured re-IPL path becomes unavailable while the Linux
|
When the configured re\-IPL path becomes unavailable while the Linux
|
||||||
instance is running, at least one operational path to the re-IPL volume
|
instance is running, at least one operational path to the re\-IPL volume
|
||||||
must be available, or must become available.
|
must be available, or must become available.
|
||||||
If no such path is available when the Linux instance is rebooted, the
|
If no such path is available when the Linux instance is rebooted, the
|
||||||
re-IPL path is not changed.
|
re\-IPL path is not changed.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
The tool assumes that any manually reconfigured re-IPL device is valid
|
The tool assumes that any manually reconfigured re\-IPL device is valid
|
||||||
and operational.
|
and operational.
|
||||||
.RS 2
|
.RS 2
|
||||||
.PP
|
.PP
|
||||||
The tool treats a newly configured re-IPL device like the initially
|
The tool treats a newly configured re\-IPL device like the initially
|
||||||
configured re-IPL device.
|
configured re\-IPL device.
|
||||||
In particular, if the newly configured re-IPL device fulfills the
|
In particular, if the newly configured re\-IPL device fulfills the
|
||||||
requirements of the tool, re-IPL path failover takes place if the
|
requirements of the tool, re\-IPL path failover takes place if the
|
||||||
configured re-IPL path becomes unavailable.
|
configured re\-IPL path becomes unavailable.
|
||||||
.RE
|
.RE
|
||||||
.SS Caution with Manual Changes to the Configured re-IPL Target
|
.SS Caution with Manual Changes to the Configured re\-IPL Target
|
||||||
.PP
|
\f[B]chreipl\-fcp\-mpath\f[R] is designed to accept operator\-inititated
|
||||||
\f[B]chreipl-fcp-mpath\f[R] is designed to accept operator-inititated
|
changes of the re\-IPL device.
|
||||||
changes of the re-IPL device.
|
|
||||||
However, concurrent changes by the operator and tool driven changes can
|
However, concurrent changes by the operator and tool driven changes can
|
||||||
result in the operator change being overwritten.
|
result in the operator change being overwritten.
|
||||||
.PP
|
.PP
|
||||||
To avoid this problem, change the re-IPL device only during steady-state
|
To avoid this problem, change the re\-IPL device only during
|
||||||
operations, when no path events happen.
|
steady\-state operations, when no path events happen.
|
||||||
Alternatively, make sure that no events are processed while you change
|
Alternatively, make sure that no events are processed while you change
|
||||||
the device.
|
the device.
|
||||||
See EXAMPLES for one way to suspend event processing.
|
See EXAMPLES for one way to suspend event processing.
|
||||||
.SH MESSAGES
|
.SH MESSAGES
|
||||||
.PP
|
During monitoring and event processing, \f[B]chreipl\-fcp\-mpath\f[R]
|
||||||
During monitoring and event processing, \f[B]chreipl-fcp-mpath\f[R]
|
|
||||||
writes messages to the syslog.
|
writes messages to the syslog.
|
||||||
.PP
|
.PP
|
||||||
When the configured re-IPL path is changed to a different path to the
|
When the configured re\-IPL path is changed to a different path to the
|
||||||
same volume (priority \f[I]daemon.notice\f[R]):
|
same volume (priority \f[I]daemon.notice\f[R]):
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
Changed re-IPL path to: <device-bus-id>:<wwpn>:<lun>.
|
Changed re\-IPL path to: <device\-bus\-id>:<wwpn>:<lun>.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
When a path event indicates that the last available path has become
|
When a path event indicates that the last available path has become
|
||||||
non-operational (priority \f[I]daemon.alert\f[R]):
|
non\-operational (priority \f[I]daemon.alert\f[R]):
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
The re-IPL device cannot be changed because no operational path to the
|
The re\-IPL device cannot be changed because no operational path to the
|
||||||
re-IPL volume remains.
|
re\-IPL volume remains.
|
||||||
The next re-IPL might fail unless you re-attach or enable at least one
|
The next re\-IPL might fail unless you re\-attach or enable at least one
|
||||||
valid path to the re-IPL volume.
|
valid path to the re\-IPL volume.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
When changing the configured re-IPL device failed because of an error
|
When changing the configured re\-IPL device failed because of an error
|
||||||
with the used Linux kernel interface (priority \f[I]daemon.crit\f[R]):
|
with the used Linux kernel interface (priority \f[I]daemon.crit\f[R]):
|
||||||
.RS
|
.RS
|
||||||
.PP
|
.PP
|
||||||
Changing the re-IPL device failed.
|
Changing the re\-IPL device failed.
|
||||||
The current re-IPL settings might be inconsistent.
|
The current re\-IPL settings might be inconsistent.
|
||||||
Check and correct the settings (see the README.md of chreipl-fcp-mpath)
|
Check and correct the settings (see the README.md of
|
||||||
to make sure that the current re-IPL device is valid.
|
chreipl\-fcp\-mpath) to make sure that the current re\-IPL device is
|
||||||
|
valid.
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
A failure to change the re-IPL device can indicate an inconsistent
|
A failure to change the re\-IPL device can indicate an inconsistent
|
||||||
setting that cannot be corrected automatically by
|
setting that cannot be corrected automatically by
|
||||||
\f[B]chreipl-fcp-mpath\f[R].
|
\f[B]chreipl\-fcp\-mpath\f[R].
|
||||||
As a result, the next re-IPL might fail or might not use the intended
|
As a result, the next re\-IPL might fail or might not use the intended
|
||||||
re-IPL device.
|
re\-IPL device.
|
||||||
.PP
|
.PP
|
||||||
You can use the following tools to check and correct the current
|
You can use the following tools to check and correct the current
|
||||||
settings:
|
settings:
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[B]lsreipl\f[R] to confirm that the intended re-IPL device is
|
\f[B]lsreipl\f[R] to confirm that the intended re\-IPL device is
|
||||||
configured;
|
configured;
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[B]chreipl\f[R] to change the re-IPL device;
|
\f[B]chreipl\f[R] to change the re\-IPL device;
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[B]lszfcp\f[R] to inspect the state of available paths to the re-IPL
|
\f[B]lszfcp\f[R] to inspect the state of available paths to the re\-IPL
|
||||||
device.
|
device.
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
.SS Manual Changes to the Configured re-IPL Device
|
.SS Manual Changes to the Configured re\-IPL Device
|
||||||
.PP
|
|
||||||
As outlined in DESCRIPTION, be cautious when manually changing the
|
As outlined in DESCRIPTION, be cautious when manually changing the
|
||||||
configured re-IPL device.
|
configured re\-IPL device.
|
||||||
Assure that your reconfiguration actions do not collide with concurrent
|
Assure that your reconfiguration actions do not collide with concurrent
|
||||||
automatic event processing by \f[B]chreipl-fcp-mpath\f[R].
|
automatic event processing by \f[B]chreipl\-fcp\-mpath\f[R].
|
||||||
You can avoid such collisions, by stopping event processing, making your
|
You can avoid such collisions, by stopping event processing, making your
|
||||||
changes, and then re-enabling event processing.
|
changes, and then re\-enabling event processing.
|
||||||
You need \f[I]root\f[R] privileges for running the commands in the
|
You need \f[I]root\f[R] privileges for running the commands in the
|
||||||
following example:
|
following example:
|
||||||
.IP
|
.IP
|
||||||
.nf
|
.EX
|
||||||
\f[C]
|
|
||||||
\[ti] # udevadm settle
|
\[ti] # udevadm settle
|
||||||
\[ti] # udevadm control --stop-exec-queue
|
\[ti] # udevadm control \-\-stop\-exec\-queue
|
||||||
\[ti] # chreipl ...
|
\[ti] # chreipl ...
|
||||||
\[ti] # udevadm control --start-exec-queue
|
\[ti] # udevadm control \-\-start\-exec\-queue
|
||||||
\f[R]
|
.EE
|
||||||
.fi
|
|
||||||
.SS Listing messages with journalctl
|
.SS Listing messages with journalctl
|
||||||
.PP
|
|
||||||
If your Linux instance includes \f[B]journalctl\f[R], use the following
|
If your Linux instance includes \f[B]journalctl\f[R], use the following
|
||||||
command to list all messages that are issued by
|
command to list all messages that are issued by
|
||||||
\f[B]chreipl-fcp-mpath\f[R]:
|
\f[B]chreipl\-fcp\-mpath\f[R]:
|
||||||
.IP
|
.IP
|
||||||
.nf
|
.EX
|
||||||
\f[C]
|
\[ti] # journalctl \-t chreipl\-fcp\-mpath
|
||||||
\[ti] # journalctl -t chreipl-fcp-mpath
|
.EE
|
||||||
\f[R]
|
|
||||||
.fi
|
|
||||||
.PP
|
.PP
|
||||||
To list only messages that were issued since the last IPL, use this
|
To list only messages that were issued since the last IPL, use this
|
||||||
command:
|
command:
|
||||||
.IP
|
.IP
|
||||||
.nf
|
.EX
|
||||||
\f[C]
|
\[ti] # journalctl \-t chreipl\-fcp\-mpath \-b
|
||||||
\[ti] # journalctl -t chreipl-fcp-mpath -b
|
.EE
|
||||||
\f[R]
|
|
||||||
.fi
|
|
||||||
.SH REPORTING BUGS
|
.SH REPORTING BUGS
|
||||||
.PP
|
|
||||||
Use the \f[B]Issues\f[R] functionality on GitHub to report any bugs in
|
Use the \f[B]Issues\f[R] functionality on GitHub to report any bugs in
|
||||||
\f[B]chreipl-fcp-mpath\f[R]: s390-tools
|
\f[B]chreipl\-fcp\-mpath\f[R]: \c
|
||||||
Issues (https://github.com/ibm-s390-linux/s390-tools/issues).
|
.UR https://github.com/ibm-s390-linux/s390-tools/issues
|
||||||
|
s390\-tools Issues
|
||||||
|
.UE \c
|
||||||
|
\&.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.PP
|
|
||||||
\f[B]chreipl\f[R](8), \f[B]dracut\f[R](8), \f[B]journalctl\f[R](1),
|
\f[B]chreipl\f[R](8), \f[B]dracut\f[R](8), \f[B]journalctl\f[R](1),
|
||||||
\f[B]lsreipl(8)\f[R], \f[B]lszfcp\f[R](8), \f[B]multipath\f[R](8),
|
\f[B]lsreipl(8)\f[R], \f[B]lszfcp\f[R](8), \f[B]multipath\f[R](8),
|
||||||
\f[B]multipathd\f[R](8), \f[B]udev\f[R](7), \f[B]udevadm\f[R](8),
|
\f[B]multipathd\f[R](8), \f[B]udev\f[R](7), \f[B]udevadm\f[R](8),
|
||||||
|
|||||||
25
common.mak
25
common.mak
@@ -32,7 +32,7 @@ endif
|
|||||||
# 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 := 37
|
RELEASE := 41
|
||||||
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)
|
||||||
@@ -119,6 +119,10 @@ ifneq ($(HOST_ARCH),$(BUILD_ARCH))
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# *_FOR_BUILD variables define compilation configurations for binaries used
|
||||||
|
# during the build process (e.g. autocompleteion script generators). This
|
||||||
|
# is especially important for cross-compilation where these binaries need to
|
||||||
|
# be executed on the build system.
|
||||||
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
|
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
|
||||||
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
|
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
|
||||||
|
|
||||||
@@ -165,7 +169,7 @@ ifeq ("${ENABLE_WERROR}", "1")
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
DEFAULT_CPPFLAGS = -D_GNU_SOURCE
|
DEFAULT_CPPFLAGS = -D_GNU_SOURCE
|
||||||
DEFAULT_LDFLAGS = -rdynamic
|
DEFAULT_LDFLAGS = -rdynamic -Wl,--as-needed
|
||||||
|
|
||||||
ifeq ("${ASAN}","1")
|
ifeq ("${ASAN}","1")
|
||||||
DEFAULT_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
DEFAULT_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
|
||||||
@@ -201,7 +205,7 @@ endef
|
|||||||
# $5: Additional compiler & linker options (optional)
|
# $5: Additional compiler & linker options (optional)
|
||||||
#
|
#
|
||||||
check_dep=\
|
check_dep=\
|
||||||
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
|
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) -Wl,--no-as-needed $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
|
||||||
if [ $$? != 0 ]; \
|
if [ $$? != 0 ]; \
|
||||||
then \
|
then \
|
||||||
printf " REQCHK %s (%s)\n" $1 $2; \
|
printf " REQCHK %s (%s)\n" $1 $2; \
|
||||||
@@ -265,9 +269,12 @@ LIBDIR = $(INSTALLDIR)/lib
|
|||||||
USRLIBDIR = $(INSTALLDIR)/usr/lib
|
USRLIBDIR = $(INSTALLDIR)/usr/lib
|
||||||
USRLIB64DIR = $(INSTALLDIR)/usr/lib64
|
USRLIB64DIR = $(INSTALLDIR)/usr/lib64
|
||||||
SYSCONFDIR = $(INSTALLDIR)/etc
|
SYSCONFDIR = $(INSTALLDIR)/etc
|
||||||
MANDIR = $(INSTALLDIR)/usr/share/man
|
DATADIR = $(INSTALLDIR)/usr/share
|
||||||
|
MANDIR = $(DATADIR)/man
|
||||||
|
BASHCOMPLETIONDIR = $(DATADIR)/bash-completion/completions
|
||||||
|
ZSHCOMPLETIONDIR = $(DATADIR)/zsh/site-functions
|
||||||
VARDIR = $(INSTALLDIR)/var
|
VARDIR = $(INSTALLDIR)/var
|
||||||
TOOLS_DATADIR = $(INSTALLDIR)/usr/share/s390-tools
|
TOOLS_DATADIR = $(DATADIR)/s390-tools
|
||||||
TOOLS_LIBDIR = $(INSTALLDIR)/lib/s390-tools
|
TOOLS_LIBDIR = $(INSTALLDIR)/lib/s390-tools
|
||||||
ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
|
ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
|
||||||
# Systemd support files are installed only if a directory is specified
|
# Systemd support files are installed only if a directory is specified
|
||||||
@@ -337,14 +344,6 @@ endif
|
|||||||
export INSTALL CFLAGS CXXFLAGS \
|
export INSTALL CFLAGS CXXFLAGS \
|
||||||
LDFLAGS CPPFLAGS ALL_CFLAGS ALL_CXXFLAGS ALL_LDFLAGS ALL_CPPFLAGS
|
LDFLAGS CPPFLAGS ALL_CFLAGS ALL_CXXFLAGS ALL_LDFLAGS ALL_CPPFLAGS
|
||||||
|
|
||||||
ifneq ($(shell $(CC_SILENT) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
|
|
||||||
NO_PIE_CFLAGS := -fno-pie
|
|
||||||
NO_PIE_LDFLAGS := -no-pie
|
|
||||||
else
|
|
||||||
NO_PIE_CFLAGS :=
|
|
||||||
NO_PIE_LDFLAGS :=
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Overwrite implicit makefile rules for having nice compile output
|
# Overwrite implicit makefile rules for having nice compile output
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
ifeq ("${C}","1")
|
ifeq ("${C}","1")
|
||||||
|
|||||||
81
common_autocomp.mak
Normal file
81
common_autocomp.mak
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# Copyright IBM Corp. 2025
|
||||||
|
|
||||||
|
|
||||||
|
# This file defines the build process for shell autocompletion binaries
|
||||||
|
#
|
||||||
|
# How to incorporate it into tool Makefiles:
|
||||||
|
#
|
||||||
|
# 0. The file with the autocompletion script generation code should be named
|
||||||
|
# 'autocompletion_generator_host.c'
|
||||||
|
#
|
||||||
|
# 1. Define the 'bash-completions' and 'zsh-completions' variables: both must be a list
|
||||||
|
# of the names of all the shell completion scripts that belong to the tools the Makefile
|
||||||
|
# is responsible for building.
|
||||||
|
#
|
||||||
|
# (The name of a zsh completion script is the same as the name of the tool,
|
||||||
|
# prefixed by an underscore)
|
||||||
|
#
|
||||||
|
# (The name of a bash completion script is the same as the name of the tool,
|
||||||
|
# suffixed by '.bash')
|
||||||
|
#
|
||||||
|
# 2. include this file
|
||||||
|
#
|
||||||
|
# +1: Add the autocompletion scripts to the .gitignore file
|
||||||
|
#
|
||||||
|
# (See cpumf or dasdfmt as example)
|
||||||
|
|
||||||
|
|
||||||
|
autocomplete-bin := autocompletion_generator_host
|
||||||
|
|
||||||
|
autocomp-object := $(rootdir)/libutil/util_autocomp_host.o
|
||||||
|
|
||||||
|
$(autocomp-object): $(rootdir)/libutil
|
||||||
|
$(MAKE) -C $(rootdir)/libutil/ $(notdir $@)
|
||||||
|
|
||||||
|
$(autocomplete-bin).o: $(autocomplete-bin).c
|
||||||
|
$(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) -I $(rootdir)/include -c $< -o $@
|
||||||
|
|
||||||
|
$(autocomplete-bin): $(autocomplete-bin).o $(autocomp-object)
|
||||||
|
$(LINK_FOR_BUILD) $^ -o $@
|
||||||
|
|
||||||
|
$(bash-completions) $(zsh-completions) &: $(autocomplete-bin)
|
||||||
|
./$(autocomplete-bin)
|
||||||
|
|
||||||
|
install-shell-completions: $(bash-completions) $(zsh-completions)
|
||||||
|
$(INSTALL) -d -m 755 $(DESTDIR)$(ZSHCOMPLETIONDIR)
|
||||||
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BASHCOMPLETIONDIR)
|
||||||
|
for completion in $(bash-completions); do \
|
||||||
|
$(INSTALL) -m 644 $$completion $(DESTDIR)$(BASHCOMPLETIONDIR); \
|
||||||
|
done
|
||||||
|
for completion in $(zsh-completions); do \
|
||||||
|
$(INSTALL) -m 644 $$completion $(DESTDIR)$(ZSHCOMPLETIONDIR); \
|
||||||
|
done
|
||||||
|
|
||||||
|
all: $(zsh-completions) $(bash-completions)
|
||||||
|
|
||||||
|
install: install-shell-completions
|
||||||
|
|
||||||
|
.PHONY: install-shell-completions $(rootdir)/libutil
|
||||||
|
|
||||||
|
clean-autocomplete-bin:
|
||||||
|
$(RM) -- $(autocomplete-bin)
|
||||||
|
|
||||||
|
clean: clean-autocomplete-bin
|
||||||
|
|
||||||
|
ifdef bash-completions
|
||||||
|
clean-bash-completions:
|
||||||
|
$(RM) -- $(bash-completions)
|
||||||
|
|
||||||
|
clean: clean-bash-completions
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifdef zsh-completions
|
||||||
|
clean-zsh-completions:
|
||||||
|
$(RM) -- $(zsh-completions)
|
||||||
|
|
||||||
|
clean: clean-zsh-completions
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: clean-autocomplete-bin clean-bash-completions clean-zsh-completions
|
||||||
@@ -22,7 +22,7 @@ ALL_CPPFLAGS += -DVERSION=$(VERSION)
|
|||||||
all: check_dep cpacfstats cpacfstatsd
|
all: check_dep cpacfstats cpacfstatsd
|
||||||
|
|
||||||
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \
|
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \
|
||||||
$(rootdir)/libutil/libutil.a
|
$(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
|
||||||
|
|
||||||
cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o
|
cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o
|
||||||
|
|||||||
@@ -79,9 +79,11 @@ the cpacfstats client application.
|
|||||||
|
|
||||||
Example usage scenario:
|
Example usage scenario:
|
||||||
.P
|
.P
|
||||||
1. Start the cpacfstatsd daemon with root privileges.
|
1. Start the cpacfstatsd daemon with root privileges using 'systemctl start
|
||||||
|
cpacfstatsd'.
|
||||||
.P
|
.P
|
||||||
2. Check for successful startup by using the ps and syslog commands.
|
2. Check for successful startup by using the 'systemctl status cpacfstatsd'
|
||||||
|
command.
|
||||||
.P
|
.P
|
||||||
3. Enable the CPACF counters of interest. For example, enable all counters
|
3. Enable the CPACF counters of interest. For example, enable all counters
|
||||||
by issuing cpacfstats -e.
|
by issuing cpacfstats -e.
|
||||||
@@ -95,7 +97,7 @@ cryptographic counters as required. To reset, use, for example, cpacfstats
|
|||||||
6. Disable all the CPACF measurements, for example, by using cpacfstats
|
6. Disable all the CPACF measurements, for example, by using cpacfstats
|
||||||
-d.
|
-d.
|
||||||
.P
|
.P
|
||||||
7. Shutdown the cpacfstatsd daemon by using killall cpacfstatsd.
|
7. Shutdown the cpacfstatsd daemon by using 'systemctl stop cpacfstatsd'.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
@@ -177,6 +179,12 @@ the errno value.
|
|||||||
ECC counters are only available since z15. cpacfstats will show the
|
ECC counters are only available since z15. cpacfstats will show the
|
||||||
counters as \fIunsupported\fR if the hardware does not support ECC
|
counters as \fIunsupported\fR if the hardware does not support ECC
|
||||||
counters.
|
counters.
|
||||||
|
|
||||||
|
CPU-MF counters have to be authorized on HMC or SE to be available and are
|
||||||
|
otherwise shown as \fIunauthorized\fR. 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
|
||||||
|
\fICrypto activity counter set authorization control\fR checkbox.
|
||||||
.
|
.
|
||||||
.SH APPENDIX
|
.SH APPENDIX
|
||||||
The detailed pai counter names are:
|
The detailed pai counter names are:
|
||||||
|
|||||||
@@ -175,9 +175,10 @@ static void print_virtual_counter_answer(int s,
|
|||||||
int ctr, int state, uint64_t value)
|
int ctr, int state, uint64_t value)
|
||||||
{
|
{
|
||||||
static const char *const states[] = {
|
static const char *const states[] = {
|
||||||
[DISABLED] = "disabled",
|
[DISABLED] = "disabled",
|
||||||
[ENABLED] = "enabled",
|
[ENABLED] = "enabled",
|
||||||
[UNSUPPORTED] = "unsupported"
|
[UNSUPPORTED] = "unsupported",
|
||||||
|
[UNAUTHORIZED] = "unauthorized"
|
||||||
};
|
};
|
||||||
int paictr = 0, paistate = 0, ec;
|
int paictr = 0, paistate = 0, ec;
|
||||||
uint64_t i, paivalue = 0;
|
uint64_t i, paivalue = 0;
|
||||||
@@ -242,6 +243,8 @@ static void print_answer(int s, int ctr, int state, uint64_t value)
|
|||||||
printf(" %s counter: disabled\n", counter_str[ctr]);
|
printf(" %s counter: disabled\n", counter_str[ctr]);
|
||||||
else if (state == UNSUPPORTED)
|
else if (state == UNSUPPORTED)
|
||||||
printf(" %s counter: unsupported\n", counter_str[ctr]);
|
printf(" %s counter: unsupported\n", counter_str[ctr]);
|
||||||
|
else if (state == UNAUTHORIZED)
|
||||||
|
printf(" %s counter: unauthorized\n", counter_str[ctr]);
|
||||||
else
|
else
|
||||||
printf(" %s counter: %lu\n", counter_str[ctr], value);
|
printf(" %s counter: %lu\n", counter_str[ctr], value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,8 @@ enum cmd_e {
|
|||||||
enum state_e {
|
enum state_e {
|
||||||
DISABLED = 0,
|
DISABLED = 0,
|
||||||
ENABLED,
|
ENABLED,
|
||||||
UNSUPPORTED
|
UNSUPPORTED,
|
||||||
|
UNAUTHORIZED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum counter_type {
|
enum counter_type {
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ static int do_enable(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
|||||||
}
|
}
|
||||||
state = ENABLED;
|
state = ENABLED;
|
||||||
}
|
}
|
||||||
if (state != UNSUPPORTED) {
|
if (state != UNSUPPORTED && state != UNAUTHORIZED) {
|
||||||
rc = perf_read_ctr(i, &value, supported_counters);
|
rc = perf_read_ctr(i, &value, supported_counters);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
|
||||||
#include "cpacfstats.h"
|
#include "cpacfstats.h"
|
||||||
|
#include "lib/libcpumf.h"
|
||||||
#include "../include/lib/zt_common.h"
|
#include "../include/lib/zt_common.h"
|
||||||
|
|
||||||
/* correlation between counter and perf counter string */
|
/* correlation between counter and perf counter string */
|
||||||
@@ -123,16 +124,6 @@ static struct percpucounter *findcpu(unsigned int cpunum, int unlinkflag)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
static int perf_supported(void)
|
||||||
{
|
{
|
||||||
return !access("/proc/sys/kernel/perf_event_paranoid", R_OK);
|
return !access("/proc/sys/kernel/perf_event_paranoid", R_OK);
|
||||||
@@ -150,6 +141,10 @@ static int perf_counter_supported(const char *pmu, const char *counter)
|
|||||||
return !access(buf, R_OK);
|
return !access(buf, R_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns 1 if counters are authorized, -1 if counters are unauthorized,
|
||||||
|
* and 0 otherwise which indicates that the counters are unsupported
|
||||||
|
*/
|
||||||
static int cpumf_authorized(void)
|
static int cpumf_authorized(void)
|
||||||
{
|
{
|
||||||
unsigned vermin, vermax, auth;
|
unsigned vermin, vermax, auth;
|
||||||
@@ -168,10 +163,12 @@ static int cpumf_authorized(void)
|
|||||||
if (sscanf(line,
|
if (sscanf(line,
|
||||||
"CPU-MF: Counter facility: version=%d.%d authorization=%x",
|
"CPU-MF: Counter facility: version=%d.%d authorization=%x",
|
||||||
&vermin, &vermax, &auth) == 3) {
|
&vermin, &vermax, &auth) == 3) {
|
||||||
if (auth & 0x8)
|
if (auth & 0x8) {
|
||||||
res = 1;
|
res = 1;
|
||||||
else
|
} else {
|
||||||
eprint("CPU-MF counters not authorized.\n");
|
eprint("CPU-MF counters not authorized.\n");
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -242,7 +239,7 @@ static int activatecpu(unsigned int cpu, unsigned int *supported_counters)
|
|||||||
}
|
}
|
||||||
/* activate CPU-MF */
|
/* activate CPU-MF */
|
||||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||||
if (ctr_state[i] == UNSUPPORTED)
|
if (ctr_state[i] == UNSUPPORTED || ctr_state[i] == UNAUTHORIZED)
|
||||||
continue;
|
continue;
|
||||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||||
pfm_event.size = sizeof(pfm_event);
|
pfm_event.size = sizeof(pfm_event);
|
||||||
@@ -407,7 +404,7 @@ static int perf_load_counter_data(void)
|
|||||||
int i, res = 0;
|
int i, res = 0;
|
||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; ++i) {
|
for (i = 0; i < ALL_COUNTER; ++i) {
|
||||||
if (ctr_state[i] != UNSUPPORTED)
|
if (ctr_state[i] != UNSUPPORTED && ctr_state[i] != UNAUTHORIZED)
|
||||||
res |= perf_event_encode(&pmf_counter_data[i].pmutype,
|
res |= perf_event_encode(&pmf_counter_data[i].pmutype,
|
||||||
&pmf_counter_data[i].eventid,
|
&pmf_counter_data[i].eventid,
|
||||||
pmf_counter_name[i].pmu,
|
pmf_counter_name[i].pmu,
|
||||||
@@ -483,6 +480,7 @@ int perf_init(unsigned int *supported_counters)
|
|||||||
};
|
};
|
||||||
unsigned long maxfd;
|
unsigned long maxfd;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
|
int cpumf_state;
|
||||||
int i, num;
|
int i, num;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
@@ -496,10 +494,15 @@ int perf_init(unsigned int *supported_counters)
|
|||||||
* counters for PAI. */
|
* counters for PAI. */
|
||||||
num = ALL_COUNTER + 2;
|
num = ALL_COUNTER + 2;
|
||||||
|
|
||||||
if (!cpumf_authorized()) {
|
cpumf_state = cpumf_authorized();
|
||||||
|
if (cpumf_state == 0) {
|
||||||
for (i = 0; i < ALL_COUNTER; ++i)
|
for (i = 0; i < ALL_COUNTER; ++i)
|
||||||
ctr_state[i] = UNSUPPORTED;
|
ctr_state[i] = UNSUPPORTED;
|
||||||
num -= ALL_COUNTER;
|
num -= ALL_COUNTER;
|
||||||
|
} else if (cpumf_state == -1) {
|
||||||
|
for (i = 0; i < ALL_COUNTER; ++i)
|
||||||
|
ctr_state[i] = UNAUTHORIZED;
|
||||||
|
num -= ALL_COUNTER;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < ALL_COUNTER; i++) {
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
if (!perf_counter_supported("cpum_cf", cpum_cf[i])) {
|
if (!perf_counter_supported("cpum_cf", cpum_cf[i])) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ include ../common.mak
|
|||||||
BIN_FILES = lscpumf chcpumf lshwc pai lspai
|
BIN_FILES = lscpumf chcpumf lshwc pai lspai
|
||||||
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8 lspai.8
|
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8 lspai.8
|
||||||
|
|
||||||
|
zsh-completions := $(addprefix _,$(BIN_FILES))
|
||||||
|
bash-completions := $(addsuffix .bash,$(BIN_FILES))
|
||||||
|
|
||||||
|
include ../common_autocomp.mak
|
||||||
|
|
||||||
all: $(BIN_FILES)
|
all: $(BIN_FILES)
|
||||||
|
|
||||||
libs = $(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
|
libs = $(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
|
||||||
|
|||||||
28
cpumf/autocompletion_generator_host.c
Normal file
28
cpumf/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Autocompletion generation - for cpumf family of tools
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 "lib/util_autocomp.h"
|
||||||
|
|
||||||
|
#include "chcpumf_cli.h"
|
||||||
|
#include "lscpumf_cli.h"
|
||||||
|
#include "lshwc_cli.h"
|
||||||
|
#include "lspai_cli.h"
|
||||||
|
#include "pai_cli.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
generate_autocomp(chcpumf_opt_vec, "chcpumf");
|
||||||
|
generate_autocomp(lscpumf_opt_vec, "lscpumf");
|
||||||
|
generate_autocomp(lshwc_opt_vec, "lshwc");
|
||||||
|
generate_autocomp(lspai_opt_vec, "lspai");
|
||||||
|
generate_autocomp(pai_opt_vec, "pai");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
* 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 <errno.h>
|
#include <err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -16,38 +16,16 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "lib/util_opt.h"
|
|
||||||
#include "lib/util_prg.h"
|
|
||||||
#include "lib/util_base.h"
|
|
||||||
|
|
||||||
#include "lib/libcpumf.h"
|
#include "lib/libcpumf.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
|
#include "lib/util_prg.h"
|
||||||
|
|
||||||
|
#include "chcpumf_cli.h"
|
||||||
|
|
||||||
static unsigned int verbose;
|
static unsigned int verbose;
|
||||||
static unsigned long min_sdb, max_sdb;
|
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 = {
|
static const struct util_prg prg = {
|
||||||
.desc = "Change CPU Measurement facility charactertics",
|
.desc = "Change CPU Measurement facility charactertics",
|
||||||
.copyright_vec = {
|
.copyright_vec = {
|
||||||
@@ -88,21 +66,22 @@ static long parse_buffersize(char *string)
|
|||||||
static int write_sfb(unsigned int min, unsigned int max)
|
static int write_sfb(unsigned int min, unsigned int max)
|
||||||
{
|
{
|
||||||
int rc = EXIT_SUCCESS;
|
int rc = EXIT_SUCCESS;
|
||||||
char text[64];
|
char text[64], *path;
|
||||||
size_t len;
|
size_t len;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
fp = fopen(S390_CPUMSF_BUFFERSZ, "w");
|
path = util_path_sysfs(S390_CPUMSF_BUFFERSZ);
|
||||||
|
fp = fopen(path, "w");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
err(EXIT_FAILURE, S390_CPUMSF_BUFFERSZ);
|
err(EXIT_FAILURE, "%s", path);
|
||||||
snprintf(text, sizeof(text), "%u,%u", min, max);
|
snprintf(text, sizeof(text), "%u,%u", min, max);
|
||||||
len = strlen(text) + 1;
|
len = strlen(text) + 1;
|
||||||
if (fwrite(text, 1, len, fp) != len) {
|
if (fwrite(text, 1, len, fp) != len) {
|
||||||
warn(S390_CPUMSF_BUFFERSZ);
|
warn("%s", path);
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (fclose(fp)) {
|
if (fclose(fp)) {
|
||||||
warn(S390_CPUMSF_BUFFERSZ);
|
warn("%s", path);
|
||||||
rc = EXIT_FAILURE;
|
rc = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (verbose && rc != EXIT_FAILURE)
|
if (verbose && rc != EXIT_FAILURE)
|
||||||
@@ -110,6 +89,7 @@ static int write_sfb(unsigned int min, unsigned int max)
|
|||||||
" Minimum:%7d sample-data-blocks\n"
|
" Minimum:%7d sample-data-blocks\n"
|
||||||
" Maximum:%7d sample-data-blocks\n",
|
" Maximum:%7d sample-data-blocks\n",
|
||||||
min, max);
|
min, max);
|
||||||
|
free(path);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +141,7 @@ int main(int argc, char **argv)
|
|||||||
unsigned long my_min, my_max;
|
unsigned long my_min, my_max;
|
||||||
|
|
||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(chcpumf_opt_vec, NULL);
|
||||||
|
|
||||||
parse_args(argc, argv);
|
parse_args(argc, argv);
|
||||||
if (geteuid())
|
if (geteuid())
|
||||||
|
|||||||
40
cpumf/chcpumf_cli.h
Normal file
40
cpumf/chcpumf_cli.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for chcpumf
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 CHCPUMF_CLI_H
|
||||||
|
#define CHCPUMF_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
static struct util_opt chcpumf_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
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
700
cpumf/lscpumf.c
700
cpumf/lscpumf.c
@@ -7,8 +7,7 @@
|
|||||||
* 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 <ctype.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -31,6 +30,8 @@
|
|||||||
|
|
||||||
#include "lib/libcpumf.h"
|
#include "lib/libcpumf.h"
|
||||||
|
|
||||||
|
#include "lscpumf_cli.h"
|
||||||
|
|
||||||
#define ACTION_NONE 0
|
#define ACTION_NONE 0
|
||||||
#define ACTION_INFO 1
|
#define ACTION_INFO 1
|
||||||
#define ACTION_CNT 2
|
#define ACTION_CNT 2
|
||||||
@@ -39,7 +40,7 @@
|
|||||||
static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
|
static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
|
||||||
|
|
||||||
/* This defines the number of pages a Sample Data Buffer Table (SDBT) can hold
|
/* This defines the number of pages a Sample Data Buffer Table (SDBT) can hold
|
||||||
* as payload data. Each SDBT is one PAGE (4096 bytes) and continas 512 eight
|
* as payload data. Each SDBT is one PAGE (4096 bytes) and contains 512 eight
|
||||||
* byte data pointers to Sample Data Buffers (SDB). The last entry of a SDBT
|
* byte data pointers to Sample Data Buffers (SDB). The last entry of a SDBT
|
||||||
* points to another SDBT and can not store payload.
|
* points to another SDBT and can not store payload.
|
||||||
*/
|
*/
|
||||||
@@ -47,33 +48,6 @@ static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
|
|||||||
|
|
||||||
/* File names to read data from */
|
/* File names to read data from */
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
|
||||||
UTIL_OPT_SECTION("OPTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "list-counters", no_argument, NULL, 'c' },
|
|
||||||
.desc = "Lists counters for which the LPAR is authorized.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "list-all-counters", no_argument, NULL, 'C' },
|
|
||||||
.desc = "Lists counters regardless of LPAR authorization.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "name", no_argument, NULL, 'n' },
|
|
||||||
.desc = "Displays counter names.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "info", no_argument, NULL, 'i' },
|
|
||||||
.desc = "Displays detailed information.",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "list-sampling-events", no_argument, NULL, 's' },
|
|
||||||
.desc = "Lists sampling events for which the LPAR is authorized.",
|
|
||||||
},
|
|
||||||
UTIL_OPT_HELP,
|
|
||||||
UTIL_OPT_VERSION,
|
|
||||||
UTIL_OPT_END
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct util_prg prg = {
|
static const struct util_prg prg = {
|
||||||
.desc = "List CPU Measurement facility charactertics",
|
.desc = "List CPU Measurement facility charactertics",
|
||||||
.copyright_vec = {
|
.copyright_vec = {
|
||||||
@@ -139,7 +113,7 @@ static struct samples { /* Sample definition for all machines */
|
|||||||
* The CPU Measurement facility has a first and second version number.
|
* The CPU Measurement facility has a first and second version number.
|
||||||
*
|
*
|
||||||
* The first version number governs basic counter set and the
|
* The first version number governs basic counter set and the
|
||||||
* problem state counter set. Currently used are first verion numbers 1 and 3.
|
* problem state counter set. Currently used are first version numbers 1 and 3.
|
||||||
* The counter numbers are identifical for version number 1 and 3, but
|
* The counter numbers are identifical for version number 1 and 3, but
|
||||||
* have different purpose and description.
|
* have different purpose and description.
|
||||||
*
|
*
|
||||||
@@ -162,13 +136,6 @@ static struct samples { /* Sample definition for all machines */
|
|||||||
* Second version number: >3 Range 448 to 495 inclusive (48 counters)
|
* Second version number: >3 Range 448 to 495 inclusive (48 counters)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CPUMF_CTRSET_NONE 0
|
|
||||||
#define CPUMF_CTRSET_BASIC 2
|
|
||||||
#define CPUMF_CTRSET_PROBLEM_STATE 4
|
|
||||||
#define CPUMF_CTRSET_CRYPTO 8
|
|
||||||
#define CPUMF_CTRSET_EXTENDED 1
|
|
||||||
#define CPUMF_CTRSET_MT_DIAG 32
|
|
||||||
|
|
||||||
struct counters {
|
struct counters {
|
||||||
int ctrnum;
|
int ctrnum;
|
||||||
int ctrset;
|
int ctrset;
|
||||||
@@ -634,7 +601,7 @@ static struct counters cpumcf_z10_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1D_L3_LOCAL_WRITES",
|
.name = "L1D_L3_LOCAL_WRITES",
|
||||||
.desc = "A directory write to the Level-1 D-Cache directory"
|
.desc = "A directory write to the Level-1 D-Cache directory"
|
||||||
"\n\t\twhere the installtion cache line was source from"
|
"\n\t\twhere the installation cache line was source from"
|
||||||
"\n\t\tthe Level-3 cache that is on the same book as the"
|
"\n\t\tthe Level-3 cache that is on the same book as the"
|
||||||
"\n\t\tData cache (Local L2 cache)",
|
"\n\t\tData cache (Local L2 cache)",
|
||||||
},
|
},
|
||||||
@@ -1923,7 +1890,7 @@ static struct counters cpumcf_z14_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1931,7 +1898,7 @@ static struct counters cpumcf_z14_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom On-Chip memory",
|
"\n\t\tfrom On-Chip memory",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1939,7 +1906,7 @@ static struct counters cpumcf_z14_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2349,7 +2316,7 @@ static struct counters cpumcf_z15_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2357,7 +2324,7 @@ static struct counters cpumcf_z15_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom On-Chip memory",
|
"\n\t\tfrom On-Chip memory",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -2365,7 +2332,7 @@ static struct counters cpumcf_z15_counters[] = {
|
|||||||
.ctrset = CPUMF_CTRSET_EXTENDED,
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
|
||||||
.desc = "A directory write to the Level-1 Instruction cache"
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
"\n\t\tdirectory where the returned cache ine was sourced"
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -3136,6 +3103,641 @@ static struct counters cpumcf_z16_counters[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct counters cpumcf_z17_counters[] = {
|
||||||
|
{
|
||||||
|
.ctrnum = 128,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "L1D_RO_EXCL_WRITES",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache where"
|
||||||
|
"\n\t\tthe line was originally in a Read-Only state in the"
|
||||||
|
"\n\t\tcache but has been updated to be in the Exclusive"
|
||||||
|
"\n\t\tstate that allows stores to the cache line.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 129,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DTLB2_WRITES",
|
||||||
|
.desc = "A translation has been written into The Translation"
|
||||||
|
"\n\t\tLookaside Buffer 2 (TLB2) and the request was made"
|
||||||
|
"\n\t\tby the Level-1 Data cache. This is a replacement"
|
||||||
|
"\n\t\tfor what was provided for the DTLB on z13 and prior"
|
||||||
|
"\n\t\tmachines.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 130,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DTLB2_MISSES",
|
||||||
|
.desc = "A TLB2 miss is in progress for a request made by"
|
||||||
|
"\n\t\tthe Level-1 Data cache. Incremented by one for"
|
||||||
|
"\n\t\tevery TLB2 miss in progress for the Level-1 Data"
|
||||||
|
"\n\t\tcache on this cycle. This is a replacement for what"
|
||||||
|
"\n\t\twas provided for the DTLB on z13 and prior"
|
||||||
|
"\n\t\tmachines.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 131,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "CRSTE_1MB_WRITES",
|
||||||
|
.desc = "A translation entry was written into the Combined"
|
||||||
|
"\n\t\tRegion and Segment Table Entry array in the Level-2"
|
||||||
|
"\n\t\tTLB for a one-megabyte page.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 132,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DTLB2_GPAGE_WRITES",
|
||||||
|
.desc = "A translation entry for a two-gigabyte page was"
|
||||||
|
"\n\t\twritten into the Level-2 TLB.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 134,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ITLB2_WRITES",
|
||||||
|
.desc = "A translation entry has been written into the"
|
||||||
|
"\n\t\tTranslation Lookaside Buffer 2 (TLB2) and the"
|
||||||
|
"\n\t\trequest was made by the Level-1 Instruction cache."
|
||||||
|
"\n\t\tThis is a replacement for what was provided for the"
|
||||||
|
"\n\t\tITLB on z13 and prior machines.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 135,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ITLB2_MISSES",
|
||||||
|
.desc = "A TLB2 miss is in progress for a request made by"
|
||||||
|
"\n\t\tthe Level-1 Instruction cache. Incremented by one"
|
||||||
|
"\n\t\tfor every TLB2 miss in progress for the Level-1"
|
||||||
|
"\n\t\tInstruction cache in a cycle. This is a replacement"
|
||||||
|
"\n\t\tfor what was provided for the ITLB on z13 and prior"
|
||||||
|
"\n\t\tmachines.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 137,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TLB2_PTE_WRITES",
|
||||||
|
.desc = "A translation entry was written into the Page Table"
|
||||||
|
"\n\t\tEntry array in the Level-2 TLB.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 138,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TLB2_CRSTE_WRITES",
|
||||||
|
.desc = "Translation entries were written into the Combined"
|
||||||
|
"\n\t\tRegion and Segment Table Entry array and the Page"
|
||||||
|
"\n\t\tTable Entry array in the Level-2 TLB.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 139,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TLB2_ENGINES_BUSY",
|
||||||
|
.desc = "The number of Level-2 TLB translation engines busy"
|
||||||
|
"\n\t\tin a cycle.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 140,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TX_C_TEND",
|
||||||
|
.desc = "A TEND instruction has completed in a constrained"
|
||||||
|
"\n\t\ttransactional-execution mode.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 141,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TX_NC_TEND",
|
||||||
|
.desc = "A TEND instruction has completed in a non-"
|
||||||
|
"\n\t\tconstrained transactional-execution mode.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 143,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "L1C_TLB2_MISSES",
|
||||||
|
.desc = "Increments by one for any cycle where a Level-1"
|
||||||
|
"\n\t\tcache or Level-2 TLB miss is in progress.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 145,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_REQ",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 146,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_REQ_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache with"
|
||||||
|
"\n\t\tintervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 147,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_REQ_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache after using"
|
||||||
|
"\n\t\tchip level horizontal persistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 148,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_REQ_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache after using"
|
||||||
|
"\n\t\tdrawer level horizontal persistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 149,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_CHIP",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 150,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_CHIP_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache with intervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 151,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_CHIP_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache after using chip"
|
||||||
|
"\n\t\tlevel horizontal persistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 152,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_CHIP_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache after using drawer"
|
||||||
|
"\n\t\tlevel horizontal persistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 153,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_MODULE",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Module Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 154,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_DRAWER",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Drawer Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 155,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_OFF_DRAWER",
|
||||||
|
.desc = "A directory write to the Level-1 Data cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an Off-Drawer Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 156,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_CHIP_MEMORY",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from On-Chip memory.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 157,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_MODULE_MEMORY",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from On-Module memory.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 158,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_ON_DRAWER_MEMORY",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from On-Drawer memory.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 159,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DCW_OFF_DRAWER_MEMORY",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from Off-Drawer memory.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 160,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_MODULE_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Module Level-2"
|
||||||
|
"\n\t\tcache with intervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 161,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_MODULE_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Module Level-2"
|
||||||
|
"\n\t\tcache after using chip level horizontal"
|
||||||
|
"\n\t\tpersistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 162,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_MODULE_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Module Level-2"
|
||||||
|
"\n\t\tcache after using drawer level horizontal"
|
||||||
|
"\n\t\tpersistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 163,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_DRAWER_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Drawer Level-2"
|
||||||
|
"\n\t\tcache with intervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 164,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_DRAWER_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tinstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Drawer Level-2"
|
||||||
|
"\n\t\tcache after using chip level horizontal"
|
||||||
|
"\n\t\tpersistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 165,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_ON_DRAWER_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tinstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an On-Drawer Level-2"
|
||||||
|
"\n\t\tcache after using drawer level horizontal"
|
||||||
|
"\n\t\tpersistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 166,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_OFF_DRAWER_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tinstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
|
||||||
|
"\n\t\tcache with intervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 167,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_OFF_DRAWER_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tinstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
|
||||||
|
"\n\t\tcache after using chip level horizontal"
|
||||||
|
"\n\t\tpersistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 168,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "IDCW_OFF_DRAWER_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Data or Level-1"
|
||||||
|
"\n\t\tInstruction cache directory where the returned"
|
||||||
|
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
|
||||||
|
"\n\t\tcache after using drawer level horizontal"
|
||||||
|
"\n\t\tpersistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 169,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_REQ",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tthe requestors Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 170,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_REQ_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache with"
|
||||||
|
"\n\t\tintervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 171,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_REQ_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache after using"
|
||||||
|
"\n\t\tchip level horizontal persistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 172,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_REQ_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom the requestors Level-2 cache after using"
|
||||||
|
"\n\t\tdrawer level horizontal persistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 173,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_CHIP",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 174,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_CHIP_IV",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache with intervention.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 175,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_CHIP_CHIP_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip Level-2 cache after using chip"
|
||||||
|
"\n\t\tlevel horizontal persistence, Chip-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 176,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_CHIP_DRAWER_HIT",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Chip level 2 cache after using drawer"
|
||||||
|
"\n\t\tlevel horizontal persistence, Drawer-HP hit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 177,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_MODULE",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Module Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 178,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_ON_DRAWER",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an On-Drawer Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 179,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "ICW_OFF_DRAWER",
|
||||||
|
.desc = "A directory write to the Level-1 Instruction cache"
|
||||||
|
"\n\t\tdirectory where the returned cache line was sourced"
|
||||||
|
"\n\t\tfrom an Off-Drawer Level-2 cache.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 202,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "CYCLES_SAMETHRD",
|
||||||
|
.desc = "The number of cycles the CPU is not in wait state"
|
||||||
|
"\n\t\tand the CPU is running by itself on the Core.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 203,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "CYCLES_DIFFTHRD",
|
||||||
|
.desc = "The number of cycles the CPU is not in wait state"
|
||||||
|
"\n\t\tand the CPU is running with another thread on the"
|
||||||
|
"\n\t\tCore.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 204,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "INST_SAMETHRD",
|
||||||
|
.desc = "The number of instructions executed on the CPU and"
|
||||||
|
"\n\t\tthe CPU is running by itself on the Core.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 205,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "INST_DIFFTHRD",
|
||||||
|
.desc = "The number of instructions executed on the CPU and"
|
||||||
|
"\n\t\tthe CPU is running with another thread on the Core.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 206,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "WRONG_BRANCH_PREDICTION",
|
||||||
|
.desc = "A count of the number of branches that were"
|
||||||
|
"\n\t\tpredicted incorrectly by the branch prediction"
|
||||||
|
"\n\t\tlogic in the Core. This includes incorrectly"
|
||||||
|
"\n\t\tpredicted branches that are executed in Firmware."
|
||||||
|
"\n\t\tExamples of instructions implemented in Firmware"
|
||||||
|
"\n\t\tare complicated instructions like MVCL (Move"
|
||||||
|
"\n\t\tCharacter Long) and PC (Program Call).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 225,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "VX_BCD_EXECUTION_SLOTS",
|
||||||
|
.desc = "Count of floating point execution slots used for"
|
||||||
|
"\n\t\tfinished vector arithmetic Binary Coded Decimal"
|
||||||
|
"\n\t\tinstructions. Instructions: VAP, VSP, VMP, VMSP,"
|
||||||
|
"\n\t\tVDP, VSDP, VRP, VLIP, VSRP, VPSOP, VCP, VTP, VPKZ,"
|
||||||
|
"\n\t\tVUPKZ, VCVB, VCVBG, VCVD, VCVDG, VSCHP, VSCSHP,"
|
||||||
|
"\n\t\tVCSPH, VCLZDP, VPKZR, VSRPR, VUPKZH, VUPKZL, VTZ,"
|
||||||
|
"\n\t\tVUPH, VUPL, VCVBX, VCVDX.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 226,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DECIMAL_INSTRUCTIONS",
|
||||||
|
.desc = "Decimal instruction dispatched. Instructions: CVB,"
|
||||||
|
"\n\t\tCVD, AP, CP, DP, ED, EDMK, MP, SRP, SP, ZAP, TP.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 232,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "LAST_HOST_TRANSLATIONS",
|
||||||
|
.desc = "Last Host Translation done.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 244,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TX_NC_TABORT",
|
||||||
|
.desc = "A transaction abort has occurred in a non-"
|
||||||
|
"\n\t\tconstrained transactional-execution mode.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 245,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TX_C_TABORT_NO_SPECIAL",
|
||||||
|
.desc = "A transaction abort has occurred in a constrained"
|
||||||
|
"\n\t\ttransactional-execution mode and the CPU is not"
|
||||||
|
"\n\t\tusing any special logic to allow the transaction to"
|
||||||
|
"\n\t\tcomplete.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 246,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "TX_C_TABORT_SPECIAL",
|
||||||
|
.desc = "A transaction abort has occurred in a constrained"
|
||||||
|
"\n\t\ttransactional-execution mode and the CPU is using"
|
||||||
|
"\n\t\tspecial logic to allow the transaction to complete.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 248,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DFLT_ACCESS",
|
||||||
|
.desc = "Cycles CPU spent obtaining access to Deflate unit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 253,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DFLT_CYCLES",
|
||||||
|
.desc = "Cycles CPU is using Deflate unit.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 256,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "SORTL",
|
||||||
|
.desc = "Increments by one for every SORT LISTS (SORTL)"
|
||||||
|
"\n\t\tinstruction executed.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 265,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DFLT_CC",
|
||||||
|
.desc = "Increments by one for every DEFLATE CONVERSION CALL"
|
||||||
|
"\n\t\t(DFLTCC) instruction executed.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 266,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "DFLT_CCFINISH",
|
||||||
|
.desc = "Increments by one for every DEFLATE CONVERSION CALL"
|
||||||
|
"\n\t\t(DFLTCC) instruction executed that ended in"
|
||||||
|
"\n\t\tCondition Codes 0, 1 or 2.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 267,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_INVOCATIONS",
|
||||||
|
.desc = "Increments by one for every NEURAL NETWORK"
|
||||||
|
"\n\t\tPROCESSING ASSIST (NNPA) instruction executed.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 268,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_COMPLETIONS",
|
||||||
|
.desc = "Increments by one for every NEURAL NETWORK"
|
||||||
|
"\n\t\tPROCESSING ASSIST (NNPA) instruction executed that"
|
||||||
|
"\n\t\tended in Condition Code 0.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 269,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_WAIT_LOCK",
|
||||||
|
.desc = "Cycles CPU spent obtaining access to IBM Z"
|
||||||
|
"\n\t\tIntegrated Accelerator for AI.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 270,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_HOLD_LOCK",
|
||||||
|
.desc = "Cycles CPU is using IBM Z Integrated Accelerator"
|
||||||
|
"\n\t\tfor AI.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 272,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_INST_ONCHIP",
|
||||||
|
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
|
||||||
|
"\n\t\tinstruction has used the Local On-Chip IBM Z"
|
||||||
|
"\n\t\tIntegrated Accelerator for AI during its execution",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 273,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_INST_OFFCHIP",
|
||||||
|
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
|
||||||
|
"\n\t\tinstruction has used an Off-Chip IBM Z Integrated"
|
||||||
|
"\n\t\tAccelerator for AI during its execution.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 274,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_INST_DIFF",
|
||||||
|
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
|
||||||
|
"\n\t\tinstruction has used a different IBM Z Integrated"
|
||||||
|
"\n\t\tAccelerator for AI since it was last executed.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 276,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_4K_PREFETCH",
|
||||||
|
.desc = "Number of 4K prefetches done for a remote IBM Z"
|
||||||
|
"\n\t\tIntegated Accelerator for AI.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 277,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_COMPL_LOCK",
|
||||||
|
.desc = "A PERFORM LOCKED OPERATION (PLO) has completed.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 278,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_RETRY_LOCK",
|
||||||
|
.desc = "A PERFORM LOCKED OPERATION (PLO) has been retried and"
|
||||||
|
"\n\t\tthe CPU did not use any special logic to allow the"
|
||||||
|
"\n\t\tPLO to complete.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 279,
|
||||||
|
.ctrset = CPUMF_CTRSET_EXTENDED,
|
||||||
|
.name = "NNPA_RETRY_LOCK_WITH_PLO",
|
||||||
|
.desc = "A PERFORM LOCKED OPERATION (PLO) has been retried and"
|
||||||
|
"\n\t\tthe CPU is using special logic to allow PLO to"
|
||||||
|
"\n\t\tcomplete.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 448,
|
||||||
|
.ctrset = CPUMF_CTRSET_MT_DIAG,
|
||||||
|
.name = "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
|
||||||
|
.desc = "Cycle count with one thread active",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ctrnum = 449,
|
||||||
|
.ctrset = CPUMF_CTRSET_MT_DIAG,
|
||||||
|
.name = "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
|
||||||
|
.desc = "Cycle count with two threads active",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/* Return the type number of the CPU Measurement facility from the sysfs file.
|
/* Return the type number of the CPU Measurement facility from the sysfs file.
|
||||||
* If the type number is equal to PERF_TYPE_RAW, then the prefix is 'r' to
|
* If the type number is equal to PERF_TYPE_RAW, then the prefix is 'r' to
|
||||||
* specify the raw counter number by the perf tool.
|
* specify the raw counter number by the perf tool.
|
||||||
@@ -3476,6 +4078,12 @@ static struct counters *get_counter(int ctrset, size_t *len)
|
|||||||
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
|
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
|
||||||
cp = cpumcf_z16_counters;
|
cp = cpumcf_z16_counters;
|
||||||
*len = ARRAY_SIZE(cpumcf_z16_counters);
|
*len = ARRAY_SIZE(cpumcf_z16_counters);
|
||||||
|
break;
|
||||||
|
case UTIL_ARCH_MACHINE_TYPE_Z17:
|
||||||
|
case UTIL_ARCH_MACHINE_TYPE_Z17_2:
|
||||||
|
cp = cpumcf_z17_counters;
|
||||||
|
*len = ARRAY_SIZE(cpumcf_z17_counters);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3526,7 +4134,7 @@ int main(int argc, char **argv)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(lscpumf_opt_vec, NULL);
|
||||||
|
|
||||||
ret = parse_args(argc, argv);
|
ret = parse_args(argc, argv);
|
||||||
if (read_info() == EXIT_FAILURE)
|
if (read_info() == EXIT_FAILURE)
|
||||||
|
|||||||
44
cpumf/lscpumf_cli.h
Normal file
44
cpumf/lscpumf_cli.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for lscpumf
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LSCPUMF_CLI_H
|
||||||
|
#define LSCPUMF_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
static struct util_opt lscpumf_opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "list-counters", no_argument, NULL, 'c' },
|
||||||
|
.desc = "Lists counters for which the LPAR is authorized.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "list-all-counters", no_argument, NULL, 'C' },
|
||||||
|
.desc = "Lists counters regardless of LPAR authorization.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "name", no_argument, NULL, 'n' },
|
||||||
|
.desc = "Displays counter names.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "info", no_argument, NULL, 'i' },
|
||||||
|
.desc = "Displays detailed information.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "list-sampling-events", no_argument, NULL, 's' },
|
||||||
|
.desc = "Lists sampling events for which the LPAR is authorized.",
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
UTIL_OPT_VERSION,
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
359
cpumf/lshwc.c
359
cpumf/lshwc.c
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright IBM Corp. 2021
|
/* Copyright IBM Corp. 2021, 2024
|
||||||
*
|
*
|
||||||
* 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,11 +37,13 @@
|
|||||||
#include "lib/util_base.h"
|
#include "lib/util_base.h"
|
||||||
#include "lib/util_path.h"
|
#include "lib/util_path.h"
|
||||||
#include "lib/util_scandir.h"
|
#include "lib/util_scandir.h"
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_str.h"
|
||||||
#include "lib/util_file.h"
|
#include "lib/util_file.h"
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
#include "lib/libcpumf.h"
|
#include "lib/libcpumf.h"
|
||||||
|
|
||||||
#include "lshwc.h"
|
#include "lshwc.h"
|
||||||
|
#include "lshwc_cli.h"
|
||||||
|
|
||||||
#define CPUS_ONLINE "/sys/devices/system/cpu/online"
|
#define CPUS_ONLINE "/sys/devices/system/cpu/online"
|
||||||
#define CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
|
#define CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
|
||||||
@@ -51,18 +53,92 @@
|
|||||||
|
|
||||||
static unsigned int read_interval = IOCTLSLEEP;
|
static unsigned int read_interval = IOCTLSLEEP;
|
||||||
static int cfvn, csvn, authorization;
|
static int cfvn, csvn, authorization;
|
||||||
static unsigned long loop_count = 1;
|
static unsigned long loop_count = 1, timeout;
|
||||||
static unsigned char *ioctlbuffer;
|
static unsigned char *ioctlbuffer;
|
||||||
static bool allcpu;
|
static bool allcpu;
|
||||||
|
static char *ctrformat = "%ld";
|
||||||
|
static bool shortname;
|
||||||
|
static bool hideundef;
|
||||||
|
static bool delta, firstread;
|
||||||
|
static int output_format = FMT_CSV;
|
||||||
|
static bool quote_all;
|
||||||
|
static char *ctrlist; /* Comma separated list of counter to extract */
|
||||||
|
|
||||||
static unsigned int max_possible_cpus; /* No of possible CPUs */
|
static unsigned int max_possible_cpus; /* No of possible CPUs */
|
||||||
static struct ctrname { /* List of defined counters */
|
static struct ctrname { /* List of defined counters */
|
||||||
char *name; /* Counter name */
|
char *name; /* Counter name */
|
||||||
|
char *label; /* Output name */
|
||||||
bool hitcnt; /* Counter number read from ioctl() */
|
bool hitcnt; /* Counter number read from ioctl() */
|
||||||
unsigned long total; /* Total counter value */
|
unsigned long total; /* Total counter value */
|
||||||
unsigned long *ccv; /* Per CPU counter value */
|
unsigned long *ccv; /* Per CPU counter value */
|
||||||
|
unsigned long *ccvprv; /* Per CPU counter value (previous read) */
|
||||||
} ctrname[MAXCTRS];
|
} ctrname[MAXCTRS];
|
||||||
|
|
||||||
|
struct time_formats {
|
||||||
|
char epoch[32];
|
||||||
|
char date_time[32];
|
||||||
|
char date[16];
|
||||||
|
char time[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mk_labels(void)
|
||||||
|
{
|
||||||
|
char label[64];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
||||||
|
if (shortname) {
|
||||||
|
if (ctrname[i].name)
|
||||||
|
snprintf(label, sizeof(label), "%s", ctrname[i].name);
|
||||||
|
else
|
||||||
|
snprintf(label, sizeof(label), "U%ld", i);
|
||||||
|
} else {
|
||||||
|
if (output_format == FMT_CSV)
|
||||||
|
snprintf(label, sizeof(label), "%s(%ld)",
|
||||||
|
ctrname[i].name ?: "Counter", i);
|
||||||
|
else if (ctrname[i].name)
|
||||||
|
snprintf(label, sizeof(label), "%s", ctrname[i].name);
|
||||||
|
else
|
||||||
|
label[0] = 0;
|
||||||
|
}
|
||||||
|
if (output_format != FMT_CSV)
|
||||||
|
util_str_tolower(label);
|
||||||
|
ctrname[i].label = util_strdup(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *mk_name(int ctr, char *name)
|
||||||
|
{
|
||||||
|
char ctrset[8];
|
||||||
|
|
||||||
|
if (!shortname)
|
||||||
|
return util_strdup(name);
|
||||||
|
|
||||||
|
switch (libcpumf_ctrset(ctr, cfvn, csvn)) {
|
||||||
|
case CPUMF_CTRSET_BASIC:
|
||||||
|
ctrset[0] = 'B';
|
||||||
|
break;
|
||||||
|
case CPUMF_CTRSET_PROBLEM_STATE:
|
||||||
|
ctrset[0] = 'P';
|
||||||
|
break;
|
||||||
|
case CPUMF_CTRSET_CRYPTO:
|
||||||
|
ctrset[0] = 'C';
|
||||||
|
break;
|
||||||
|
case CPUMF_CTRSET_EXTENDED:
|
||||||
|
ctrset[0] = 'E';
|
||||||
|
break;
|
||||||
|
case CPUMF_CTRSET_MT_DIAG:
|
||||||
|
ctrset[0] = 'M';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ctrset[0] = 'U';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sprintf(ctrset, "%c%d", ctrset[0], ctr);
|
||||||
|
|
||||||
|
return util_strdup(ctrset);
|
||||||
|
}
|
||||||
|
|
||||||
static bool read_counternames(void)
|
static bool read_counternames(void)
|
||||||
{
|
{
|
||||||
struct dirent **namelist = NULL;
|
struct dirent **namelist = NULL;
|
||||||
@@ -77,9 +153,11 @@ static bool read_counternames(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i < count && ctr >= 0; i++) {
|
for (i = 0; i < count && ctr >= 0; i++) {
|
||||||
|
if (!ctr_in_list(namelist[i]->d_name, ctrlist))
|
||||||
|
continue;
|
||||||
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
||||||
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1)
|
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1)
|
||||||
ctrname[ctr].name = util_strdup(namelist[i]->d_name);
|
ctrname[ctr].name = mk_name(ctr, namelist[i]->d_name);
|
||||||
else
|
else
|
||||||
warnx("Cannot parse %s", ctrpath);
|
warnx("Cannot parse %s", ctrpath);
|
||||||
free(ctrpath);
|
free(ctrpath);
|
||||||
@@ -93,7 +171,9 @@ static void free_counternames(void)
|
|||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
||||||
free(ctrname[i].name);
|
free(ctrname[i].name);
|
||||||
|
free(ctrname[i].label);
|
||||||
free(ctrname[i].ccv);
|
free(ctrname[i].ccv);
|
||||||
|
free(ctrname[i].ccvprv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,77 +378,111 @@ static bool check_setpossible(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_header(void)
|
static void safe_strtime(char *dest, size_t size, const char *fmt, const struct tm *tm)
|
||||||
{
|
{
|
||||||
static bool header;
|
if (!strftime(dest, size, fmt, tm))
|
||||||
bool comma = false;
|
dest[0] = 0;
|
||||||
|
|
||||||
if (header)
|
|
||||||
return; /* Printed already */
|
|
||||||
printf("Date,Time,CPU,"); /* Print counter name and number */
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
|
||||||
if (!ctrname[i].hitcnt)
|
|
||||||
continue;
|
|
||||||
if (comma)
|
|
||||||
putchar(',');
|
|
||||||
printf("%s(%ld)", ctrname[i].name ?: "Counter", i);
|
|
||||||
comma = true;
|
|
||||||
}
|
|
||||||
putchar('\n');
|
|
||||||
header = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void line(char *header)
|
static void generate_timestamp(struct time_formats *date)
|
||||||
{
|
{
|
||||||
bool comma;
|
time_t now = time(NULL);
|
||||||
|
struct tm *now_tm = localtime(&now);
|
||||||
|
|
||||||
show_header();
|
safe_strtime(date->date_time, sizeof(date->date_time), "%F %T%z", now_tm);
|
||||||
if (allcpu) {
|
safe_strtime(date->date, sizeof(date->date), "%F", now_tm);
|
||||||
for (unsigned int h = 0; h < max_possible_cpus; ++h) {
|
safe_strtime(date->time, sizeof(date->time), "%T", now_tm);
|
||||||
char txt[16];
|
safe_strtime(date->epoch, sizeof(date->epoch), "%s", now_tm);
|
||||||
|
}
|
||||||
|
|
||||||
if (!check[h].cpu_hit)
|
static void output_times(struct time_formats date)
|
||||||
continue;
|
{
|
||||||
comma = false;
|
if (output_format == FMT_CSV) {
|
||||||
snprintf(txt, sizeof(txt), "CPU%d,", h);
|
util_fmt_pair(FMT_PERSIST, "Date", "%s", date.date);
|
||||||
printf("%s%s", header, txt);
|
util_fmt_pair(FMT_PERSIST, "Time", "%s", date.time);
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
} else {
|
||||||
if (!ctrname[i].hitcnt)
|
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "date_time", "%s", date.date_time);
|
||||||
continue;
|
util_fmt_pair(FMT_PERSIST, "time_epoch", "%s", date.epoch);
|
||||||
if (comma)
|
|
||||||
putchar(',');
|
|
||||||
printf("%ld", ctrname[i].ccv[h]);
|
|
||||||
comma = true;
|
|
||||||
}
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Print total count of all CPUs */
|
static void prepare_counter(size_t id, unsigned long value)
|
||||||
printf("%sTotal,", header);
|
{
|
||||||
comma = false;
|
if (output_format == FMT_CSV) {
|
||||||
|
util_fmt_pair(FMT_PERSIST, ctrname[id].label, ctrformat, value);
|
||||||
|
} else {
|
||||||
|
util_fmt_obj_start(FMT_ROW, NULL);
|
||||||
|
if (strlen(ctrname[id].label))
|
||||||
|
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "name", ctrname[id].label);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "id", ctrformat, id);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "value", ctrformat, value);
|
||||||
|
util_fmt_obj_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_per_cpu(struct time_formats date)
|
||||||
|
{
|
||||||
|
for (unsigned int h = 0; h < max_possible_cpus; ++h) {
|
||||||
|
if (!check[h].cpu_hit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char txt[16];
|
||||||
|
|
||||||
|
snprintf(txt, sizeof(txt), "CPU%d", h);
|
||||||
|
util_fmt_obj_start(FMT_ROW, "cpu_%d", h);
|
||||||
|
output_times(date);
|
||||||
|
if (output_format == FMT_CSV) {
|
||||||
|
util_fmt_pair(FMT_PERSIST, "CPU", "CPU%d", h);
|
||||||
|
} else {
|
||||||
|
util_fmt_pair(FMT_PERSIST, "cpu", "%d", h);
|
||||||
|
util_fmt_obj_start(FMT_LIST, "counters");
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
||||||
|
if (!ctrname[i].hitcnt)
|
||||||
|
continue;
|
||||||
|
if (hideundef && !ctrname[i].name)
|
||||||
|
continue;
|
||||||
|
prepare_counter(i, ctrname[i].ccv[h]);
|
||||||
|
}
|
||||||
|
if (output_format != FMT_CSV)
|
||||||
|
util_fmt_obj_end();
|
||||||
|
util_fmt_obj_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void output_total(struct time_formats date)
|
||||||
|
{
|
||||||
|
util_fmt_obj_start(FMT_ROW, "total");
|
||||||
|
output_times(date);
|
||||||
|
if (output_format == FMT_CSV) {
|
||||||
|
util_fmt_pair(FMT_PERSIST, "CPU", "%s", delta && !firstread ? "Delta" : "Total");
|
||||||
|
} else {
|
||||||
|
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "cpu", "%s",
|
||||||
|
delta && !firstread ? "delta" : "total");
|
||||||
|
util_fmt_obj_start(FMT_LIST, "counters");
|
||||||
|
}
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
||||||
if (!ctrname[i].hitcnt)
|
if (!ctrname[i].hitcnt)
|
||||||
continue;
|
continue;
|
||||||
if (comma)
|
if (hideundef && !ctrname[i].name)
|
||||||
putchar(',');
|
continue;
|
||||||
printf("%ld", ctrname[i].total);
|
prepare_counter(i, ctrname[i].total);
|
||||||
comma = true;
|
|
||||||
ctrname[i].total = 0;
|
ctrname[i].total = 0;
|
||||||
ctrname[i].hitcnt = false;
|
ctrname[i].hitcnt = false;
|
||||||
}
|
}
|
||||||
putchar('\n');
|
if (output_format != FMT_CSV)
|
||||||
|
util_fmt_obj_end();
|
||||||
|
util_fmt_obj_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show(void)
|
static void show_format(void)
|
||||||
{
|
{
|
||||||
time_t now = time(NULL);
|
struct time_formats now;
|
||||||
struct tm *now_tm;
|
|
||||||
char now_text[32];
|
|
||||||
|
|
||||||
now_tm = localtime(&now);
|
generate_timestamp(&now);
|
||||||
strftime(now_text, sizeof(now_text), "%F,%T,", now_tm);
|
if (allcpu)
|
||||||
line(now_text);
|
output_per_cpu(now);
|
||||||
|
output_total(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return Counter set size numbers (in counters) */
|
/* Return Counter set size numbers (in counters) */
|
||||||
@@ -442,11 +556,18 @@ static bool add_countervalue(size_t idx, unsigned int cpu, unsigned long value)
|
|||||||
warnx("Invalid CPU number %d", cpu);
|
warnx("Invalid CPU number %d", cpu);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ctrname[idx].ccv) /* Unknown counter */
|
if (delta) {
|
||||||
ctrname[idx].ccv = calloc(max_possible_cpus,
|
if (firstread) {
|
||||||
sizeof(unsigned long));
|
ctrname[idx].ccvprv[cpu] = value;
|
||||||
if (ctrname[idx].ccv)
|
ctrname[idx].ccv[cpu] = value;
|
||||||
|
} else {
|
||||||
|
ctrname[idx].ccv[cpu] = value - ctrname[idx].ccvprv[cpu];
|
||||||
|
ctrname[idx].ccvprv[cpu] = value;
|
||||||
|
value = ctrname[idx].ccv[cpu];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
ctrname[idx].ccv[cpu] = value;
|
ctrname[idx].ccv[cpu] = value;
|
||||||
|
}
|
||||||
ctrname[idx].total += value;
|
ctrname[idx].total += value;
|
||||||
ctrname[idx].hitcnt = true;
|
ctrname[idx].hitcnt = true;
|
||||||
return true;
|
return true;
|
||||||
@@ -493,7 +614,8 @@ static int test_read(struct s390_hwctr_read *read)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
show();
|
show_format();
|
||||||
|
firstread = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,6 +678,7 @@ static void do_sleep(void)
|
|||||||
static int do_it(char *s)
|
static int do_it(char *s)
|
||||||
{
|
{
|
||||||
struct s390_hwctr_start start;
|
struct s390_hwctr_start start;
|
||||||
|
unsigned int flags = FMT_WARN;
|
||||||
int ioctlfd;
|
int ioctlfd;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -575,6 +698,24 @@ static int do_it(char *s)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output_format == FMT_CSV)
|
||||||
|
flags |= FMT_NOMETA;
|
||||||
|
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ)
|
||||||
|
flags |= FMT_HANDLEINT;
|
||||||
|
if (quote_all)
|
||||||
|
flags |= FMT_QUOTEALL;
|
||||||
|
|
||||||
|
mk_labels();
|
||||||
|
util_fmt_init(stdout, output_format, flags, 1);
|
||||||
|
util_fmt_obj_start(FMT_DEFAULT, "lshwc");
|
||||||
|
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ) {
|
||||||
|
util_fmt_obj_start(FMT_ROW, "cpumcf info");
|
||||||
|
util_fmt_pair(FMT_PERSIST, "counter first", "%d", cfvn);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "counter second", "%d", csvn);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "authorization", "%d", authorization);
|
||||||
|
util_fmt_obj_end();
|
||||||
|
}
|
||||||
|
util_fmt_obj_start(FMT_LIST, "measurements");
|
||||||
for (unsigned long i = 0; !rc && i < loop_count; ++i) {
|
for (unsigned long i = 0; !rc && i < loop_count; ++i) {
|
||||||
rc = do_read(ioctlfd);
|
rc = do_read(ioctlfd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -584,32 +725,14 @@ static int do_it(char *s)
|
|||||||
if (read_interval && i + 1 < loop_count)
|
if (read_interval && i + 1 < loop_count)
|
||||||
do_sleep();
|
do_sleep();
|
||||||
}
|
}
|
||||||
|
util_fmt_obj_end();
|
||||||
|
util_fmt_obj_end();
|
||||||
|
util_fmt_exit();
|
||||||
rc = do_stop(ioctlfd);
|
rc = do_stop(ioctlfd);
|
||||||
close(ioctlfd);
|
close(ioctlfd);
|
||||||
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
|
||||||
UTIL_OPT_SECTION("OPTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "all", no_argument, NULL, 'a' },
|
|
||||||
.desc = "Displays all CPUs in output"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "loop", required_argument, NULL, 'l' },
|
|
||||||
.argument = "NUMBER",
|
|
||||||
.desc = "Specifies loop count for next read"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "interval", required_argument, NULL, 'i' },
|
|
||||||
.argument = "NUMBER",
|
|
||||||
.desc = "Specifies interval between read operations (seconds)"
|
|
||||||
},
|
|
||||||
UTIL_OPT_HELP,
|
|
||||||
UTIL_OPT_VERSION,
|
|
||||||
UTIL_OPT_END
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct util_prg prg = {
|
static const struct util_prg prg = {
|
||||||
.desc = "Read CPU Measurement facility counter sets",
|
.desc = "Read CPU Measurement facility counter sets",
|
||||||
.copyright_vec = {
|
.copyright_vec = {
|
||||||
@@ -634,11 +757,13 @@ static void have_support(void)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
enum util_fmt_t fmt;
|
||||||
|
unsigned long no;
|
||||||
char *slash;
|
char *slash;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(lshwc_opt_vec, NULL);
|
||||||
|
|
||||||
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
@@ -665,12 +790,71 @@ int main(int argc, char **argv)
|
|||||||
if (errno || *slash)
|
if (errno || *slash)
|
||||||
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||||
break;
|
break;
|
||||||
|
case 'H':
|
||||||
|
hideundef = true;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
shortname = true;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
ctrformat = "%lx";
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
ctrformat = "%#lx";
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
allcpu = true;
|
allcpu = true;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
delta = true;
|
||||||
|
firstread = true;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
errno = 0;
|
||||||
|
no = strtoul(optarg, &slash, 0);
|
||||||
|
if (errno)
|
||||||
|
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||||
|
switch (*slash) {
|
||||||
|
case 's':
|
||||||
|
case '\0':
|
||||||
|
timeout += no;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
timeout += no * 60;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
timeout += no * 60 * 60;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
timeout += no * 60 * 60 * 24;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
quote_all = true;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
if (!util_fmt_name_to_type(optarg, &fmt))
|
||||||
|
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
|
||||||
|
output_format = fmt;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
hideundef = true;
|
||||||
|
ctrlist = util_strdup(optarg);
|
||||||
|
util_str_rm_whitespace(optarg, ctrlist);
|
||||||
|
util_str_toupper(ctrlist);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timeout && timeout < read_interval)
|
||||||
|
read_interval = timeout;
|
||||||
|
/* If no timeout specified, simply add zero */
|
||||||
|
loop_count += timeout / read_interval;
|
||||||
|
|
||||||
have_support();
|
have_support();
|
||||||
if (!libcpumf_cpumcf_info(&cfvn, &csvn, &authorization))
|
if (!libcpumf_cpumcf_info(&cfvn, &csvn, &authorization))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -681,6 +865,11 @@ int main(int argc, char **argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < ARRAY_SIZE(ctrname); ++i) {
|
||||||
|
ctrname[i].ccv = util_zalloc(max_possible_cpus * sizeof(unsigned long));
|
||||||
|
ctrname[i].ccvprv = util_zalloc(max_possible_cpus * sizeof(unsigned long));
|
||||||
|
}
|
||||||
|
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
ch = do_it(NULL);
|
ch = do_it(NULL);
|
||||||
} else {
|
} else {
|
||||||
@@ -692,5 +881,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
free_counternames();
|
free_counternames();
|
||||||
free(check);
|
free(check);
|
||||||
|
free(ioctlbuffer);
|
||||||
|
free(ctrlist);
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|||||||
78
cpumf/lshwc_cli.h
Normal file
78
cpumf/lshwc_cli.h
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for lshwc
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LSHWC_CLI_H
|
||||||
|
#define LSHWC_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
static struct util_opt lshwc_opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "all", no_argument, NULL, 'a' },
|
||||||
|
.desc = "Displays all CPUs in output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "loop", required_argument, NULL, 'l' },
|
||||||
|
.argument = "NUMBER",
|
||||||
|
.desc = "Specifies loop count for next read"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "interval", required_argument, NULL, 'i' },
|
||||||
|
.argument = "NUMBER",
|
||||||
|
.desc = "Specifies interval between read operations (seconds)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "short", no_argument, NULL, 's' },
|
||||||
|
.desc = "Abbreviate counter name with counter set letter and number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "hex0x", no_argument, NULL, 'X' },
|
||||||
|
.desc = "Counter values in hexadecimal format with leading 0x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "hex", no_argument, NULL, 'x' },
|
||||||
|
.desc = "Counter values in hexadecimal format"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "hide", no_argument, NULL, 'H' },
|
||||||
|
.desc = "Do not display undefined counters of a counter set"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "delta", no_argument, NULL, 'd' },
|
||||||
|
.desc = "Display delta counter values"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "timeout", required_argument, NULL, 't' },
|
||||||
|
.argument = "NUMBER",
|
||||||
|
.desc = "run time in s (seconds) m (minutes) h (hours) and d (days)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "quote-all", no_argument, NULL, 'q' },
|
||||||
|
.desc = "Apply quoting to all output elements"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "format", required_argument, NULL, 'f' },
|
||||||
|
.argument = "FORMAT",
|
||||||
|
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "counters", required_argument, NULL, 'c' },
|
||||||
|
.argument = "LIST",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
.desc = "Specify comma separated list of counters to display"
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
UTIL_OPT_VERSION,
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
514
cpumf/lspai.c
514
cpumf/lspai.c
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
/* List available Processor Assist Instrumentation (PAI) counters. */
|
/* List available Processor Assist Instrumentation (PAI) counters. */
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -17,33 +16,26 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
|
||||||
#include "lib/util_opt.h"
|
|
||||||
#include "lib/util_prg.h"
|
|
||||||
#include "lib/util_base.h"
|
#include "lib/util_base.h"
|
||||||
#include "lib/util_path.h"
|
|
||||||
#include "lib/util_scandir.h"
|
|
||||||
#include "lib/util_libc.h"
|
|
||||||
#include "lib/util_file.h"
|
#include "lib/util_file.h"
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_libc.h"
|
||||||
#include "lib/util_list.h"
|
#include "lib/util_list.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
|
#include "lib/util_prg.h"
|
||||||
|
#include "lib/util_scandir.h"
|
||||||
|
#include "lib/util_str.h"
|
||||||
#include "lib/libcpumf.h"
|
#include "lib/libcpumf.h"
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
#include "lspai_cli.h"
|
||||||
UTIL_OPT_SECTION("OPTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "numeric", no_argument, NULL, 'n' },
|
|
||||||
.desc = "Sort PAI counters by counter number"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "type", required_argument, NULL, 't' },
|
|
||||||
.argument = "TYPE",
|
|
||||||
.desc = "Type of PAI counters to show: crypto, nnpa"
|
|
||||||
},
|
|
||||||
UTIL_OPT_HELP,
|
|
||||||
UTIL_OPT_VERSION,
|
|
||||||
UTIL_OPT_END
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct util_prg prg = {
|
static const struct util_prg prg = {
|
||||||
.desc = "List Processor Assist Information counter sets",
|
.desc = "List Processor Assist Information counter sets",
|
||||||
@@ -51,13 +43,24 @@ static const struct util_prg prg = {
|
|||||||
{
|
{
|
||||||
.owner = "IBM Corp.",
|
.owner = "IBM Corp.",
|
||||||
.pub_first = 2023,
|
.pub_first = 2023,
|
||||||
.pub_last = 2023,
|
.pub_last = 2025,
|
||||||
},
|
},
|
||||||
UTIL_PRG_COPYRIGHT_END
|
UTIL_PRG_COPYRIGHT_END
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool allcpu; /* Show counter values per CPU */
|
||||||
static bool numsort; /* If true sort counter numerically */
|
static bool numsort; /* If true sort counter numerically */
|
||||||
|
static bool shortname; /* Use abbreviated counter names */
|
||||||
|
static bool delta, firstread; /* Display delta values */
|
||||||
|
static int output_format = -1; /* Generate style if >= 0 */
|
||||||
|
static unsigned int max_cpus; /* # of CPUs to read counter values from */
|
||||||
|
static unsigned int max_fds; /* # of file descriptor to read counter values */
|
||||||
|
static unsigned long loops; /* # loops */
|
||||||
|
static unsigned long read_interval = DEFAULT_LOOP_INTERVAL;
|
||||||
|
static cpu_set_t cpu_online_mask;
|
||||||
|
static char *ctrformat = "%ld"; /* Default counter output format */
|
||||||
|
static char *ctrlist; /* Comma separated list of counter to extract */
|
||||||
|
|
||||||
#define PAI_PATH "/bus/event_source/devices/%s"
|
#define PAI_PATH "/bus/event_source/devices/%s"
|
||||||
|
|
||||||
@@ -69,9 +72,18 @@ enum pai_types { /* Bit mask for supported PAI counters */
|
|||||||
|
|
||||||
static int pai_types_show;
|
static int pai_types_show;
|
||||||
|
|
||||||
|
struct pai_cpudata { /* Event data per CPU */
|
||||||
|
int fd; /* Event file descriptor */
|
||||||
|
int cpu; /* CPU number */
|
||||||
|
unsigned long value; /* Event value */
|
||||||
|
unsigned long prev_value; /* Previous value for deltas */
|
||||||
|
};
|
||||||
|
|
||||||
struct pai_ctrname { /* List of defined counters */
|
struct pai_ctrname { /* List of defined counters */
|
||||||
char *name; /* Counter name */
|
char *name; /* Counter name */
|
||||||
unsigned long nr; /* Counter number */
|
unsigned long nr; /* Counter number */
|
||||||
|
unsigned long total; /* Total count on all CPus */
|
||||||
|
struct pai_cpudata *data; /* Counter data per CPU */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pai_node { /* Head for PAI counter sets */
|
struct pai_node { /* Head for PAI counter sets */
|
||||||
@@ -104,6 +116,20 @@ static unsigned long pai_type_base(enum pai_types t)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return character for this counter set. */
|
||||||
|
static char pai_type_char(enum pai_types t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case pai_type_crypto:
|
||||||
|
return 'C';
|
||||||
|
case pai_type_nnpa:
|
||||||
|
return 'N';
|
||||||
|
case pai_type_max:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 'U';
|
||||||
|
}
|
||||||
|
|
||||||
/* Test PAI counter name from command line option. */
|
/* Test PAI counter name from command line option. */
|
||||||
static const char *pai_type_name(enum pai_types t)
|
static const char *pai_type_name(enum pai_types t)
|
||||||
{
|
{
|
||||||
@@ -145,16 +171,6 @@ static int pai_ctrcmp(const void *p1, const void *p2)
|
|||||||
return l->nr > r->nr ? 1 : -1;
|
return l->nr > r->nr ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert string to upper case. */
|
|
||||||
static char *str2uc(const char *s)
|
|
||||||
{
|
|
||||||
char *uc = util_strdup(s), *old_uc = uc;
|
|
||||||
|
|
||||||
for (; *uc; ++uc)
|
|
||||||
*uc = toupper(*uc);
|
|
||||||
return old_uc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read counter names and assigned event number from sysfs file tree.
|
/* Read counter names and assigned event number from sysfs file tree.
|
||||||
* Exit when sysfs directory can not be scanned.
|
* Exit when sysfs directory can not be scanned.
|
||||||
*/
|
*/
|
||||||
@@ -162,7 +178,7 @@ static void read_counternames(struct pai_node *node)
|
|||||||
{
|
{
|
||||||
int i, more = 0, ctr = 0, count = 0;
|
int i, more = 0, ctr = 0, count = 0;
|
||||||
struct dirent **namelist = NULL;
|
struct dirent **namelist = NULL;
|
||||||
char *path, *ctrpath;
|
char *path, *ctrpath, sname[128];
|
||||||
|
|
||||||
/* Read counter names and assigned event number. */
|
/* Read counter names and assigned event number. */
|
||||||
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
|
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
|
||||||
@@ -175,9 +191,18 @@ static void read_counternames(struct pai_node *node)
|
|||||||
for (i = 0; i < count && ctr >= 0; i++) {
|
for (i = 0; i < count && ctr >= 0; i++) {
|
||||||
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
||||||
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1) {
|
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1) {
|
||||||
|
snprintf(sname, sizeof(sname), "%c%ld",
|
||||||
|
pai_type_char(node->type), ctr - node->base);
|
||||||
|
if (!ctr_in_list(sname, ctrlist) &&
|
||||||
|
!ctr_in_list(namelist[i]->d_name, ctrlist)) {
|
||||||
|
/* Counter not listed in --counters option */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
node->ctrlist[node->ctridx].data = NULL;
|
||||||
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
|
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
|
||||||
node->ctrlist[node->ctridx++].nr = ctr;
|
node->ctrlist[node->ctridx++].nr = ctr;
|
||||||
more++;
|
more++;
|
||||||
|
max_fds++;
|
||||||
} else {
|
} else {
|
||||||
warnx("Cannot parse %s", ctrpath);
|
warnx("Cannot parse %s", ctrpath);
|
||||||
}
|
}
|
||||||
@@ -190,12 +215,47 @@ static void read_counternames(struct pai_node *node)
|
|||||||
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
|
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_painode(void)
|
static void format_painode(enum util_fmt_t fmt)
|
||||||
|
{
|
||||||
|
struct pai_node *node;
|
||||||
|
|
||||||
|
util_fmt_init(stdout, fmt, FMT_HANDLEINT, 1);
|
||||||
|
util_fmt_obj_start(FMT_DEFAULT, NULL);
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
util_fmt_obj_start(FMT_DEFAULT, "pmu");
|
||||||
|
util_fmt_pair(FMT_PERSIST, "base", "%d", node->base);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "type", "%d", node->pmu);
|
||||||
|
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "pmu-name", "%s", node->sysfs_name);
|
||||||
|
util_fmt_obj_start(FMT_LIST, "counters");
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
util_fmt_obj_start(FMT_ROW, "counter");
|
||||||
|
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
|
||||||
|
if (shortname)
|
||||||
|
util_fmt_pair(FMT_QUOTE, "name", "%c%d",
|
||||||
|
pai_type_char(node->type),
|
||||||
|
node->ctrlist[i].nr - node->base);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
|
||||||
|
util_fmt_obj_end();
|
||||||
|
}
|
||||||
|
util_fmt_obj_end(); /* Counters */
|
||||||
|
util_fmt_obj_end(); /* PMU */
|
||||||
|
}
|
||||||
|
util_fmt_obj_end();
|
||||||
|
util_fmt_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_painode(void)
|
||||||
{
|
{
|
||||||
struct pai_node *node;
|
struct pai_node *node;
|
||||||
int indent = 0;
|
int indent = 0;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
|
if (output_format != -1) {
|
||||||
|
format_painode(output_format);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
util_list_iterate(&pai_list, node) {
|
util_list_iterate(&pai_list, node) {
|
||||||
for (int i = 0; i < node->ctridx; ++i)
|
for (int i = 0; i < node->ctridx; ++i)
|
||||||
indent = MAX((size_t)indent, strlen(node->ctrlist[i].name));
|
indent = MAX((size_t)indent, strlen(node->ctrlist[i].name));
|
||||||
@@ -223,8 +283,10 @@ static void free_painode(void)
|
|||||||
|
|
||||||
util_list_iterate_safe(&pai_list, node, next) {
|
util_list_iterate_safe(&pai_list, node, next) {
|
||||||
free(node->name_uc);
|
free(node->name_uc);
|
||||||
for (int i = 0; i < node->ctridx; ++i)
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
free(node->ctrlist[i].name);
|
free(node->ctrlist[i].name);
|
||||||
|
free(node->ctrlist[i].data);
|
||||||
|
}
|
||||||
free(node->ctrlist);
|
free(node->ctrlist);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
@@ -238,12 +300,13 @@ static void make_painode(enum pai_types t)
|
|||||||
node->type = t;
|
node->type = t;
|
||||||
node->sysfs_name = pai_type_sysfs(t);
|
node->sysfs_name = pai_type_sysfs(t);
|
||||||
node->name = pai_type_name(t);
|
node->name = pai_type_name(t);
|
||||||
node->name_uc = str2uc(node->name);
|
node->name_uc = util_strdup(node->name);
|
||||||
|
util_str_toupper(node->name_uc);
|
||||||
node->filter_name = pai_type_filter(t);
|
node->filter_name = pai_type_filter(t);
|
||||||
node->base = pai_type_base(t);
|
node->base = pai_type_base(t);
|
||||||
|
|
||||||
/* Read PMU type number. */
|
/* Read PMU type number. */
|
||||||
path = util_path_sysfs(PAI_PATH, node->sysfs_name);
|
util_asprintf(&path, PAI_PATH, node->sysfs_name);
|
||||||
node->pmu = libcpumf_pmutype(path);
|
node->pmu = libcpumf_pmutype(path);
|
||||||
if (node->pmu < 0)
|
if (node->pmu < 0)
|
||||||
errx(EXIT_FAILURE, "Cannot open %s", path);
|
errx(EXIT_FAILURE, "Cannot open %s", path);
|
||||||
@@ -267,6 +330,267 @@ static void sort_painode(void)
|
|||||||
util_list_sort(&pai_list, painode_cmp, NULL);
|
util_list_sort(&pai_list, painode_cmp, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read counter value. */
|
||||||
|
static unsigned long event_read(int fd)
|
||||||
|
{
|
||||||
|
unsigned long count;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = read(fd, &count, sizeof(count));
|
||||||
|
if (rc != sizeof(count))
|
||||||
|
err(EXIT_FAILURE, "Failed to read counter value");
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write header. */
|
||||||
|
static void line_header(void)
|
||||||
|
{
|
||||||
|
struct pai_node *node;
|
||||||
|
static bool header;
|
||||||
|
bool comma = false;
|
||||||
|
|
||||||
|
if (header)
|
||||||
|
return; /* Printed already */
|
||||||
|
printf("Date,Time,CPU,"); /* Print counter name and number */
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
if (comma)
|
||||||
|
putchar(',');
|
||||||
|
if (shortname) {
|
||||||
|
printf("%c%ld", pai_type_char(node->type),
|
||||||
|
node->ctrlist[i].nr - node->base);
|
||||||
|
} else {
|
||||||
|
printf("%s(%ld)", node->ctrlist[i].name ?: node->name_uc,
|
||||||
|
node->ctrlist[i].nr - node->base);
|
||||||
|
}
|
||||||
|
comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
header = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print CPU specific counter values. */
|
||||||
|
static void line_cpu(char *header)
|
||||||
|
{
|
||||||
|
struct pai_cpudata *data;
|
||||||
|
struct pai_node *node;
|
||||||
|
bool comma;
|
||||||
|
char txt[16];
|
||||||
|
|
||||||
|
for (unsigned int h = 0; h < max_cpus; ++h) {
|
||||||
|
comma = false;
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
data = &node->ctrlist[i].data[h];
|
||||||
|
if (!comma) {
|
||||||
|
snprintf(txt, sizeof(txt), "CPU%d,", data->cpu);
|
||||||
|
printf("%s,%s", header, txt);
|
||||||
|
} else {
|
||||||
|
putchar(',');
|
||||||
|
}
|
||||||
|
printf(ctrformat, data->value);
|
||||||
|
comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write an output line. */
|
||||||
|
static void line_out(char *header)
|
||||||
|
{
|
||||||
|
struct pai_node *node;
|
||||||
|
bool comma;
|
||||||
|
|
||||||
|
line_header();
|
||||||
|
if (allcpu)
|
||||||
|
line_cpu(header);
|
||||||
|
|
||||||
|
/* Print total count of all CPUs */
|
||||||
|
printf("%s,%s,", header, delta && !firstread ? "Delta" : "Total");
|
||||||
|
comma = false;
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
if (comma)
|
||||||
|
putchar(',');
|
||||||
|
printf(ctrformat, node->ctrlist[i].total);
|
||||||
|
comma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a formatted line. */
|
||||||
|
static void format_line_out(time_t now, char *now_text)
|
||||||
|
{
|
||||||
|
static unsigned int called;
|
||||||
|
struct pai_node *node;
|
||||||
|
char cpuid[16];
|
||||||
|
|
||||||
|
if (!called) {
|
||||||
|
util_fmt_init(stdout, output_format, FMT_DEFAULT | FMT_HANDLEINT, 1);
|
||||||
|
util_fmt_obj_start(FMT_DEFAULT, NULL);
|
||||||
|
util_fmt_obj_start(FMT_LIST, "measurements");
|
||||||
|
}
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
if (!node->ctridx) /* Counter set not selected */
|
||||||
|
continue;
|
||||||
|
util_fmt_obj_start(FMT_DEFAULT, "entry");
|
||||||
|
util_fmt_pair(FMT_PERSIST, "iteration", "%d", called++);
|
||||||
|
util_fmt_pair(FMT_PERSIST, "time_epoch", "%d", now);
|
||||||
|
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "time", "%s", now_text);
|
||||||
|
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "valuetype",
|
||||||
|
(delta && !firstread) ? "delta" : "total");
|
||||||
|
util_fmt_obj_start(FMT_LIST, "counters");
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
util_fmt_obj_start(FMT_ROW, "counter");
|
||||||
|
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
|
||||||
|
if (shortname)
|
||||||
|
util_fmt_pair(FMT_QUOTE, "shortname", "%c%d",
|
||||||
|
pai_type_char(node->type),
|
||||||
|
node->ctrlist[i].nr - node->base);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, "value", ctrformat, node->ctrlist[i].total);
|
||||||
|
if (allcpu) {
|
||||||
|
for (unsigned int j = 0; j < max_cpus; ++j) {
|
||||||
|
snprintf(cpuid, sizeof(cpuid), "cpu%d", j);
|
||||||
|
util_fmt_pair(FMT_DEFAULT, cpuid, ctrformat,
|
||||||
|
node->ctrlist[i].data[j].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
util_fmt_obj_end();
|
||||||
|
}
|
||||||
|
util_fmt_obj_end(); /* Counters */
|
||||||
|
util_fmt_obj_end(); /* Entry */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate formatted output. */
|
||||||
|
static void format_line_end(void)
|
||||||
|
{
|
||||||
|
util_fmt_obj_end(); /* Iteration */
|
||||||
|
util_fmt_obj_end(); /* Default */
|
||||||
|
util_fmt_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Display counter values. */
|
||||||
|
static void show_values(void)
|
||||||
|
{
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm *now_tm;
|
||||||
|
char now_text[32];
|
||||||
|
|
||||||
|
now_tm = localtime(&now);
|
||||||
|
if (output_format != -1) {
|
||||||
|
strftime(now_text, sizeof(now_text), "%F %T%z", now_tm);
|
||||||
|
format_line_out(now, now_text);
|
||||||
|
} else {
|
||||||
|
strftime(now_text, sizeof(now_text), "%F,%T", now_tm);
|
||||||
|
line_out(now_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read each counter value. */
|
||||||
|
static void read_painode(void)
|
||||||
|
{
|
||||||
|
struct pai_cpudata *data;
|
||||||
|
struct pai_node *node;
|
||||||
|
unsigned long value;
|
||||||
|
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
node->ctrlist[i].total = 0;
|
||||||
|
for (size_t j = 0; j < max_cpus; ++j) {
|
||||||
|
data = &node->ctrlist[i].data[j];
|
||||||
|
value = event_read(data->fd);
|
||||||
|
if (delta) {
|
||||||
|
data->value = value - data->prev_value;
|
||||||
|
data->prev_value = value;
|
||||||
|
} else {
|
||||||
|
data->value = value;
|
||||||
|
}
|
||||||
|
node->ctrlist[i].total += data->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wait_painode(void)
|
||||||
|
{
|
||||||
|
for (unsigned long i = 0; i < loops; ++i) {
|
||||||
|
read_painode();
|
||||||
|
show_values();
|
||||||
|
if (i + 1 < loops)
|
||||||
|
sleep(read_interval);
|
||||||
|
firstread = false;
|
||||||
|
}
|
||||||
|
format_line_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install one event. */
|
||||||
|
static int event_add(int cpu, int idx, struct pai_node *node)
|
||||||
|
{
|
||||||
|
struct perf_event_attr attr;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
memset(&attr, 0, sizeof(attr));
|
||||||
|
attr.size = sizeof(attr);
|
||||||
|
attr.config = node->ctrlist[idx].nr;
|
||||||
|
attr.type = node->pmu;
|
||||||
|
fd = perf_event_open(&attr, -1, cpu, -1, 0);
|
||||||
|
if (fd == -1)
|
||||||
|
err(EXIT_FAILURE, "Failed to open perf event: file descriptor not available");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase number of file descriptors this process can open. */
|
||||||
|
static void event_fdlimit(void)
|
||||||
|
{
|
||||||
|
unsigned int needed = 3 + max_fds * max_cpus;
|
||||||
|
struct rlimit rlimit;
|
||||||
|
|
||||||
|
if (getrlimit(RLIMIT_NOFILE, &rlimit) == -1)
|
||||||
|
err(EXIT_FAILURE, "Failed to read RLIMIT_NOFILE");
|
||||||
|
if (needed > rlimit.rlim_cur)
|
||||||
|
rlimit.rlim_cur = needed;
|
||||||
|
if (setrlimit(RLIMIT_NOFILE, &rlimit) == -1)
|
||||||
|
err(EXIT_FAILURE, "Failed to set RLIMIT_NOFILE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Install all events and iterate over requested read operations. */
|
||||||
|
static void event_painode(void)
|
||||||
|
{
|
||||||
|
size_t pai_cpudata_sz = sizeof(struct pai_cpudata) * max_cpus;
|
||||||
|
struct pai_cpudata *data;
|
||||||
|
struct pai_node *node;
|
||||||
|
|
||||||
|
event_fdlimit();
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
node->ctrlist[i].data = util_malloc(pai_cpudata_sz);
|
||||||
|
data = node->ctrlist[i].data;
|
||||||
|
for (unsigned int j = 0; j < CPU_SETSIZE; ++j) {
|
||||||
|
if (CPU_ISSET(j, &cpu_online_mask)) {
|
||||||
|
data->cpu = j;
|
||||||
|
data->fd = event_add(j, i, node);
|
||||||
|
data->value = 0;
|
||||||
|
data->prev_value = 0;
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wait_painode();
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
for (unsigned int j = 0; j < max_cpus; ++j)
|
||||||
|
close(node->ctrlist[i].data[j].fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for hardware support and return false if not available. */
|
/* Check for hardware support and return false if not available. */
|
||||||
static bool have_support(enum pai_types t)
|
static bool have_support(enum pai_types t)
|
||||||
{
|
{
|
||||||
@@ -303,19 +627,60 @@ static void check_type_name(const char *type)
|
|||||||
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
|
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get list of specified CPUs from command line. Check if these CPUs
|
||||||
|
* exist and are online. Ignore those CPUs which are not available and
|
||||||
|
* issue one warning when CPUs have been specified but are not online.
|
||||||
|
*/
|
||||||
|
static void get_cpulist(char *parm)
|
||||||
|
{
|
||||||
|
bool warned = false;
|
||||||
|
cpu_set_t cpulist;
|
||||||
|
int i, rc;
|
||||||
|
|
||||||
|
CPU_ZERO(&cpulist);
|
||||||
|
rc = libcpumf_cpuset(parm, &cpulist);
|
||||||
|
if (rc)
|
||||||
|
err(EXIT_FAILURE, "Cannot parse cpulist %s", parm);
|
||||||
|
for (i = 0; i < CPU_SETSIZE; ++i) {
|
||||||
|
if (CPU_ISSET(i, &cpulist) && !CPU_ISSET(i, &cpu_online_mask)) {
|
||||||
|
if (!warned) {
|
||||||
|
warnx("some CPU(s) are offline, ignored");
|
||||||
|
warned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!CPU_ISSET(i, &cpulist) && CPU_ISSET(i, &cpu_online_mask))
|
||||||
|
CPU_CLR(i, &cpu_online_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
bool list_only = true;
|
||||||
|
enum util_fmt_t fmt;
|
||||||
|
bool i_flag = false;
|
||||||
|
bool l_flag = false;
|
||||||
|
char *endchar;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
util_list_init(&pai_list, struct pai_node, node);
|
util_list_init(&pai_list, struct pai_node, node);
|
||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(lspai_opt_vec, NULL);
|
||||||
|
|
||||||
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
default:
|
default:
|
||||||
util_opt_print_parse_error(ch, argv);
|
util_opt_print_parse_error(ch, argv);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
case 'a':
|
||||||
|
allcpu = true;
|
||||||
|
list_only = false;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
delta = true;
|
||||||
|
firstread = true;
|
||||||
|
list_only = false;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
util_prg_print_help();
|
util_prg_print_help();
|
||||||
util_opt_print_help();
|
util_opt_print_help();
|
||||||
@@ -323,16 +688,80 @@ int main(int argc, char **argv)
|
|||||||
case 'v':
|
case 'v':
|
||||||
util_prg_print_version();
|
util_prg_print_version();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
case 'i':
|
||||||
|
i_flag = true;
|
||||||
|
list_only = false;
|
||||||
|
errno = 0;
|
||||||
|
read_interval = strtoul(optarg, &endchar, 0);
|
||||||
|
if (errno || *endchar)
|
||||||
|
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
l_flag = true;
|
||||||
|
list_only = false;
|
||||||
|
errno = 0;
|
||||||
|
loops = strtoul(optarg, &endchar, 0);
|
||||||
|
if (errno || *endchar)
|
||||||
|
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
numsort = true;
|
numsort = true;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
list_only = false;
|
||||||
|
shortname = true;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
check_type_name(optarg);
|
check_type_name(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
list_only = false;
|
||||||
|
ctrformat = "%lx";
|
||||||
|
break;
|
||||||
|
case 'X':
|
||||||
|
list_only = false;
|
||||||
|
ctrformat = "%#lx";
|
||||||
|
break;
|
||||||
|
case OPT_FORMAT:
|
||||||
|
if (!util_fmt_name_to_type(optarg, &fmt))
|
||||||
|
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
|
||||||
|
output_format = fmt;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
ctrlist = util_strdup(optarg);
|
||||||
|
util_str_rm_whitespace(optarg, ctrlist);
|
||||||
|
util_str_toupper(ctrlist);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing specified, show all PAI counters */
|
if (i_flag && !l_flag) {
|
||||||
|
util_prg_print_help();
|
||||||
|
util_opt_print_help();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read currently online CPUs and create a bit mask.
|
||||||
|
* This bitmap of online CPUs is used to check command line parameter
|
||||||
|
* for valid CPUs
|
||||||
|
* When any of the flags which set variable list_only to false have
|
||||||
|
* be specified, lets also show the counter value, not just list them.
|
||||||
|
*/
|
||||||
|
if (optind < argc) /* List of CPUs on command line */
|
||||||
|
list_only = false;
|
||||||
|
if (!list_only) { /* Show counter values */
|
||||||
|
ch = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &cpu_online_mask);
|
||||||
|
if (ch)
|
||||||
|
err(EXIT_FAILURE, "Cannot read file /sys/" S390_CPUS_ONLINE);
|
||||||
|
while (optind < argc)
|
||||||
|
get_cpulist(argv[optind++]);
|
||||||
|
max_cpus = CPU_COUNT(&cpu_online_mask);
|
||||||
|
if (!loops)
|
||||||
|
loops = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing specified, use all PAI counters */
|
||||||
if (!pai_types_show)
|
if (!pai_types_show)
|
||||||
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
|
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
|
||||||
|
|
||||||
@@ -346,7 +775,12 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort_painode();
|
sort_painode();
|
||||||
show_painode();
|
ch = EXIT_SUCCESS;
|
||||||
|
if (!list_only)
|
||||||
|
event_painode();
|
||||||
|
else
|
||||||
|
list_painode();
|
||||||
free_painode();
|
free_painode();
|
||||||
|
free(ctrlist);
|
||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|||||||
81
cpumf/lspai_cli.h
Normal file
81
cpumf/lspai_cli.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for lspai
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LSPAI_CLI_H
|
||||||
|
#define LSPAI_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
#define STR_SUB(x) #x
|
||||||
|
#define STR(x) STR_SUB(x)
|
||||||
|
|
||||||
|
#define OPT_FORMAT 256 /* --format XXX option */
|
||||||
|
#define DEFAULT_LOOP_INTERVAL 60 /* loop interval in seconds */
|
||||||
|
|
||||||
|
static struct util_opt lspai_opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "all", no_argument, NULL, 'a' },
|
||||||
|
.desc = "Displays all CPUs in output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "delta", no_argument, NULL, 'd' },
|
||||||
|
.desc = "Display delta counter values"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "counters", required_argument, NULL, 'c' },
|
||||||
|
.argument = "LIST",
|
||||||
|
.desc = "Specify comma separated list of counters to display"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "format", required_argument, NULL, OPT_FORMAT },
|
||||||
|
.argument = "FORMAT",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "loops", required_argument, NULL, 'l' },
|
||||||
|
.argument = "COUNT",
|
||||||
|
.desc = "Number of read operations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "interval", required_argument, NULL, 'i' },
|
||||||
|
.argument = "SECONDS",
|
||||||
|
.desc = "Time to wait between loop iterations (default "
|
||||||
|
STR(DEFAULT_LOOP_INTERVAL) "s)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "numeric", no_argument, NULL, 'n' },
|
||||||
|
.desc = "Sort PAI counters by counter number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "short", no_argument, NULL, 's' },
|
||||||
|
.desc = "Abbreviate counter name with counter set letter and number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "type", required_argument, NULL, 't' },
|
||||||
|
.argument = "TYPE",
|
||||||
|
.desc = "Type of PAI counters to show: crypto, nnpa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "hex0x", no_argument, NULL, 'X' },
|
||||||
|
.desc = "Counter values in hexadecimal format with leading 0x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "hex", no_argument, NULL, 'x' },
|
||||||
|
.desc = "Counter values in hexadecimal format"
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
UTIL_OPT_VERSION,
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,9 +17,9 @@ chcpumf \- manage the CPU-measurement facilities support
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B chcpumf
|
.B chcpumf
|
||||||
.RB [ \-m | \-\-min
|
.RB [ \-m | \-\-min
|
||||||
.IR num_sdb ]
|
.IR NUM_SDB ]
|
||||||
.RB [ \-x | \-\-max
|
.RB [ \-x | \-\-max
|
||||||
.IR num_sdb ]
|
.IR NUM_SDB ]
|
||||||
.RB [ \-V | \-\-verbose ]
|
.RB [ \-V | \-\-verbose ]
|
||||||
.br
|
.br
|
||||||
.B chcpumf
|
.B chcpumf
|
||||||
@@ -36,14 +36,14 @@ facilities for Linux on System z.
|
|||||||
.
|
.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BR \-m ", " \-\-min " \fInum_sdb\fP"
|
.BR \-m ", " \-\-min " \fINUM_SDB\fP"
|
||||||
Specifies the minimum sampling facility buffer size in sample-data-blocks
|
Specifies the minimum sampling facility buffer size in sample-data-blocks
|
||||||
(SDB). A sample-data-block consumes about 4 kilobytes.
|
(SDB). A sample-data-block consumes about 4 kilobytes.
|
||||||
|
|
||||||
This is the initial buffer size when you start the sampling facility.
|
This is the initial buffer size when you start the sampling facility.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-x ", " \-\-max " \fInum_sdb\fP"
|
.BR \-x ", " \-\-max " \fINUM_SDB\fP"
|
||||||
Specifies the maximum sampling facility buffer size in sample-data-blocks
|
Specifies the maximum sampling facility buffer size in sample-data-blocks
|
||||||
(SDB). A sample-data-block consumes about 4 kilobytes.
|
(SDB). A sample-data-block consumes about 4 kilobytes.
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ 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
|
For Linux version 5.5 and later, the raw event identifier is
|
||||||
displayed as <type>:<number>, where type is an integer that the kernel
|
displayed as <type>:<number>, where type is an integer that the kernel
|
||||||
assignes to the CPU Measurement counter facility device driver.
|
assigns to the CPU Measurement counter facility device driver.
|
||||||
For earlier Linux versions the raw event identifier is displayed as r<number>.
|
For earlier Linux versions the raw event identifier is displayed as r<number>.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -7,19 +7,25 @@
|
|||||||
.\" ----------------------------------------------------------------------
|
.\" ----------------------------------------------------------------------
|
||||||
.ds c \fBlshwc\fP
|
.ds c \fBlshwc\fP
|
||||||
.
|
.
|
||||||
.TH \*c "8" "May 2022" "s390-tools" "CPU-MF management programs"
|
.TH \*c "8" "Mar 2025" "s390-tools" "CPU-MF management programs"
|
||||||
.
|
.
|
||||||
.SH NAME
|
.SH NAME
|
||||||
lshwc \- extract CPU Measurement Facilities counter sets
|
lshwc \- extract CPU Measurement Facilities counter sets
|
||||||
.
|
.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\*c
|
\*c
|
||||||
.RB [ \-a ]
|
.RB [ \-a ][ \-d ][ \-H ][ \-s ][ \-x ][ \-X ][ \-q ]
|
||||||
.RB [ \-l
|
.RB [ \-l
|
||||||
.IR count ]
|
.IR COUNT ]
|
||||||
.RB [ \-i
|
.RB [ \-i
|
||||||
.IR interval ]
|
.IR INTERVAL ]
|
||||||
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
|
.RB [ \-t
|
||||||
|
.IR TIME ]
|
||||||
|
.RB [ \-f
|
||||||
|
.IR FORMAT ]
|
||||||
|
.RB [ \-c
|
||||||
|
.IR LIST ]
|
||||||
|
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
.BR \-h | \-\-help
|
.BR \-h | \-\-help
|
||||||
@@ -51,17 +57,130 @@ Displays counter values from each CPU.
|
|||||||
The default is a total summary line of all counters from all CPUs.
|
The default is a total summary line of all counters from all CPUs.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-i ", " \-\-interval \fI\ seconds\fP
|
.BR \-d ", " \-\-delta
|
||||||
|
Displays counter values in form of deltas.
|
||||||
|
Each counter value shows the increment to the previous output line.
|
||||||
|
Without this flag the total value of each counter is displayed.
|
||||||
|
See Examples.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
|
||||||
Specifies a time interval, in seconds,
|
Specifies a time interval, in seconds,
|
||||||
that the command waits between read operations.
|
that the command waits between read operations.
|
||||||
The default is 60 seconds.
|
The default is 60 seconds.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-l ", " \-\-loop \fI\ count\fP
|
.BR \-l ", " \-\-loop \fI\ COUNT\fP
|
||||||
Performs the specified number of read operations.
|
Performs the specified number of read operations.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
|
.BR \-H ", " \-\-hide
|
||||||
|
Do not display values of undefined counters.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-s ", " \-\-short
|
||||||
|
Displays counter names as short names in the heading.
|
||||||
|
A short name consists of
|
||||||
|
a letter for the counter set followed by a number.
|
||||||
|
For example,
|
||||||
|
this flag displays counter number 0 in the basic counter
|
||||||
|
set as
|
||||||
|
.B B0
|
||||||
|
instead of
|
||||||
|
.BR Cycles .
|
||||||
|
Valid counter set letters are:
|
||||||
|
.RS
|
||||||
|
.IP B
|
||||||
|
Basic counter set
|
||||||
|
.IP P
|
||||||
|
Problem state counter set
|
||||||
|
.IP C
|
||||||
|
Crypto counter set
|
||||||
|
.IP E
|
||||||
|
Extended counter set
|
||||||
|
.IP M
|
||||||
|
MT-Diagnostic counter set
|
||||||
|
.IP U
|
||||||
|
Undefined counter.
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-t ", " \-\-time
|
||||||
|
Specifies the runtime as an integer in days,
|
||||||
|
hours, minutes or seconds.
|
||||||
|
This option can be specified multiple times:
|
||||||
|
the runtime sums up.
|
||||||
|
Specify time as an integer followed by one of the letters
|
||||||
|
.RS
|
||||||
|
.IP d
|
||||||
|
Specifies the runtime in days.
|
||||||
|
.IP h
|
||||||
|
Specifies the runtime in hours.
|
||||||
|
.IP m
|
||||||
|
Specifies the runtime in minutes.
|
||||||
|
.IP s
|
||||||
|
Specifies the runtime in seconds.
|
||||||
|
This is the default when no letter is given.
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-x ", " \-\-hex
|
||||||
|
Displays counter values as hexadecimal values.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-X ", " \-\-hex0x
|
||||||
|
Displays counter values as hexadecimal values with a leading 0x prefix.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-q
|
||||||
|
Apply quoting to every output element, regardless of content or format.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-f ", " \-\-format \fI\ FORMAT\fP
|
||||||
|
Retrieve output in one of the following formats:
|
||||||
|
JSON, CSV, JSON-SEQ or PAIRS.
|
||||||
|
If no format is specified, the output defaults to CSV.
|
||||||
|
.
|
||||||
|
.SS JSON Output Structure
|
||||||
|
The JSON output contains two top-level objects:
|
||||||
|
.B "meta"
|
||||||
|
and
|
||||||
|
.B "lshwc"
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B meta
|
||||||
|
General metadata such as API version, host, and timestamp.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B lshwc
|
||||||
|
Measurement data and configuration.
|
||||||
|
|
||||||
|
.RS
|
||||||
|
.IP \fBcpumcf info\fP
|
||||||
|
CPU Measurement Counter Facility information.
|
||||||
|
.IP \fBmeasurements\fP
|
||||||
|
An array of objects, each representing a CPU or "total".
|
||||||
|
Each object includes:
|
||||||
|
.RS
|
||||||
|
.IP \fBcpu\fP
|
||||||
|
CPU identifier, such as 0, 1 or "delta" or "total".
|
||||||
|
.IP \fBdate_time\fP
|
||||||
|
Timestamp in ISO 8601 format.
|
||||||
|
.IP \fBtime_epoch\fP
|
||||||
|
The number of seconds since the epoch: 1970-01-01 00:00:00 UTC.
|
||||||
|
.IP \fBcounters\fP
|
||||||
|
An array of counter objects, each containing \fBname\fP (if available), \fBid\fP,
|
||||||
|
and \fBvalue\fP.
|
||||||
|
.RE
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-c ", " \-\-counters \fI\ LIST\fP
|
||||||
|
Specify a comma-separated list of counter names to be printed.
|
||||||
|
If a counter name does not match any valid counter name, it is omitted. (Implies -H)
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
|
||||||
A comma-separated list of CPUs.
|
A comma-separated list of CPUs.
|
||||||
Each CPU can optionally be followed by characters that specify the counter set.
|
Each CPU can optionally be followed by characters that specify the counter set.
|
||||||
See below for details.
|
See below for details.
|
||||||
@@ -94,7 +213,7 @@ Two read operations are performed and a summary line is printed for each
|
|||||||
read operation.
|
read operation.
|
||||||
.sp 1
|
.sp 1
|
||||||
.nf
|
.nf
|
||||||
.ft CW
|
.ft CR
|
||||||
# lshwc -l2 0-1:BP
|
# lshwc -l2 0-1:BP
|
||||||
Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES(3),L1D_DIR_WRITES(4),
|
Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES(3),L1D_DIR_WRITES(4),
|
||||||
L1D_PENALTY_CYCLES(5),PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
L1D_PENALTY_CYCLES(5),PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
||||||
@@ -105,10 +224,10 @@ Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES
|
|||||||
.ft
|
.ft
|
||||||
.fi
|
.fi
|
||||||
.sp 1
|
.sp 1
|
||||||
This example shows the counter values of the problem state counter set
|
This example shows the counter values of the problem state counter set per CPU.
|
||||||
per CPU. CPU 0 and CPU 1 is selected.
|
CPU 0 and CPU 1 are selected.
|
||||||
.nf
|
.nf
|
||||||
.ft CW
|
.ft CR
|
||||||
.sp 1
|
.sp 1
|
||||||
# lshwc -l3 -a 0-1:P
|
# lshwc -l3 -a 0-1:P
|
||||||
Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
||||||
@@ -123,6 +242,121 @@ Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
|
|||||||
2021-04-01,11:56:47,Total,6432163447,2978400903
|
2021-04-01,11:56:47,Total,6432163447,2978400903
|
||||||
.ft
|
.ft
|
||||||
.fi
|
.fi
|
||||||
|
.sp 1
|
||||||
|
This example shows the counter values of the basic counter set
|
||||||
|
using delta output format.
|
||||||
|
.nf
|
||||||
|
.ft CR
|
||||||
|
.sp 1
|
||||||
|
# lshwc -d -l 10 -i 5 -s :b
|
||||||
|
Date,Time,CPU,B0,B1,B2,B3,B4,B5
|
||||||
|
2025-03-26,10:34:19,Total,208075,117287,1950,50548,1082,49609
|
||||||
|
2025-03-26,10:34:24,Delta,85800055,70353492,590286,13228290,364034,12945804
|
||||||
|
2025-03-26,10:34:29,Delta,70654751,60656797,483047,10838672,305703,10570868
|
||||||
|
2025-03-26,10:34:34,Delta,81043162,69476160,587141,13228161,376662,12868298
|
||||||
|
2025-03-26,10:34:39,Delta,73434017,62675417,524857,11787256,333966,11543649
|
||||||
|
2025-03-26,10:34:44,Delta,68367967,58452919,506712,11370740,310785,10589883
|
||||||
|
2025-03-26,10:34:49,Delta,70351947,57607764,507675,11433377,312433,10676243
|
||||||
|
2025-03-26,10:34:54,Delta,77154817,65371168,562153,12671030,349750,12311061
|
||||||
|
2025-03-26,10:34:59,Delta,88871882,75441201,655310,14875963,392530,13773130
|
||||||
|
2025-03-26,10:35:04,Delta,83763472,71730813,609260,13643680,366992,12672405
|
||||||
|
.ft
|
||||||
|
.fi
|
||||||
|
.sp 1
|
||||||
|
This example shows the counter values of the problem state counter set with
|
||||||
|
CPU 3 selected.
|
||||||
|
.nf
|
||||||
|
.ft CR
|
||||||
|
.sp 1
|
||||||
|
# lshwc -l2 -a 3:P -H --format json
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"api_level": 1,
|
||||||
|
"version": "2.37.0-build-20250616",
|
||||||
|
"host": "b46lp08.lnxne.boe",
|
||||||
|
"time_epoch": 1750094646,
|
||||||
|
"time": "2025-06-16 19:24:06+0200"
|
||||||
|
},
|
||||||
|
"lshwc": {
|
||||||
|
"cpumcf info": {
|
||||||
|
"counter first": 3,
|
||||||
|
"counter second": 8,
|
||||||
|
"authorization": 47
|
||||||
|
},
|
||||||
|
"measurements": [
|
||||||
|
{
|
||||||
|
"date_time": "2025-06-16 19:24:06+0200",
|
||||||
|
"time_epoch": 1750094646,
|
||||||
|
"cpu": 3,
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "problem_state_cpu_cycles",
|
||||||
|
"id": 32,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "problem_state_instructions",
|
||||||
|
"id": 33,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date_time": "2025-06-16 19:24:06+0200",
|
||||||
|
"time_epoch": 1750094646,
|
||||||
|
"cpu": "total",
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "problem_state_cpu_cycles",
|
||||||
|
"id": 32,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "problem_state_instructions",
|
||||||
|
"id": 33,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date_time": "2025-06-16 19:25:06+0200",
|
||||||
|
"time_epoch": 1750094706,
|
||||||
|
"cpu": 3,
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "problem_state_cpu_cycles",
|
||||||
|
"id": 32,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "problem_state_instructions",
|
||||||
|
"id": 33,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date_time": "2025-06-16 19:25:06+0200",
|
||||||
|
"time_epoch": 1750094706,
|
||||||
|
"cpu": "total",
|
||||||
|
"counters": [
|
||||||
|
{
|
||||||
|
"name": "problem_state_cpu_cycles",
|
||||||
|
"id": 32,
|
||||||
|
"value": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "problem_state_instructions",
|
||||||
|
"id": 33,
|
||||||
|
"value": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ft
|
||||||
|
.fi
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR lscpumf (8)
|
.BR lscpumf (8)
|
||||||
.BR chcpumf (8)
|
.BR chcpumf (8)
|
||||||
|
|||||||
@@ -10,13 +10,30 @@
|
|||||||
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
|
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
|
||||||
.
|
.
|
||||||
.SH NAME
|
.SH NAME
|
||||||
lspai \- list Processor Activity Instrumentation (PAI) counters
|
\*c \- list Processor Activity Instrumentation (PAI) counters and values
|
||||||
.
|
.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\*c
|
\*c
|
||||||
|
.RB [ \-\-format
|
||||||
|
.IR FORMAT ]
|
||||||
|
.RB [ \-n ]
|
||||||
|
.RB [ \-t
|
||||||
|
.IR TYPE ]
|
||||||
|
.br
|
||||||
|
\*c
|
||||||
|
.RB [ \-\-format
|
||||||
|
.IR FORMAT ]
|
||||||
.RB [ \-n ]
|
.RB [ \-n ]
|
||||||
.RB [ \-t
|
.RB [ \-t
|
||||||
.IR "\ TYPE" ]
|
.IR "\ TYPE" ]
|
||||||
|
.RB [ \-a ][ \-d ][ \-i
|
||||||
|
.IR SECONDS ]
|
||||||
|
.RB [ \-l
|
||||||
|
.IR COUNT ]
|
||||||
|
.RB [ \-s ][ \-x ][ \-x ]
|
||||||
|
.RB [ \-c
|
||||||
|
.IR LIST ]
|
||||||
|
.RI [ CPULIST ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
.BR \-h | \-\-help
|
.BR \-h | \-\-help
|
||||||
@@ -26,10 +43,34 @@ lspai \- list Processor Activity Instrumentation (PAI) counters
|
|||||||
.
|
.
|
||||||
.
|
.
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
On the first line
|
||||||
\*c displays the Processor Activity Instrumentation (PAI) counters
|
\*c displays the Processor Activity Instrumentation (PAI) counters
|
||||||
for Linux on IBM Z.
|
for Linux on IBM Z.
|
||||||
The output is a human-readable list of available PAI counter
|
The output lists the available PAI counter names
|
||||||
names and numbers.
|
and numbers in various formats.
|
||||||
|
If
|
||||||
|
.I CPULIST
|
||||||
|
is specified or any of the options
|
||||||
|
.BR \-a ,
|
||||||
|
.BR \-d ,
|
||||||
|
.BR \-s ,
|
||||||
|
.BR \-x ,
|
||||||
|
.BR \-X ,
|
||||||
|
.B \-l
|
||||||
|
or
|
||||||
|
.BR \-i,
|
||||||
|
are present on the command line,
|
||||||
|
\*c command extracts counter values from the
|
||||||
|
specified PAI counter sets.
|
||||||
|
Counter sets can be specified and extracted for individual CPUs.
|
||||||
|
By default the output is a comma-separated list of values.
|
||||||
|
Each line starts with a timestamp
|
||||||
|
followed by the extracted counter values.
|
||||||
|
A header line shows each counter name and the
|
||||||
|
counter number in parenthesis.
|
||||||
|
For other formats, use the
|
||||||
|
.B \-\-format
|
||||||
|
option.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BR \-h ", " \-\-help
|
.BR \-h ", " \-\-help
|
||||||
@@ -40,7 +81,44 @@ Displays help information, then exits.
|
|||||||
Displays version information, then exits.
|
Displays version information, then exits.
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-t ", " \-\-type "\ TYPE"
|
.BR \-a ", " \-\-allcpu
|
||||||
|
Displays counter values from each CPU.
|
||||||
|
The default is a total summary line of all counters from all CPUs.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-d ", " \-\-delta
|
||||||
|
Displays counter values in form of deltas.
|
||||||
|
Each counter value shows the increment to the previous output line.
|
||||||
|
Without this flag the total value of each counter is displayed.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-c ", " \-\-counters \fI\ LIST\fP
|
||||||
|
Specify a comma separated list of counter names to
|
||||||
|
be printed.
|
||||||
|
If a counter name does not match any valid counter
|
||||||
|
name, it is omitted.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-s ", " \-\-short
|
||||||
|
Displays counter names as short names in the heading.
|
||||||
|
A short name consists of
|
||||||
|
a letter for the counter set followed by a number.
|
||||||
|
For example,
|
||||||
|
this flag displays counter number 0 in the PAI crypto counter
|
||||||
|
set as
|
||||||
|
.B C0
|
||||||
|
instead of
|
||||||
|
.BR CRYPTO_ALL .
|
||||||
|
Valid counter set letters are:
|
||||||
|
.RS
|
||||||
|
.IP C
|
||||||
|
PAI crypto counter set
|
||||||
|
.IP N
|
||||||
|
PAI NNPA counter set
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-t ", " \-\-type "\ \fITYPE\fP"
|
||||||
Specifies the PAI counter set to list.
|
Specifies the PAI counter set to list.
|
||||||
Valid counter set values are
|
Valid counter set values are
|
||||||
.I crypto
|
.I crypto
|
||||||
@@ -55,6 +133,32 @@ Crypto refers to the Cryptografic Processing Assist facility counter set.
|
|||||||
Shows the PAI counter sets sorted by counter number.
|
Shows the PAI counter sets sorted by counter number.
|
||||||
Default sort order is PAI counter name.
|
Default sort order is PAI counter name.
|
||||||
.
|
.
|
||||||
|
.TP
|
||||||
|
.BI \-\-format "\ FORMAT"
|
||||||
|
Retrieve output in one of the following formats:
|
||||||
|
JSON, csv, json-seq or pairs.
|
||||||
|
If no format is specified,
|
||||||
|
the output defaults to a human-readable format.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
|
||||||
|
Specifies a time interval, in seconds,
|
||||||
|
that the command waits between read operations.
|
||||||
|
The default is 60 seconds.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-l ", " \-\-loop \fI\ COUNT\fP
|
||||||
|
Performs the specified number of read operations.
|
||||||
|
The default is one.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-x ", " \-\-hex
|
||||||
|
Displays counter values as hexadecimal values.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-X ", " \-\-hex0x
|
||||||
|
Displays counter values as hexadecimal values with a leading 0x prefix.
|
||||||
|
.
|
||||||
.SH "EXAMPLE"
|
.SH "EXAMPLE"
|
||||||
The \*c invocation lists all PAI Neural Network Processing Assist Facility
|
The \*c invocation lists all PAI Neural Network Processing Assist Facility
|
||||||
(NNPA) counters in numeric order:
|
(NNPA) counters in numeric order:
|
||||||
@@ -75,6 +179,58 @@ suitable for
|
|||||||
.IR perf "(8)"
|
.IR perf "(8)"
|
||||||
event specification by name.
|
event specification by name.
|
||||||
The third gives a short explanation, if available.
|
The third gives a short explanation, if available.
|
||||||
|
.sp 1
|
||||||
|
The \*c invocation displays all PAI Neural Network Processing Assist Facility
|
||||||
|
(NNPA) counters values.
|
||||||
|
Ten iterations with a two second delay in between
|
||||||
|
is printed on the screen.
|
||||||
|
.nf
|
||||||
|
# lspai -i 2 -l 10 -t nnpa -n
|
||||||
|
Date,Time,CPU,NNPA_ALL(0),NNPA_ADD(1),NNPA_SUB(2),NNPA_MUL(3),NNPA_DIV(4),
|
||||||
|
NNPA_MIN(5),NNPA_MAX(6),NNPA_LOG(7),NNPA_EXP(8),NNPA_IBM_RESERVED_9(9),
|
||||||
|
NNPA_RELU(10),NNPA_TANH(11),NNPA_SIGMOID(12),NNPA_SOFTMAX(13),NNPA_BATCHNORM(14),
|
||||||
|
NNPA_MAXPOOL2D(15),NNPA_AVGPOOL2D(16),NNPA_LSTMACT(17),NNPA_GRUACT(18),
|
||||||
|
NNPA_CONVOLUTION(19),NNPA_MATMUL_OP(20),NNPA_MATMUL_OP_BCAST23(21),
|
||||||
|
NNPA_SMALLBATCH(22),NNPA_LARGEDIM(23),NNPA_SMALLTENSOR(24),NNPA_1MFRAME(25),
|
||||||
|
NNPA_2GFRAME(26),NNPA_ACCESSEXCEPT(27)
|
||||||
|
2025-05-13,08:18:27,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:29,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:31,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:33,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:35,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:37,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:39,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:41,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:43,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
2025-05-13,08:18:45,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||||
|
#
|
||||||
|
.fi
|
||||||
|
.sp 1
|
||||||
|
This \*c example displays the value of PAI crypto counter number 7.
|
||||||
|
It is field number 116 in the output.
|
||||||
|
This counter is incremented after \*c is started and
|
||||||
|
the table shows the delta values for PAI crypto counter 7.
|
||||||
|
.nf
|
||||||
|
# lspai -d -s -i 5 -l3 -t crypto | \
|
||||||
|
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
|
||||||
|
Date,Time,CPU,C0,C7
|
||||||
|
2025-06-24,13:02:24,Total,0,0
|
||||||
|
2025-06-24,13:02:29,Delta,77122286,77122284
|
||||||
|
2025-06-24,13:02:34,Delta,92574403,92574403
|
||||||
|
#
|
||||||
|
.fi
|
||||||
|
.sp 1
|
||||||
|
The following table shows the total value for PAI crypto counter 7
|
||||||
|
after \*c is started.
|
||||||
|
.nf
|
||||||
|
# lspai -s -i 5 -l3 -t crypto | \
|
||||||
|
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
|
||||||
|
Date,Time,CPU,C0,C7
|
||||||
|
2025-06-24,13:03:01,Total,0,0
|
||||||
|
2025-06-24,13:03:06,Total,72550754,72566121
|
||||||
|
2025-06-24,13:03:11,Total,164633982,164650377
|
||||||
|
#
|
||||||
|
.fi
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR pai (8)
|
.BR pai (8)
|
||||||
.BR lscpumf (8)
|
.BR lscpumf (8)
|
||||||
|
|||||||
@@ -15,24 +15,24 @@ pai \- record and report Processor Activity Instrumentation (PAI) counters
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\*c
|
\*c
|
||||||
.RB [ \-V ][ \-m | \-\-mapsize
|
.RB [ \-V ][ \-m | \-\-mapsize
|
||||||
.IR size ]
|
.IR SIZE ]
|
||||||
.RB [ \-i | \-\-interval
|
.RB [ \-i | \-\-interval
|
||||||
.IR ms ]
|
.IR MS ]
|
||||||
.RB [ \-R | \-\-realtime
|
.RB [ \-R | \-\-realtime
|
||||||
.IR prio ]
|
.IR PRIO ]
|
||||||
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
.BR \-c | \-\-crypto [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
.RB [ \-V ][ \-m | \-\-mapsize
|
.RB [ \-V ][ \-m | \-\-mapsize
|
||||||
.IR size ]
|
.IR SIZE ]
|
||||||
.RB [ \-i | \-\-interval
|
.RB [ \-i | \-\-interval
|
||||||
.IR ms ]
|
.IR MS ]
|
||||||
.RB [ \-R | \-\-realtime
|
.RB [ \-R | \-\-realtime
|
||||||
.IR prio ]
|
.IR PRIO ]
|
||||||
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
.BR \-n | \-\-nnpa [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIfiles\fP ]
|
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIFILES\fP ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
.BR \-h | \-\-help
|
.BR \-h | \-\-help
|
||||||
@@ -73,7 +73,7 @@ Reporting evaluates files that are created by recording.
|
|||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.BR \-c ", " \-\-crypto "\fR[\fIcpulist\fR][:\fIdata\fR]"
|
.BR \-c ", " \-\-crypto "\fR[\fICPULIST\fR][:\fIDATA\fR]"
|
||||||
Records data for all (default) or a specified list of CPUs.
|
Records data for all (default) or a specified list of CPUs.
|
||||||
The CPU list is a comma-separated list of CPU numbers and ranges.
|
The CPU list is a comma-separated list of CPU numbers and ranges.
|
||||||
In a range, a hyphen separates the first CPU number
|
In a range, a hyphen separates the first CPU number
|
||||||
@@ -106,7 +106,7 @@ execution.
|
|||||||
.RE
|
.RE
|
||||||
.
|
.
|
||||||
.TP
|
.TP
|
||||||
.BR \-n ", " \-\-nnpa "\fR[\fIcpulist\fR][:\fIdata\fR]"
|
.BR \-n ", " \-\-nnpa "\fR[\fICPULIST\fR][:\fIDATA\fR]"
|
||||||
Records data for all (default) or a specified list of CPUs.
|
Records data for all (default) or a specified list of CPUs.
|
||||||
The CPU list is a comma-separated list of CPU numbers and ranges.
|
The CPU list is a comma-separated list of CPU numbers and ranges.
|
||||||
In a range, a hyphen separates the first CPU number
|
In a range, a hyphen separates the first CPU number
|
||||||
@@ -241,7 +241,7 @@ The program runs for 10 seconds
|
|||||||
(10 intervals of 1000 milliseconds).
|
(10 intervals of 1000 milliseconds).
|
||||||
.sp 1
|
.sp 1
|
||||||
.nf
|
.nf
|
||||||
.ft CW
|
.ft CR
|
||||||
# \*c -c0 10
|
# \*c -c0 10
|
||||||
.ft R
|
.ft R
|
||||||
.fi
|
.fi
|
||||||
@@ -256,7 +256,7 @@ and a comma-separated list of counter number, colon (:),
|
|||||||
and the counter value n hexadecimal notation.
|
and the counter value n hexadecimal notation.
|
||||||
.sp 1
|
.sp 1
|
||||||
.nf
|
.nf
|
||||||
.ft CW
|
.ft CR
|
||||||
# \*c -r
|
# \*c -r
|
||||||
0x62a668f2fa 0 event 4096 sample pid 4956/4956 9:0xa7,73:0x8,74:0x18
|
0x62a668f2fa 0 event 4096 sample pid 4956/4956 9:0xa7,73:0x8,74:0x18
|
||||||
0x6319c75653 0 event 4096 sample pid 4972/4972 32:0x1
|
0x6319c75653 0 event 4096 sample pid 4972/4972 32:0x1
|
||||||
|
|||||||
68
cpumf/pai.c
68
cpumf/pai.c
@@ -40,7 +40,9 @@
|
|||||||
#include "lib/util_prg.h"
|
#include "lib/util_prg.h"
|
||||||
#include "lib/util_scandir.h"
|
#include "lib/util_scandir.h"
|
||||||
#include "lib/libcpumf.h"
|
#include "lib/libcpumf.h"
|
||||||
|
|
||||||
#include "pai.h"
|
#include "pai.h"
|
||||||
|
#include "pai_cli.h"
|
||||||
|
|
||||||
#define S390_EVT_PAI_CRYPTO 0x1000
|
#define S390_EVT_PAI_CRYPTO 0x1000
|
||||||
#define S390_EVT_PAI_NNPA 0x1800
|
#define S390_EVT_PAI_NNPA 0x1800
|
||||||
@@ -59,14 +61,6 @@ static struct util_list list_pai_event;
|
|||||||
static struct util_list list_pmu_event;
|
static struct util_list list_pmu_event;
|
||||||
static bool summary;
|
static bool summary;
|
||||||
|
|
||||||
/* System call to perf_event_open(2) */
|
|
||||||
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
|
|
||||||
int cpu, int group_fd, unsigned long flags)
|
|
||||||
{
|
|
||||||
return syscall(__NR_perf_event_open, hw_event, pid, cpu,
|
|
||||||
group_fd, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ev_dealloc(void)
|
static void ev_dealloc(void)
|
||||||
{
|
{
|
||||||
struct pai_event *next, *p;
|
struct pai_event *next, *p;
|
||||||
@@ -509,7 +503,7 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
|||||||
__u64 sample_type = pa->sample_type;
|
__u64 sample_type = pa->sample_type;
|
||||||
int allcnt = 0, cnt = 0, rawok = 0;
|
int allcnt = 0, cnt = 0, rawok = 0;
|
||||||
struct perf_event_header *hdr;
|
struct perf_event_header *hdr;
|
||||||
size_t offset = sizeof(*pa);
|
size_t offset = pa->size;
|
||||||
__u64 evtnum = pa->config;
|
__u64 evtnum = pa->config;
|
||||||
struct pai_event_out ev;
|
struct pai_event_out ev;
|
||||||
size_t limit;
|
size_t limit;
|
||||||
@@ -520,6 +514,8 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
|||||||
unsigned char valid;
|
unsigned char valid;
|
||||||
} last_csout = { 0, 0, 0 };
|
} last_csout = { 0, 0, 0 };
|
||||||
|
|
||||||
|
if (verbose && (sizeof(*pa) != pa->size))
|
||||||
|
printf("size perf_event_attr mismatch %zu/%zu\n", sizeof(*pa), offset);
|
||||||
while (offset < len) {
|
while (offset < len) {
|
||||||
hdr = (struct perf_event_header *)(buf + offset);
|
hdr = (struct perf_event_header *)(buf + offset);
|
||||||
memset(&ev, 0, sizeof(ev));
|
memset(&ev, 0, sizeof(ev));
|
||||||
@@ -743,8 +739,8 @@ static int add_events(int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(pmuname);
|
|
||||||
warnx("failed building event list for %s", pmuname);
|
warnx("failed building event list for %s", pmuname);
|
||||||
|
free(pmuname);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -841,7 +837,7 @@ static int map_check(char *fn, int (*fct)(char *, unsigned char *, size_t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
if (p == MAP_FAILED) {
|
if (p == MAP_FAILED) {
|
||||||
warnx("%s cannot map file", fn);
|
warnx("%s cannot map file", fn);
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -933,54 +929,6 @@ static void parse_cpulist(int enr, const char *parm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
|
||||||
UTIL_OPT_SECTION("OPTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "crypto", optional_argument, NULL, 'c' },
|
|
||||||
.argument = "CPULIST[:DATA]",
|
|
||||||
.desc = "Collect PAI crypto counters"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "nnpa", optional_argument, NULL, 'n' },
|
|
||||||
.argument = "CPULIST[:DATA]",
|
|
||||||
.desc = "Collect PAI nnpa counters"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "mapsize", required_argument, NULL, 'm' },
|
|
||||||
.argument = "SIZE",
|
|
||||||
.desc = "Specifies number of 4KB pages for event ring buffer"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "report", no_argument, NULL, 'r' },
|
|
||||||
.desc = "Report file contents"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "realtime", required_argument, NULL, 'R' },
|
|
||||||
.argument = "PRIO",
|
|
||||||
.desc = "Collect data with this RT SCHED_FIFO priority"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "interval", required_argument, NULL, 'i' },
|
|
||||||
.argument = "NUMBER",
|
|
||||||
.desc = "Specifies interval between read operations in milliseconds"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "verbose", no_argument, NULL, 'V' },
|
|
||||||
.desc = "Verbose output"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "humantime", no_argument, NULL, 'H' },
|
|
||||||
.desc = "Human readable timestamp in seconds.nanoseconds"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "summary", no_argument, NULL, 'S' },
|
|
||||||
.desc = "Print summary of all non-zero counter values"
|
|
||||||
},
|
|
||||||
UTIL_OPT_HELP,
|
|
||||||
UTIL_OPT_VERSION,
|
|
||||||
UTIL_OPT_END
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct util_prg prg = {
|
static const struct util_prg prg = {
|
||||||
.desc = "Record and report Processor Activity Instrumentation Facility Counters.",
|
.desc = "Record and report Processor Activity Instrumentation Facility Counters.",
|
||||||
.copyright_vec = {
|
.copyright_vec = {
|
||||||
@@ -1046,7 +994,7 @@ int main(int argc, char **argv)
|
|||||||
util_list_init(&list_pai_event, struct pai_event, node);
|
util_list_init(&list_pai_event, struct pai_event, node);
|
||||||
util_list_init(&list_pmu_event, struct pmu_events, node);
|
util_list_init(&list_pmu_event, struct pmu_events, node);
|
||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(pai_opt_vec, NULL);
|
||||||
|
|
||||||
/* Read currently online CPUs and create a bit mask.
|
/* Read currently online CPUs and create a bit mask.
|
||||||
* This bitmap of online CPUs is used to check command line parameter
|
* This bitmap of online CPUs is used to check command line parameter
|
||||||
|
|||||||
65
cpumf/pai_cli.h
Normal file
65
cpumf/pai_cli.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for pai
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 PAI_CLI_H
|
||||||
|
#define PAI_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
static struct util_opt pai_opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "crypto", optional_argument, NULL, 'c' },
|
||||||
|
.argument = "CPULIST[:DATA]",
|
||||||
|
.desc = "Collect PAI crypto counters"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "nnpa", optional_argument, NULL, 'n' },
|
||||||
|
.argument = "CPULIST[:DATA]",
|
||||||
|
.desc = "Collect PAI nnpa counters"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "mapsize", required_argument, NULL, 'm' },
|
||||||
|
.argument = "SIZE",
|
||||||
|
.desc = "Specifies number of 4KB pages for event ring buffer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "report", no_argument, NULL, 'r' },
|
||||||
|
.desc = "Report file contents"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "realtime", required_argument, NULL, 'R' },
|
||||||
|
.argument = "PRIO",
|
||||||
|
.desc = "Collect data with this RT SCHED_FIFO priority"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "interval", required_argument, NULL, 'i' },
|
||||||
|
.argument = "NUMBER",
|
||||||
|
.desc = "Specifies interval between read operations in milliseconds"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "verbose", no_argument, NULL, 'V' },
|
||||||
|
.desc = "Verbose output"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "humantime", no_argument, NULL, 'H' },
|
||||||
|
.desc = "Human readable timestamp in seconds.nanoseconds"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "summary", no_argument, NULL, 'S' },
|
||||||
|
.desc = "Print summary of all non-zero counter values"
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
UTIL_OPT_VERSION,
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -314,8 +314,7 @@ void check_config()
|
|||||||
cpuplugd_debug("Daemon started with vertical polarization.\n");
|
cpuplugd_debug("Daemon started with vertical polarization.\n");
|
||||||
cpuplugd_debug("Cpu adjustments won't be made until system ");
|
cpuplugd_debug("Cpu adjustments won't be made until system ");
|
||||||
cpuplugd_debug("is in horizontal polarization\n");
|
cpuplugd_debug("is in horizontal polarization\n");
|
||||||
} else if (saved_polarization == PLR_HORIZONTAL &&
|
} else if (cpu == 1) {
|
||||||
cpu == 1) {
|
|
||||||
apply_cpu_config();
|
apply_cpu_config();
|
||||||
}
|
}
|
||||||
if (memory == 1) {
|
if (memory == 1) {
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ int get_polarization(void)
|
|||||||
char *path;
|
char *path;
|
||||||
|
|
||||||
path = util_path_sysfs("devices/system/cpu/dispatching");
|
path = util_path_sysfs("devices/system/cpu/dispatching");
|
||||||
|
if (!util_path_exists(path))
|
||||||
|
return PLR_NONE;
|
||||||
if (util_file_read_i(&polarization, NUM_BASE, path) < 0) {
|
if (util_file_read_i(&polarization, NUM_BASE, path) < 0) {
|
||||||
polarization = -1;
|
polarization = -1;
|
||||||
cpuplugd_debug("failed to read system polarization\n");
|
cpuplugd_debug("failed to read system polarization\n");
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#define CPUSTATS 10
|
#define CPUSTATS 10
|
||||||
#define PLR_HORIZONTAL 0
|
#define PLR_HORIZONTAL 0
|
||||||
#define PLR_VERTICAL 1
|
#define PLR_VERTICAL 1
|
||||||
|
#define PLR_NONE 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Precedence of C operators
|
* Precedence of C operators
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
include ../common.mak
|
include ../common.mak
|
||||||
|
|
||||||
|
zsh-completions = _dasdfmt
|
||||||
|
bash-completions = dasdfmt.bash
|
||||||
|
|
||||||
|
include ../common_autocomp.mak
|
||||||
|
|
||||||
all: dasdfmt
|
all: dasdfmt
|
||||||
|
|
||||||
libs = $(rootdir)/libdasd/libdasd.a \
|
libs = $(rootdir)/libdasd/libdasd.a \
|
||||||
|
|||||||
20
dasdfmt/autocompletion_generator_host.c
Normal file
20
dasdfmt/autocompletion_generator_host.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
/*
|
||||||
|
* Autocompletion generation - for dasdfmt tool
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 "lib/util_autocomp.h"
|
||||||
|
|
||||||
|
#include "dasdfmt_cli.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
generate_autocomp(opt_vec, "dasdfmt");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#include "dasdfmt.h"
|
#include "dasdfmt.h"
|
||||||
|
#include "dasdfmt_cli.h"
|
||||||
|
|
||||||
#define BUSIDSIZE 8
|
#define BUSIDSIZE 8
|
||||||
#define SEC_PER_DAY (60 * 60 * 24)
|
#define SEC_PER_DAY (60 * 60 * 24)
|
||||||
@@ -81,112 +82,6 @@ static struct dasdfmt_globals {
|
|||||||
.dasd_info = { 0 },
|
.dasd_info = { 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Defines for options with no short command */
|
|
||||||
#define OPT_CHECK 128
|
|
||||||
#define OPT_NOZERO 129
|
|
||||||
#define OPT_NODISCARD 130
|
|
||||||
|
|
||||||
static struct util_opt opt_vec[] = {
|
|
||||||
UTIL_OPT_SECTION("FORMAT ACTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "mode", required_argument, NULL, 'M' },
|
|
||||||
.argument = "MODE",
|
|
||||||
.desc = "Specify scope of operation using MODE:\n"
|
|
||||||
" full: Full device (default)\n"
|
|
||||||
" quick: Only the first two tracks\n"
|
|
||||||
" expand: Unformatted tracks at device end",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "check", no_argument, NULL, OPT_CHECK },
|
|
||||||
.desc = "Perform complete format check on device",
|
|
||||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
|
||||||
},
|
|
||||||
UTIL_OPT_SECTION("FORMAT OPTIONS"),
|
|
||||||
{
|
|
||||||
.option = { "blocksize", required_argument, NULL, 'b' },
|
|
||||||
.argument = "SIZE",
|
|
||||||
.desc = "Format blocks to SIZE bytes (default 4096)",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "disk_layout", required_argument, NULL, 'd' },
|
|
||||||
.argument = "LAYOUT",
|
|
||||||
.desc = "Specify the disk layout:\n"
|
|
||||||
" cdl: Compatible Disk Layout (default)\n"
|
|
||||||
" ldl: Linux Disk Layout",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "keep_volser", no_argument, NULL, 'k' },
|
|
||||||
.desc = "Do not change the current volume serial",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "label", required_argument, NULL, 'l' },
|
|
||||||
.argument = "VOLSER",
|
|
||||||
.desc = "Specify volume serial number",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "no_label", no_argument, NULL, 'L' },
|
|
||||||
.desc = "Don't write a disk label",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "requestsize", required_argument, NULL, 'r' },
|
|
||||||
.argument = "NUM",
|
|
||||||
.desc = "Process NUM cylinders in one formatting step",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "norecordzero", no_argument, NULL, OPT_NOZERO },
|
|
||||||
.desc = "Prevent storage server from modifying record 0",
|
|
||||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "no-discard", no_argument, NULL, OPT_NODISCARD },
|
|
||||||
.desc = "Do not discard space before formatting",
|
|
||||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { NULL, no_argument, NULL, 'y' },
|
|
||||||
.desc = "Start formatting without further user-confirmation",
|
|
||||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
|
||||||
},
|
|
||||||
UTIL_OPT_SECTION("DISPLAY PROGRESS"),
|
|
||||||
{
|
|
||||||
.option = { "hashmarks", required_argument, NULL, 'm' },
|
|
||||||
.argument = "NUM",
|
|
||||||
.desc = "Show a hashmark every NUM cylinders",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "progressbar", no_argument, NULL, 'p' },
|
|
||||||
.desc = "Show a progressbar",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "percentage", no_argument, NULL, 'P' },
|
|
||||||
.desc = "Show progress in percent",
|
|
||||||
},
|
|
||||||
UTIL_OPT_SECTION("MISC"),
|
|
||||||
{
|
|
||||||
.option = { "check_host_count", no_argument, NULL, 'C' },
|
|
||||||
.desc = "Check if device is in use by other hosts",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "force", no_argument, NULL, 'F' },
|
|
||||||
.desc = "Format without performing sanity checking",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { "test", no_argument, NULL, 't' },
|
|
||||||
.desc = "Run in dry-run mode without modifying the DASD",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.option = { NULL, no_argument, NULL, 'v' },
|
|
||||||
.desc = "Print verbose messages when executing",
|
|
||||||
.flags = UTIL_OPT_FLAG_NOLONG,
|
|
||||||
},
|
|
||||||
UTIL_OPT_HELP,
|
|
||||||
{
|
|
||||||
.option = { "version", no_argument, NULL, 'V' },
|
|
||||||
.desc = "Print version information, then exit",
|
|
||||||
},
|
|
||||||
UTIL_OPT_END
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Report error, free memory, and exit */
|
/* Report error, free memory, and exit */
|
||||||
static void error(const char *format, ...)
|
static void error(const char *format, ...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -69,13 +70,13 @@ static void error(const char *format, ...)
|
|||||||
"is in invalid format\n",prog_name);}
|
"is in invalid format\n",prog_name);}
|
||||||
|
|
||||||
typedef struct bootstrap1 {
|
typedef struct bootstrap1 {
|
||||||
u_int32_t key;
|
uint32_t key;
|
||||||
u_int32_t data[6];
|
uint32_t data[6];
|
||||||
} __attribute__ ((packed)) bootstrap1_t;
|
} __attribute__ ((packed)) bootstrap1_t;
|
||||||
|
|
||||||
typedef struct bootstrap2 {
|
typedef struct bootstrap2 {
|
||||||
u_int32_t key;
|
uint32_t key;
|
||||||
u_int32_t data[36];
|
uint32_t data[36];
|
||||||
} __attribute__ ((packed)) bootstrap2_t;
|
} __attribute__ ((packed)) bootstrap2_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
123
dasdfmt/dasdfmt_cli.h
Normal file
123
dasdfmt/dasdfmt_cli.h
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* Command line utilities - for dasdfmt
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 DASDFMT_CLI_H
|
||||||
|
#define DASDFMT_CLI_H
|
||||||
|
|
||||||
|
#include "lib/util_fmt.h"
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
/* Defines for options with no short command */
|
||||||
|
#define OPT_CHECK 128
|
||||||
|
#define OPT_NOZERO 129
|
||||||
|
#define OPT_NODISCARD 130
|
||||||
|
|
||||||
|
static struct util_opt opt_vec[] = {
|
||||||
|
UTIL_OPT_SECTION("FORMAT ACTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "mode", required_argument, NULL, 'M' },
|
||||||
|
.argument = "MODE",
|
||||||
|
.desc = "Specify scope of operation using MODE:\n"
|
||||||
|
" full: Full device (default)\n"
|
||||||
|
" quick: Only the first two tracks\n"
|
||||||
|
" expand: Unformatted tracks at device end",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "check", no_argument, NULL, OPT_CHECK },
|
||||||
|
.desc = "Perform complete format check on device",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
},
|
||||||
|
UTIL_OPT_SECTION("FORMAT OPTIONS"),
|
||||||
|
{
|
||||||
|
.option = { "blocksize", required_argument, NULL, 'b' },
|
||||||
|
.argument = "SIZE",
|
||||||
|
.desc = "Format blocks to SIZE bytes (default 4096)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "disk_layout", required_argument, NULL, 'd' },
|
||||||
|
.argument = "LAYOUT",
|
||||||
|
.desc = "Specify the disk layout:\n"
|
||||||
|
" cdl: Compatible Disk Layout (default)\n"
|
||||||
|
" ldl: Linux Disk Layout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "keep_volser", no_argument, NULL, 'k' },
|
||||||
|
.desc = "Do not change the current volume serial",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "label", required_argument, NULL, 'l' },
|
||||||
|
.argument = "VOLSER",
|
||||||
|
.desc = "Specify volume serial number",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "no_label", no_argument, NULL, 'L' },
|
||||||
|
.desc = "Don't write a disk label",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "requestsize", required_argument, NULL, 'r' },
|
||||||
|
.argument = "NUM",
|
||||||
|
.desc = "Process NUM cylinders in one formatting step",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "norecordzero", no_argument, NULL, OPT_NOZERO },
|
||||||
|
.desc = "Prevent storage server from modifying record 0",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "no-discard", no_argument, NULL, OPT_NODISCARD },
|
||||||
|
.desc = "Do not discard space before formatting",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { NULL, no_argument, NULL, 'y' },
|
||||||
|
.desc = "Start formatting without further user-confirmation",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||||
|
},
|
||||||
|
UTIL_OPT_SECTION("DISPLAY PROGRESS"),
|
||||||
|
{
|
||||||
|
.option = { "hashmarks", required_argument, NULL, 'm' },
|
||||||
|
.argument = "NUM",
|
||||||
|
.desc = "Show a hashmark every NUM cylinders",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "progressbar", no_argument, NULL, 'p' },
|
||||||
|
.desc = "Show a progressbar",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "percentage", no_argument, NULL, 'P' },
|
||||||
|
.desc = "Show progress in percent",
|
||||||
|
},
|
||||||
|
UTIL_OPT_SECTION("MISC"),
|
||||||
|
{
|
||||||
|
.option = { "check_host_count", no_argument, NULL, 'C' },
|
||||||
|
.desc = "Check if device is in use by other hosts",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "force", no_argument, NULL, 'F' },
|
||||||
|
.desc = "Format without performing sanity checking",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { "test", no_argument, NULL, 't' },
|
||||||
|
.desc = "Run in dry-run mode without modifying the DASD",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.option = { NULL, no_argument, NULL, 'v' },
|
||||||
|
.desc = "Print verbose messages when executing",
|
||||||
|
.flags = UTIL_OPT_FLAG_NOLONG,
|
||||||
|
},
|
||||||
|
UTIL_OPT_HELP,
|
||||||
|
{
|
||||||
|
.option = { "version", no_argument, NULL, 'V' },
|
||||||
|
.desc = "Print version information, then exit",
|
||||||
|
},
|
||||||
|
UTIL_OPT_END
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -23,16 +23,21 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lib/dasd_base.h"
|
#include "lib/dasd_base.h"
|
||||||
#include "lib/util_base.h"
|
|
||||||
#include "lib/util_file.h"
|
#include "lib/util_file.h"
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
#include "lib/util_opt.h"
|
#include "lib/util_opt.h"
|
||||||
#include "lib/util_prg.h"
|
#include "lib/util_prg.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define RD_BUFFER_SIZE 80
|
#define RD_BUFFER_SIZE 80
|
||||||
#define TEMP_DEV_MAX_RETRIES 1000
|
#define TEMP_DEV_MAX_RETRIES 1000
|
||||||
|
|
||||||
|
#ifndef FTW_CONTINUE
|
||||||
|
#define FTW_CONTINUE 0
|
||||||
|
#define FTW_STOP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct util_prg prg = {
|
static const struct util_prg prg = {
|
||||||
.desc = "Display DASD volume serial number and ID information",
|
.desc = "Display DASD volume serial number and ID information",
|
||||||
.args = "-i BUSID | -b BLOCKDEV | -d DEVNODE",
|
.args = "-i BUSID | -b BLOCKDEV | -d DEVNODE",
|
||||||
@@ -212,7 +217,7 @@ static int dinfo_read_dasd_vlabel(char *device, struct volume_label *vlabel,
|
|||||||
if (lseek(f, vlabel_start, SEEK_SET) < 0)
|
if (lseek(f, vlabel_start, SEEK_SET) < 0)
|
||||||
goto error_close;
|
goto error_close;
|
||||||
|
|
||||||
bzero(vlabel, vlsize);
|
memset(vlabel, 0, vlsize);
|
||||||
|
|
||||||
if (read(f, vlabel, vlsize) != vlsize) {
|
if (read(f, vlabel, vlsize) != vlsize) {
|
||||||
warnx("Could not read volume label");
|
warnx("Could not read volume label");
|
||||||
@@ -220,15 +225,15 @@ static int dinfo_read_dasd_vlabel(char *device, struct volume_label *vlabel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dasd_info.FBA_layout) {
|
if (dasd_info.FBA_layout) {
|
||||||
bzero(&tmp, vlsize);
|
memset(&tmp, 0, vlsize);
|
||||||
memcpy(&tmp, vlabel, vlsize);
|
memcpy(&tmp, vlabel, vlsize);
|
||||||
memcpy(vlabel->vollbl, &tmp, vlsize - 4);
|
memcpy(vlabel->vollbl, &tmp, vlsize - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(f);
|
close(f);
|
||||||
|
|
||||||
bzero(readbuf, 7);
|
memset(readbuf, 0, 7);
|
||||||
bzero(vollbl, 5);
|
memset(vollbl, 0, 5);
|
||||||
strncpy(vollbl, vlabel->vollbl, 4);
|
strncpy(vollbl, vlabel->vollbl, 4);
|
||||||
dinfo_ebcdic_dec(vollbl, vollbl, 4);
|
dinfo_ebcdic_dec(vollbl, vollbl, 4);
|
||||||
|
|
||||||
@@ -283,7 +288,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
|
|||||||
char filename[] = "dasdinfo0000";
|
char filename[] = "dasdinfo0000";
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
unsigned int path;
|
unsigned int path;
|
||||||
int retry;
|
unsigned int retry;
|
||||||
int rc;
|
int rc;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
@@ -294,7 +299,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
|
|||||||
if (pathname[path] == NULL)
|
if (pathname[path] == NULL)
|
||||||
continue;
|
continue;
|
||||||
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
|
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
|
||||||
sprintf(filename, "dasdinfo%04d", retry);
|
snprintf(filename, sizeof(filename), "dasdinfo%04d", retry);
|
||||||
result = dinfo_make_path(pathname[path], filename);
|
result = dinfo_make_path(pathname[path], filename);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -334,7 +339,7 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
|
|||||||
char *p = NULL;
|
char *p = NULL;
|
||||||
int ma, mi;
|
int ma, mi;
|
||||||
|
|
||||||
bzero(tmp, RD_BUFFER_SIZE);
|
memset(tmp, 0, RD_BUFFER_SIZE);
|
||||||
util_strlcpy(tmp, str, RD_BUFFER_SIZE);
|
util_strlcpy(tmp, str, RD_BUFFER_SIZE);
|
||||||
p = strchr(tmp, ':');
|
p = strchr(tmp, ':');
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
@@ -354,18 +359,26 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
|
|||||||
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
|
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
|
||||||
{
|
{
|
||||||
char *readbuf = NULL;
|
char *readbuf = NULL;
|
||||||
|
char *path;
|
||||||
|
|
||||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
if (!readbuf) {
|
if (!readbuf) {
|
||||||
warnx("Error: Not enough memory to allocate readbuffer");
|
warnx("Error: Not enough memory to allocate readbuffer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
path = util_path_sysfs("block/%s/dev", blockdev);
|
||||||
"/sys/block/%s/dev", blockdev) < 0)
|
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, path) < 0) {
|
||||||
|
free(path);
|
||||||
|
free(readbuf);
|
||||||
return -1;
|
return -1;
|
||||||
if (dinfo_extract_dev(dev, readbuf) != 0)
|
}
|
||||||
|
free(path);
|
||||||
|
if (dinfo_extract_dev(dev, readbuf) != 0) {
|
||||||
|
free(readbuf);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(readbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +387,7 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
|||||||
int tflag, struct FTW *ftwbuf)
|
int tflag, struct FTW *ftwbuf)
|
||||||
{
|
{
|
||||||
char *tempdir;
|
char *tempdir;
|
||||||
char linkdir[128];
|
char *linkdir;
|
||||||
ssize_t i;
|
|
||||||
|
|
||||||
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
|
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
|
||||||
strlen(searchbusid)) != 0))
|
strlen(searchbusid)) != 0))
|
||||||
@@ -387,14 +399,13 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
|
|||||||
*/
|
*/
|
||||||
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
|
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
i = readlink(tempdir, linkdir, 128);
|
linkdir = util_readlink(tempdir);
|
||||||
free(tempdir);
|
free(tempdir);
|
||||||
if ((i < 0) || (i >= 128))
|
if (strstr(linkdir, "dasd") == NULL) {
|
||||||
return -1;
|
free(linkdir);
|
||||||
/* append '\0' because readlink returns non zero terminated string */
|
|
||||||
tempdir[i + 1] = '\0';
|
|
||||||
if (strstr(linkdir, "dasd") == NULL)
|
|
||||||
return FTW_CONTINUE;
|
return FTW_CONTINUE;
|
||||||
|
}
|
||||||
|
free(linkdir);
|
||||||
free(busiddir);
|
free(busiddir);
|
||||||
busiddir = strdup(fpath);
|
busiddir = strdup(fpath);
|
||||||
if (busiddir == NULL)
|
if (busiddir == NULL)
|
||||||
@@ -439,7 +450,7 @@ dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
|
|||||||
|
|
||||||
char *tempdir = NULL;
|
char *tempdir = NULL;
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
char *sysfsdir = "/sys/devices/";
|
char *sysfsdir = util_path_sysfs("devices/");
|
||||||
|
|
||||||
/* dinfo_is_devnode needs to know the busid */
|
/* dinfo_is_devnode needs to know the busid */
|
||||||
searchbusid = busid;
|
searchbusid = busid;
|
||||||
@@ -475,6 +486,7 @@ out:
|
|||||||
out2:
|
out2:
|
||||||
free(busiddir);
|
free(busiddir);
|
||||||
free(result);
|
free(result);
|
||||||
|
free(sysfsdir);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,6 +498,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
|||||||
DIR *directory = NULL;
|
DIR *directory = NULL;
|
||||||
struct dirent *dir_entry = NULL;
|
struct dirent *dir_entry = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
char *path;
|
||||||
|
|
||||||
if (stat(devnode, &stat_buffer) != 0) {
|
if (stat(devnode, &stat_buffer) != 0) {
|
||||||
warnx("Error: could not stat %s", devnode);
|
warnx("Error: could not stat %s", devnode);
|
||||||
@@ -495,32 +508,34 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
|||||||
sprintf(stat_dev, "%d:%d", major(stat_buffer.st_rdev),
|
sprintf(stat_dev, "%d:%d", major(stat_buffer.st_rdev),
|
||||||
minor(stat_buffer.st_rdev));
|
minor(stat_buffer.st_rdev));
|
||||||
|
|
||||||
directory = opendir("/sys/block/");
|
path = util_path_sysfs("block/");
|
||||||
|
directory = opendir(path);
|
||||||
if (directory == NULL) {
|
if (directory == NULL) {
|
||||||
warnx("Error: could not open directory /sys/block");
|
warnx("Error: could not open directory %s", path);
|
||||||
|
free(path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
if (!readbuf) {
|
if (!readbuf) {
|
||||||
warnx("Error: Not enough memory to allocate readbuffer");
|
warnx("Error: Not enough memory to allocate readbuffer");
|
||||||
|
free(path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((dir_entry = readdir(directory)) != NULL) {
|
while ((dir_entry = readdir(directory)) != NULL) {
|
||||||
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
|
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, "%s%s/dev", path,
|
||||||
"/sys/block/%s/dev",
|
|
||||||
dir_entry->d_name) < 0)
|
dir_entry->d_name) < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(stat_dev, readbuf,
|
if (strncmp(stat_dev, readbuf,
|
||||||
MAX(strlen(stat_dev), strlen(readbuf) - 1)) == 0) {
|
MAX(strlen(stat_dev), strlen(readbuf) - 1)) == 0) {
|
||||||
rc = snprintf(*uidfile, RD_BUFFER_SIZE,
|
rc = snprintf(*uidfile, RD_BUFFER_SIZE, "%s%s/device/uid", path,
|
||||||
"/sys/block/%s/device/uid",
|
|
||||||
dir_entry->d_name);
|
dir_entry->d_name);
|
||||||
if (rc >= RD_BUFFER_SIZE) {
|
if (rc >= RD_BUFFER_SIZE) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: Device name was truncated\n");
|
"Error: Device name was truncated\n");
|
||||||
|
free(path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +544,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
closedir(directory);
|
closedir(directory);
|
||||||
|
free(path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,16 +642,18 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
|
if (!readbuf)
|
||||||
if (!(readbuf && uidfile))
|
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
/* try to read the uid attribute */
|
/* try to read the uid attribute */
|
||||||
if (busid) {
|
if (busid) {
|
||||||
sprintf(uidfile, "/sys/bus/ccw/devices/%s/uid", busid);
|
uidfile = util_path_sysfs("bus/ccw/devices/%s/uid", busid);
|
||||||
} else if (blockdev) {
|
} else if (blockdev) {
|
||||||
sprintf(uidfile, "/sys/block/%s/device/uid", blockdev);
|
uidfile = util_path_sysfs("block/%s/device/uid", blockdev);
|
||||||
} else if (devnode) {
|
} else if (devnode) {
|
||||||
|
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
|
||||||
|
if (!uidfile)
|
||||||
|
exit(1);
|
||||||
if (dinfo_get_uid_from_devnode(&uidfile, devnode) != 0)
|
if (dinfo_get_uid_from_devnode(&uidfile, devnode) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
* it under the terms of the MIT license. See LICENSE for details.
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _LARGEFILE64_SOURCE /* needed for unistd.h */
|
|
||||||
#define _FILE_OFFSET_BITS 64 /* needed for unistd.h */
|
#define _FILE_OFFSET_BITS 64 /* needed for unistd.h */
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -17,6 +16,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -428,7 +428,7 @@ dasdview_read_vlabel(dasdview_info_t *info, volume_label_t *vlabel)
|
|||||||
|
|
||||||
pos = info->dasd_info.label_block * info->blksize;
|
pos = info->dasd_info.label_block * info->blksize;
|
||||||
|
|
||||||
bzero(vlabel, sizeof(volume_label_t));
|
memset(vlabel, 0, sizeof(volume_label_t));
|
||||||
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
||||||
!info->dasd_info.FBA_layout) {
|
!info->dasd_info.FBA_layout) {
|
||||||
/* OS/390 and zOS compatible disk layout */
|
/* OS/390 and zOS compatible disk layout */
|
||||||
@@ -466,7 +466,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
printf("\n--- volume label -----------------------------"
|
printf("\n--- volume label -----------------------------"
|
||||||
"---------------------------------\n");
|
"---------------------------------\n");
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.volkey, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.volkey, 4);
|
||||||
printf("volume label key : ascii '%4s'\n", s4);
|
printf("volume label key : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -474,7 +476,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s4, 5); bzero(s4, 5); strncpy((char *)s4, vlabel.vollbl, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.vollbl, 4);
|
||||||
printf("\n\nvolume label identifier : ascii '%4s'\n", s4);
|
printf("\n\nvolume label identifier : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -482,7 +486,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s6, 7); bzero(t6, 7); strncpy((char *)s6, vlabel.volid, 6);
|
memset(s6, 0, 7);
|
||||||
|
memset(t6, 0, 7);
|
||||||
|
strncpy((char *)s6, vlabel.volid, 6);
|
||||||
printf("\n\nvolume identifier : ascii '%6s'\n", s6);
|
printf("\n\nvolume identifier : ascii '%6s'\n", s6);
|
||||||
vtoc_ebcdic_dec((char *)s6, (char *)t6, 6);
|
vtoc_ebcdic_dec((char *)s6, (char *)t6, 6);
|
||||||
printf(" : ebcdic '%6s'\n", t6);
|
printf(" : ebcdic '%6s'\n", t6);
|
||||||
@@ -503,7 +509,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
vtoc_get_cyl_from_cchhb(&vlabel.vtoc),
|
vtoc_get_cyl_from_cchhb(&vlabel.vtoc),
|
||||||
vtoc_get_head_from_cchhb(&vlabel.vtoc), vlabel.vtoc.b);
|
vtoc_get_head_from_cchhb(&vlabel.vtoc), vlabel.vtoc.b);
|
||||||
|
|
||||||
bzero(s5, 6); bzero(t5, 6); strncpy((char *)s5, vlabel.res1, 5);
|
memset(s5, 0, 6);
|
||||||
|
memset(t5, 0, 6);
|
||||||
|
strncpy((char *)s5, vlabel.res1, 5);
|
||||||
printf("reserved : ascii '%5s'\n", s5);
|
printf("reserved : ascii '%5s'\n", s5);
|
||||||
vtoc_ebcdic_dec((char *)s5, (char *)t5, 5);
|
vtoc_ebcdic_dec((char *)s5, (char *)t5, 5);
|
||||||
printf(" : ebcdic '%5s'\n", t5);
|
printf(" : ebcdic '%5s'\n", t5);
|
||||||
@@ -511,7 +519,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
printf("%02x", s5[i]);
|
printf("%02x", s5[i]);
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.cisize, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.cisize, 4);
|
||||||
printf("\n\nCI size for FBA : ascii '%4s'\n", s4);
|
printf("\n\nCI size for FBA : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -519,7 +529,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.blkperci, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.blkperci, 4);
|
||||||
printf("\n\nblocks per CI (FBA) : ascii '%4s'\n", s4);
|
printf("\n\nblocks per CI (FBA) : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -527,7 +539,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.labperci, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.labperci, 4);
|
||||||
printf("\n\nlabels per CI (FBA) : ascii '%4s'\n", s4);
|
printf("\n\nlabels per CI (FBA) : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -535,7 +549,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); strncpy((char *)s4, vlabel.res2, 4);
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
strncpy((char *)s4, vlabel.res2, 4);
|
||||||
printf("\n\nreserved : ascii '%4s'\n", s4);
|
printf("\n\nreserved : ascii '%4s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 4);
|
||||||
printf(" : ebcdic '%4s'\n", t4);
|
printf(" : ebcdic '%4s'\n", t4);
|
||||||
@@ -543,7 +559,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
printf("%02x", s4[i]);
|
printf("%02x", s4[i]);
|
||||||
|
|
||||||
bzero(s14, 15); bzero(t14, 15); strncpy(s14, vlabel.lvtoc, 14);
|
memset(s14, 0, 15);
|
||||||
|
memset(t14, 0, 15);
|
||||||
|
strncpy(s14, vlabel.lvtoc, 14);
|
||||||
printf("\n\nowner code for VTOC : ascii '%14s'\n", s14);
|
printf("\n\nowner code for VTOC : ascii '%14s'\n", s14);
|
||||||
vtoc_ebcdic_dec(s14, t14, 14);
|
vtoc_ebcdic_dec(s14, t14, 14);
|
||||||
printf(" ebcdic '%14s'\n", t14);
|
printf(" ebcdic '%14s'\n", t14);
|
||||||
@@ -556,9 +574,10 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
printf(" ");
|
printf(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(s29, 30); strncpy(s29, vlabel.res3, 28);
|
memset(s29, 0, 30);
|
||||||
|
strncpy(s29, vlabel.res3, 28);
|
||||||
printf("\n\nreserved : ascii '%28s'\n", s29);
|
printf("\n\nreserved : ascii '%28s'\n", s29);
|
||||||
bzero(t29, 30);
|
memset(t29, 0, 30);
|
||||||
vtoc_ebcdic_dec(s29, t29, 28);
|
vtoc_ebcdic_dec(s29, t29, 28);
|
||||||
printf(" ebcdic '%28s'\n", t29);
|
printf(" ebcdic '%28s'\n", t29);
|
||||||
printf(" hex ");
|
printf(" hex ");
|
||||||
@@ -573,7 +592,9 @@ dasdview_print_vlabel(dasdview_info_t *info)
|
|||||||
" ");
|
" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(s4, 5); bzero(t4, 5); s4[0] = vlabel.ldl_version;
|
memset(s4, 0, 5);
|
||||||
|
memset(t4, 0, 5);
|
||||||
|
s4[0] = vlabel.ldl_version;
|
||||||
printf("\n\nldl_version : ascii '%1s'\n", s4);
|
printf("\n\nldl_version : ascii '%1s'\n", s4);
|
||||||
vtoc_ebcdic_dec((char *)s4, (char *)t4, 1);
|
vtoc_ebcdic_dec((char *)s4, (char *)t4, 1);
|
||||||
printf(" : ebcdic '%1s'\n", t4);
|
printf(" : ebcdic '%1s'\n", t4);
|
||||||
@@ -609,8 +630,8 @@ dasdview_print_volser(dasdview_info_t *info)
|
|||||||
dasdview_read_vlabel(info, &vlabel);
|
dasdview_read_vlabel(info, &vlabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(vollbl, 5);
|
memset(vollbl, 0, 5);
|
||||||
bzero(volser, 7);
|
memset(volser, 0, 7);
|
||||||
strncpy(vollbl, vlabel.vollbl, 4);
|
strncpy(vollbl, vlabel.vollbl, 4);
|
||||||
vtoc_ebcdic_dec(vollbl, vollbl, 4);
|
vtoc_ebcdic_dec(vollbl, vollbl, 4);
|
||||||
|
|
||||||
@@ -631,12 +652,12 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
volume_label_t vlabel;
|
volume_label_t vlabel;
|
||||||
format1_label_t tmp;
|
format1_label_t tmp;
|
||||||
unsigned long maxblk, pos;
|
unsigned long maxblk, pos;
|
||||||
u_int64_t vtocblk;
|
uint64_t vtocblk;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pos = info->dasd_info.label_block * info->blksize;
|
pos = info->dasd_info.label_block * info->blksize;
|
||||||
|
|
||||||
bzero(&vlabel, sizeof(vlabel));
|
memset(&vlabel, 0, sizeof(vlabel));
|
||||||
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
|
||||||
!info->dasd_info.FBA_layout) {
|
!info->dasd_info.FBA_layout) {
|
||||||
/* OS/390 and zOS compatible disk layout */
|
/* OS/390 and zOS compatible disk layout */
|
||||||
@@ -648,7 +669,7 @@ dasdview_read_vtoc(dasdview_info_t *info)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
vtocblk = (u_int64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
vtocblk = (uint64_t)vtoc_get_cyl_from_cchhb(&vlabel.vtoc) *
|
||||||
info->geo.heads * info->geo.sectors +
|
info->geo.heads * info->geo.sectors +
|
||||||
vtoc_get_head_from_cchhb(&vlabel.vtoc) * info->geo.sectors +
|
vtoc_get_head_from_cchhb(&vlabel.vtoc) * info->geo.sectors +
|
||||||
vlabel.vtoc.b;
|
vlabel.vtoc.b;
|
||||||
@@ -747,13 +768,13 @@ static void dasdview_print_format1_8_short_info(format1_label_t *f1,
|
|||||||
char s6[7], s13[14], s44[45];
|
char s6[7], s13[14], s44[45];
|
||||||
unsigned long track_low, track_up;
|
unsigned long track_low, track_up;
|
||||||
|
|
||||||
bzero(s44, 45);
|
memset(s44, 0, 45);
|
||||||
strncpy(s44, f1->DS1DSNAM, 44);
|
strncpy(s44, f1->DS1DSNAM, 44);
|
||||||
vtoc_ebcdic_dec(s44, s44, 44);
|
vtoc_ebcdic_dec(s44, s44, 44);
|
||||||
bzero(s6, 7);
|
memset(s6, 0, 7);
|
||||||
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
||||||
vtoc_ebcdic_dec(s6, s6, 6);
|
vtoc_ebcdic_dec(s6, s6, 6);
|
||||||
bzero(s13, 14);
|
memset(s13, 0, 14);
|
||||||
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
||||||
vtoc_ebcdic_dec(s13, s13, 13);
|
vtoc_ebcdic_dec(s13, s13, 13);
|
||||||
|
|
||||||
@@ -837,13 +858,13 @@ static void dasdview_print_format1_8_short_info_raw(format1_label_t *f1,
|
|||||||
struct dscb *dscb;
|
struct dscb *dscb;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
bzero(s44, 45);
|
memset(s44, 0, 45);
|
||||||
strncpy(s44, f1->DS1DSNAM, 44);
|
strncpy(s44, f1->DS1DSNAM, 44);
|
||||||
vtoc_ebcdic_dec(s44, s44, 44);
|
vtoc_ebcdic_dec(s44, s44, 44);
|
||||||
bzero(s6, 7);
|
memset(s6, 0, 7);
|
||||||
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
strncpy(s6, (char *)f1->DS1DSSN, 6);
|
||||||
vtoc_ebcdic_dec(s6, s6, 6);
|
vtoc_ebcdic_dec(s6, s6, 6);
|
||||||
bzero(s13, 14);
|
memset(s13, 0, 14);
|
||||||
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
strncpy(s13, (char *)f1->DS1SYSCD, 13);
|
||||||
vtoc_ebcdic_dec(s13, s13, 13);
|
vtoc_ebcdic_dec(s13, s13, 13);
|
||||||
|
|
||||||
@@ -1071,7 +1092,7 @@ static void dasdview_print_vtoc_info_raw(dasdview_info_t *info)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: the explicit cylinder/head conversion for large volume
|
* Note: the explicit cylinder/head conversion for large volume
|
||||||
* adresses should not be necessary for entries that point to
|
* addresses should not be necessary for entries that point to
|
||||||
* vtoc labels, as those must be located in the first 65K-1 tracks,
|
* vtoc labels, as those must be located in the first 65K-1 tracks,
|
||||||
* but we do it anyway to be on the safe side.
|
* but we do it anyway to be on the safe side.
|
||||||
*/
|
*/
|
||||||
@@ -1080,9 +1101,9 @@ static void dasdview_print_format1_8_no_head(format1_label_t *f1)
|
|||||||
char s6[7], s13[14], s44[45];
|
char s6[7], s13[14], s44[45];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bzero(s6, 7);
|
memset(s6, 0, 7);
|
||||||
bzero(s13, 14);
|
memset(s13, 0, 14);
|
||||||
bzero(s44, 45);
|
memset(s44, 0, 45);
|
||||||
|
|
||||||
strncpy(s44, f1->DS1DSNAM, 44);
|
strncpy(s44, f1->DS1DSNAM, 44);
|
||||||
printf("DS1DSNAM : ascii '%44s'\n", s44);
|
printf("DS1DSNAM : ascii '%44s'\n", s44);
|
||||||
@@ -1865,7 +1886,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
|
|
||||||
/* seek in SEEK_STEP steps */
|
/* seek in SEEK_STEP steps */
|
||||||
for (i = 1; i <= j; i++) {
|
for (i = 1; i <= j; i++) {
|
||||||
rc = lseek64(fd, SEEK_STEP, SEEK_CUR);
|
rc = lseek(fd, SEEK_STEP, SEEK_CUR);
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
printf("*** rc: %d (%d) ***\n", rc, errno);
|
printf("*** rc: %d (%d) ***\n", rc, errno);
|
||||||
printf("*** j: %llu ***\n", j);
|
printf("*** j: %llu ***\n", j);
|
||||||
@@ -1918,7 +1939,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
|
|
||||||
count = info->begin;
|
count = info->begin;
|
||||||
for (i = 1; i <= j; i++) {
|
for (i = 1; i <= j; i++) {
|
||||||
bzero(dumpstr, DUMP_STRING_SIZE);
|
memset(dumpstr, 0, DUMP_STRING_SIZE);
|
||||||
rc = read(fd, &dumpstr, DUMP_STRING_SIZE);
|
rc = read(fd, &dumpstr, DUMP_STRING_SIZE);
|
||||||
if (rc != DUMP_STRING_SIZE) {
|
if (rc != DUMP_STRING_SIZE) {
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -1937,7 +1958,7 @@ static void dasdview_view_standard(dasdview_info_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k > 0) {
|
if (k > 0) {
|
||||||
bzero(dumpstr, DUMP_STRING_SIZE);
|
memset(dumpstr, 0, DUMP_STRING_SIZE);
|
||||||
rc = read(fd, &dumpstr, k);
|
rc = read(fd, &dumpstr, k);
|
||||||
if (rc != (int)k) {
|
if (rc != (int)k) {
|
||||||
close(fd);
|
close(fd);
|
||||||
@@ -1976,8 +1997,8 @@ static void dasdview_print_format_raw(unsigned int size, char *dumpstr)
|
|||||||
while (residual) {
|
while (residual) {
|
||||||
/* we handle at most 16 bytes per line */
|
/* we handle at most 16 bytes per line */
|
||||||
count = MIN(residual, 16u);
|
count = MIN(residual, 16u);
|
||||||
bzero(asc, 17);
|
memset(asc, 0, 17);
|
||||||
bzero(ebc, 17);
|
memset(ebc, 0, 17);
|
||||||
printf("|");
|
printf("|");
|
||||||
memcpy(asc, data, count);
|
memcpy(asc, data, count);
|
||||||
memcpy(ebc, data, count);
|
memcpy(ebc, data, count);
|
||||||
@@ -2066,7 +2087,7 @@ static void dasdview_print_raw_track(char *trackdata,
|
|||||||
{
|
{
|
||||||
struct eckd_count *ecount;
|
struct eckd_count *ecount;
|
||||||
char *data;
|
char *data;
|
||||||
u_int32_t record;
|
uint32_t record;
|
||||||
|
|
||||||
record = 0;
|
record = 0;
|
||||||
data = trackdata;
|
data = trackdata;
|
||||||
@@ -2091,8 +2112,8 @@ static void dasdview_print_raw_track(char *trackdata,
|
|||||||
|
|
||||||
static void dasdview_view_raw(dasdview_info_t *info)
|
static void dasdview_view_raw(dasdview_info_t *info)
|
||||||
{
|
{
|
||||||
u_int64_t residual, trckstart, trckend, track, trckbuffsize;
|
uint64_t residual, trckstart, trckend, track, trckbuffsize;
|
||||||
u_int64_t tracks_to_read, trckcount, i;
|
uint64_t tracks_to_read, trckcount, i;
|
||||||
char *trackdata;
|
char *trackdata;
|
||||||
char *data;
|
char *data;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -2187,7 +2208,7 @@ int main(int argc, char *argv[])
|
|||||||
util_prg_init(&prg);
|
util_prg_init(&prg);
|
||||||
util_opt_init(opt_vec, NULL);
|
util_opt_init(opt_vec, NULL);
|
||||||
|
|
||||||
bzero(&info, sizeof(info));
|
memset(&info, 0, sizeof(info));
|
||||||
while (1) {
|
while (1) {
|
||||||
oc = util_opt_getopt_long(argc, argv);
|
oc = util_opt_getopt_long(argc, argv);
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#define DASDVIEW_H
|
#define DASDVIEW_H
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
* SECTION: Definitions needed for DASD-API (see dasd.h)
|
* SECTION: Definitions needed for DASD-API (see dasd.h)
|
||||||
@@ -68,7 +69,7 @@ typedef struct dasdview_info
|
|||||||
int dasd_info_version;
|
int dasd_info_version;
|
||||||
unsigned int blksize;
|
unsigned int blksize;
|
||||||
struct hd_geometry geo;
|
struct hd_geometry geo;
|
||||||
u_int32_t hw_cylinders;
|
uint32_t hw_cylinders;
|
||||||
|
|
||||||
unsigned long long begin;
|
unsigned long long begin;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
. ds pfont \\n[.f]
|
. ds pfont \\n[.f]
|
||||||
. nh
|
. nh
|
||||||
. na
|
. na
|
||||||
. ft CW
|
. ft CR
|
||||||
\\$*
|
\\$*
|
||||||
. ft \\*[pfont]
|
. ft \\*[pfont]
|
||||||
. ad
|
. ad
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
#include "dref.h"
|
#include "dref.h"
|
||||||
#include "dump.h"
|
#include "dump.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "idcache.h"
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
|
|
||||||
@@ -656,16 +655,18 @@ static int read_symlink(struct task *task, const char *filename,
|
|||||||
task->opts->read_chunk_size;
|
task->opts->read_chunk_size;
|
||||||
int rc = EXIT_OK;
|
int rc = EXIT_OK;
|
||||||
|
|
||||||
|
/* If @relname is NULL, use @filename with AT_FDCWD. */
|
||||||
|
if (!relname) {
|
||||||
|
relname = filename;
|
||||||
|
dirfd = AT_FDCWD;
|
||||||
|
}
|
||||||
|
|
||||||
while (!is_aborted(task)) {
|
while (!is_aborted(task)) {
|
||||||
buffer_make_room(buffer, currlen, false,
|
buffer_make_room(buffer, currlen, false,
|
||||||
task->opts->max_buffer_size);
|
task->opts->max_buffer_size);
|
||||||
|
|
||||||
cancel_enable();
|
cancel_enable();
|
||||||
if (relname)
|
actual = readlinkat(dirfd, relname, buffer->addr, buffer->size);
|
||||||
actual = readlinkat(dirfd, relname, buffer->addr,
|
|
||||||
buffer->size);
|
|
||||||
else
|
|
||||||
actual = readlink(filename, buffer->addr, buffer->size);
|
|
||||||
cancel_disable();
|
cancel_disable();
|
||||||
|
|
||||||
if (actual == -1) {
|
if (actual == -1) {
|
||||||
|
|||||||
@@ -1,2 +1,7 @@
|
|||||||
# Load protected key support module on s390 early at boot
|
# Load protected key support module on s390 early at boot
|
||||||
pkey
|
pkey
|
||||||
|
pkey_pckmo
|
||||||
|
pkey_ep11
|
||||||
|
pkey_cca
|
||||||
|
paes_s390
|
||||||
|
phmac_s390
|
||||||
|
|||||||
@@ -18,3 +18,17 @@ CPI_SYSTEM_NAME=""
|
|||||||
# CPI sysplex name
|
# CPI sysplex name
|
||||||
#
|
#
|
||||||
CPI_SYSPLEX_NAME=""
|
CPI_SYSPLEX_NAME=""
|
||||||
|
|
||||||
|
#
|
||||||
|
# CPI permit on protected virtualization guests
|
||||||
|
#
|
||||||
|
# Important: Set CPI_PERMIT_ON_PVGUEST=1 only if you trust the host system.
|
||||||
|
# Enabling these options allows the host to receive potentially sensitive
|
||||||
|
# Control-Program Identification (CPI) data from the protected virtualization
|
||||||
|
# guest, including:
|
||||||
|
# - system_type
|
||||||
|
# - system_level
|
||||||
|
# - sysplex_name
|
||||||
|
# - system_name
|
||||||
|
#
|
||||||
|
CPI_PERMIT_ON_PVGUEST=
|
||||||
|
|||||||
2
etc/udev/rules.d/59-virtio-blk.rules
Normal file
2
etc/udev/rules.d/59-virtio-blk.rules
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
SUBSYSTEM=="block", ACTION=="add", KERNEL=="vd*[!0-9]", TEST=="queue/rotational", ATTR{queue/rotational}="0"
|
||||||
|
SUBSYSTEM=="block", ACTION=="add", KERNEL=="vd*[!0-9]", TEST=="queue/scheduler", ATTR{queue/scheduler}="none"
|
||||||
4
etc/udev/rules.d/80-hotplug-cpu.rules
Normal file
4
etc/udev/rules.d/80-hotplug-cpu.rules
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
# Rules to set online a newly hotplugged cpu on s390x
|
||||||
|
#
|
||||||
|
SUBSYSTEM=="cpu", ACTION=="add", CONST{arch}=="s390*", ATTR{configure}=="1", TEST=="online", ATTR{online}!="1", ATTR{online}="1"
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
@@ -211,9 +212,9 @@ static void setpos(fdasd_anchor_t *anc, int dsn, int pos)
|
|||||||
anc->partno[dsn] = pos;
|
anc->partno[dsn] = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
static uint32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
||||||
{
|
{
|
||||||
u_int32_t cyl;
|
uint32_t cyl;
|
||||||
|
|
||||||
/* large volume */
|
/* large volume */
|
||||||
if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
|
if (anc->f4->DS4DEVCT.DS4DSCYL == LV_COMPAT_CYL &&
|
||||||
@@ -221,7 +222,7 @@ static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
|||||||
return anc->f4->DS4DCYL;
|
return anc->f4->DS4DCYL;
|
||||||
/* normal volume */
|
/* normal volume */
|
||||||
if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
|
if (anc->f4->DS4DEVCT.DS4DEVFG & ALTERNATE_CYLINDERS_USED)
|
||||||
cyl = anc->f4->DS4DEVCT.DS4DSCYL - (u_int16_t)anc->f4->DS4DEVAC;
|
cyl = anc->f4->DS4DEVCT.DS4DSCYL - (uint16_t)anc->f4->DS4DEVAC;
|
||||||
else
|
else
|
||||||
cyl = anc->f4->DS4DEVCT.DS4DSCYL;
|
cyl = anc->f4->DS4DEVCT.DS4DSCYL;
|
||||||
|
|
||||||
@@ -230,7 +231,7 @@ static u_int32_t get_usable_cylinders(fdasd_anchor_t *anc)
|
|||||||
|
|
||||||
static void get_addr_of_highest_f1_f8_label(fdasd_anchor_t *anc, cchhb_t *addr)
|
static void get_addr_of_highest_f1_f8_label(fdasd_anchor_t *anc, cchhb_t *addr)
|
||||||
{
|
{
|
||||||
u_int8_t record;
|
uint8_t record;
|
||||||
/* We have to count the following labels:
|
/* We have to count the following labels:
|
||||||
* one format 4
|
* one format 4
|
||||||
* one format 5
|
* one format 5
|
||||||
@@ -406,7 +407,7 @@ static void fdasd_error(fdasd_anchor_t *anc, enum fdasd_failure why, char *str)
|
|||||||
*/
|
*/
|
||||||
static int read_line(void)
|
static int read_line(void)
|
||||||
{
|
{
|
||||||
bzero(line_buffer, LINE_LENGTH);
|
memset(line_buffer, 0, LINE_LENGTH);
|
||||||
line_ptr = line_buffer;
|
line_ptr = line_buffer;
|
||||||
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
|
if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
|
||||||
clearerr(stdin);
|
clearerr(stdin);
|
||||||
@@ -493,7 +494,7 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
|||||||
volume_label_t *vlabel;
|
volume_label_t *vlabel;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bzero(anc, sizeof(fdasd_anchor_t));
|
memset(anc, 0, sizeof(fdasd_anchor_t));
|
||||||
|
|
||||||
for (i = 0; i < USABLE_PARTITIONS; i++)
|
for (i = 0; i < USABLE_PARTITIONS; i++)
|
||||||
setpos(anc, i, -1);
|
setpos(anc, i, -1);
|
||||||
@@ -519,17 +520,17 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
|||||||
fdasd_error(anc, malloc_failed,
|
fdasd_error(anc, malloc_failed,
|
||||||
"FMT9 DSCB memory allocation failed.");
|
"FMT9 DSCB memory allocation failed.");
|
||||||
|
|
||||||
bzero(anc->f4, sizeof(format4_label_t));
|
memset(anc->f4, 0, sizeof(format4_label_t));
|
||||||
bzero(anc->f5, sizeof(format5_label_t));
|
memset(anc->f5, 0, sizeof(format5_label_t));
|
||||||
bzero(anc->f7, sizeof(format7_label_t));
|
memset(anc->f7, 0, sizeof(format7_label_t));
|
||||||
bzero(anc->f9, sizeof(format9_label_t));
|
memset(anc->f9, 0, sizeof(format9_label_t));
|
||||||
vtoc_init_format9_label(anc->f9);
|
vtoc_init_format9_label(anc->f9);
|
||||||
|
|
||||||
vlabel = malloc(sizeof(volume_label_t));
|
vlabel = malloc(sizeof(volume_label_t));
|
||||||
if (vlabel == NULL)
|
if (vlabel == NULL)
|
||||||
fdasd_error(anc, malloc_failed,
|
fdasd_error(anc, malloc_failed,
|
||||||
"Volume label memory allocation failed.");
|
"Volume label memory allocation failed.");
|
||||||
bzero(vlabel, sizeof(volume_label_t));
|
memset(vlabel, 0, sizeof(volume_label_t));
|
||||||
anc->vlabel = vlabel;
|
anc->vlabel = vlabel;
|
||||||
|
|
||||||
for (i = 1; i <= USABLE_PARTITIONS; i++) {
|
for (i = 1; i <= USABLE_PARTITIONS; i++) {
|
||||||
@@ -551,7 +552,7 @@ static void fdasd_initialize_anchor(fdasd_anchor_t *anc)
|
|||||||
if (part_info->f1 == NULL)
|
if (part_info->f1 == NULL)
|
||||||
fdasd_error(anc, malloc_failed,
|
fdasd_error(anc, malloc_failed,
|
||||||
"FMT1 DSCB memory allocation failed.");
|
"FMT1 DSCB memory allocation failed.");
|
||||||
bzero(part_info->f1, sizeof(format1_label_t));
|
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||||
|
|
||||||
if (prev_part_info) {
|
if (prev_part_info) {
|
||||||
prev_part_info->next = part_info;
|
prev_part_info->next = part_info;
|
||||||
@@ -975,7 +976,7 @@ static void fdasd_verify_device(fdasd_anchor_t *anc, char *name)
|
|||||||
* Note:
|
* Note:
|
||||||
* - 'version' and 'help' are priority options.
|
* - 'version' and 'help' are priority options.
|
||||||
* All other parameters are ignored in that case.
|
* All other parameters are ignored in that case.
|
||||||
* - 'silent' and 'verbose' are allways allowed in any
|
* - 'silent' and 'verbose' are always allowed in any
|
||||||
* combination.
|
* combination.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -1052,10 +1053,10 @@ static void fdasd_show_mapping(fdasd_anchor_t *anc)
|
|||||||
int i = 0, j = 0, dev_len;
|
int i = 0, j = 0, dev_len;
|
||||||
|
|
||||||
printf("\ndevice .........: %s\n", options.device);
|
printf("\ndevice .........: %s\n", options.device);
|
||||||
bzero(str, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
vtoc_volume_label_get_label(anc->vlabel, str);
|
vtoc_volume_label_get_label(anc->vlabel, str);
|
||||||
printf("volume label ...: %.4s\n", str);
|
printf("volume label ...: %.4s\n", str);
|
||||||
bzero(str, sizeof(str));
|
memset(str, 0, sizeof(str));
|
||||||
vtoc_volume_label_get_volser(anc->vlabel, str);
|
vtoc_volume_label_get_volser(anc->vlabel, str);
|
||||||
printf("volume serial ..: %s\n\n", str);
|
printf("volume serial ..: %s\n\n", str);
|
||||||
|
|
||||||
@@ -1080,7 +1081,7 @@ static void fdasd_show_mapping(fdasd_anchor_t *anc)
|
|||||||
if (part_info->used != 0x01)
|
if (part_info->used != 0x01)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bzero(dsname, sizeof(dsname));
|
memset(dsname, 0, sizeof(dsname));
|
||||||
strncpy(dsname, part_info->f1->DS1DSNAM, 44);
|
strncpy(dsname, part_info->f1->DS1DSNAM, 44);
|
||||||
vtoc_ebcdic_dec(dsname, dsname, 44);
|
vtoc_ebcdic_dec(dsname, dsname, 44);
|
||||||
|
|
||||||
@@ -1103,7 +1104,7 @@ static void fdasd_print_volser(fdasd_anchor_t *anc)
|
|||||||
{
|
{
|
||||||
char volser[VOLSER_LENGTH + 1];
|
char volser[VOLSER_LENGTH + 1];
|
||||||
|
|
||||||
bzero(volser, VOLSER_LENGTH);
|
memset(volser, 0, VOLSER_LENGTH);
|
||||||
vtoc_ebcdic_dec(anc->vlabel->volid, volser, VOLSER_LENGTH);
|
vtoc_ebcdic_dec(anc->vlabel->volid, volser, VOLSER_LENGTH);
|
||||||
printf("%6.6s\n", volser);
|
printf("%6.6s\n", volser);
|
||||||
}
|
}
|
||||||
@@ -1372,7 +1373,7 @@ static void fdasd_write_vtoc_labels(fdasd_anchor_t *anc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* write empty labels to the rest of the blocks */
|
/* write empty labels to the rest of the blocks */
|
||||||
bzero(&emptyf1, sizeof(emptyf1));
|
memset(&emptyf1, 0, sizeof(emptyf1));
|
||||||
while (blk < maxblk) {
|
while (blk < maxblk) {
|
||||||
vtoc_write_label(options.device, blk, &emptyf1, NULL,
|
vtoc_write_label(options.device, blk, &emptyf1, NULL,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
@@ -1425,7 +1426,7 @@ static void fdasd_recreate_vtoc_unconditional(fdasd_anchor_t *anc)
|
|||||||
anc->formatted_cylinders, geo.heads);
|
anc->formatted_cylinders, geo.heads);
|
||||||
|
|
||||||
while (part_info != NULL) {
|
while (part_info != NULL) {
|
||||||
bzero(part_info->f1, sizeof(format1_label_t));
|
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||||
|
|
||||||
if (part_info->used == 0x01) {
|
if (part_info->used == 0x01) {
|
||||||
part_info->used = 0x00;
|
part_info->used = 0x00;
|
||||||
@@ -1826,7 +1827,7 @@ static void fdasd_process_valid_vtoc(fdasd_anchor_t *anc, unsigned long blk)
|
|||||||
|
|
||||||
/* go through remaining labels, f4 label already done */
|
/* go through remaining labels, f4 label already done */
|
||||||
for (i = 1; i < geo.sectors; i++) {
|
for (i = 1; i < geo.sectors; i++) {
|
||||||
bzero(&f1_label, f1_size);
|
memset(&f1_label, 0, f1_size);
|
||||||
vtoc_read_label(options.device, blk, &f1_label, NULL, NULL,
|
vtoc_read_label(options.device, blk, &f1_label, NULL, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
@@ -2470,9 +2471,9 @@ static int fdasd_get_partition_data(fdasd_anchor_t *anc, extent_t *part_extent,
|
|||||||
unsigned long start, stop, limit;
|
unsigned long start, stop, limit;
|
||||||
partition_info_t *part_tmp;
|
partition_info_t *part_tmp;
|
||||||
cchh_t llimit, ulimit;
|
cchh_t llimit, ulimit;
|
||||||
u_int16_t hh, head;
|
uint16_t hh, head;
|
||||||
u_int32_t cc, cyl;
|
uint32_t cc, cyl;
|
||||||
u_int8_t b1, b2;
|
uint8_t b1, b2;
|
||||||
char mesg[48];
|
char mesg[48];
|
||||||
|
|
||||||
start = FIRST_USABLE_TRK;
|
start = FIRST_USABLE_TRK;
|
||||||
@@ -2675,7 +2676,7 @@ static void fdasd_dequeue_old_partition(fdasd_anchor_t *anc,
|
|||||||
part_info->start_trk = 0x0;
|
part_info->start_trk = 0x0;
|
||||||
part_info->end_trk = 0x0;
|
part_info->end_trk = 0x0;
|
||||||
part_info->fspace_trk = 0x0;
|
part_info->fspace_trk = 0x0;
|
||||||
bzero(part_info->f1, sizeof(format1_label_t));
|
memset(part_info->f1, 0, sizeof(format1_label_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2758,7 +2759,7 @@ static void fdasd_remove_partition(fdasd_anchor_t *anc)
|
|||||||
if (anc->used_partitions != 0)
|
if (anc->used_partitions != 0)
|
||||||
get_addr_of_highest_f1_f8_label(anc, &hf1);
|
get_addr_of_highest_f1_f8_label(anc, &hf1);
|
||||||
else
|
else
|
||||||
bzero(&hf1, sizeof(struct cchhb));
|
memset(&hf1, 0, sizeof(struct cchhb));
|
||||||
|
|
||||||
vtoc_update_format4_label(anc->f4, &hf1, anc->f4->DS4DSREC + 1);
|
vtoc_update_format4_label(anc->f4, &hf1, anc->f4->DS4DSREC + 1);
|
||||||
vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose,
|
vtoc_set_freespace(anc->f4, anc->f5, anc->f7, '+', anc->verbose,
|
||||||
@@ -2777,8 +2778,8 @@ static void fdasd_auto_partition(fdasd_anchor_t *anc)
|
|||||||
{
|
{
|
||||||
partition_info_t *part_info = anc->first;
|
partition_info_t *part_info = anc->first;
|
||||||
cchh_t llimit, ulimit;
|
cchh_t llimit, ulimit;
|
||||||
u_int16_t head;
|
uint16_t head;
|
||||||
u_int32_t cyl;
|
uint32_t cyl;
|
||||||
extent_t ext;
|
extent_t ext;
|
||||||
cchhb_t hf1;
|
cchhb_t hf1;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#ifndef FDASD_H
|
#ifndef FDASD_H
|
||||||
#define FDASD_H
|
#define FDASD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* SECTION: Definitions needed for DASD-API (see dasd.h) *
|
* SECTION: Definitions needed for DASD-API (see dasd.h) *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@@ -67,7 +69,7 @@ static struct fdasd_options options = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct partition_info {
|
typedef struct partition_info {
|
||||||
u_int8_t used;
|
uint8_t used;
|
||||||
unsigned long start_trk;
|
unsigned long start_trk;
|
||||||
unsigned long end_trk;
|
unsigned long end_trk;
|
||||||
unsigned long len_trk;
|
unsigned long len_trk;
|
||||||
@@ -100,7 +102,7 @@ typedef struct fdasd_anchor {
|
|||||||
int option_reuse;
|
int option_reuse;
|
||||||
int option_recreate;
|
int option_recreate;
|
||||||
int partno[USABLE_PARTITIONS];
|
int partno[USABLE_PARTITIONS];
|
||||||
u_int16_t dev_type;
|
uint16_t dev_type;
|
||||||
unsigned int used_partitions;
|
unsigned int used_partitions;
|
||||||
unsigned long label_pos;
|
unsigned long label_pos;
|
||||||
unsigned int blksize;
|
unsigned int blksize;
|
||||||
@@ -113,8 +115,8 @@ typedef struct fdasd_anchor {
|
|||||||
partition_info_t *last;
|
partition_info_t *last;
|
||||||
volume_label_t *vlabel;
|
volume_label_t *vlabel;
|
||||||
config_data_t confdata[USABLE_PARTITIONS];
|
config_data_t confdata[USABLE_PARTITIONS];
|
||||||
u_int32_t hw_cylinders;
|
uint32_t hw_cylinders;
|
||||||
u_int32_t formatted_cylinders;
|
uint32_t formatted_cylinders;
|
||||||
} fdasd_anchor_t;
|
} fdasd_anchor_t;
|
||||||
|
|
||||||
enum offset {lower, upper};
|
enum offset {lower, upper};
|
||||||
|
|||||||
@@ -365,6 +365,13 @@ function add_hsci {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#### Set MTU for the veth pair
|
||||||
|
ndev_mtu="$(cat /sys/class/net/${ndev}/mtu)"
|
||||||
|
hsdev_mtu="$(cat /sys/class/net/${hsdev}/mtu)"
|
||||||
|
hsci_mtu=$(( ndev_mtu < hsdev_mtu ? ndev_mtu : hsdev_mtu ))
|
||||||
|
ip link set dev $hscibp mtu $hsci_mtu
|
||||||
|
ip link set dev $hsci mtu $hsci_mtu
|
||||||
|
|
||||||
#### Set veth pair to UP
|
#### Set veth pair to UP
|
||||||
ip link set dev $hscibp up >/dev/null 2>&1
|
ip link set dev $hscibp up >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
#define DBFS_WAIT_TIME_US 10000
|
#define DBFS_WAIT_TIME_US 10000
|
||||||
|
|
||||||
extern int dg_debugfs_init(int exit_on_err);
|
int dg_debugfs_init(int exit_on_err);
|
||||||
extern int dg_debugfs_vm_init(void);
|
int dg_debugfs_vm_init(void);
|
||||||
extern int dg_debugfs_lpar_init(void);
|
int dg_debugfs_lpar_init(void);
|
||||||
extern int dg_debugfs_open(const char *file);
|
int dg_debugfs_open(const char *file);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* z/VM diag 0C prototypes
|
* z/VM diag 0C prototypes
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define CPU_TYPE_LEN 16
|
#define CPU_TYPE_LEN 16
|
||||||
#define DEBUGFS_FILE "diag_204"
|
#define DEBUGFS_FILE "diag_204"
|
||||||
|
|
||||||
|
static struct sd_sys *l_cur_lpar;
|
||||||
static u64 l_update_time_us;
|
static u64 l_update_time_us;
|
||||||
static long l_204_buf_size;
|
static long l_204_buf_size;
|
||||||
|
|
||||||
@@ -36,7 +37,8 @@ static long l_204_buf_size;
|
|||||||
struct l_x_info_blk_hdr {
|
struct l_x_info_blk_hdr {
|
||||||
u8 npar;
|
u8 npar;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 reserved1[6];
|
u8 reserved1[4];
|
||||||
|
u16 this_part;
|
||||||
u64 curtod1;
|
u64 curtod1;
|
||||||
u64 curtod2;
|
u64 curtod2;
|
||||||
u8 reserved[40];
|
u8 reserved[40];
|
||||||
@@ -158,6 +160,21 @@ static void *l_sd_sys_fill(struct sd_sys *lpar, struct l_x_sys_hdr *sys_hdr)
|
|||||||
return cpu_info;
|
return cpu_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the time delta between samples using current partition's
|
||||||
|
* online time.
|
||||||
|
*/
|
||||||
|
static u64 l_sd_cur_lpar_delta_time_get(void)
|
||||||
|
{
|
||||||
|
struct sd_cpu *cpu;
|
||||||
|
|
||||||
|
cpu = sd_cpu_get(l_cur_lpar, "0");
|
||||||
|
if (!cpu->d_prev || !cpu->d_cur)
|
||||||
|
return 0;
|
||||||
|
return l_sub_64(cpu->d_cur->online_time_us,
|
||||||
|
cpu->d_prev->online_time_us);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill one physical CPU with data
|
* Fill one physical CPU with data
|
||||||
*/
|
*/
|
||||||
@@ -241,9 +258,9 @@ static void l_read_debugfs(struct l_debugfs_d204_hdr **hdr,
|
|||||||
*/
|
*/
|
||||||
static void l_sd_sys_root_fill(struct sd_sys *sys)
|
static void l_sd_sys_root_fill(struct sd_sys *sys)
|
||||||
{
|
{
|
||||||
|
struct l_x_sys_hdr *sys_hdr, *this_part;
|
||||||
struct l_x_info_blk_hdr *time_hdr;
|
struct l_x_info_blk_hdr *time_hdr;
|
||||||
struct l_debugfs_d204_hdr *hdr;
|
struct l_debugfs_d204_hdr *hdr;
|
||||||
struct l_x_sys_hdr *sys_hdr;
|
|
||||||
struct sd_sys *lpar;
|
struct sd_sys *lpar;
|
||||||
char lpar_id[10];
|
char lpar_id[10];
|
||||||
int i;
|
int i;
|
||||||
@@ -262,18 +279,23 @@ static void l_sd_sys_root_fill(struct sd_sys *sys)
|
|||||||
usleep(DBFS_WAIT_TIME_US);
|
usleep(DBFS_WAIT_TIME_US);
|
||||||
} while (1);
|
} while (1);
|
||||||
sys_hdr = ((void *) time_hdr) + sizeof(struct l_x_info_blk_hdr);
|
sys_hdr = ((void *) time_hdr) + sizeof(struct l_x_info_blk_hdr);
|
||||||
|
this_part = ((void *)time_hdr) + time_hdr->this_part;
|
||||||
for (i = 0; i < time_hdr->npar; i++) {
|
for (i = 0; i < time_hdr->npar; i++) {
|
||||||
l_sys_hdr__sys_name(sys_hdr, lpar_id);
|
l_sys_hdr__sys_name(sys_hdr, lpar_id);
|
||||||
lpar = sd_sys_get(sys, lpar_id);
|
lpar = sd_sys_get(sys, lpar_id);
|
||||||
if (!lpar)
|
if (!lpar)
|
||||||
lpar = sd_sys_new(sys, lpar_id);
|
lpar = sd_sys_new(sys, lpar_id);
|
||||||
|
if (sys_hdr == this_part)
|
||||||
|
l_cur_lpar = lpar;
|
||||||
lpar->threads_per_core = l_thread_cnt(sys_hdr);
|
lpar->threads_per_core = l_thread_cnt(sys_hdr);
|
||||||
sys_hdr = l_sd_sys_fill(lpar, sys_hdr);
|
sys_hdr = l_sd_sys_fill(lpar, sys_hdr);
|
||||||
sd_sys_commit(lpar);
|
sd_sys_commit(lpar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (time_hdr->flags & LPAR_PHYS_FLG)
|
if (time_hdr->flags & LPAR_PHYS_FLG) {
|
||||||
l_sd_sys_root_cpu_phys_fill(sys, (void *) sys_hdr);
|
l_sd_sys_root_cpu_phys_fill(sys, (void *) sys_hdr);
|
||||||
|
sd_phys_delta_time_us_set(sys, l_sd_cur_lpar_delta_time_get());
|
||||||
|
}
|
||||||
ht_free(hdr);
|
ht_free(hdr);
|
||||||
sd_sys_commit(sys);
|
sd_sys_commit(sys);
|
||||||
}
|
}
|
||||||
@@ -290,6 +312,16 @@ static void l_sd_update(void)
|
|||||||
sd_sys_update_end(root, l_update_time_us);
|
sd_sys_update_end(root, l_update_time_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported physical information items
|
||||||
|
*/
|
||||||
|
static struct sd_sys_item *l_phys_item_vec[] = {
|
||||||
|
&sd_sys_item_core_cnt,
|
||||||
|
&sd_sys_item_phys_mgm_diff,
|
||||||
|
&sd_sys_item_mgm,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Supported system items
|
* Supported system items
|
||||||
*/
|
*/
|
||||||
@@ -364,6 +396,7 @@ static struct sd_cpu_type *l_cpu_type_vec[] = {
|
|||||||
static struct sd_dg l_sd_dg = {
|
static struct sd_dg l_sd_dg = {
|
||||||
.update_sys = l_sd_update,
|
.update_sys = l_sd_update,
|
||||||
.cpu_type_vec = l_cpu_type_vec,
|
.cpu_type_vec = l_cpu_type_vec,
|
||||||
|
.phys_item_vec = l_phys_item_vec,
|
||||||
.sys_item_vec = l_sys_item_vec,
|
.sys_item_vec = l_sys_item_vec,
|
||||||
.sys_item_enable_vec = l_sys_item_enable_vec,
|
.sys_item_enable_vec = l_sys_item_enable_vec,
|
||||||
.cpu_item_vec = l_cpu_item_vec,
|
.cpu_item_vec = l_cpu_item_vec,
|
||||||
@@ -383,6 +416,6 @@ int dg_debugfs_lpar_init(void)
|
|||||||
return fh;
|
return fh;
|
||||||
else
|
else
|
||||||
close(fh);
|
close(fh);
|
||||||
sd_dg_register(&l_sd_dg, 1);
|
sd_dg_register(&l_sd_dg, 1, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,6 +358,6 @@ int dg_debugfs_vm_init(void)
|
|||||||
close(fh);
|
close(fh);
|
||||||
l_2fc_buf_size = sizeof(struct l_debugfs_d2fc_hdr);
|
l_2fc_buf_size = sizeof(struct l_debugfs_d2fc_hdr);
|
||||||
l_guest_name_init();
|
l_guest_name_init();
|
||||||
sd_dg_register(&dg_debugfs_vm_dg, 0);
|
sd_dg_register(&dg_debugfs_vm_dg, 0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <mntent.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,6 +24,10 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef _PATH_MOUNTED
|
||||||
|
#define _PATH_MOUNTED "/etc/mtab"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "lib/util_fmt.h"
|
#include "lib/util_fmt.h"
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "lib/util_base.h"
|
#include "lib/util_base.h"
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
|
#include "lib/util_time.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define G0(x) MAX(0, (s64) (x))
|
#define G0(x) MAX(0, (s64) (x))
|
||||||
@@ -25,23 +26,23 @@
|
|||||||
/*
|
/*
|
||||||
* Helper Prototypes
|
* Helper Prototypes
|
||||||
*/
|
*/
|
||||||
extern void hyptop_helper_init(void);
|
void hyptop_helper_init(void);
|
||||||
extern char *ht_strstrip(char *str);
|
char *ht_strstrip(char *str);
|
||||||
extern char *ht_strdup(const char *str);
|
char *ht_strdup(const char *str);
|
||||||
extern void ht_print_head(const char *sys);
|
void ht_print_head(const char *sys);
|
||||||
extern void ht_print_help_icon(void);
|
void ht_print_help_icon(void);
|
||||||
extern void ht_ebcdic_to_ascii(char *in, char *out, size_t len);
|
void ht_ebcdic_to_ascii(char *in, char *out, size_t len);
|
||||||
extern char *ht_mount_point_get(const char *fs_type);
|
char *ht_mount_point_get(const char *fs_type);
|
||||||
extern u64 ht_ext_tod_2_us(void *tod_ext);
|
u64 ht_ext_tod_2_us(void *tod_ext);
|
||||||
extern void ht_print_time(void);
|
void ht_print_time(void);
|
||||||
extern s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core);
|
s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory alloc functions
|
* Memory alloc functions
|
||||||
*/
|
*/
|
||||||
extern void *ht_zalloc(size_t size);
|
void *ht_zalloc(size_t size);
|
||||||
extern void *ht_alloc(size_t size);
|
void *ht_alloc(size_t size);
|
||||||
extern void *ht_realloc(void *ptr, size_t size);
|
void *ht_realloc(void *ptr, size_t size);
|
||||||
static inline void ht_free(void *ptr)
|
static inline void ht_free(void *ptr)
|
||||||
{
|
{
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ shown.
|
|||||||
Select sort field for current window. To reverse the sort order, specify the
|
Select sort field for current window. To reverse the sort order, specify the
|
||||||
option twice. See FIELDS below for definitions.
|
option twice. See FIELDS below for definitions.
|
||||||
.TP
|
.TP
|
||||||
.BR "\-t <TYPE>,..." " or " "\-\-cpu_types=<TYPE>,..."
|
.BR "\-t <TYPE>,..." " or " "\-\-cpu-types=<TYPE>,..."
|
||||||
Select CPU types that are used for CPU time calculations. See CPU TYPES
|
Select CPU types that are used for CPU time calculations. See CPU TYPES
|
||||||
below for definitions.
|
below for definitions.
|
||||||
.TP
|
.TP
|
||||||
.BR "\-b" " or " "\-\-batch_mode"
|
.BR "\-b" " or " "\-\-batch-mode"
|
||||||
Use batch mode (no curses). This can be useful for sending output from hyptop
|
Use batch mode (no curses). This can be useful for sending output from hyptop
|
||||||
to another program, a file, or a line mode terminal.
|
to another program, a file, or a line mode terminal.
|
||||||
In this mode no user input is accepted.
|
In this mode no user input is accepted.
|
||||||
@@ -113,13 +113,20 @@ All values are enclosed in double quotation marks and separated by commas. The
|
|||||||
first line of output contains a list of headings. Subsequent lines each
|
first line of output contains a list of headings. Subsequent lines each
|
||||||
represent data for one system in one iteration.
|
represent data for one system in one iteration.
|
||||||
.PP
|
.PP
|
||||||
This option implies the "\-\-batch_mode" option.
|
This option implies the "\-\-batch-mode" option.
|
||||||
|
.RE
|
||||||
|
.BR "\-\-all"
|
||||||
|
.RS
|
||||||
|
Use this option with the "--format" option to include fields without valid
|
||||||
|
values in the output. Fields without valid values are omitted from the output
|
||||||
|
by default. When you use the "--all" option, the invalid values are included
|
||||||
|
and shown as "null".
|
||||||
.RE
|
.RE
|
||||||
.TP
|
.TP
|
||||||
.BR "\-d <SECONDS>" " or " "\-\-delay=<SECONDS>"
|
.BR "\-d <SECONDS>" " or " "\-\-delay=<SECONDS>"
|
||||||
Specifies the delay between screen updates.
|
Specifies the delay between screen updates.
|
||||||
.TP
|
.TP
|
||||||
.BR "\-m <FACTOR>" " or " "\-\-smt_factor=<FACTOR>"
|
.BR "\-m <FACTOR>" " or " "\-\-smt-factor=<FACTOR>"
|
||||||
Specifies a workload dependent SMT speedup factor.
|
Specifies a workload dependent SMT speedup factor.
|
||||||
For IBM z15 servers, the default value is 1.3. If the workload benefits
|
For IBM z15 servers, the default value is 1.3. If the workload benefits
|
||||||
from SMT, you can specify a higher value. If the workload does not benefit
|
from SMT, you can specify a higher value. If the workload does not benefit
|
||||||
@@ -239,7 +246,7 @@ The following units are supported:
|
|||||||
|
|
||||||
.SH CPU TYPES
|
.SH CPU TYPES
|
||||||
Depending on the hypervisor different CPU types are supported. These CPU
|
Depending on the hypervisor different CPU types are supported. These CPU
|
||||||
types can be selected either interactively or with the "--cpu_types"
|
types can be selected either interactively or with the "--cpu-types"
|
||||||
command line option. The calculation of the CPU data only uses CPUs of
|
command line option. The calculation of the CPU data only uses CPUs of
|
||||||
the specified types.
|
the specified types.
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static enum hyptop_win_action l_sleep(time_t time_s, long time_us)
|
|||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
|
||||||
ts.tv_sec = time_s;
|
ts.tv_sec = time_s;
|
||||||
ts.tv_nsec = time_us * 1000;
|
ts.tv_nsec = util_usecs_to_nsecs(time_us);
|
||||||
|
|
||||||
nanosleep(&ts, NULL);
|
nanosleep(&ts, NULL);
|
||||||
return WIN_KEEP;
|
return WIN_KEEP;
|
||||||
@@ -231,6 +231,8 @@ static void l_fmt_init(void)
|
|||||||
return;
|
return;
|
||||||
if (g.o.format == FMT_CSV)
|
if (g.o.format == FMT_CSV)
|
||||||
flags |= FMT_QUOTEALL;
|
flags |= FMT_QUOTEALL;
|
||||||
|
if (g.o.format == FMT_CSV || g.o.format_all)
|
||||||
|
flags |= FMT_KEEPINVAL;
|
||||||
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
|
if (g.o.format == FMT_JSON || g.o.format == FMT_JSONSEQ)
|
||||||
flags |= FMT_HANDLEINT;
|
flags |= FMT_HANDLEINT;
|
||||||
util_fmt_init(stdout, g.o.format, flags, 1);
|
util_fmt_init(stdout, g.o.format, flags, 1);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ struct hyptop_opts {
|
|||||||
unsigned int win_specified;
|
unsigned int win_specified;
|
||||||
unsigned int batch_mode_specified;
|
unsigned int batch_mode_specified;
|
||||||
unsigned int format_specified;
|
unsigned int format_specified;
|
||||||
|
unsigned int format_all;
|
||||||
enum util_fmt_t format;
|
enum util_fmt_t format;
|
||||||
unsigned int iterations_specified;
|
unsigned int iterations_specified;
|
||||||
unsigned int iterations;
|
unsigned int iterations;
|
||||||
@@ -183,10 +184,10 @@ enum hyptop_win_action {
|
|||||||
WIN_KEEP,
|
WIN_KEEP,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum hyptop_win_action hyptop_process_input_timeout(void);
|
enum hyptop_win_action hyptop_process_input_timeout(void);
|
||||||
extern enum hyptop_win_action hyptop_process_input(void);
|
enum hyptop_win_action hyptop_process_input(void);
|
||||||
extern enum hyptop_win_action win_switch(struct hyptop_win *w);
|
enum hyptop_win_action win_switch(struct hyptop_win *w);
|
||||||
extern enum hyptop_win_action win_back(void);
|
enum hyptop_win_action win_back(void);
|
||||||
|
|
||||||
struct hyptop_win;
|
struct hyptop_win;
|
||||||
struct hyptop_win {
|
struct hyptop_win {
|
||||||
@@ -205,25 +206,25 @@ struct hyptop_win {
|
|||||||
* Window sys_list
|
* Window sys_list
|
||||||
*/
|
*/
|
||||||
extern struct hyptop_win win_sys_list;
|
extern struct hyptop_win win_sys_list;
|
||||||
extern void win_sys_list_init(void);
|
void win_sys_list_init(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Window sys
|
* Window sys
|
||||||
*/
|
*/
|
||||||
extern struct hyptop_win win_sys;
|
extern struct hyptop_win win_sys;
|
||||||
extern void win_sys_set(const char *sys_id);
|
void win_sys_set(const char *sys_id);
|
||||||
extern void win_sys_init(void);
|
void win_sys_init(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Window cpu_types
|
* Window cpu_types
|
||||||
*/
|
*/
|
||||||
extern void win_cpu_types_init(void);
|
void win_cpu_types_init(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Misc functions
|
* Misc functions
|
||||||
*/
|
*/
|
||||||
extern void hyptop_update_term(void);
|
void hyptop_update_term(void);
|
||||||
extern void __noreturn hyptop_exit(int rc);
|
void __noreturn hyptop_exit(int rc);
|
||||||
extern void hyptop_text_mode(void);
|
void hyptop_text_mode(void);
|
||||||
|
|
||||||
#endif /* HYPTOP_H */
|
#endif /* HYPTOP_H */
|
||||||
|
|||||||
@@ -39,17 +39,28 @@ static char HELP_TEXT[] =
|
|||||||
"-s, --sys SYSTEM[,..] Systems for current window\n"
|
"-s, --sys SYSTEM[,..] Systems for current window\n"
|
||||||
"-f, --fields LETTER[:UNIT][,..] Fields and units for current window\n"
|
"-f, --fields LETTER[:UNIT][,..] Fields and units for current window\n"
|
||||||
"-S, --sort LETTER Sort field for current window\n"
|
"-S, --sort LETTER Sort field for current window\n"
|
||||||
"-t, --cpu_types TYPE[,..] CPU types used for time calculations\n"
|
"-t, --cpu-types TYPE[,..] CPU types used for time calculations\n"
|
||||||
"-b, --batch_mode Use batch mode (no curses)\n"
|
"-b, --batch-mode Use batch mode (no curses)\n"
|
||||||
" --format FORMAT Output format (" FMT_TYPE_NAMES "), implies -b\n"
|
" --format FORMAT Output format (" FMT_TYPE_NAMES "), implies -b\n"
|
||||||
|
" --all Include omitted fields (with values of null)\n"
|
||||||
|
" in the output of --format.\n"
|
||||||
"-d, --delay SECONDS Delay time between screen updates\n"
|
"-d, --delay SECONDS Delay time between screen updates\n"
|
||||||
"-m, --smt_factor FACTOR Machine generation dependent SMT speedup factor.\n"
|
"-m, --smt-factor FACTOR Machine generation dependent SMT speedup factor.\n"
|
||||||
"-n, --iterations NUMBER Number of iterations before ending\n";
|
"-n, --iterations NUMBER Number of iterations before ending\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Options with long-name only
|
* Options with long-name only
|
||||||
*/
|
*/
|
||||||
#define OPT_FORMAT 256 /* --format */
|
#define OPT_FORMAT 256 /* --format */
|
||||||
|
#define OPT_FORMAT_ALL 261 /* --all*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Options with underscore to keep compatibility
|
||||||
|
*/
|
||||||
|
#define OPT_BATCH_MODE 257 /* --batch_mode */
|
||||||
|
#define OPT_SORT_FIELD 258 /* --sort | --sort_field */
|
||||||
|
#define OPT_CPU_TYPES 259 /* --cpu_types */
|
||||||
|
#define OPT_SMT_FACTOR 260 /* --smt_factor */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize default settings
|
* Initialize default settings
|
||||||
@@ -313,6 +324,15 @@ static void l_format_set(const char *str)
|
|||||||
g.o.format = fmt;
|
g.o.format = fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the "--all" option to display omitted null values
|
||||||
|
* while using "--format"
|
||||||
|
*/
|
||||||
|
static void l_format_all_set(void)
|
||||||
|
{
|
||||||
|
g.o.format_all = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make option consisteny checks at end of command line parsing
|
* Make option consisteny checks at end of command line parsing
|
||||||
*/
|
*/
|
||||||
@@ -320,6 +340,8 @@ static void l_parse_finish(void)
|
|||||||
{
|
{
|
||||||
if (g.o.iterations_specified && g.o.iterations == 0)
|
if (g.o.iterations_specified && g.o.iterations == 0)
|
||||||
hyptop_exit(0);
|
hyptop_exit(0);
|
||||||
|
if (!g.o.format_specified && g.o.format_all)
|
||||||
|
ERR_EXIT("The --all option requires the -–format option\n");
|
||||||
if (g.o.cur_win != &win_sys)
|
if (g.o.cur_win != &win_sys)
|
||||||
return;
|
return;
|
||||||
if (!win_sys.opts.sys.specified)
|
if (!win_sys.opts.sys.specified)
|
||||||
@@ -339,15 +361,20 @@ void opts_parse(int argc, char *argv[])
|
|||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{ "version", no_argument, NULL, 'v'},
|
{ "version", no_argument, NULL, 'v'},
|
||||||
{ "help", no_argument, NULL, 'h'},
|
{ "help", no_argument, NULL, 'h'},
|
||||||
{ "batch_mode", no_argument, NULL, 'b'},
|
{ "batch-mode", no_argument, NULL, 'b'},
|
||||||
|
{ "batch_mode", no_argument, NULL, OPT_BATCH_MODE},
|
||||||
|
{ "all", no_argument, NULL, OPT_FORMAT_ALL },
|
||||||
{ "delay", required_argument, NULL, 'd'},
|
{ "delay", required_argument, NULL, 'd'},
|
||||||
{ "smt_factor", required_argument, NULL, 'm'},
|
{ "smt-factor", required_argument, NULL, 'm'},
|
||||||
|
{ "smt_factor", required_argument, NULL, OPT_SMT_FACTOR},
|
||||||
{ "window", required_argument, NULL, 'w'},
|
{ "window", required_argument, NULL, 'w'},
|
||||||
{ "sys", required_argument, NULL, 's'},
|
{ "sys", required_argument, NULL, 's'},
|
||||||
{ "iterations", required_argument, NULL, 'n'},
|
{ "iterations", required_argument, NULL, 'n'},
|
||||||
{ "fields", required_argument, NULL, 'f'},
|
{ "fields", required_argument, NULL, 'f'},
|
||||||
{ "sort_field", required_argument, NULL, 'S'},
|
{ "sort-field", required_argument, NULL, 'S'},
|
||||||
{ "cpu_types", required_argument, NULL, 't'},
|
{ "sort_field", required_argument, NULL, OPT_SORT_FIELD},
|
||||||
|
{ "cpu-types", required_argument, NULL, 't'},
|
||||||
|
{ "cpu_types", required_argument, NULL, OPT_CPU_TYPES},
|
||||||
{ "format", required_argument, NULL, OPT_FORMAT },
|
{ "format", required_argument, NULL, OPT_FORMAT },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
@@ -366,12 +393,14 @@ void opts_parse(int argc, char *argv[])
|
|||||||
case 'h':
|
case 'h':
|
||||||
l_usage();
|
l_usage();
|
||||||
hyptop_exit(0);
|
hyptop_exit(0);
|
||||||
|
case OPT_BATCH_MODE:
|
||||||
case 'b':
|
case 'b':
|
||||||
l_batch_mode_set();
|
l_batch_mode_set();
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
l_delay_set(optarg);
|
l_delay_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_SMT_FACTOR:
|
||||||
case 'm':
|
case 'm':
|
||||||
l_factor_set(optarg);
|
l_factor_set(optarg);
|
||||||
break;
|
break;
|
||||||
@@ -384,18 +413,23 @@ void opts_parse(int argc, char *argv[])
|
|||||||
case 'n':
|
case 'n':
|
||||||
l_iterations_set(optarg);
|
l_iterations_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_CPU_TYPES:
|
||||||
case 't':
|
case 't':
|
||||||
l_cpu_types_set(optarg);
|
l_cpu_types_set(optarg);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
l_fields_set(optarg);
|
l_fields_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_SORT_FIELD:
|
||||||
case 'S':
|
case 'S':
|
||||||
l_sort_field_set(optarg);
|
l_sort_field_set(optarg);
|
||||||
break;
|
break;
|
||||||
case OPT_FORMAT:
|
case OPT_FORMAT:
|
||||||
l_format_set(optarg);
|
l_format_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
case OPT_FORMAT_ALL:
|
||||||
|
l_format_all_set();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
l_std_usage_exit();
|
l_std_usage_exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
|
|
||||||
#include "hyptop.h"
|
#include "hyptop.h"
|
||||||
|
|
||||||
extern void opts_parse(int argc, char *argv[]);
|
void opts_parse(int argc, char *argv[]);
|
||||||
extern void opts_iterations_next(void);
|
void opts_iterations_next(void);
|
||||||
extern int opts_sys_specified(struct hyptop_win *win, const char* sys_name);
|
int opts_sys_specified(struct hyptop_win *win, const char *sys_name);
|
||||||
extern void opt_verify_systems(void);
|
void opt_verify_systems(void);
|
||||||
|
|
||||||
#endif /* OPTS_H */
|
#endif /* OPTS_H */
|
||||||
|
|||||||
26
hyptop/sd.h
26
hyptop/sd.h
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#define SD_DG_INIT_INTERVAL_SEC 1
|
#define SD_DG_INIT_INTERVAL_SEC 1
|
||||||
#define SD_SYS_ID_SIZE 9
|
#define SD_SYS_ID_SIZE 9
|
||||||
|
#define SD_SYS_DEFAULT_ID "PHYSICAL"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU info
|
* CPU info
|
||||||
@@ -77,6 +78,7 @@ struct sd_sys {
|
|||||||
struct util_list_node list;
|
struct util_list_node list;
|
||||||
struct sd_info i;
|
struct sd_info i;
|
||||||
u64 update_time_us;
|
u64 update_time_us;
|
||||||
|
u64 phys_delta_us;
|
||||||
u32 child_cnt;
|
u32 child_cnt;
|
||||||
u32 child_cnt_active;
|
u32 child_cnt_active;
|
||||||
struct util_list child_list;
|
struct util_list child_list;
|
||||||
@@ -134,6 +136,11 @@ static inline void sd_sys_update_time_us_set(struct sd_sys *sys, u64 value)
|
|||||||
sys->update_time_us = value;
|
sys->update_time_us = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void sd_phys_delta_time_us_set(struct sd_sys *sys, u64 value)
|
||||||
|
{
|
||||||
|
sys->phys_delta_us = value;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU type
|
* CPU type
|
||||||
*/
|
*/
|
||||||
@@ -301,8 +308,8 @@ struct sd_cpu_item {
|
|||||||
#define sd_cpu_item_type(x) ((x)->type)
|
#define sd_cpu_item_type(x) ((x)->type)
|
||||||
#define sd_cpu_item_table_col(item) (&(item)->table_col)
|
#define sd_cpu_item_table_col(item) (&(item)->table_col)
|
||||||
|
|
||||||
extern int sd_cpu_item_available(struct sd_cpu_item *item);
|
int sd_cpu_item_available(struct sd_cpu_item *item);
|
||||||
extern int sd_cpu_item_cnt(void);
|
int sd_cpu_item_cnt(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Item access functions
|
* Item access functions
|
||||||
@@ -370,8 +377,8 @@ struct sd_sys_item {
|
|||||||
#define sd_sys_item_table_col(item) (&item->table_col)
|
#define sd_sys_item_table_col(item) (&item->table_col)
|
||||||
#define sd_sys_item_type(item) (item->type)
|
#define sd_sys_item_type(item) (item->type)
|
||||||
|
|
||||||
extern int sd_sys_item_available(struct sd_sys_item *item);
|
int sd_sys_item_available(struct sd_sys_item *item);
|
||||||
extern int sd_sys_item_cnt(void);
|
int sd_sys_item_cnt(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Item access functions
|
* Item access functions
|
||||||
@@ -437,19 +444,23 @@ extern struct sd_sys_item sd_sys_item_os_name;
|
|||||||
extern struct sd_sys_item sd_sys_item_samples_total;
|
extern struct sd_sys_item sd_sys_item_samples_total;
|
||||||
extern struct sd_sys_item sd_sys_item_samples_cpu_using;
|
extern struct sd_sys_item sd_sys_item_samples_cpu_using;
|
||||||
|
|
||||||
|
extern struct sd_sys_item sd_sys_item_phys_mgm_diff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data gatherer backend
|
* Data gatherer backend
|
||||||
*/
|
*/
|
||||||
struct sd_dg {
|
struct sd_dg {
|
||||||
void (*update_sys)(void);
|
void (*update_sys)(void);
|
||||||
struct sd_cpu_type **cpu_type_vec;
|
struct sd_cpu_type **cpu_type_vec;
|
||||||
|
struct sd_sys_item **phys_item_vec;
|
||||||
struct sd_sys_item **sys_item_vec;
|
struct sd_sys_item **sys_item_vec;
|
||||||
struct sd_sys_item **sys_item_enable_vec;
|
struct sd_sys_item **sys_item_enable_vec;
|
||||||
struct sd_cpu_item **cpu_item_vec;
|
struct sd_cpu_item **cpu_item_vec;
|
||||||
struct sd_cpu_item **cpu_item_enable_vec;
|
struct sd_cpu_item **cpu_item_enable_vec;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sd_dg_register(struct sd_dg *, int);
|
void sd_dg_register(struct sd_dg *, int, int);
|
||||||
|
int sd_dg_has_phys_data(void);
|
||||||
int sd_dg_has_core_data(void);
|
int sd_dg_has_core_data(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -461,6 +472,9 @@ int sd_dg_has_core_data(void);
|
|||||||
#define sd_cpu_iterate(parent, cpu) \
|
#define sd_cpu_iterate(parent, cpu) \
|
||||||
util_list_iterate(&parent->cpu_list, cpu)
|
util_list_iterate(&parent->cpu_list, cpu)
|
||||||
|
|
||||||
|
#define sd_phys_item_iterate(ptr, i) \
|
||||||
|
for (i = 0; (ptr = sd.dg->phys_item_vec[i]); i++)
|
||||||
|
|
||||||
#define sd_sys_item_iterate(ptr, i) \
|
#define sd_sys_item_iterate(ptr, i) \
|
||||||
for (i = 0; (ptr = sd.dg->sys_item_vec[i]); i++)
|
for (i = 0; (ptr = sd.dg->sys_item_vec[i]); i++)
|
||||||
|
|
||||||
@@ -506,7 +520,7 @@ static inline s64 l_cpu_info_s64(struct sd_cpu_info *info,
|
|||||||
* Misc
|
* Misc
|
||||||
*/
|
*/
|
||||||
void sd_update(void);
|
void sd_update(void);
|
||||||
extern void sd_init(void);
|
void sd_init(void);
|
||||||
|
|
||||||
static inline u64 l_sub_64(u64 x, u64 y)
|
static inline u64 l_sub_64(u64 x, u64 y)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ static int l_cpu_type_cnt;
|
|||||||
static int l_sys_item_cnt;
|
static int l_sys_item_cnt;
|
||||||
static int l_cpu_item_cnt;
|
static int l_cpu_item_cnt;
|
||||||
static int l_has_core_data;
|
static int l_has_core_data;
|
||||||
|
static int l_has_phys_data;
|
||||||
static struct sd_sys *l_root_sys;
|
static struct sd_sys *l_root_sys;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -148,7 +149,7 @@ void sd_update(void)
|
|||||||
/*
|
/*
|
||||||
* Register a data gatherer
|
* Register a data gatherer
|
||||||
*/
|
*/
|
||||||
void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
void sd_dg_register(struct sd_dg *dg, int has_core_data, int has_phys_data)
|
||||||
{
|
{
|
||||||
struct timespec ts = {SD_DG_INIT_INTERVAL_SEC, 0};
|
struct timespec ts = {SD_DG_INIT_INTERVAL_SEC, 0};
|
||||||
struct sd_sys_item *sys_item;
|
struct sd_sys_item *sys_item;
|
||||||
@@ -156,6 +157,7 @@ void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
l_has_core_data = has_core_data;
|
l_has_core_data = has_core_data;
|
||||||
|
l_has_phys_data = has_phys_data;
|
||||||
sd.dg = dg;
|
sd.dg = dg;
|
||||||
for (i = 0; dg->cpu_type_vec[i]; i++)
|
for (i = 0; dg->cpu_type_vec[i]; i++)
|
||||||
dg->cpu_type_vec[i]->idx = (1UL << i);
|
dg->cpu_type_vec[i]->idx = (1UL << i);
|
||||||
@@ -172,6 +174,14 @@ void sd_dg_register(struct sd_dg *dg, int has_core_data)
|
|||||||
l_cpu_types_init();
|
l_cpu_types_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does backend has physical CPUs data?
|
||||||
|
*/
|
||||||
|
int sd_dg_has_phys_data(void)
|
||||||
|
{
|
||||||
|
return l_has_phys_data;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does backend has core data?
|
* Does backend has core data?
|
||||||
*/
|
*/
|
||||||
@@ -419,7 +429,7 @@ int sd_cpu_item_cnt(void)
|
|||||||
*/
|
*/
|
||||||
void sd_init(void)
|
void sd_init(void)
|
||||||
{
|
{
|
||||||
l_root_sys = sd_sys_new(NULL, "root");
|
l_root_sys = sd_sys_new(NULL, SD_SYS_DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ static double l_cpu_diff(struct sd_cpu_item *item, struct sd_cpu *cpu, int sign)
|
|||||||
if (online_time_diff_us == 0)
|
if (online_time_diff_us == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
factor = ((double) online_time_diff_us) / 1000000 * cpu->cnt;
|
factor = util_usecs_to_secs(online_time_diff_us) * cpu->cnt;
|
||||||
if (sign)
|
if (sign)
|
||||||
diff_us = l_cpu_info_s64(cpu->d_cur, item->offset) -
|
diff_us = l_cpu_info_s64(cpu->d_cur, item->offset) -
|
||||||
l_cpu_info_s64(cpu->d_prev, item->offset);
|
l_cpu_info_s64(cpu->d_prev, item->offset);
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ static double l_cpu_info_diff_u64(struct sd_sys_item *item, struct sd_cpu *cpu,
|
|||||||
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
||||||
l_cpu_info_u64(cpu->d_prev, item->offset));
|
l_cpu_info_u64(cpu->d_prev, item->offset));
|
||||||
}
|
}
|
||||||
factor = ((double) online_time_diff_us) / 1000000;
|
factor = util_usecs_to_secs(online_time_diff_us);
|
||||||
diff_us /= factor;
|
diff_us /= factor;
|
||||||
return diff_us;
|
return diff_us;
|
||||||
}
|
}
|
||||||
@@ -220,9 +220,56 @@ static u64 l_sys_smt_util(struct sd_sys_item *item, struct sd_sys *sys)
|
|||||||
return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core);
|
return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* value = (value_current - value_prev) / online_time_diff
|
||||||
|
*/
|
||||||
|
static double l_phys_cpu_info_diff_u64(struct sd_sys_item *item,
|
||||||
|
struct sd_cpu *cpu,
|
||||||
|
u64 time_diff_us)
|
||||||
|
{
|
||||||
|
double factor, diff_us;
|
||||||
|
|
||||||
|
if (!sd_cpu_type_selected(cpu->type))
|
||||||
|
return 0;
|
||||||
|
if (sd_cpu_state(cpu) == SD_CPU_STATE_STOPPED)
|
||||||
|
return 0;
|
||||||
|
if (time_diff_us == 0)
|
||||||
|
return 0;
|
||||||
|
diff_us = l_sub_64(l_cpu_info_u64(cpu->d_cur, item->offset),
|
||||||
|
l_cpu_info_u64(cpu->d_prev, item->offset));
|
||||||
|
factor = util_usecs_to_secs(time_diff_us);
|
||||||
|
diff_us /= factor;
|
||||||
|
return diff_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SUM over all CPUs: value = (value_current - value_prev) / online_time_diff
|
||||||
|
*/
|
||||||
|
static u64 l_sys_phys_cpu_info_diff_u64(struct sd_sys_item *item, struct sd_sys *sys)
|
||||||
|
{
|
||||||
|
struct sd_cpu *cpu;
|
||||||
|
u64 rc = 0;
|
||||||
|
|
||||||
|
sd_cpu_iterate(sys, cpu) {
|
||||||
|
if (!cpu->d_prev || !cpu->d_cur)
|
||||||
|
return 0;
|
||||||
|
rc += l_phys_cpu_info_diff_u64(item, cpu, sys->phys_delta_us);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* System item definitions
|
* System item definitions
|
||||||
*/
|
*/
|
||||||
|
struct sd_sys_item sd_sys_item_phys_mgm_diff = {
|
||||||
|
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
||||||
|
.offset = SD_CPU_INFO_OFFSET(mgm_time_us),
|
||||||
|
.type = SD_TYPE_U64,
|
||||||
|
.desc = "Management time per second",
|
||||||
|
.fn_set = l_sys_cpu_info_set,
|
||||||
|
.fn_u64 = l_sys_phys_cpu_info_diff_u64,
|
||||||
|
};
|
||||||
|
|
||||||
struct sd_sys_item sd_sys_item_core_cnt = {
|
struct sd_sys_item sd_sys_item_core_cnt = {
|
||||||
.table_col = TABLE_COL_CNT_SUM('#', "#core"),
|
.table_col = TABLE_COL_CNT_SUM('#', "#core"),
|
||||||
.type = SD_TYPE_U32,
|
.type = SD_TYPE_U32,
|
||||||
|
|||||||
@@ -260,6 +260,10 @@ void table_row_del_all(struct table *t)
|
|||||||
util_list_remove(&t->row_list, row);
|
util_list_remove(&t->row_list, row);
|
||||||
table_row_free(row);
|
table_row_free(row);
|
||||||
}
|
}
|
||||||
|
if (t->row_physical) {
|
||||||
|
table_row_free(t->row_physical);
|
||||||
|
t->row_physical = NULL;
|
||||||
|
}
|
||||||
l_row_last_init(t);
|
l_row_last_init(t);
|
||||||
t->row_cnt_marked = 0;
|
t->row_cnt_marked = 0;
|
||||||
t->ready = 0;
|
t->ready = 0;
|
||||||
@@ -418,6 +422,8 @@ static void l_row_last_calc(struct table *t)
|
|||||||
*/
|
*/
|
||||||
void table_finish(struct table *t)
|
void table_finish(struct table *t)
|
||||||
{
|
{
|
||||||
|
if (t->row_physical)
|
||||||
|
l_row_format(t, t->row_physical);
|
||||||
l_row_last_calc(t);
|
l_row_last_calc(t);
|
||||||
t->ready = 1;
|
t->ready = 1;
|
||||||
}
|
}
|
||||||
@@ -463,6 +469,8 @@ void table_rebuild(struct table *t)
|
|||||||
l_col_max_width_init(t, col);
|
l_col_max_width_init(t, col);
|
||||||
util_list_iterate(&t->row_list, row)
|
util_list_iterate(&t->row_list, row)
|
||||||
l_row_format(t, row);
|
l_row_format(t, row);
|
||||||
|
if (t->row_physical)
|
||||||
|
l_row_format(t, t->row_physical);
|
||||||
l_row_format(t, t->row_last);
|
l_row_format(t, t->row_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -921,6 +929,10 @@ static void l_table_print_curses(struct table *t)
|
|||||||
}
|
}
|
||||||
ht_reverse_on();
|
ht_reverse_on();
|
||||||
l_row_print(t, t->row_last);
|
l_row_print(t, t->row_last);
|
||||||
|
if (t->row_physical) {
|
||||||
|
hyptop_print_nl();
|
||||||
|
l_row_print(t, t->row_physical);
|
||||||
|
}
|
||||||
hyptop_print_seek_back(0);
|
hyptop_print_seek_back(0);
|
||||||
ht_reverse_off();
|
ht_reverse_off();
|
||||||
#ifdef WITH_SCROLL_BAR
|
#ifdef WITH_SCROLL_BAR
|
||||||
@@ -952,6 +964,10 @@ static void l_table_print_all(struct table *t)
|
|||||||
}
|
}
|
||||||
l_row_print(t, t->row_last);
|
l_row_print(t, t->row_last);
|
||||||
hyptop_print_nl();
|
hyptop_print_nl();
|
||||||
|
if (t->row_physical) {
|
||||||
|
l_row_print(t, t->row_physical);
|
||||||
|
hyptop_print_nl();
|
||||||
|
}
|
||||||
hyptop_printf("------------------------------------------------------"
|
hyptop_printf("------------------------------------------------------"
|
||||||
"-------------------------\n");
|
"-------------------------\n");
|
||||||
}
|
}
|
||||||
@@ -972,10 +988,15 @@ static void l_row_print_formatted(struct table *t, struct table_row *row)
|
|||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
struct table_entry *e = &row->entries[col_nr];
|
struct table_entry *e = &row->entries[col_nr];
|
||||||
|
|
||||||
if (row == t->row_last && col_nr == 0)
|
if (row == t->row_last && col_nr == 0) {
|
||||||
|
if (g.o.format == FMT_CSV)
|
||||||
|
util_fmt_pair(FMT_QUOTE, col->head, "SUM", e->str);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (table_col_needs_quotes(col))
|
if (table_col_needs_quotes(col))
|
||||||
flags = FMT_QUOTE;
|
flags = FMT_QUOTE;
|
||||||
|
if (strcmp(e->str, "-") == 0 || strcmp(e->str, "") == 0)
|
||||||
|
flags |= FMT_INVAL;
|
||||||
util_fmt_pair(flags, col->head, "%s", e->str);
|
util_fmt_pair(flags, col->head, "%s", e->str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -991,6 +1012,11 @@ static void l_table_print_all_formatted(struct table *t)
|
|||||||
util_fmt_pair(FMT_PERSIST, "iteration", "%u", g.o.iterations_act);
|
util_fmt_pair(FMT_PERSIST, "iteration", "%u", g.o.iterations_act);
|
||||||
ht_fmt_time();
|
ht_fmt_time();
|
||||||
ht_fmt_cpu_types();
|
ht_fmt_cpu_types();
|
||||||
|
if (t->row_physical) {
|
||||||
|
util_fmt_obj_start(FMT_ROW, "physical_information");
|
||||||
|
l_row_print_formatted(t, t->row_physical);
|
||||||
|
util_fmt_obj_end(); /* physical_information{} */
|
||||||
|
}
|
||||||
if (strcmp(g.o.cur_win->id, "sys_list") == 0)
|
if (strcmp(g.o.cur_win->id, "sys_list") == 0)
|
||||||
util_fmt_obj_start(FMT_LIST, "systems");
|
util_fmt_obj_start(FMT_LIST, "systems");
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ struct table {
|
|||||||
struct table_col **col_vec;
|
struct table_col **col_vec;
|
||||||
struct table_col *col_selected;
|
struct table_col *col_selected;
|
||||||
struct table_row *row_last;
|
struct table_row *row_last;
|
||||||
|
struct table_row *row_physical;
|
||||||
int row_cnt;
|
int row_cnt;
|
||||||
int row_cnt_marked;
|
int row_cnt_marked;
|
||||||
int row_cnt_extra;
|
int row_cnt_extra;
|
||||||
@@ -361,37 +362,37 @@ enum table_scroll_unit {
|
|||||||
*/
|
*/
|
||||||
extern struct table *table_new(int extra_rows, int sorted, int first_bold,
|
extern struct table *table_new(int extra_rows, int sorted, int first_bold,
|
||||||
int with_units);
|
int with_units);
|
||||||
extern void table_reset(struct table *t);
|
void table_reset(struct table *t);
|
||||||
extern void table_rebuild(struct table *t);
|
void table_rebuild(struct table *t);
|
||||||
extern void table_finish(struct table *t);
|
void table_finish(struct table *t);
|
||||||
extern void table_print(struct table *t);
|
void table_print(struct table *t);
|
||||||
extern void table_process_input(struct table *t, int c);
|
void table_process_input(struct table *t, int c);
|
||||||
|
|
||||||
extern void table_col_unit_next(struct table *t, char hotkey);
|
void table_col_unit_next(struct table *t, char hotkey);
|
||||||
extern void table_col_unit_prev(struct table *t, char hotkey);
|
void table_col_unit_prev(struct table *t, char hotkey);
|
||||||
extern int table_col_unit_set(struct table *t, char hotkey, const char *unit);
|
int table_col_unit_set(struct table *t, char hotkey, const char *unit);
|
||||||
extern void table_col_add(struct table *t, struct table_col *col);
|
void table_col_add(struct table *t, struct table_col *col);
|
||||||
extern int table_col_select(struct table *t, char hotkey);
|
int table_col_select(struct table *t, char hotkey);
|
||||||
extern void table_col_select_next(struct table *t);
|
void table_col_select_next(struct table *t);
|
||||||
extern void table_col_select_prev(struct table *t);
|
void table_col_select_prev(struct table *t);
|
||||||
extern void table_col_enable_toggle(struct table *t, char hotkey);
|
void table_col_enable_toggle(struct table *t, char hotkey);
|
||||||
|
|
||||||
extern void table_row_del_all(struct table *t);
|
void table_row_del_all(struct table *t);
|
||||||
extern void table_row_add(struct table *t, struct table_row *row);
|
void table_row_add(struct table *t, struct table_row *row);
|
||||||
extern void table_row_mark(struct table *t, struct table_row *row);
|
void table_row_mark(struct table *t, struct table_row *row);
|
||||||
extern void table_row_mark_del_all(struct table *t);
|
void table_row_mark_del_all(struct table *t);
|
||||||
extern void table_row_mark_toggle(struct table *t, struct table_row *row);
|
void table_row_mark_toggle(struct table *t, struct table_row *row);
|
||||||
extern void table_row_mark_toggle_by_key(struct table *t, const char *mark_key);
|
void table_row_mark_toggle_by_key(struct table *t, const char *mark_key);
|
||||||
extern void table_row_select_down(struct table *t, enum table_scroll_unit unit);
|
void table_row_select_down(struct table *t, enum table_scroll_unit unit);
|
||||||
extern void table_row_select_up(struct table *t, enum table_scroll_unit unit);
|
void table_row_select_up(struct table *t, enum table_scroll_unit unit);
|
||||||
extern void table_row_select_key_get(struct table *t, char str[TABLE_STR_MAX]);
|
void table_row_select_key_get(struct table *t, char str[TABLE_STR_MAX]);
|
||||||
extern struct table_row *table_row_alloc(struct table *t);
|
struct table_row *table_row_alloc(struct table *t);
|
||||||
|
|
||||||
extern void table_scroll_down(struct table *t, enum table_scroll_unit unit);
|
void table_scroll_down(struct table *t, enum table_scroll_unit unit);
|
||||||
extern void table_scroll_up(struct table *t, enum table_scroll_unit unit);
|
void table_scroll_up(struct table *t, enum table_scroll_unit unit);
|
||||||
|
|
||||||
extern void table_fmt_start(void);
|
void table_fmt_start(void);
|
||||||
extern void table_fmt_end(void);
|
void table_fmt_end(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry add functions
|
* Entry add functions
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ struct table_col_unit table_col_unit_us = {
|
|||||||
*/
|
*/
|
||||||
static int l_unit_ms(struct table_col *col, struct table_entry *e)
|
static int l_unit_ms(struct table_col *col, struct table_entry *e)
|
||||||
{
|
{
|
||||||
return l_unit_raw_div(col, e, 1000, L_COL_FMT_STR_2);
|
return l_unit_raw_div(col, e, USEC_PER_MSEC, L_COL_FMT_STR_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct table_col_unit table_col_unit_ms = {
|
struct table_col_unit table_col_unit_ms = {
|
||||||
@@ -167,7 +167,7 @@ struct table_col_unit table_col_unit_ms = {
|
|||||||
*/
|
*/
|
||||||
static int l_unit_perc(struct table_col *col, struct table_entry *e)
|
static int l_unit_perc(struct table_col *col, struct table_entry *e)
|
||||||
{
|
{
|
||||||
return l_unit_raw_div(col, e, 10000, L_COL_FMT_STR_2);
|
return l_unit_raw_div(col, e, (USEC_PER_SEC / 100), L_COL_FMT_STR_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct table_col_unit table_col_unit_perc = {
|
struct table_col_unit table_col_unit_perc = {
|
||||||
@@ -182,7 +182,7 @@ struct table_col_unit table_col_unit_perc = {
|
|||||||
*/
|
*/
|
||||||
static int l_unit_s(struct table_col *col, struct table_entry *e)
|
static int l_unit_s(struct table_col *col, struct table_entry *e)
|
||||||
{
|
{
|
||||||
return l_unit_raw_div(col, e, 1000000, L_COL_FMT_STR_2);
|
return l_unit_raw_div(col, e, USEC_PER_SEC, L_COL_FMT_STR_2);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct table_col_unit table_col_unit_s = {
|
struct table_col_unit table_col_unit_s = {
|
||||||
@@ -197,7 +197,7 @@ struct table_col_unit table_col_unit_s = {
|
|||||||
*/
|
*/
|
||||||
static int l_unit_m(struct table_col *col, struct table_entry *e)
|
static int l_unit_m(struct table_col *col, struct table_entry *e)
|
||||||
{
|
{
|
||||||
return l_unit_raw_div(col, e, 1000000 * 60, L_COL_FMT_STR_0);
|
return l_unit_raw_div(col, e, USEC_PER_SEC * 60, L_COL_FMT_STR_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct table_col_unit table_col_unit_m = {
|
static struct table_col_unit table_col_unit_m = {
|
||||||
@@ -214,7 +214,7 @@ static int l_unit_hm_u64(char *str, u64 v1, int negative)
|
|||||||
{
|
{
|
||||||
u64 time_tmp, time_h, time_m;
|
u64 time_tmp, time_h, time_m;
|
||||||
|
|
||||||
time_tmp = v1 / (1000000 * 60);
|
time_tmp = v1 / (USEC_PER_SEC * 60);
|
||||||
time_h = time_tmp / 60;
|
time_h = time_tmp / 60;
|
||||||
time_m = time_tmp - time_h * 60;
|
time_m = time_tmp - time_h * 60;
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ static int l_unit_dhm_u64(char *str, u64 v1, int negative)
|
|||||||
{
|
{
|
||||||
u64 time_tmp, time_d, time_h, time_m;
|
u64 time_tmp, time_d, time_h, time_m;
|
||||||
|
|
||||||
time_tmp = v1 / (1000000 * 60);
|
time_tmp = v1 / (USEC_PER_SEC * 60);
|
||||||
time_d = time_tmp / (60 * 24);
|
time_d = time_tmp / (60 * 24);
|
||||||
time_h = time_tmp / 60 - time_d * 24;
|
time_h = time_tmp / 60 - time_d * 24;
|
||||||
time_m = time_tmp - time_h * 60 - time_d * 60 * 24;
|
time_m = time_tmp - time_h * 60 - time_d * 60 * 24;
|
||||||
@@ -312,10 +312,8 @@ static int l_unit_vis(struct table_col *col, struct table_entry *e)
|
|||||||
assert(col->type == TABLE_COL_TYPE_U64);
|
assert(col->type == TABLE_COL_TYPE_U64);
|
||||||
|
|
||||||
sprintf(e->str, "|");
|
sprintf(e->str, "|");
|
||||||
val1_perc = e->d.u64.v1;
|
val1_perc = util_usecs_to_secs(e->d.u64.v1);
|
||||||
val1_perc /= 1000000;
|
val2_perc = util_usecs_to_secs(e->d.u64.v2);
|
||||||
val2_perc = e->d.u64.v2;
|
|
||||||
val2_perc /= 1000000;
|
|
||||||
val1_nr = (val1_perc * L_VISUAL_ROW_CNT) + 0.5;
|
val1_nr = (val1_perc * L_VISUAL_ROW_CNT) + 0.5;
|
||||||
val2_nr = (val2_perc * L_VISUAL_ROW_CNT) + 0.5;
|
val2_nr = (val2_perc * L_VISUAL_ROW_CNT) + 0.5;
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ struct win_cpu_types {
|
|||||||
struct hyptop_win *win_help;
|
struct hyptop_win *win_help;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hyptop_win *win_cpu_types_new(void);
|
struct hyptop_win *win_cpu_types_new(void);
|
||||||
|
|
||||||
#endif /* WIN_CPU_TYPES_H */
|
#endif /* WIN_CPU_TYPES_H */
|
||||||
|
|||||||
@@ -162,6 +162,22 @@ static void l_sys_item_add(struct table_row *table_row, struct sd_sys *sys,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void l_row_add_physical(struct table *t, struct sd_sys *sys)
|
||||||
|
{
|
||||||
|
struct sd_sys_item *item;
|
||||||
|
struct table_row *row;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
row = table_row_alloc(t);
|
||||||
|
table_row_entry_str_add(row, &l_col_sys, sd_sys_id(sys));
|
||||||
|
sd_phys_item_iterate(item, i) {
|
||||||
|
if (!sd_sys_item_set(sys, item))
|
||||||
|
continue;
|
||||||
|
l_sys_item_add(row, sys, item);
|
||||||
|
}
|
||||||
|
t->row_physical = row;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add system to table
|
* Add system to table
|
||||||
*/
|
*/
|
||||||
@@ -196,6 +212,8 @@ static void l_table_create(void)
|
|||||||
continue;
|
continue;
|
||||||
l_sys_add(guest);
|
l_sys_add(guest);
|
||||||
}
|
}
|
||||||
|
if (sd_dg_has_phys_data())
|
||||||
|
l_row_add_physical(l_t, parent);
|
||||||
table_finish(l_t);
|
table_finish(l_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +342,11 @@ static void l_run(struct hyptop_win *win)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void win_sys_list_set_phys_table_cols(void)
|
||||||
|
{
|
||||||
|
sd_sys_item_phys_mgm_diff.table_col = sd_sys_item_mgm_diff.table_col;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize window
|
* Initialize window
|
||||||
*/
|
*/
|
||||||
@@ -337,7 +360,7 @@ void win_sys_list_init(void)
|
|||||||
int item_cnt;
|
int item_cnt;
|
||||||
|
|
||||||
/* Alloc table and add columns */
|
/* Alloc table and add columns */
|
||||||
l_t = table_new(1, 1, 1, 1);
|
l_t = table_new(2, 1, 1, 1);
|
||||||
table_col_add(l_t, &l_col_sys);
|
table_col_add(l_t, &l_col_sys);
|
||||||
|
|
||||||
item_cnt = sd_sys_item_cnt() + 1;
|
item_cnt = sd_sys_item_cnt() + 1;
|
||||||
@@ -351,6 +374,8 @@ void win_sys_list_init(void)
|
|||||||
col_vec[i] = col;
|
col_vec[i] = col;
|
||||||
col_desc_vec[i] = item->desc;
|
col_desc_vec[i] = item->desc;
|
||||||
}
|
}
|
||||||
|
if (sd_dg_has_phys_data())
|
||||||
|
win_sys_list_set_phys_table_cols();
|
||||||
/* Enable fields */
|
/* Enable fields */
|
||||||
if (win_sys_list.opts.fields.specified)
|
if (win_sys_list.opts.fields.specified)
|
||||||
l_fields_enable_cmdline();
|
l_fields_enable_cmdline();
|
||||||
|
|||||||
@@ -31,11 +31,9 @@
|
|||||||
#define ECKD2DUMP_STACK_SIZE _AC(0x2000, UL)
|
#define ECKD2DUMP_STACK_SIZE _AC(0x2000, UL)
|
||||||
#define STAGE2_MAX_SIZE _AC(0x3000, UL)
|
#define STAGE2_MAX_SIZE _AC(0x3000, UL)
|
||||||
|
|
||||||
#define STAGE2_DUMPER_SIZE_V1 _AC(0x1000, UL)
|
#define STAGE2_DUMPER_SIZE_SV _AC(0x3000, UL)
|
||||||
#define STAGE2_DUMPER_SIZE_V2 _AC(0x2000, UL)
|
|
||||||
#define STAGE2_DUMPER_SIZE_V3 _AC(0x3000, UL)
|
|
||||||
#define STAGE2_DUMPER_SIZE_MV _AC(0x4000, UL)
|
#define STAGE2_DUMPER_SIZE_MV _AC(0x4000, UL)
|
||||||
#define STAGE2_DUMPER_SIZE_ZLIB _AC(0x8000, UL)
|
#define STAGE2_DUMPER_SIZE_SV_ZLIB _AC(0x8000, UL)
|
||||||
|
|
||||||
#define STAGE3_ENTRY _AC(0xa000, UL)
|
#define STAGE3_ENTRY _AC(0xa000, UL)
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#define UNPACK_FACILITY _AC(161, U)
|
#define UNPACK_FACILITY _AC(161, U)
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
#include <asm/types.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -380,18 +381,6 @@ static __always_inline int is_zvm(void)
|
|||||||
return cpuid.version == 0xff;
|
return cpuid.version == 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To avoid conflicts add a macro guard since __vector128 is also
|
|
||||||
* defined in 'linux/asm/types.h'.
|
|
||||||
*/
|
|
||||||
#ifndef _S390_TYPES_H
|
|
||||||
/*
|
|
||||||
* Vector register definition
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
uint32_t u[4];
|
|
||||||
} __vector128;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save vector registers
|
* Save vector registers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -27,16 +27,9 @@
|
|||||||
#define DF_S390_CPU_MAX 512
|
#define DF_S390_CPU_MAX 512
|
||||||
#define DF_S390_MAGIC_BLK_ECKD 3
|
#define DF_S390_MAGIC_BLK_ECKD 3
|
||||||
#define DF_S390_DUMPER_MAGIC_SIZE 7
|
#define DF_S390_DUMPER_MAGIC_SIZE 7
|
||||||
#define DF_S390_DUMPER_MAGIC32 "ZECKD31"
|
|
||||||
#define DF_S390_DUMPER_MAGIC64 "ZECKD64"
|
|
||||||
#define DF_S390_DUMPER_MAGIC_EXT "XECKD64"
|
#define DF_S390_DUMPER_MAGIC_EXT "XECKD64"
|
||||||
#define DF_S390_DUMPER_MAGIC32_FBA "ZDFBA31"
|
|
||||||
#define DF_S390_DUMPER_MAGIC64_FBA "ZDFBA64"
|
|
||||||
#define DF_S390_DUMPER_MAGIC_FBA_EXT "XDFBA64"
|
#define DF_S390_DUMPER_MAGIC_FBA_EXT "XDFBA64"
|
||||||
#define DF_S390_DUMPER_MAGIC_MV "ZMULT64"
|
|
||||||
#define DF_S390_DUMPER_MAGIC_MV_EXT "XMULT64"
|
#define DF_S390_DUMPER_MAGIC_MV_EXT "XMULT64"
|
||||||
#define OLD_DUMPER_HEX_INSTR1 "\x0d\x10\x47\xf0" /* BASR + 1st halfword of BC */
|
|
||||||
#define OLD_DUMPER_HEX_INSTR2 "\x0d\xd0" /* BASR 13,0 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Architecture of dumped system
|
* Architecture of dumped system
|
||||||
|
|||||||
@@ -379,6 +379,25 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
|
|||||||
const char *cert_pem_filename,
|
const char *cert_pem_filename,
|
||||||
const struct ekmf_ext_lib *ext_lib, bool verbose);
|
const struct ekmf_ext_lib *ext_lib, bool verbose);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates that a certificate has the same public key as the secure identity
|
||||||
|
* key (field identity_secure_key in config structure) .
|
||||||
|
*
|
||||||
|
* @param config the configuration structure. Only field
|
||||||
|
* identity_secure_key must be specified, all others
|
||||||
|
* are optional.
|
||||||
|
* @param x509_cert the X509 certificate object to validate
|
||||||
|
* @param ext_lib External secure key crypto library to use
|
||||||
|
* @param verbose if true, verbose messages are printed
|
||||||
|
*
|
||||||
|
* @returns a negative errno in case of an error, 0 if success.
|
||||||
|
* -EINVAL: invalid parameter, or certificate is not valid
|
||||||
|
* -ENOMEM: Failed to allocate memory
|
||||||
|
* any other errno from file I/O routines
|
||||||
|
*/
|
||||||
|
int ekmf_validate_cert(const struct ekmf_config *config, const X509 *x509_cert,
|
||||||
|
const struct ekmf_ext_lib *ext_lib, bool verbose);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves settings from the EKMFWeb server, such as the template names for
|
* Retrieves settings from the EKMFWeb server, such as the template names for
|
||||||
* generating keys in EKMFWeb.
|
* generating keys in EKMFWeb.
|
||||||
|
|||||||
@@ -9,17 +9,38 @@
|
|||||||
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
|
||||||
#define S390_CPUMF_CF "/sys/devices/cpum_cf/"
|
#define S390_CPUMF_CF "devices/cpum_cf/"
|
||||||
#define S390_CPUMF_CFDIAG "/sys/devices/cpum_cf_diag/"
|
#define S390_CPUMF_CFDIAG "devices/cpum_cf_diag/"
|
||||||
#define S390_CPUMF_SF "/sys/devices/cpum_sf/"
|
#define S390_CPUMF_SF "devices/cpum_sf/"
|
||||||
#define S390_CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
|
#define S390_CPUS_ONLINE "devices/system/cpu/online"
|
||||||
#define S390_CPUS_ONLINE "/sys/devices/system/cpu/online"
|
#define S390_CPUMSF_BUFFERSZ "module/kernel/parameters/cpum_sfb_size"
|
||||||
#define S390_CPUMSF_BUFFERSZ "/sys/module/kernel/parameters/cpum_sfb_size"
|
#define S390_SYSFS_PAI_CRYPTO "devices/pai_crypto/"
|
||||||
#define S390_SYSFS_PAI_CRYPTO "/sys/devices/pai_crypto/"
|
#define S390_SYSFS_PAI_EXT "devices/pai_ext/"
|
||||||
#define S390_SYSFS_PAI_EXT "/sys/devices/pai_ext/"
|
|
||||||
#define S390_SYSFS_PAI_NNPA S390_SYSFS_PAI_EXT "events/NNPA_ALL"
|
#define S390_SYSFS_PAI_NNPA S390_SYSFS_PAI_EXT "events/NNPA_ALL"
|
||||||
|
|
||||||
|
#define CPUMF_CTRSET_NONE 0
|
||||||
|
#define CPUMF_CTRSET_EXTENDED 1
|
||||||
|
#define CPUMF_CTRSET_BASIC 2
|
||||||
|
#define CPUMF_CTRSET_PROBLEM_STATE 4
|
||||||
|
#define CPUMF_CTRSET_CRYPTO 8
|
||||||
|
#define CPUMF_CTRSET_MT_DIAG 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return counter set a counter belongs to.
|
||||||
|
*
|
||||||
|
* Return the counter set a given counter belongs to, given the
|
||||||
|
* CPU Measurement facility counter version first and second number.
|
||||||
|
*
|
||||||
|
* @param[in] ctr Counter number
|
||||||
|
* @param[in] cfvn CPUM Counter facility first version number
|
||||||
|
* @param[in] csvn CPUM Counter facility second version number
|
||||||
|
* @retval >=0 Counter set number to counter belongs to
|
||||||
|
*/
|
||||||
|
int libcpumf_ctrset(int ctr, int cfvn, int csvn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read out the PMU type from a given file.
|
* Read out the PMU type from a given file.
|
||||||
*
|
*
|
||||||
@@ -96,7 +117,7 @@ bool libcpumf_have_cpumcf(void);
|
|||||||
*
|
*
|
||||||
* @param[out] min Minimum supported sampling interval
|
* @param[out] min Minimum supported sampling interval
|
||||||
* @param[out] max Maximum supported sampling interval
|
* @param[out] max Maximum supported sampling interval
|
||||||
* @param[out] speed Current CPU speed, number of CPU cylces per
|
* @param[out] speed Current CPU speed, number of CPU cycles per
|
||||||
* microsecond
|
* microsecond
|
||||||
* @param[out] basic_sz Basic sample size in bytes
|
* @param[out] basic_sz Basic sample size in bytes
|
||||||
* @param[out] diag_sz Diagnostic sample size in bytes
|
* @param[out] diag_sz Diagnostic sample size in bytes
|
||||||
@@ -163,4 +184,37 @@ bool libcpumf_have_pai_ext(void);
|
|||||||
* @retval false PAI_NNPA counter Facility is not available
|
* @retval false PAI_NNPA counter Facility is not available
|
||||||
*/
|
*/
|
||||||
bool libcpumf_have_pai_nnpa(void);
|
bool libcpumf_have_pai_nnpa(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper for the perf_event_open syscall used to configure performance events.
|
||||||
|
* This function simplifies usage of perf_event_open and provides a consistent
|
||||||
|
* interface for libcpumf internals.
|
||||||
|
*
|
||||||
|
* @param hw_event Pointer to perf_event_attr structure describing the event
|
||||||
|
* @param pid Target process ID (0 for current process)
|
||||||
|
* @param cpu Target CPU (-1 for all CPUs)
|
||||||
|
* @param group_fd File descriptor of event group leader, or -1 if none
|
||||||
|
* @param flags Additional flags (usually 0)
|
||||||
|
*
|
||||||
|
* @return File descriptor for the opened event on success
|
||||||
|
* @return -1 on failure, errno is set appropriately
|
||||||
|
*/
|
||||||
|
|
||||||
|
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd,
|
||||||
|
unsigned long flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a counter name is present in a comma-separated list of counters.
|
||||||
|
*
|
||||||
|
* This function checks whether the given counter name appears in the
|
||||||
|
* provided list. If the list is NULL, the function assumes all counters
|
||||||
|
* are allowed and returns true.
|
||||||
|
*
|
||||||
|
* @param name Name of the counter to search for
|
||||||
|
* @param ctrlist Comma-separated list of counter names, or NULL
|
||||||
|
*
|
||||||
|
* @return true if the counter is in the list or list is NULL
|
||||||
|
* @return false otherwise
|
||||||
|
*/
|
||||||
|
bool ctr_in_list(char *name, char *ctrlist);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ enum util_arch_machine_type {
|
|||||||
UTIL_ARCH_MACHINE_TYPE_Z15_T02 = 8562,
|
UTIL_ARCH_MACHINE_TYPE_Z15_T02 = 8562,
|
||||||
UTIL_ARCH_MACHINE_TYPE_Z16 = 3931,
|
UTIL_ARCH_MACHINE_TYPE_Z16 = 3931,
|
||||||
UTIL_ARCH_MACHINE_TYPE_Z16_A02 = 3932,
|
UTIL_ARCH_MACHINE_TYPE_Z16_A02 = 3932,
|
||||||
|
UTIL_ARCH_MACHINE_TYPE_Z17 = 9175,
|
||||||
|
UTIL_ARCH_MACHINE_TYPE_Z17_2 = 9176,
|
||||||
};
|
};
|
||||||
|
|
||||||
int util_arch_machine_type(void);
|
int util_arch_machine_type(void);
|
||||||
|
|||||||
22
include/lib/util_autocomp.h
Normal file
22
include/lib/util_autocomp.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* autocomp - command line autocompletion
|
||||||
|
*
|
||||||
|
* Generating autocompletion scripts for bash and zsh
|
||||||
|
* based on util_opt struct
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LIB_UTIL_AUTOCOMP_H
|
||||||
|
#define LIB_UTIL_AUTOCOMP_H
|
||||||
|
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
|
||||||
|
void generate_autocomp(struct util_opt *opt_vec, char *tool_name);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#ifndef LIB_UTIL_LIBC_H
|
#ifndef LIB_UTIL_LIBC_H
|
||||||
#define LIB_UTIL_LIBC_H
|
#define LIB_UTIL_LIBC_H
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -45,7 +46,7 @@ void *__util_zalloc(const char *func, const char *file, int line, size_t size);
|
|||||||
/**
|
/**
|
||||||
* Re-allocate memory or exit in case of failure
|
* Re-allocate memory or exit in case of failure
|
||||||
*
|
*
|
||||||
* @param[in] ptr Pointer ot old memory buffer
|
* @param[in] ptr Pointer to old memory buffer
|
||||||
* @param[in] size Number of bytes to be allocated
|
* @param[in] size Number of bytes to be allocated
|
||||||
*
|
*
|
||||||
* @returns Pointer to memory buffer created with realloc()
|
* @returns Pointer to memory buffer created with realloc()
|
||||||
@@ -124,6 +125,29 @@ do { \
|
|||||||
va_end(ap); \
|
va_end(ap); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the target of a symbolic link at the given path.
|
||||||
|
*
|
||||||
|
* @param[in] path Path to the symbolic link
|
||||||
|
* @return Newly allocated string with the link target, or NULL on error
|
||||||
|
*/
|
||||||
|
#define util_readlink(path) __util_readlinkat(__func__, __FILE__, __LINE__, AT_FDCWD, path)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the target of a symbolic link relative to a directory file descriptor.
|
||||||
|
*
|
||||||
|
* Semantics:
|
||||||
|
* - If path is absolute, dirfd is ignored, per readlinkat semantics.
|
||||||
|
* - If path is relative, it is resolved relative to dirfd.
|
||||||
|
*
|
||||||
|
* @param[in] dirfd Directory file descriptor or AT_FDCWD
|
||||||
|
* @param[in] path Path to the symbolic link
|
||||||
|
* @return Newly allocated string with the link target, or NULL on error
|
||||||
|
*/
|
||||||
|
#define util_readlinkat(dirfd, path) __util_readlinkat(__func__, __FILE__, __LINE__, dirfd, path)
|
||||||
|
|
||||||
|
char *__util_readlinkat(const char *func, const char *file, int line, int dirfd, const char *path);
|
||||||
|
|
||||||
int __util_vsprintf(const char *func, const char *file, int line,
|
int __util_vsprintf(const char *func, const char *file, int line,
|
||||||
char *str, const char *fmt, va_list ap);
|
char *str, const char *fmt, va_list ap);
|
||||||
char *util_strcat_realloc(char *str1, const char *str2);
|
char *util_strcat_realloc(char *str1, const char *str2);
|
||||||
|
|||||||
58
include/lib/util_parse.h
Normal file
58
include/lib/util_parse.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* util - Utility function library
|
||||||
|
*
|
||||||
|
* String parsing utility functions
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2026
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_UTIL_PARSE_H
|
||||||
|
#define LIB_UTIL_PARSE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct util_range {
|
||||||
|
size_t start;
|
||||||
|
size_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse a boolean input string into a boolean value
|
||||||
|
* Accepts: "0"/"1", "n"/"y", "no"/"yes", "f"/"t", "false"/"true", "off"/"on"
|
||||||
|
* Case-insensitive
|
||||||
|
* @param input: Input string to parse
|
||||||
|
* @return: 1 for true, 0 for false, -EINVAL for invalid input
|
||||||
|
*/
|
||||||
|
int util_parse_bool(const char *input);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse byte sizes with optional unit suffixes
|
||||||
|
* Supports: K/KiB, M/MiB, G/GiB, T/TiB, P/PiB, E/EiB
|
||||||
|
* K/M/G/T/P/E use 1000-based multipliers
|
||||||
|
* KiB/MiB/GiB/TiB/PiB/EiB use 1024-based multipliers
|
||||||
|
* @param input: Input string to parse
|
||||||
|
* @param bytes: Pointer to store parsed byte size
|
||||||
|
* @return: 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int util_parse_byte_size(const char *input, size_t *bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse numeric ranges in the format "start-end"
|
||||||
|
* @param input: Input string to parse (format: "start-end")
|
||||||
|
* @param range: Pointer to util_range struct to store result
|
||||||
|
* @return: 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int util_parse_range(const char *input, struct util_range *range);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse integers with support for different bases
|
||||||
|
* Supports: decimal, hex (0x prefix), binary (0b prefix), octal (0o prefix)
|
||||||
|
* @param input: Input string to parse
|
||||||
|
* @param value: Pointer to store parsed integer value
|
||||||
|
* @return: 0 on success, negative error code on failure
|
||||||
|
*/
|
||||||
|
int util_parse_int(const char *input, size_t *value);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -31,6 +31,7 @@ struct util_proc_dev_entry {
|
|||||||
#define UTIL_PROC_DEV_ENTRY_SD "sd"
|
#define UTIL_PROC_DEV_ENTRY_SD "sd"
|
||||||
#define UTIL_PROC_DEV_ENTRY_BLKEXT "blkext"
|
#define UTIL_PROC_DEV_ENTRY_BLKEXT "blkext"
|
||||||
#define UTIL_PROC_DEV_ENTRY_MD "md"
|
#define UTIL_PROC_DEV_ENTRY_MD "md"
|
||||||
|
#define UTIL_PROC_DEV_ENTRY_DM "device-mapper"
|
||||||
|
|
||||||
int util_proc_part_get_entry(dev_t device, struct util_proc_part_entry *entry);
|
int util_proc_part_get_entry(dev_t device, struct util_proc_part_entry *entry);
|
||||||
void util_proc_part_free_entry(struct util_proc_part_entry *entry);
|
void util_proc_part_free_entry(struct util_proc_part_entry *entry);
|
||||||
|
|||||||
19
include/lib/util_str.h
Normal file
19
include/lib/util_str.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* @defgroup util_str_h util_str: String functions
|
||||||
|
* @{
|
||||||
|
* @brief Manipulate and work with strings
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LIB_UTIL_STR_H
|
||||||
|
#define LIB_UTIL_STR_H
|
||||||
|
|
||||||
|
void util_str_rm_whitespace(const char *src, char *dest);
|
||||||
|
const char *util_startswith(const char *s, const char *prefix);
|
||||||
|
const char *util_startswith_no_case(const char *s, const char *prefix);
|
||||||
|
|
||||||
|
#endif /** LIB_UTIL_STR_H @} */
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#define LIB_UTIL_SYS_H
|
#define LIB_UTIL_SYS_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
int util_sys_get_dev_addr(const char *dev, char *addr);
|
int util_sys_get_dev_addr(const char *dev, char *addr);
|
||||||
bool util_sys_dev_is_partition(dev_t dev);
|
bool util_sys_dev_is_partition(dev_t dev);
|
||||||
|
|||||||
202
include/lib/util_time.h
Normal file
202
include/lib/util_time.h
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* util_time - Time related helper functions and definitions
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2025
|
||||||
|
*
|
||||||
|
* 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 LIB_UTIL_TIME_H
|
||||||
|
#define LIB_UTIL_TIME_H
|
||||||
|
|
||||||
|
#define NSEC_PER_USEC 1000L
|
||||||
|
#define NSEC_PER_MSEC 1000000L
|
||||||
|
#define NSEC_PER_SEC 1000000000L
|
||||||
|
|
||||||
|
#define USEC_PER_MSEC 1000L
|
||||||
|
#define USEC_PER_SEC 1000000L
|
||||||
|
|
||||||
|
#define MSEC_PER_SEC 1000L
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert nanoseconds to microseconds
|
||||||
|
*
|
||||||
|
* Convert value from nanoseconds to microseconds by dividing the
|
||||||
|
* value to NSEC_PER_USEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in nanoseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in microseconds
|
||||||
|
*/
|
||||||
|
static inline double util_nsecs_to_usecs(double val)
|
||||||
|
{
|
||||||
|
return val / NSEC_PER_USEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert nanoseconds to milliseconds
|
||||||
|
*
|
||||||
|
* Convert value from nanoseconds to milliseconds by dividing the
|
||||||
|
* value to NSEC_PER_MSEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in nanoseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in milliseconds
|
||||||
|
*/
|
||||||
|
static inline double util_nsecs_to_msecs(double val)
|
||||||
|
{
|
||||||
|
return val / NSEC_PER_MSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert nanoseconds to seconds
|
||||||
|
*
|
||||||
|
* Convert value from nanoseconds to seconds by dividing the
|
||||||
|
* value to NSEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in nanoseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in seconds
|
||||||
|
*/
|
||||||
|
static inline double util_nsecs_to_secs(double val)
|
||||||
|
{
|
||||||
|
return val / NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert microseconds to nanoseconds
|
||||||
|
*
|
||||||
|
* Convert value from microseconds to nanoseconds by multiplying the
|
||||||
|
* value with NSEC_PER_USEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in microseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in nanoseconds
|
||||||
|
*/
|
||||||
|
static inline double util_usecs_to_nsecs(double val)
|
||||||
|
{
|
||||||
|
return val * NSEC_PER_USEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert microseconds to milliseconds
|
||||||
|
*
|
||||||
|
* Convert value from microseconds to milliseconds by dividing the
|
||||||
|
* value to USEC_PER_MSEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in microseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in milliseconds
|
||||||
|
*/
|
||||||
|
static inline double util_usecs_to_msecs(double val)
|
||||||
|
{
|
||||||
|
return val / USEC_PER_MSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert microseconds to seconds
|
||||||
|
*
|
||||||
|
* Convert value from microseconds to seconds by dividing the
|
||||||
|
* value to USEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in nanoseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in seconds
|
||||||
|
*/
|
||||||
|
static inline double util_usecs_to_secs(double val)
|
||||||
|
{
|
||||||
|
return val / USEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert milliseconds to nanoseconds
|
||||||
|
*
|
||||||
|
* Convert value from milliseconds to nanoseconds by multiplying the
|
||||||
|
* value with NSEC_PER_MSEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in milliseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in nanoseconds
|
||||||
|
*/
|
||||||
|
static inline double util_msecs_to_nsecs(double val)
|
||||||
|
{
|
||||||
|
return val * NSEC_PER_MSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert milliseconds to microseconds
|
||||||
|
*
|
||||||
|
* Convert value from milliseconds to microseconds by multiplying the
|
||||||
|
* value with USEC_PER_MSEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in milliseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in microseconds
|
||||||
|
*/
|
||||||
|
static inline double util_msecs_to_usecs(double val)
|
||||||
|
{
|
||||||
|
return val * USEC_PER_MSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert milliseconds to seconds
|
||||||
|
*
|
||||||
|
* Convert value from milliseconds to seconds by dividing the
|
||||||
|
* value to MSEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in milliseconds
|
||||||
|
*
|
||||||
|
* @returns Time value in seconds
|
||||||
|
*/
|
||||||
|
static inline double util_msecs_to_secs(double val)
|
||||||
|
{
|
||||||
|
return val / MSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert seconds to nanoseconds
|
||||||
|
*
|
||||||
|
* Convert value from seconds to nanoseconds by multiplying the
|
||||||
|
* value with NSEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in seconds
|
||||||
|
*
|
||||||
|
* @returns Time value in nanoseconds
|
||||||
|
*/
|
||||||
|
static inline double util_secs_to_nsecs(double val)
|
||||||
|
{
|
||||||
|
return val * NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert seconds to microseconds
|
||||||
|
*
|
||||||
|
* Convert value from seconds to microseconds by multiplying the
|
||||||
|
* value with USEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in seconds
|
||||||
|
*
|
||||||
|
* @returns Time value in microseconds
|
||||||
|
*/
|
||||||
|
static inline double util_secs_to_usecs(double val)
|
||||||
|
{
|
||||||
|
return val * USEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert seconds to milliseconds
|
||||||
|
*
|
||||||
|
* Convert value from seconds to milliseconds by multiplying the
|
||||||
|
* value with MSEC_PER_SEC constant.
|
||||||
|
*
|
||||||
|
* @param[in] val Time value in seconds
|
||||||
|
*
|
||||||
|
* @returns Time value in milliseconds
|
||||||
|
*/
|
||||||
|
static inline double util_secs_to_msecs(double val)
|
||||||
|
{
|
||||||
|
return val * MSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LIB_UTIL_TIME_H */
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -44,27 +45,27 @@
|
|||||||
|
|
||||||
typedef struct ttr
|
typedef struct ttr
|
||||||
{
|
{
|
||||||
u_int16_t tt;
|
uint16_t tt;
|
||||||
u_int8_t r;
|
uint8_t r;
|
||||||
} __attribute__ ((packed)) ttr_t;
|
} __attribute__ ((packed)) ttr_t;
|
||||||
|
|
||||||
typedef struct cchhb
|
typedef struct cchhb
|
||||||
{
|
{
|
||||||
u_int16_t cc;
|
uint16_t cc;
|
||||||
u_int16_t hh;
|
uint16_t hh;
|
||||||
u_int8_t b;
|
uint8_t b;
|
||||||
} __attribute__ ((packed)) cchhb_t;
|
} __attribute__ ((packed)) cchhb_t;
|
||||||
|
|
||||||
typedef struct cchh
|
typedef struct cchh
|
||||||
{
|
{
|
||||||
u_int16_t cc;
|
uint16_t cc;
|
||||||
u_int16_t hh;
|
uint16_t hh;
|
||||||
} __attribute__ ((packed)) cchh_t;
|
} __attribute__ ((packed)) cchh_t;
|
||||||
|
|
||||||
typedef struct labeldate
|
typedef struct labeldate
|
||||||
{
|
{
|
||||||
u_int8_t year;
|
uint8_t year;
|
||||||
u_int16_t day;
|
uint16_t day;
|
||||||
} __attribute__ ((packed)) labeldate_t;
|
} __attribute__ ((packed)) labeldate_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -84,7 +85,7 @@ typedef struct volume_label
|
|||||||
char volkey[4]; /* volume key = volume label */
|
char volkey[4]; /* volume key = volume label */
|
||||||
char vollbl[4]; /* volume label */
|
char vollbl[4]; /* volume label */
|
||||||
char volid[6]; /* volume identifier */
|
char volid[6]; /* volume identifier */
|
||||||
u_int8_t security; /* security byte */
|
uint8_t security; /* security byte */
|
||||||
cchhb_t vtoc; /* VTOC address */
|
cchhb_t vtoc; /* VTOC address */
|
||||||
char res1[5]; /* reserved */
|
char res1[5]; /* reserved */
|
||||||
char cisize[4]; /* CI-size for FBA,... */
|
char cisize[4]; /* CI-size for FBA,... */
|
||||||
@@ -118,8 +119,8 @@ static inline int is_vol1(char *this)
|
|||||||
|
|
||||||
typedef struct extent
|
typedef struct extent
|
||||||
{
|
{
|
||||||
u_int8_t typeind; /* extent type indicator */
|
uint8_t typeind; /* extent type indicator */
|
||||||
u_int8_t seqno; /* extent sequence number */
|
uint8_t seqno; /* extent sequence number */
|
||||||
cchh_t llimit; /* starting point of this extent */
|
cchh_t llimit; /* starting point of this extent */
|
||||||
cchh_t ulimit; /* ending point of this extent */
|
cchh_t ulimit; /* ending point of this extent */
|
||||||
} __attribute__ ((packed)) extent_t;
|
} __attribute__ ((packed)) extent_t;
|
||||||
@@ -127,16 +128,16 @@ typedef struct extent
|
|||||||
|
|
||||||
typedef struct dev_const
|
typedef struct dev_const
|
||||||
{
|
{
|
||||||
u_int16_t DS4DSCYL; /* number of logical cyls */
|
uint16_t DS4DSCYL; /* number of logical cyls */
|
||||||
u_int16_t DS4DSTRK; /* number of tracks in a logical cylinder */
|
uint16_t DS4DSTRK; /* number of tracks in a logical cylinder */
|
||||||
u_int16_t DS4DEVTK; /* device track length */
|
uint16_t DS4DEVTK; /* device track length */
|
||||||
u_int8_t DS4DEVI; /* non-last keyed record overhead */
|
uint8_t DS4DEVI; /* non-last keyed record overhead */
|
||||||
u_int8_t DS4DEVL; /* last keyed record overhead */
|
uint8_t DS4DEVL; /* last keyed record overhead */
|
||||||
u_int8_t DS4DEVK; /* non-keyed record overhead differential */
|
uint8_t DS4DEVK; /* non-keyed record overhead differential */
|
||||||
u_int8_t DS4DEVFG; /* flag byte */
|
uint8_t DS4DEVFG; /* flag byte */
|
||||||
u_int16_t DS4DEVTL; /* device tolerance */
|
uint16_t DS4DEVTL; /* device tolerance */
|
||||||
u_int8_t DS4DEVDT; /* number of DSCB's per track */
|
uint8_t DS4DEVDT; /* number of DSCB's per track */
|
||||||
u_int8_t DS4DEVDB; /* number of directory blocks per track */
|
uint8_t DS4DEVDB; /* number of directory blocks per track */
|
||||||
} __attribute__ ((packed)) dev_const_t;
|
} __attribute__ ((packed)) dev_const_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -146,33 +147,33 @@ typedef struct dev_const
|
|||||||
typedef struct format1_label
|
typedef struct format1_label
|
||||||
{
|
{
|
||||||
char DS1DSNAM[44]; /* data set name */
|
char DS1DSNAM[44]; /* data set name */
|
||||||
u_int8_t DS1FMTID; /* format identifier */
|
uint8_t DS1FMTID; /* format identifier */
|
||||||
unsigned char DS1DSSN[6];/* data set serial number */
|
unsigned char DS1DSSN[6];/* data set serial number */
|
||||||
u_int16_t DS1VOLSQ; /* volume sequence number */
|
uint16_t DS1VOLSQ; /* volume sequence number */
|
||||||
labeldate_t DS1CREDT; /* creation date: ydd */
|
labeldate_t DS1CREDT; /* creation date: ydd */
|
||||||
labeldate_t DS1EXPDT; /* expiration date */
|
labeldate_t DS1EXPDT; /* expiration date */
|
||||||
u_int8_t DS1NOEPV; /* number of extents on volume */
|
uint8_t DS1NOEPV; /* number of extents on volume */
|
||||||
u_int8_t DS1NOBDB; /* no. of bytes used in last direction blk */
|
uint8_t DS1NOBDB; /* no. of bytes used in last direction blk */
|
||||||
u_int8_t DS1FLAG1; /* flag 1 */
|
uint8_t DS1FLAG1; /* flag 1 */
|
||||||
unsigned char DS1SYSCD[13]; /* system code */
|
unsigned char DS1SYSCD[13]; /* system code */
|
||||||
labeldate_t DS1REFD; /* date last referenced */
|
labeldate_t DS1REFD; /* date last referenced */
|
||||||
u_int8_t DS1SMSFG; /* system managed storage indicators */
|
uint8_t DS1SMSFG; /* system managed storage indicators */
|
||||||
u_int8_t DS1SCXTF; /* sec. space extension flag byte */
|
uint8_t DS1SCXTF; /* sec. space extension flag byte */
|
||||||
u_int16_t DS1SCXTV; /* secondary space extension value */
|
uint16_t DS1SCXTV; /* secondary space extension value */
|
||||||
u_int8_t DS1DSRG1; /* data set organisation byte 1 */
|
uint8_t DS1DSRG1; /* data set organisation byte 1 */
|
||||||
u_int8_t DS1DSRG2; /* data set organisation byte 2 */
|
uint8_t DS1DSRG2; /* data set organisation byte 2 */
|
||||||
u_int8_t DS1RECFM; /* record format */
|
uint8_t DS1RECFM; /* record format */
|
||||||
u_int8_t DS1OPTCD; /* option code */
|
uint8_t DS1OPTCD; /* option code */
|
||||||
u_int16_t DS1BLKL; /* block length */
|
uint16_t DS1BLKL; /* block length */
|
||||||
u_int16_t DS1LRECL; /* record length */
|
uint16_t DS1LRECL; /* record length */
|
||||||
u_int8_t DS1KEYL; /* key length */
|
uint8_t DS1KEYL; /* key length */
|
||||||
u_int16_t DS1RKP; /* relative key position */
|
uint16_t DS1RKP; /* relative key position */
|
||||||
u_int8_t DS1DSIND; /* data set indicators */
|
uint8_t DS1DSIND; /* data set indicators */
|
||||||
u_int8_t DS1SCAL1; /* secondary allocation flag byte */
|
uint8_t DS1SCAL1; /* secondary allocation flag byte */
|
||||||
char DS1SCAL3[3]; /* secondary allocation quantity */
|
char DS1SCAL3[3]; /* secondary allocation quantity */
|
||||||
ttr_t DS1LSTAR; /* last used track and block on track */
|
ttr_t DS1LSTAR; /* last used track and block on track */
|
||||||
u_int16_t DS1TRBAL; /* space remaining on last used track */
|
uint16_t DS1TRBAL; /* space remaining on last used track */
|
||||||
u_int16_t res1; /* reserved */
|
uint16_t res1; /* reserved */
|
||||||
extent_t DS1EXT1; /* first extent description */
|
extent_t DS1EXT1; /* first extent description */
|
||||||
extent_t DS1EXT2; /* second extent description */
|
extent_t DS1EXT2; /* second extent description */
|
||||||
extent_t DS1EXT3; /* third extent description */
|
extent_t DS1EXT3; /* third extent description */
|
||||||
@@ -184,7 +185,7 @@ typedef struct format3_label
|
|||||||
{
|
{
|
||||||
char DS3KEYID[4]; /* key identifier */
|
char DS3KEYID[4]; /* key identifier */
|
||||||
extent_t DS3EXTNT[4]; /* first 4 extent descriptions */
|
extent_t DS3EXTNT[4]; /* first 4 extent descriptions */
|
||||||
u_int8_t DS3FMTID; /* format identifier */
|
uint8_t DS3FMTID; /* format identifier */
|
||||||
extent_t DS3ADEXT[9]; /* last 9 extent description */
|
extent_t DS3ADEXT[9]; /* last 9 extent description */
|
||||||
cchhb_t DS3PTRDS; /* pointer to next format3 DSCB */
|
cchhb_t DS3PTRDS; /* pointer to next format3 DSCB */
|
||||||
} __attribute__ ((packed)) format3_label_t;
|
} __attribute__ ((packed)) format3_label_t;
|
||||||
@@ -193,15 +194,15 @@ typedef struct format3_label
|
|||||||
typedef struct format4_label
|
typedef struct format4_label
|
||||||
{
|
{
|
||||||
char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */
|
char DS4KEYCD[44]; /* key code for VTOC labels: 44 times 0x04 */
|
||||||
u_int8_t DS4IDFMT; /* format identifier */
|
uint8_t DS4IDFMT; /* format identifier */
|
||||||
cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */
|
cchhb_t DS4HPCHR; /* highest address of a format 1 DSCB */
|
||||||
u_int16_t DS4DSREC; /* number of available DSCB's */
|
uint16_t DS4DSREC; /* number of available DSCB's */
|
||||||
cchh_t DS4HCCHH; /* CCHH of next available alternate track */
|
cchh_t DS4HCCHH; /* CCHH of next available alternate track */
|
||||||
u_int16_t DS4NOATK; /* number of remaining alternate tracks */
|
uint16_t DS4NOATK; /* number of remaining alternate tracks */
|
||||||
u_int8_t DS4VTOCI; /* VTOC indicators */
|
uint8_t DS4VTOCI; /* VTOC indicators */
|
||||||
u_int8_t DS4NOEXT; /* number of extents in VTOC */
|
uint8_t DS4NOEXT; /* number of extents in VTOC */
|
||||||
u_int8_t DS4SMSFG; /* system managed storage indicators */
|
uint8_t DS4SMSFG; /* system managed storage indicators */
|
||||||
u_int8_t DS4DEVAC; /* number of alternate cylinders.
|
uint8_t DS4DEVAC; /* number of alternate cylinders.
|
||||||
Subtract from first two bytes of
|
Subtract from first two bytes of
|
||||||
DS4DEVSZ to get number of usable
|
DS4DEVSZ to get number of usable
|
||||||
cylinders. can be zero. valid
|
cylinders. can be zero. valid
|
||||||
@@ -214,21 +215,21 @@ typedef struct format4_label
|
|||||||
char DS4F6PTR[5]; /* pointer to first format 6 DSCB */
|
char DS4F6PTR[5]; /* pointer to first format 6 DSCB */
|
||||||
extent_t DS4VTOCE; /* VTOC extent description */
|
extent_t DS4VTOCE; /* VTOC extent description */
|
||||||
char res2[10]; /* reserved */
|
char res2[10]; /* reserved */
|
||||||
u_int8_t DS4EFLVL; /* extended free-space management level */
|
uint8_t DS4EFLVL; /* extended free-space management level */
|
||||||
cchhb_t DS4EFPTR; /* pointer to extended free-space info */
|
cchhb_t DS4EFPTR; /* pointer to extended free-space info */
|
||||||
char res3; /* reserved */
|
char res3; /* reserved */
|
||||||
u_int32_t DS4DCYL; /* number of logical cyls */
|
uint32_t DS4DCYL; /* number of logical cyls */
|
||||||
char res4[2]; /* reserved */
|
char res4[2]; /* reserved */
|
||||||
u_int8_t DS4DEVF2; /* device flags */
|
uint8_t DS4DEVF2; /* device flags */
|
||||||
char res5; /* reserved */
|
char res5; /* reserved */
|
||||||
} __attribute__ ((packed)) format4_label_t;
|
} __attribute__ ((packed)) format4_label_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ds5ext
|
typedef struct ds5ext
|
||||||
{
|
{
|
||||||
u_int16_t t; /* RTA of the first track of free extent */
|
uint16_t t; /* RTA of the first track of free extent */
|
||||||
u_int16_t fc; /* number of whole cylinders in free ext. */
|
uint16_t fc; /* number of whole cylinders in free ext. */
|
||||||
u_int8_t ft; /* number of remaining free tracks */
|
uint8_t ft; /* number of remaining free tracks */
|
||||||
} __attribute__ ((packed)) ds5ext_t;
|
} __attribute__ ((packed)) ds5ext_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -237,7 +238,7 @@ typedef struct format5_label
|
|||||||
char DS5KEYID[4]; /* key identifier */
|
char DS5KEYID[4]; /* key identifier */
|
||||||
ds5ext_t DS5AVEXT; /* first available (free-space) extent. */
|
ds5ext_t DS5AVEXT; /* first available (free-space) extent. */
|
||||||
ds5ext_t DS5EXTAV[7]; /* seven available extents */
|
ds5ext_t DS5EXTAV[7]; /* seven available extents */
|
||||||
u_int8_t DS5FMTID; /* format identifier */
|
uint8_t DS5FMTID; /* format identifier */
|
||||||
ds5ext_t DS5MAVET[18]; /* eighteen available extents */
|
ds5ext_t DS5MAVET[18]; /* eighteen available extents */
|
||||||
cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */
|
cchhb_t DS5PTRDS; /* pointer to next format5 DSCB */
|
||||||
} __attribute__ ((packed)) format5_label_t;
|
} __attribute__ ((packed)) format5_label_t;
|
||||||
@@ -245,8 +246,8 @@ typedef struct format5_label
|
|||||||
|
|
||||||
typedef struct ds7ext
|
typedef struct ds7ext
|
||||||
{
|
{
|
||||||
u_int32_t a; /* starting RTA value */
|
uint32_t a; /* starting RTA value */
|
||||||
u_int32_t b; /* ending RTA value + 1 */
|
uint32_t b; /* ending RTA value + 1 */
|
||||||
} __attribute__ ((packed)) ds7ext_t;
|
} __attribute__ ((packed)) ds7ext_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -254,7 +255,7 @@ typedef struct format7_label
|
|||||||
{
|
{
|
||||||
char DS7KEYID[4]; /* key identifier */
|
char DS7KEYID[4]; /* key identifier */
|
||||||
ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */
|
ds7ext_t DS7EXTNT[5]; /* space for 5 extent descriptions */
|
||||||
u_int8_t DS7FMTID; /* format identifier */
|
uint8_t DS7FMTID; /* format identifier */
|
||||||
ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */
|
ds7ext_t DS7ADEXT[11]; /* space for 11 extent descriptions */
|
||||||
char res1[2]; /* reserved */
|
char res1[2]; /* reserved */
|
||||||
cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */
|
cchhb_t DS7PTRDS; /* pointer to next FMT7 DSCB */
|
||||||
@@ -263,12 +264,12 @@ typedef struct format7_label
|
|||||||
|
|
||||||
typedef struct format9_label
|
typedef struct format9_label
|
||||||
{
|
{
|
||||||
u_int8_t DS9KEYID; /* key code for format 9 labels (0x09) */
|
uint8_t DS9KEYID; /* key code for format 9 labels (0x09) */
|
||||||
u_int8_t DS9SUBTY; /* subtype (0x01) */
|
uint8_t DS9SUBTY; /* subtype (0x01) */
|
||||||
u_int8_t DS9NUMF9; /* number of F9 datasets */
|
uint8_t DS9NUMF9; /* number of F9 datasets */
|
||||||
u_int8_t res1[41]; /* reserved */
|
uint8_t res1[41]; /* reserved */
|
||||||
u_int8_t DS9FMTID; /* format identifier */
|
uint8_t DS9FMTID; /* format identifier */
|
||||||
u_int8_t res2[90]; /* reserved */
|
uint8_t res2[90]; /* reserved */
|
||||||
cchhb_t DS9PTRDS; /* pointer to next DSCB */
|
cchhb_t DS9PTRDS; /* pointer to next DSCB */
|
||||||
} __attribute__ ((packed)) format9_label_t;
|
} __attribute__ ((packed)) format9_label_t;
|
||||||
|
|
||||||
@@ -276,31 +277,31 @@ char * vtoc_ebcdic_enc (char *source, char *target, int l);
|
|||||||
char * vtoc_ebcdic_dec (char *source, char *target, int l);
|
char * vtoc_ebcdic_dec (char *source, char *target, int l);
|
||||||
void vtoc_set_extent (
|
void vtoc_set_extent (
|
||||||
extent_t * ext,
|
extent_t * ext,
|
||||||
u_int8_t typeind,
|
uint8_t typeind,
|
||||||
u_int8_t seqno,
|
uint8_t seqno,
|
||||||
cchh_t * lower,
|
cchh_t * lower,
|
||||||
cchh_t * upper);
|
cchh_t * upper);
|
||||||
void vtoc_set_cchh (
|
void vtoc_set_cchh (
|
||||||
cchh_t * addr,
|
cchh_t * addr,
|
||||||
u_int32_t cc,
|
uint32_t cc,
|
||||||
u_int16_t hh);
|
uint16_t hh);
|
||||||
u_int32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
|
uint32_t vtoc_get_cyl_from_cchh(cchh_t *addr);
|
||||||
u_int16_t vtoc_get_head_from_cchh(cchh_t *addr);
|
uint16_t vtoc_get_head_from_cchh(cchh_t *addr);
|
||||||
void vtoc_set_cchhb (
|
void vtoc_set_cchhb (
|
||||||
cchhb_t * addr,
|
cchhb_t * addr,
|
||||||
u_int32_t cc,
|
uint32_t cc,
|
||||||
u_int16_t hh,
|
uint16_t hh,
|
||||||
u_int8_t b);
|
uint8_t b);
|
||||||
u_int32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
|
uint32_t vtoc_get_cyl_from_cchhb(cchhb_t *addr);
|
||||||
u_int16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
|
uint16_t vtoc_get_head_from_cchhb(cchhb_t *addr);
|
||||||
u_int64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo);
|
uint64_t cchhb2blk(cchhb_t *p, struct hd_geometry *geo);
|
||||||
u_int64_t cchh2blk (cchh_t *p, struct hd_geometry *geo);
|
uint64_t cchh2blk (cchh_t *p, struct hd_geometry *geo);
|
||||||
u_int32_t cchh2trk (cchh_t *p, struct hd_geometry *geo);
|
uint32_t cchh2trk (cchh_t *p, struct hd_geometry *geo);
|
||||||
|
|
||||||
void vtoc_set_date (
|
void vtoc_set_date (
|
||||||
labeldate_t * d,
|
labeldate_t * d,
|
||||||
u_int8_t year,
|
uint8_t year,
|
||||||
u_int16_t day);
|
uint16_t day);
|
||||||
|
|
||||||
void vtoc_volume_label_init (
|
void vtoc_volume_label_init (
|
||||||
volume_label_t *vlabel);
|
volume_label_t *vlabel);
|
||||||
@@ -365,12 +366,12 @@ void vtoc_init_format4_label (
|
|||||||
unsigned int tracks,
|
unsigned int tracks,
|
||||||
unsigned int blocks,
|
unsigned int blocks,
|
||||||
unsigned int blksize,
|
unsigned int blksize,
|
||||||
u_int16_t dev_type);
|
uint16_t dev_type);
|
||||||
|
|
||||||
void vtoc_update_format4_label (
|
void vtoc_update_format4_label (
|
||||||
format4_label_t *f4,
|
format4_label_t *f4,
|
||||||
cchhb_t *highest_f1,
|
cchhb_t *highest_f1,
|
||||||
u_int16_t unused_update);
|
uint16_t unused_update);
|
||||||
|
|
||||||
void vtoc_init_format5_label (
|
void vtoc_init_format5_label (
|
||||||
format5_label_t *f5);
|
format5_label_t *f5);
|
||||||
@@ -379,17 +380,17 @@ void vtoc_update_format5_label_add (
|
|||||||
format5_label_t *f5,
|
format5_label_t *f5,
|
||||||
int verbose,
|
int verbose,
|
||||||
int trk,
|
int trk,
|
||||||
u_int16_t a,
|
uint16_t a,
|
||||||
u_int16_t b,
|
uint16_t b,
|
||||||
u_int8_t c);
|
uint8_t c);
|
||||||
|
|
||||||
void vtoc_update_format5_label_del (
|
void vtoc_update_format5_label_del (
|
||||||
format5_label_t *f5,
|
format5_label_t *f5,
|
||||||
int verbose,
|
int verbose,
|
||||||
int trk,
|
int trk,
|
||||||
u_int16_t a,
|
uint16_t a,
|
||||||
u_int16_t b,
|
uint16_t b,
|
||||||
u_int8_t c);
|
uint8_t c);
|
||||||
|
|
||||||
void vtoc_init_format7_label (
|
void vtoc_init_format7_label (
|
||||||
format7_label_t *f7);
|
format7_label_t *f7);
|
||||||
@@ -397,14 +398,14 @@ void vtoc_init_format7_label (
|
|||||||
void vtoc_update_format7_label_add (
|
void vtoc_update_format7_label_add (
|
||||||
format7_label_t *f7,
|
format7_label_t *f7,
|
||||||
int verbose,
|
int verbose,
|
||||||
u_int32_t a,
|
uint32_t a,
|
||||||
u_int32_t b);
|
uint32_t b);
|
||||||
|
|
||||||
void vtoc_update_format7_label_del (
|
void vtoc_update_format7_label_del (
|
||||||
format7_label_t *f7,
|
format7_label_t *f7,
|
||||||
int verbose,
|
int verbose,
|
||||||
u_int32_t a,
|
uint32_t a,
|
||||||
u_int32_t b);
|
uint32_t b);
|
||||||
|
|
||||||
void vtoc_init_format8_label (
|
void vtoc_init_format8_label (
|
||||||
unsigned int blksize,
|
unsigned int blksize,
|
||||||
@@ -424,9 +425,9 @@ void vtoc_set_freespace(
|
|||||||
format7_label_t *f7,
|
format7_label_t *f7,
|
||||||
char ch,
|
char ch,
|
||||||
int verbose,
|
int verbose,
|
||||||
u_int32_t start,
|
uint32_t start,
|
||||||
u_int32_t stop,
|
uint32_t stop,
|
||||||
u_int32_t cyl,
|
uint32_t cyl,
|
||||||
u_int32_t trk);
|
uint32_t trk);
|
||||||
|
|
||||||
#endif /* LIB_VTOC_H */
|
#endif /* LIB_VTOC_H */
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
#define TOOLS_BINDIR STRINGIFY (S390_TOOLS_BINDIR)
|
#define TOOLS_BINDIR STRINGIFY (S390_TOOLS_BINDIR)
|
||||||
#define TOOLS_DATADIR STRINGIFY (S390_TOOLS_DATADIR)
|
#define TOOLS_DATADIR STRINGIFY (S390_TOOLS_DATADIR)
|
||||||
|
|
||||||
|
#define __used __attribute__((used))
|
||||||
#define __noreturn __attribute__((noreturn))
|
#define __noreturn __attribute__((noreturn))
|
||||||
#define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#define __aligned(x) __attribute__((aligned(x)))
|
#define __aligned(x) __attribute__((aligned(x)))
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
* 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 <errno.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -49,19 +48,19 @@ static int device_sysfs_path(const char *device, char *path, const size_t path_s
|
|||||||
*/
|
*/
|
||||||
int ccw_is_device(const char *busid)
|
int ccw_is_device(const char *busid)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
static const char *const driver_paths[] = { "dasd-eckd", "virtio_ccw", "dasd-fba" };
|
||||||
|
char *path;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(driver_paths); i++) {
|
||||||
|
path = util_path_sysfs("bus/ccw/drivers/%s/%s", driver_paths[i], busid);
|
||||||
|
if (access(path, R_OK) == 0) {
|
||||||
|
free(path);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(path, sizeof(path),
|
|
||||||
"/sys/bus/ccw/drivers/dasd-eckd/%s", busid);
|
|
||||||
if (access(path, R_OK) == 0)
|
|
||||||
return 1;
|
|
||||||
snprintf(path, sizeof(path),
|
|
||||||
"/sys/bus/ccw/drivers/virtio_ccw/%s", busid);
|
|
||||||
if (access(path, R_OK) == 0)
|
|
||||||
return 1;
|
|
||||||
snprintf(path, sizeof(path), "/sys/bus/ccw/drivers/dasd-fba/%s", busid);
|
|
||||||
if (access(path, R_OK) == 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +71,7 @@ int ccw_is_virtio_device(const char *device)
|
|||||||
{
|
{
|
||||||
char path[PATH_MAX] = { '\0' };
|
char path[PATH_MAX] = { '\0' };
|
||||||
unsigned virtio = 0;
|
unsigned virtio = 0;
|
||||||
|
char *path_pattern;
|
||||||
|
|
||||||
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -80,76 +80,37 @@ int ccw_is_virtio_device(const char *device)
|
|||||||
* The output has the following format:
|
* The output has the following format:
|
||||||
* /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
|
* /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
|
||||||
*/
|
*/
|
||||||
if (sscanf(path, "/sys/devices/css0/%*[0-9a-f.]/%*[0-9a-f.]/virtio%u", &virtio) != 1)
|
path_pattern = util_path_sysfs("devices/css0/%%*[0-9a-f.]/%%*[0-9a-f.]/virtio%%u");
|
||||||
|
if (sscanf(path, path_pattern, &virtio) != 1) {
|
||||||
|
free(path_pattern);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
free(path_pattern);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return CCW Bus ID (old sysfs)
|
* Return CCW Bus ID
|
||||||
*/
|
*/
|
||||||
static int ccw_busid_get_sysfs_old(const char *device, char *busid)
|
void ccw_busid_get(const char *device, char *busid)
|
||||||
{
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char buf[4096];
|
|
||||||
int rc = 0;
|
|
||||||
FILE *fh;
|
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/uevent", device);
|
|
||||||
fh = fopen(path, "r");
|
|
||||||
if (fh == NULL)
|
|
||||||
return -1;
|
|
||||||
/*
|
|
||||||
* The uevent file contains an entry like this:
|
|
||||||
* PHYSDEVPATH=/devices/css0/0.0.206a/0.0.7e78
|
|
||||||
*/
|
|
||||||
while (fscanf(fh, "%s", buf) >= 0) {
|
|
||||||
if (strstr(buf, "PHYSDEVPATH") != NULL) {
|
|
||||||
strcpy(busid, strrchr(buf, '/') + 1);
|
|
||||||
goto out_fclose;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = -1;
|
|
||||||
out_fclose:
|
|
||||||
fclose(fh);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return CCW Bus ID (new sysfs)
|
|
||||||
*/
|
|
||||||
static int ccw_busid_get_sysfs_new(const char *device, char *busid)
|
|
||||||
{
|
{
|
||||||
char path[PATH_MAX] = { '\0' };
|
char path[PATH_MAX] = { '\0' };
|
||||||
|
char *path_pattern;
|
||||||
|
|
||||||
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
||||||
return -1;
|
ERR_EXIT("Could not lookup device number for \"%s\"", device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The output has the following format:
|
* The output has the following format:
|
||||||
* /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda
|
* /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda
|
||||||
* /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
|
* /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
|
||||||
*/
|
*/
|
||||||
if (sscanf(path, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
|
path_pattern = util_path_sysfs("devices/css0/%%*[0-9a-f.]/%%[0-9a-f.]");
|
||||||
return -1;
|
if (sscanf(path, path_pattern, busid) != 1) {
|
||||||
return 0;
|
free(path_pattern);
|
||||||
}
|
ERR_EXIT("Could not lookup device number for \"%s\"", device);
|
||||||
|
}
|
||||||
|
free(path_pattern);
|
||||||
|
|
||||||
/*
|
return;
|
||||||
* Return the device number for a device
|
|
||||||
* dasda can be found in /sys/block/dasda/uevent or in a
|
|
||||||
* symbolic link in the same directory. the first file only
|
|
||||||
* contains the relevant information if we run on a kernel with
|
|
||||||
* has the following kernel option enabled:
|
|
||||||
* CONFIG_SYSFS_DEPRECATED
|
|
||||||
*
|
|
||||||
* This does not work when booting from tape
|
|
||||||
*/
|
|
||||||
void ccw_busid_get(const char *device, char *busid)
|
|
||||||
{
|
|
||||||
if (ccw_busid_get_sysfs_old(device, busid) == 0)
|
|
||||||
return;
|
|
||||||
if (ccw_busid_get_sysfs_new(device, busid) == 0)
|
|
||||||
return;
|
|
||||||
ERR_EXIT("Could not lookup device number for \"%s\"", device);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,26 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
|
#include "lib/util_proc.h"
|
||||||
|
#include "lib/util_base.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
|
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
#include <linux/raid/md_u.h>
|
||||||
|
|
||||||
#define BOOTPARMS_NSS_MAX 56
|
#define BOOTPARMS_NSS_MAX 56
|
||||||
#define BOOTPARMS_CCW_MAX 64
|
#define BOOTPARMS_CCW_MAX 64
|
||||||
#define BOOTPARMS_FCP_MAX 3452
|
#define BOOTPARMS_SCPDATA_MAX 3452
|
||||||
|
|
||||||
#define OPT_BRCHR 0x80
|
#define OPT_BRCHR 0x80
|
||||||
|
|
||||||
|
#define MD_MAJOR 9
|
||||||
|
|
||||||
enum target_type {
|
enum target_type {
|
||||||
TT_CCW,
|
TT_CCW,
|
||||||
TT_FCP,
|
TT_FCP,
|
||||||
@@ -414,15 +421,38 @@ static int set_reipl_type(const char *dev_name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_chreipl_helper_cmd(dev_t dev, char cmd[PATH_MAX])
|
static int is_md_device(const char *dev_name)
|
||||||
|
{
|
||||||
|
char abs_dev_name[PATH_MAX];
|
||||||
|
mdu_array_info_t array;
|
||||||
|
int is_md_device = 0;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (snprintf(abs_dev_name, PATH_MAX, "/dev/%s", dev_name) >= PATH_MAX)
|
||||||
|
return 0;
|
||||||
|
fd = open(abs_dev_name, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return 0;
|
||||||
|
if (ioctl(fd, GET_ARRAY_INFO, &array) >= 0)
|
||||||
|
is_md_device = 1;
|
||||||
|
close(fd);
|
||||||
|
return is_md_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_chreipl_helper_cmd(dev_t dev, char *dev_name, char cmd[PATH_MAX])
|
||||||
{
|
{
|
||||||
char *chreipl_helper;
|
|
||||||
struct proc_dev_entry pde;
|
struct proc_dev_entry pde;
|
||||||
|
char *chreipl_helper;
|
||||||
|
char *driver_name;
|
||||||
|
|
||||||
if (proc_dev_get_entry(dev, 1, &pde) != 0)
|
if (proc_dev_get_entry(dev, 1, &pde) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
driver_name = pde.name;
|
||||||
|
if (strcmp(driver_name, UTIL_PROC_DEV_ENTRY_BLKEXT) == 0 &&
|
||||||
|
is_md_device(dev_name))
|
||||||
|
driver_name = UTIL_PROC_DEV_ENTRY_MD;
|
||||||
util_asprintf(&chreipl_helper,
|
util_asprintf(&chreipl_helper,
|
||||||
"%s/%s.%s", TOOLS_LIBDIR, "chreipl_helper", pde.name);
|
"%s.%s", util_libdir_path("chreipl_helper"), driver_name);
|
||||||
if (access(chreipl_helper, X_OK) != 0) {
|
if (access(chreipl_helper, X_OK) != 0) {
|
||||||
proc_dev_free_entry(&pde);
|
proc_dev_free_entry(&pde);
|
||||||
free(chreipl_helper);
|
free(chreipl_helper);
|
||||||
@@ -437,7 +467,7 @@ static int get_chreipl_helper_cmd(dev_t dev, char cmd[PATH_MAX])
|
|||||||
/*
|
/*
|
||||||
* Use chreipl_helper (E.g. for device mapper devices)
|
* Use chreipl_helper (E.g. for device mapper devices)
|
||||||
*/
|
*/
|
||||||
static int set_reipl_type_helper(int maj, int min)
|
static int set_reipl_type_helper(int maj, int min, char *dev_name)
|
||||||
{
|
{
|
||||||
char helper_cmd[PATH_MAX], buf[4096];
|
char helper_cmd[PATH_MAX], buf[4096];
|
||||||
struct proc_part_entry ppe;
|
struct proc_part_entry ppe;
|
||||||
@@ -445,7 +475,7 @@ static int set_reipl_type_helper(int maj, int min)
|
|||||||
dev_t dev;
|
dev_t dev;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
|
|
||||||
if (get_chreipl_helper_cmd(makedev(maj, min), helper_cmd) != 0)
|
if (get_chreipl_helper_cmd(makedev(maj, min), dev_name, helper_cmd) != 0)
|
||||||
return -1;
|
return -1;
|
||||||
fh = popen(helper_cmd, "r");
|
fh = popen(helper_cmd, "r");
|
||||||
if (fh == NULL)
|
if (fh == NULL)
|
||||||
@@ -499,7 +529,7 @@ static void parse_node_args(char *nargv[], int nargc)
|
|||||||
ERR_EXIT("Invalid device node \"%s\" specified", path);
|
ERR_EXIT("Invalid device node \"%s\" specified", path);
|
||||||
if (set_reipl_type(ppe.name) == 0)
|
if (set_reipl_type(ppe.name) == 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (set_reipl_type_helper(major(dev), minor(dev)) == 0)
|
if (set_reipl_type_helper(major(dev), minor(dev), ppe.name) == 0)
|
||||||
goto out;
|
goto out;
|
||||||
ERR_EXIT("Unsupported device node \"%s\" specified", path);
|
ERR_EXIT("Unsupported device node \"%s\" specified", path);
|
||||||
out:
|
out:
|
||||||
@@ -719,11 +749,12 @@ static void parse_chreipl_options(int argc, char *argv[])
|
|||||||
|
|
||||||
static void check_exists(const char *path, const char *attr)
|
static void check_exists(const char *path, const char *attr)
|
||||||
{
|
{
|
||||||
char fpath[PATH_MAX];
|
char *fpath;
|
||||||
|
|
||||||
snprintf(fpath, sizeof(fpath), "/sys/firmware/%s", path);
|
fpath = util_path_sysfs("firmware/%s", path);
|
||||||
if (access(fpath, F_OK) != 0)
|
if (access(fpath, F_OK) != 0)
|
||||||
ERR_EXIT("System does not allow one to set %s", attr);
|
ERR_EXIT("System does not allow one to set %s", attr);
|
||||||
|
free(fpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_str_optional(char *string, char *file, int exit_on_fail,
|
static void write_str_optional(char *string, char *file, int exit_on_fail,
|
||||||
@@ -739,7 +770,7 @@ static void write_str_optional(char *string, char *file, int exit_on_fail,
|
|||||||
* IMPLEMENTATION:
|
* IMPLEMENTATION:
|
||||||
*
|
*
|
||||||
* "cio_ignore --is-ignored <busid>" returns 0 if the device is ignored,
|
* "cio_ignore --is-ignored <busid>" returns 0 if the device is ignored,
|
||||||
* 1 for internal errrors, and 2 if the device is not ignored.
|
* 1 for internal errors, and 2 if the device is not ignored.
|
||||||
*
|
*
|
||||||
* We get the "cio_ignore" exit status by the return code of the system()
|
* We get the "cio_ignore" exit status by the return code of the system()
|
||||||
* function via WEXITSTATUS().
|
* function via WEXITSTATUS().
|
||||||
@@ -804,6 +835,12 @@ static void chreipl_eckd(void)
|
|||||||
ERR_EXIT("Could not find DASD ECKD device \"%s\"", l.busid);
|
ERR_EXIT("Could not find DASD ECKD device \"%s\"", l.busid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_exists("reipl/eckd/device", "\"eckd\" re-IPL target");
|
||||||
|
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||||
|
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||||
|
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
if (l.reipl_clear >= 0) {
|
if (l.reipl_clear >= 0) {
|
||||||
check_exists("reipl/eckd/clear", "ECKD re-IPL clear attribute");
|
check_exists("reipl/eckd/clear", "ECKD re-IPL clear attribute");
|
||||||
write_str(l.reipl_clear ? "1" : "0", "reipl/eckd/clear");
|
write_str(l.reipl_clear ? "1" : "0", "reipl/eckd/clear");
|
||||||
@@ -817,6 +854,8 @@ static void chreipl_eckd(void)
|
|||||||
write_str(l.bootprog, "reipl/eckd/bootprog");
|
write_str(l.bootprog, "reipl/eckd/bootprog");
|
||||||
write_str(l.busid, "reipl/eckd/device");
|
write_str(l.busid, "reipl/eckd/device");
|
||||||
write_str_optional(l.loadparm, "reipl/eckd/loadparm", l.loadparm_set, "loadparm");
|
write_str_optional(l.loadparm, "reipl/eckd/loadparm", l.loadparm_set, "loadparm");
|
||||||
|
write_str_optional(l.bootparms, "reipl/eckd/scp_data", l.bootparms_set,
|
||||||
|
"boot parameters");
|
||||||
write_str("eckd", "reipl/reipl_type");
|
write_str("eckd", "reipl/reipl_type");
|
||||||
print_eckd(0, "eckd");
|
print_eckd(0, "eckd");
|
||||||
}
|
}
|
||||||
@@ -831,9 +870,9 @@ static void chreipl_fcp(void)
|
|||||||
ERR_EXIT("Could not find FCP device \"%s\"", l.busid);
|
ERR_EXIT("Could not find FCP device \"%s\"", l.busid);
|
||||||
}
|
}
|
||||||
check_exists("reipl/fcp/device", "\"fcp\" re-IPL target");
|
check_exists("reipl/fcp/device", "\"fcp\" re-IPL target");
|
||||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
|
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||||
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||||
strlen(l.bootparms), BOOTPARMS_FCP_MAX);
|
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.reipl_clear >= 0) {
|
if (l.reipl_clear >= 0) {
|
||||||
@@ -874,9 +913,9 @@ static void chreipl_nvme(void)
|
|||||||
}
|
}
|
||||||
check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target");
|
check_exists("reipl/nvme/fid", "\"nvme\" re-IPL target");
|
||||||
|
|
||||||
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_FCP_MAX) {
|
if (l.bootparms_set && strlen(l.bootparms) > BOOTPARMS_SCPDATA_MAX) {
|
||||||
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
ERR_EXIT("Maximum boot parameter length exceeded (%zu/%u)",
|
||||||
strlen(l.bootparms), BOOTPARMS_FCP_MAX);
|
strlen(l.bootparms), BOOTPARMS_SCPDATA_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.reipl_clear >= 0) {
|
if (l.reipl_clear >= 0) {
|
||||||
@@ -920,13 +959,14 @@ static void chreipl_nss(void)
|
|||||||
|
|
||||||
static void chreipl_node(void)
|
static void chreipl_node(void)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char *path;
|
||||||
|
|
||||||
if (!l.dev_set)
|
if (!l.dev_set)
|
||||||
ERR_EXIT("No device node specified");
|
ERR_EXIT("No device node specified");
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/device", l.dev);
|
path = util_path_sysfs("block/%s/device", l.dev);
|
||||||
if (chdir(path) != 0)
|
if (chdir(path) != 0)
|
||||||
ERR_EXIT("Could not find device \"%s\"", l.dev);
|
ERR_EXIT("Could not find device \"%s\"", l.dev);
|
||||||
|
free(path);
|
||||||
|
|
||||||
switch (l.reipl_type) {
|
switch (l.reipl_type) {
|
||||||
case REIPL_CCW:
|
case REIPL_CCW:
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
* 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 "lib/util_path.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
|
#include "lib/util_libc.h"
|
||||||
|
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
@@ -42,24 +46,23 @@ static const char *get_ipl_banner(int show_ipl)
|
|||||||
void print_nss(int show_ipl)
|
void print_nss(int show_ipl)
|
||||||
{
|
{
|
||||||
char *dir = show_ipl ? "ipl" : "reipl/nss";
|
char *dir = show_ipl ? "ipl" : "reipl/nss";
|
||||||
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/parm" :
|
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
|
||||||
"/sys/firmware/reipl/nss/parm";
|
|
||||||
|
|
||||||
printf("%-12s nss\n", get_ipl_banner(show_ipl));
|
printf("%-12s nss\n", get_ipl_banner(show_ipl));
|
||||||
print_fw_str("Name: %s\n", dir, "name");
|
print_fw_str("Name: %s\n", dir, "name");
|
||||||
if (access(path_bootparms, R_OK) == 0)
|
if (access(path_bootparms, R_OK) == 0)
|
||||||
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
||||||
|
free(path_bootparms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_fcp(int show_ipl, int dump)
|
void print_fcp(int show_ipl, int dump)
|
||||||
{
|
{
|
||||||
char *dir = show_ipl ? "ipl" : "reipl/fcp";
|
char *dir = show_ipl ? "ipl" : "reipl/fcp";
|
||||||
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
|
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
|
||||||
"/sys/firmware/reipl/fcp/scp_data";
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
||||||
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/fcp/clear");
|
||||||
"/sys/firmware/reipl/fcp/loadparm";
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
||||||
char loadparm[9], loadparm_path[PATH_MAX];
|
char *loadparm;
|
||||||
char *path_reipl_clear = "/sys/firmware/reipl/fcp/clear";
|
|
||||||
|
|
||||||
if (dump)
|
if (dump)
|
||||||
printf("%-12s fcp_dump\n", get_ipl_banner(show_ipl));
|
printf("%-12s fcp_dump\n", get_ipl_banner(show_ipl));
|
||||||
@@ -72,27 +75,31 @@ void print_fcp(int show_ipl, int dump)
|
|||||||
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
||||||
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
||||||
if (access(path_loadparm, R_OK) == 0) {
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
||||||
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
util_strstrip(loadparm);
|
||||||
if (strcmp(loadparm, " ") == 0)
|
|
||||||
loadparm[0] = 0;
|
|
||||||
printf("Loadparm: \"%s\"\n", loadparm);
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
free(loadparm);
|
||||||
}
|
}
|
||||||
if (access(path_bootparms, R_OK) == 0)
|
if (access(path_bootparms, R_OK) == 0)
|
||||||
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
||||||
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
|
if (access(path_secure_boot, R_OK) == 0)
|
||||||
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
||||||
|
free(path_bootparms);
|
||||||
|
free(path_loadparm);
|
||||||
|
free(path_reipl_clear);
|
||||||
|
free(path_secure_boot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_nvme(int show_ipl, int dump)
|
void print_nvme(int show_ipl, int dump)
|
||||||
{
|
{
|
||||||
char *dir = show_ipl ? "ipl" : "reipl/nvme";
|
char *dir = show_ipl ? "ipl" : "reipl/nvme";
|
||||||
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
|
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
|
||||||
"/sys/firmware/reipl/nvme/scp_data";
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
||||||
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/nvme/clear");
|
||||||
"/sys/firmware/reipl/nvme/loadparm";
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
||||||
char loadparm[9], loadparm_path[PATH_MAX];
|
char *loadparm;
|
||||||
char *path_reipl_clear = "/sys/firmware/reipl/nvme/clear";
|
|
||||||
|
|
||||||
if (dump)
|
if (dump)
|
||||||
printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
|
printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
|
||||||
@@ -104,49 +111,55 @@ void print_nvme(int show_ipl, int dump)
|
|||||||
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
print_fw_str("bootprog: %s\n", dir, "bootprog");
|
||||||
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
print_fw_str("br_lba: %s\n", dir, "br_lba");
|
||||||
if (access(path_loadparm, R_OK) == 0) {
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
||||||
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
util_strstrip(loadparm);
|
||||||
if (strcmp(loadparm, " ") == 0)
|
|
||||||
loadparm[0] = 0;
|
|
||||||
printf("Loadparm: \"%s\"\n", loadparm);
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
free(loadparm);
|
||||||
}
|
}
|
||||||
if (access(path_bootparms, R_OK) == 0)
|
if (access(path_bootparms, R_OK) == 0)
|
||||||
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
|
||||||
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
|
if (access(path_secure_boot, R_OK) == 0)
|
||||||
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
||||||
|
free(path_bootparms);
|
||||||
|
free(path_loadparm);
|
||||||
|
free(path_reipl_clear);
|
||||||
|
free(path_secure_boot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_ccw(int show_ipl)
|
void print_ccw(int show_ipl)
|
||||||
{
|
{
|
||||||
char loadparm[9], loadparm_path[PATH_MAX];
|
|
||||||
char *dir = show_ipl ? "ipl" : "reipl/ccw";
|
char *dir = show_ipl ? "ipl" : "reipl/ccw";
|
||||||
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
||||||
"/sys/firmware/reipl/ccw/loadparm";
|
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
|
||||||
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/parm" :
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/ccw/clear");
|
||||||
"/sys/firmware/reipl/ccw/parm";
|
char *loadparm;
|
||||||
char *path_reipl_clear = "/sys/firmware/reipl/ccw/clear";
|
|
||||||
|
|
||||||
printf("%-12s ccw\n", get_ipl_banner(show_ipl));
|
printf("%-12s ccw\n", get_ipl_banner(show_ipl));
|
||||||
print_fw_str("Device: %s\n", dir, "device");
|
print_fw_str("Device: %s\n", dir, "device");
|
||||||
if (access(path_loadparm, R_OK) == 0) {
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
||||||
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
util_strstrip(loadparm);
|
||||||
if (strcmp(loadparm, " ") == 0)
|
|
||||||
loadparm[0] = 0;
|
|
||||||
printf("Loadparm: \"%s\"\n", loadparm);
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
free(loadparm);
|
||||||
}
|
}
|
||||||
if (access(path_bootparms, R_OK) == 0)
|
if (access(path_bootparms, R_OK) == 0)
|
||||||
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
|
||||||
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
|
free(path_loadparm);
|
||||||
|
free(path_bootparms);
|
||||||
|
free(path_reipl_clear);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_eckd(int show_ipl, const char *name)
|
void print_eckd(int show_ipl, const char *name)
|
||||||
{
|
{
|
||||||
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
|
|
||||||
"/sys/firmware/reipl/eckd/loadparm";
|
|
||||||
char *dir = show_ipl ? "ipl" : "reipl/eckd";
|
char *dir = show_ipl ? "ipl" : "reipl/eckd";
|
||||||
char loadparm[9], loadparm_path[PATH_MAX];
|
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
|
||||||
|
char *path_reipl_clear = util_path_sysfs("firmware/reipl/eckd/clear");
|
||||||
|
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
|
||||||
|
char *loadparm;
|
||||||
|
|
||||||
printf("%-12s %s\n", get_ipl_banner(show_ipl), name);
|
printf("%-12s %s\n", get_ipl_banner(show_ipl), name);
|
||||||
|
|
||||||
@@ -155,14 +168,17 @@ void print_eckd(int show_ipl, const char *name)
|
|||||||
print_fw_str("br_chr: %s\n", dir, "br_chr");
|
print_fw_str("br_chr: %s\n", dir, "br_chr");
|
||||||
print_fw_str("Bootparm: \"%s\"\n", dir, "scp_data");
|
print_fw_str("Bootparm: \"%s\"\n", dir, "scp_data");
|
||||||
if (access(path_loadparm, R_OK) == 0) {
|
if (access(path_loadparm, R_OK) == 0) {
|
||||||
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
|
loadparm = util_file_read_text_file(path_loadparm, 1);
|
||||||
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
|
util_strstrip(loadparm);
|
||||||
if (strcmp(loadparm, " ") == 0)
|
|
||||||
loadparm[0] = 0;
|
|
||||||
printf("Loadparm: \"%s\"\n", loadparm);
|
printf("Loadparm: \"%s\"\n", loadparm);
|
||||||
|
free(loadparm);
|
||||||
}
|
}
|
||||||
if (!show_ipl)
|
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
|
||||||
print_fw_str("clear: %s\n", dir, "clear");
|
print_fw_str("clear: %s\n", dir, "clear");
|
||||||
|
if (access(path_secure_boot, R_OK) == 0)
|
||||||
|
print_fw_str("Secure boot: %s\n", "ipl", "secure");
|
||||||
|
free(path_loadparm);
|
||||||
|
free(path_secure_boot);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_lsreipl_options(int argc, char *argv[])
|
static void parse_lsreipl_options(int argc, char *argv[])
|
||||||
@@ -196,16 +212,14 @@ static void parse_lsreipl_options(int argc, char *argv[])
|
|||||||
|
|
||||||
void cmd_lsreipl(int argc, char *argv[])
|
void cmd_lsreipl(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char reipl_type_str[1024];
|
char *reipl_type_str;
|
||||||
|
|
||||||
parse_lsreipl_options(argc, argv);
|
parse_lsreipl_options(argc, argv);
|
||||||
|
|
||||||
if (l.ipl_set)
|
if (l.ipl_set)
|
||||||
read_fw_str(reipl_type_str, "ipl/ipl_type",
|
reipl_type_str = read_fw_str("ipl/ipl_type");
|
||||||
sizeof(reipl_type_str));
|
|
||||||
else
|
else
|
||||||
read_fw_str(reipl_type_str, "reipl/reipl_type",
|
reipl_type_str = read_fw_str("reipl/reipl_type");
|
||||||
sizeof(reipl_type_str));
|
|
||||||
|
|
||||||
if (strcmp(reipl_type_str, "fcp") == 0)
|
if (strcmp(reipl_type_str, "fcp") == 0)
|
||||||
print_fcp(l.ipl_set, 0);
|
print_fcp(l.ipl_set, 0);
|
||||||
@@ -225,5 +239,6 @@ void cmd_lsreipl(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
printf("%s: %s (unknown)\n", get_ipl_banner(l.ipl_set),
|
printf("%s: %s (unknown)\n", get_ipl_banner(l.ipl_set),
|
||||||
reipl_type_str);
|
reipl_type_str);
|
||||||
|
free(reipl_type_str);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
* 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 "lib/util_path.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
static const char *const usage_lsshut =
|
static const char *const usage_lsshut =
|
||||||
@@ -60,12 +62,13 @@ static void parse_lsshut_options(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
static void read_vmcmd(char *str, const char *path)
|
static void read_vmcmd(char *str, const char *path)
|
||||||
{
|
{
|
||||||
char buf[128], tmp[512];
|
|
||||||
char *ptr_old, *ptr;
|
char *ptr_old, *ptr;
|
||||||
|
char tmp[512];
|
||||||
|
char *buf;
|
||||||
|
|
||||||
*str = 0;
|
*str = 0;
|
||||||
|
buf = read_fw_str(path);
|
||||||
ptr_old = ptr = buf;
|
ptr_old = ptr = buf;
|
||||||
read_fw_str(buf, path, sizeof(buf));
|
|
||||||
while ((ptr = strchr(ptr_old, '\n'))) {
|
while ((ptr = strchr(ptr_old, '\n'))) {
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
sprintf(tmp, "\"%s\",", ptr_old);
|
sprintf(tmp, "\"%s\",", ptr_old);
|
||||||
@@ -74,23 +77,31 @@ static void read_vmcmd(char *str, const char *path)
|
|||||||
}
|
}
|
||||||
sprintf(tmp, "\"%s\"", ptr_old);
|
sprintf(tmp, "\"%s\"", ptr_old);
|
||||||
strcat(str, tmp);
|
strcat(str, tmp);
|
||||||
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_kdump(void)
|
static void print_kdump(void)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char tmp[1024];
|
char *path;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
if (stat("/sys/kernel/kexec_crash_loaded", &sb) != 0)
|
path = util_path_sysfs("kernel/kexec_crash_loaded");
|
||||||
|
if (stat(path, &sb) != 0) {
|
||||||
|
free(path);
|
||||||
return;
|
return;
|
||||||
read_str(tmp, "/sys/kernel/kexec_crash_loaded", sizeof(tmp));
|
}
|
||||||
|
tmp = util_file_read_text_file(path, 1);
|
||||||
if (strncmp(tmp, "1", 1) == 0)
|
if (strncmp(tmp, "1", 1) == 0)
|
||||||
printf("kdump,");
|
printf("kdump,");
|
||||||
|
free(path);
|
||||||
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void shutdown_trigger_print(struct shutdown_trigger *trigger)
|
static void shutdown_trigger_print(struct shutdown_trigger *trigger)
|
||||||
{
|
{
|
||||||
char tmp[1024], cmd[1024], path[PATH_MAX];
|
char cmd[1024], path[PATH_MAX];
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
sprintf(path, "shutdown_actions/%s", trigger->name_sysfs);
|
sprintf(path, "shutdown_actions/%s", trigger->name_sysfs);
|
||||||
|
|
||||||
@@ -99,7 +110,7 @@ static void shutdown_trigger_print(struct shutdown_trigger *trigger)
|
|||||||
if ((trigger == &shutdown_trigger_panic ||
|
if ((trigger == &shutdown_trigger_panic ||
|
||||||
trigger == &shutdown_trigger_restart))
|
trigger == &shutdown_trigger_restart))
|
||||||
print_kdump();
|
print_kdump();
|
||||||
read_fw_str(tmp, path, sizeof(tmp));
|
tmp = read_fw_str(path);
|
||||||
if (strncmp(tmp, "vmcmd", strlen("vmcmd")) == 0) {
|
if (strncmp(tmp, "vmcmd", strlen("vmcmd")) == 0) {
|
||||||
sprintf(path, "vmcmd/%s", trigger->name_sysfs);
|
sprintf(path, "vmcmd/%s", trigger->name_sysfs);
|
||||||
read_vmcmd(cmd, path);
|
read_vmcmd(cmd, path);
|
||||||
@@ -107,6 +118,7 @@ static void shutdown_trigger_print(struct shutdown_trigger *trigger)
|
|||||||
} else {
|
} else {
|
||||||
printf("%s\n", tmp);
|
printf("%s\n", tmp);
|
||||||
}
|
}
|
||||||
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_lsshut(int argc, char *argv[])
|
void cmd_lsshut(int argc, char *argv[])
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -18,11 +19,14 @@
|
|||||||
*/
|
*/
|
||||||
int fcp_is_device(const char *devno)
|
int fcp_is_device(const char *devno)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char *path;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/bus/ccw/drivers/zfcp/%s", devno);
|
path = util_path_sysfs("bus/ccw/drivers/zfcp/%s", devno);
|
||||||
if (chdir(path) != 0)
|
if (chdir(path) != 0) {
|
||||||
|
free(path);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,11 +35,12 @@ int fcp_is_device(const char *devno)
|
|||||||
*/
|
*/
|
||||||
void fcp_wwpn_get(const char *device, char *wwpn)
|
void fcp_wwpn_get(const char *device, char *wwpn)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], buf[20];
|
char buf[20];
|
||||||
|
char *path;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/device/wwpn", device);
|
path = util_path_sysfs("block/%s/device/wwpn", device);
|
||||||
fh = fopen(path, "r");
|
fh = fopen(path, "r");
|
||||||
if (fh == NULL)
|
if (fh == NULL)
|
||||||
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
||||||
@@ -44,19 +49,20 @@ void fcp_wwpn_get(const char *device, char *wwpn)
|
|||||||
ERR_EXIT("Could not lookup WWPN \"%s\"", path);
|
ERR_EXIT("Could not lookup WWPN \"%s\"", path);
|
||||||
util_strlcpy(wwpn, buf, 20);
|
util_strlcpy(wwpn, buf, 20);
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the lun of a device
|
* Return the lun of a device
|
||||||
*/
|
*/
|
||||||
void fcp_lun_get(const char *device, char *lun)
|
void fcp_lun_get(const char *device, char *lun)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], buf[20];
|
char buf[20];
|
||||||
|
char *path;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/device/fcp_lun", device);
|
path = util_path_sysfs("block/%s/device/fcp_lun", device);
|
||||||
fh = fopen(path, "r");
|
fh = fopen(path, "r");
|
||||||
if (fh == NULL)
|
if (fh == NULL)
|
||||||
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
||||||
@@ -65,6 +71,7 @@ void fcp_lun_get(const char *device, char *lun)
|
|||||||
ERR_EXIT("Could not lookup LUN \"%s\"", path);
|
ERR_EXIT("Could not lookup LUN \"%s\"", path);
|
||||||
util_strlcpy(lun, buf, 20);
|
util_strlcpy(lun, buf, 20);
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -72,11 +79,12 @@ void fcp_lun_get(const char *device, char *lun)
|
|||||||
*/
|
*/
|
||||||
void fcp_busid_get(const char *device, char *devno)
|
void fcp_busid_get(const char *device, char *devno)
|
||||||
{
|
{
|
||||||
char buf[4096], path[PATH_MAX];
|
char buf[4096];
|
||||||
|
char *path;
|
||||||
FILE *fh;
|
FILE *fh;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/device/hba_id", device);
|
path = util_path_sysfs("block/%s/device/hba_id", device);
|
||||||
fh = fopen(path, "r");
|
fh = fopen(path, "r");
|
||||||
if (fh == NULL)
|
if (fh == NULL)
|
||||||
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
|
||||||
@@ -85,4 +93,5 @@ void fcp_busid_get(const char *device, char *devno)
|
|||||||
ERR_EXIT("Could not find device \"%s\"", path);
|
ERR_EXIT("Could not find device \"%s\"", path);
|
||||||
strcpy(devno, buf);
|
strcpy(devno, buf);
|
||||||
fclose(fh);
|
fclose(fh);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#ifndef IPL_TOOLS_H
|
#ifndef IPL_TOOLS_H
|
||||||
#define IPL_TOOLS_H
|
#define IPL_TOOLS_H
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@@ -36,41 +35,38 @@ extern struct globals {
|
|||||||
/*
|
/*
|
||||||
* Commands
|
* Commands
|
||||||
*/
|
*/
|
||||||
extern void cmd_lsshut(int argc, char *argv[]);
|
void cmd_lsshut(int argc, char *argv[]);
|
||||||
extern void cmd_chshut(int argc, char *argv[]);
|
void cmd_chshut(int argc, char *argv[]);
|
||||||
extern void cmd_lsreipl(int argc, char *argv[]);
|
void cmd_lsreipl(int argc, char *argv[]);
|
||||||
extern void cmd_chreipl(int argc, char *argv[]);
|
void cmd_chreipl(int argc, char *argv[]);
|
||||||
|
|
||||||
extern void print_ccw(int show_ipl);
|
void print_ccw(int show_ipl);
|
||||||
extern void print_fcp(int show_ipl, int dump);
|
void print_fcp(int show_ipl, int dump);
|
||||||
extern void print_nvme(int show_ipl, int dump);
|
void print_nvme(int show_ipl, int dump);
|
||||||
extern void print_nss(int show_ipl);
|
void print_nss(int show_ipl);
|
||||||
extern void print_eckd(int show_ipl, const char *name);
|
void print_eckd(int show_ipl, const char *name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper
|
* Helper
|
||||||
*/
|
*/
|
||||||
extern int is_lpar(void);
|
int is_lpar(void);
|
||||||
extern int is_root(void);
|
int is_root(void);
|
||||||
|
|
||||||
extern void strlow(char *s);
|
void write_str(char *string, char *file);
|
||||||
|
int write_str_errno(char *string, char *file);
|
||||||
|
char *read_fw_str(const char *file);
|
||||||
|
void print_fw_str(const char *fmt, const char *dir, const char *file);
|
||||||
|
|
||||||
extern void write_str(char *string, char *file);
|
void __noreturn print_version_exit(void);
|
||||||
extern int write_str_errno(char *string, char *file);
|
void __noreturn print_help_hint_exit(void);
|
||||||
extern void read_str(char *string, const char *file, size_t len);
|
|
||||||
extern void read_fw_str(char *string, const char *file, size_t len);
|
|
||||||
extern void print_fw_str(const char *fmt, const char *dir, const char *file);
|
|
||||||
|
|
||||||
extern void __noreturn print_version_exit(void);
|
|
||||||
extern void __noreturn print_help_hint_exit(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FCP
|
* FCP
|
||||||
*/
|
*/
|
||||||
extern int fcp_is_device(const char *devno);
|
int fcp_is_device(const char *devno);
|
||||||
extern void fcp_lun_get(const char *device, char *lun);
|
void fcp_lun_get(const char *device, char *lun);
|
||||||
extern void fcp_wwpn_get(const char *device, char *wwpn);
|
void fcp_wwpn_get(const char *device, char *wwpn);
|
||||||
extern void fcp_busid_get(const char *device, char *devno);
|
void fcp_busid_get(const char *device, char *devno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NVME
|
* NVME
|
||||||
@@ -79,16 +75,16 @@ extern void fcp_busid_get(const char *device, char *devno);
|
|||||||
#define NVME_DEV_MAX_LEN 15 /* "nvme" + u32 in decimal + null */
|
#define NVME_DEV_MAX_LEN 15 /* "nvme" + u32 in decimal + null */
|
||||||
#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
|
#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
|
||||||
|
|
||||||
extern void nvme_fid_get(const char *device, char *fid);
|
void nvme_fid_get(const char *device, char *fid);
|
||||||
extern void nvme_nsid_get(const char *device, char *nsid);
|
void nvme_nsid_get(const char *device, char *nsid);
|
||||||
int nvme_is_device(char *fid_str, char *nsid_str);
|
int nvme_is_device(char *fid_str, char *nsid_str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CCW
|
* CCW
|
||||||
*/
|
*/
|
||||||
extern int ccw_is_device(const char *devno);
|
int ccw_is_device(const char *devno);
|
||||||
extern int ccw_is_virtio_device(const char *device);
|
int ccw_is_virtio_device(const char *device);
|
||||||
extern void ccw_busid_get(const char *device, char *devno);
|
void ccw_busid_get(const char *device, char *devno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shutdown trigger
|
* Shutdown trigger
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lib/util_libc.h"
|
#include "lib/util_libc.h"
|
||||||
#include "lib/util_file.h"
|
#include "lib/util_file.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
static void nvme_dev_from_bdev(char *dev_name)
|
static void nvme_dev_from_bdev(char *dev_name)
|
||||||
@@ -31,8 +33,9 @@ static void nvme_dev_from_bdev(char *dev_name)
|
|||||||
*/
|
*/
|
||||||
void nvme_fid_get(const char *device, char *fid)
|
void nvme_fid_get(const char *device, char *fid)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], buf[FID_MAX_LEN];
|
|
||||||
char nvme_dev[NVME_DEV_MAX_LEN];
|
char nvme_dev[NVME_DEV_MAX_LEN];
|
||||||
|
char buf[FID_MAX_LEN];
|
||||||
|
char *path;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An NVMe may present multiple namespaces and thus block devices, even
|
* An NVMe may present multiple namespaces and thus block devices, even
|
||||||
@@ -42,24 +45,27 @@ void nvme_fid_get(const char *device, char *fid)
|
|||||||
util_strlcpy(nvme_dev, device, sizeof(nvme_dev));
|
util_strlcpy(nvme_dev, device, sizeof(nvme_dev));
|
||||||
nvme_dev_from_bdev(nvme_dev);
|
nvme_dev_from_bdev(nvme_dev);
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "/sys/class/nvme/%s/device/function_id", nvme_dev);
|
path = util_path_sysfs("class/nvme/%s/device/function_id", nvme_dev);
|
||||||
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
||||||
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
||||||
|
|
||||||
util_strlcpy(fid, buf, FID_MAX_LEN);
|
util_strlcpy(fid, buf, FID_MAX_LEN);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Return the nsid of a device
|
* Return the nsid of a device
|
||||||
*/
|
*/
|
||||||
void nvme_nsid_get(const char *device, char *nsid)
|
void nvme_nsid_get(const char *device, char *nsid)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], buf[FID_MAX_LEN];
|
char buf[FID_MAX_LEN];
|
||||||
|
char *path;
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "/sys/block/%s/nsid", device);
|
path = util_path_sysfs("block/%s/nsid", device);
|
||||||
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
if (util_file_read_line(buf, FID_MAX_LEN, path))
|
||||||
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
|
||||||
|
|
||||||
util_strlcpy(nsid, buf, FID_MAX_LEN);
|
util_strlcpy(nsid, buf, FID_MAX_LEN);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int next_entry(DIR *dir, char *in_path, char *out_path,
|
static int next_entry(DIR *dir, char *in_path, char *out_path,
|
||||||
@@ -93,13 +99,14 @@ static int next_entry(DIR *dir, char *in_path, char *out_path,
|
|||||||
|
|
||||||
static int nvme_getdev_by_fid(char *fidstr, char *devpath)
|
static int nvme_getdev_by_fid(char *fidstr, char *devpath)
|
||||||
{
|
{
|
||||||
char temp_path[PATH_MAX+19], real_path[PATH_MAX];
|
char temp_path[PATH_MAX + 19], real_path[PATH_MAX];
|
||||||
char *sys_path = "/sys/class/nvme";
|
uint64_t target_fid, curfid;
|
||||||
u_int64_t target_fid, curfid;
|
char *sys_path;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
char *end;
|
char *end;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
|
sys_path = util_path_sysfs("class/nvme");
|
||||||
target_fid = strtoul(fidstr, &end, 16);
|
target_fid = strtoul(fidstr, &end, 16);
|
||||||
if (*end)
|
if (*end)
|
||||||
ERR_EXIT("Invalid function_id given %s", fidstr);
|
ERR_EXIT("Invalid function_id given %s", fidstr);
|
||||||
@@ -126,6 +133,7 @@ static int nvme_getdev_by_fid(char *fidstr, char *devpath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
free(sys_path);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +141,7 @@ 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 full_path[NVME_PATH_MAX+1], nsid_path[sizeof(full_path)+5];
|
||||||
char *end;
|
char *end;
|
||||||
u_int64_t nsid, curnsid;
|
uint64_t nsid, curnsid;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
|
||||||
nsid = strtoul(nsid_str, &end, 10);
|
nsid = strtoul(nsid_str, &end, 10);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#ifndef PROC_H
|
#ifndef PROC_H
|
||||||
#define PROC_H
|
#define PROC_H
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct proc_part_entry {
|
struct proc_part_entry {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user