mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
382 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2db7ce05f | ||
|
|
0031c762cf | ||
|
|
7031429d1e | ||
|
|
73d8597db1 | ||
|
|
77d0d1d1a1 | ||
|
|
77a7e11a51 | ||
|
|
279070fa43 | ||
|
|
3989e1b741 | ||
|
|
c230b5385a | ||
|
|
68ecf79b01 | ||
|
|
f2960eb0df | ||
|
|
4d004cf8b1 | ||
|
|
d8f504f271 | ||
|
|
7fb3ee4478 | ||
|
|
a95bad6c87 | ||
|
|
147ff1bf49 | ||
|
|
c91d172c99 | ||
|
|
0e4992da3a | ||
|
|
41da0f0809 | ||
|
|
f43789e16a | ||
|
|
136e5eed8c | ||
|
|
e09753f2a3 | ||
|
|
fe2d240656 | ||
|
|
6fc450f696 | ||
|
|
6a55d0c2e5 | ||
|
|
0e69dc1262 | ||
|
|
3296d85e35 | ||
|
|
0eeab96f0d | ||
|
|
283a61dc2f | ||
|
|
670bf3e870 | ||
|
|
9cfaac58ea | ||
|
|
d6b702d579 | ||
|
|
d9a9bd8dcf | ||
|
|
cad4e9e15b | ||
|
|
c0f02d2f68 | ||
|
|
5218c243f4 | ||
|
|
c364692e7a | ||
|
|
41eb7d076f | ||
|
|
1062a7cde6 | ||
|
|
54e5e99657 | ||
|
|
4c922b105b | ||
|
|
4b19b9d950 | ||
|
|
cee4bb4995 | ||
|
|
c98d8e7629 | ||
|
|
96084339f5 | ||
|
|
f8d5b4b341 | ||
|
|
5806c4e1f4 | ||
|
|
9d199e06cb | ||
|
|
f7425a08d1 | ||
|
|
f6a97902c3 | ||
|
|
962af1a90e | ||
|
|
46dadc8cc4 | ||
|
|
9c8d117cc2 | ||
|
|
d7b3196286 | ||
|
|
b6c30404bc | ||
|
|
6d15850480 | ||
|
|
858da9af57 | ||
|
|
a7373674bf | ||
|
|
613353cd33 | ||
|
|
f6e932e0fd | ||
|
|
7e31c425c9 | ||
|
|
6c4171b775 | ||
|
|
0b0960254e | ||
|
|
4d2c9267c2 | ||
|
|
7ea0dfdc17 | ||
|
|
2d3aac1241 | ||
|
|
c7fd515790 | ||
|
|
7a4ec55d77 | ||
|
|
63ff07ba38 | ||
|
|
26d7eed0aa | ||
|
|
e0034eddbf | ||
|
|
0e3034c0f6 | ||
|
|
686262fdcd | ||
|
|
2379fd8a58 | ||
|
|
3552a27ae6 | ||
|
|
39106ba760 | ||
|
|
f270ac99f0 | ||
|
|
f83af8e076 | ||
|
|
4d2c92f6d5 | ||
|
|
503e241db1 | ||
|
|
dea5f80215 | ||
|
|
c261db259b | ||
|
|
c382e7ef44 | ||
|
|
16610a211f | ||
|
|
4d57ff046d | ||
|
|
4a76efe6d5 | ||
|
|
87d43c7a32 | ||
|
|
f383278a5a | ||
|
|
a9d4b1e1b9 | ||
|
|
61c5d7d431 | ||
|
|
b7765993e2 | ||
|
|
e152b554f5 | ||
|
|
c46a066827 | ||
|
|
cf003379ac | ||
|
|
7b94783cb7 | ||
|
|
38600bb4e2 | ||
|
|
16875f7c6d | ||
|
|
381fecfc44 | ||
|
|
5648b924d6 | ||
|
|
636d2d571b | ||
|
|
d016ec129d | ||
|
|
cb77faeae7 | ||
|
|
38ea8fc3ee | ||
|
|
d8e5bc07aa | ||
|
|
3b26f79143 | ||
|
|
c366429e57 | ||
|
|
8ed478ce46 | ||
|
|
a97a8f1cba | ||
|
|
fb0b6263d1 | ||
|
|
76aaf3d4a8 | ||
|
|
08232d29b9 | ||
|
|
cfaccc5fad | ||
|
|
7da5a6b9ed | ||
|
|
7ed87bed8c | ||
|
|
46ec94d0ce | ||
|
|
6bc0b023aa | ||
|
|
13d673e0f7 | ||
|
|
c40c159173 | ||
|
|
202ded5d11 | ||
|
|
e3a698c382 | ||
|
|
3a60b4caa8 | ||
|
|
f57858b3a8 | ||
|
|
9e430b9010 | ||
|
|
ad2a42ce9e | ||
|
|
1c32635b3a | ||
|
|
558594fddf | ||
|
|
c8879322b0 | ||
|
|
d716c553c4 | ||
|
|
ab35922161 | ||
|
|
474c6adf8f | ||
|
|
f5f806af06 | ||
|
|
0a01719477 | ||
|
|
07cd9143da | ||
|
|
d064cb522f | ||
|
|
802c7db50e | ||
|
|
0f87acc2b3 | ||
|
|
998b61e5f3 | ||
|
|
c47071815b | ||
|
|
0ed6c1ccde | ||
|
|
d888a27f07 | ||
|
|
7c2ae3d2e8 | ||
|
|
c88a8b6130 | ||
|
|
32a0434bc3 | ||
|
|
a2e556858a | ||
|
|
9eab43994b | ||
|
|
c53dfa9754 | ||
|
|
81a1e13f3b | ||
|
|
8f89234f1a | ||
|
|
d757dbfbff | ||
|
|
0d9a6e45fb | ||
|
|
4d4666cff7 | ||
|
|
46092add29 | ||
|
|
1655c39ded | ||
|
|
a95dc09c6e | ||
|
|
f1f80a8a20 | ||
|
|
4c2bfb1d47 | ||
|
|
c0fc21efb3 | ||
|
|
93d3c44a1a | ||
|
|
9eea78b3ad | ||
|
|
0a3a556879 | ||
|
|
aba8900074 | ||
|
|
f5744b95db | ||
|
|
13d721afd3 | ||
|
|
90a2e6d70e | ||
|
|
bc9f8a8100 | ||
|
|
2b5e7b0491 | ||
|
|
d7c95265cd | ||
|
|
8751cfc409 | ||
|
|
01f96d30f6 | ||
|
|
fffbd93f12 | ||
|
|
ddcfbdc8d2 | ||
|
|
173fd7cdca | ||
|
|
d14e7593cc | ||
|
|
1a3d0b74f7 | ||
|
|
f6c6f0cc71 | ||
|
|
966e67a252 | ||
|
|
1c128c0d11 | ||
|
|
a3199d58db | ||
|
|
659483031e | ||
|
|
7dc2513205 | ||
|
|
0748d365a6 | ||
|
|
94a404ed10 | ||
|
|
ef1799f31f | ||
|
|
47b0960cc7 | ||
|
|
2288331a6f | ||
|
|
23e9156f43 | ||
|
|
8f99e7c4ea | ||
|
|
f3bcd94524 | ||
|
|
a2f8b19c2a | ||
|
|
588d720517 | ||
|
|
cd822cb770 | ||
|
|
b27b8e3cd3 | ||
|
|
7a2c5dc980 | ||
|
|
d9e3763d1c | ||
|
|
6f15ed3264 | ||
|
|
0d2b5af007 | ||
|
|
9e7a8f48e8 | ||
|
|
98f7a0569c | ||
|
|
551f66282e | ||
|
|
3d2ba5aaed | ||
|
|
94942a48ab | ||
|
|
ab8984a7a3 | ||
|
|
4990f643c1 | ||
|
|
34bef977e8 | ||
|
|
f36c34038b | ||
|
|
bfd0e12d22 | ||
|
|
1450f85ada | ||
|
|
2a0f1e6977 | ||
|
|
0f433b1142 | ||
|
|
ab6bcad263 | ||
|
|
e40a3e0621 | ||
|
|
e56acf4f14 | ||
|
|
17977eda30 | ||
|
|
459a257568 | ||
|
|
fb65b53b9b | ||
|
|
c8d4062f73 | ||
|
|
c8e0992814 | ||
|
|
c0a12b29d0 | ||
|
|
02dded11a5 | ||
|
|
b71279cda5 | ||
|
|
c70477f8c6 | ||
|
|
9b51b8b882 | ||
|
|
48539596ef | ||
|
|
cafa99774c | ||
|
|
b5f7ac95d8 | ||
|
|
e984b97db0 | ||
|
|
64d4e02b4f | ||
|
|
90ddef5a41 | ||
|
|
58ef99f76b | ||
|
|
43c34956fb | ||
|
|
d7dee1b9d3 | ||
|
|
94a38ebc3a | ||
|
|
0764460eaf | ||
|
|
6fd02279da | ||
|
|
6274294bc5 | ||
|
|
27708026d4 | ||
|
|
849aa5b105 | ||
|
|
0be83bfbba | ||
|
|
f8592be43d | ||
|
|
647ad51423 | ||
|
|
73f51e45a8 | ||
|
|
bc4f455151 | ||
|
|
b4b5e0b6aa | ||
|
|
9927023680 | ||
|
|
9b2fb1d4d2 | ||
|
|
689b894506 | ||
|
|
06a30ae529 | ||
|
|
ed106d7f28 | ||
|
|
9d08fd8c7e | ||
|
|
7e8126704b | ||
|
|
d96767ee45 | ||
|
|
63f31bf73e | ||
|
|
7ecfe2353f | ||
|
|
7bec672c7e | ||
|
|
5aac5deb75 | ||
|
|
54e016ae71 | ||
|
|
6b53378839 | ||
|
|
1266f86444 | ||
|
|
231c02cdeb | ||
|
|
454a8d9d7b | ||
|
|
bbe92b9cd3 | ||
|
|
7bb41732fb | ||
|
|
c217f6be6a | ||
|
|
21662d38e6 | ||
|
|
19f3842292 | ||
|
|
ae0cbf00b1 | ||
|
|
9019c6864a | ||
|
|
d1b61c37fa | ||
|
|
32b68a5fad | ||
|
|
55fdb17b18 | ||
|
|
af730c79a6 | ||
|
|
041e6131d1 | ||
|
|
5a7d7e05b8 | ||
|
|
71b93d55ef | ||
|
|
d2b5e1e2d6 | ||
|
|
a3cb877c54 | ||
|
|
6895a71cc4 | ||
|
|
d9034b01f1 | ||
|
|
488ac8c3f2 | ||
|
|
ecf36d53c8 | ||
|
|
893ad920c5 | ||
|
|
0695c79f4e | ||
|
|
8837ea24cb | ||
|
|
65222d03b9 | ||
|
|
54937495e2 | ||
|
|
8a783b81a4 | ||
|
|
093da2a5a7 | ||
|
|
b68ea5fc7d | ||
|
|
90c587408f | ||
|
|
90475fbaa5 | ||
|
|
07ff9e1da0 | ||
|
|
5637799c92 | ||
|
|
73c82441e7 | ||
|
|
6d06921276 | ||
|
|
2996b34ddf | ||
|
|
e5821301f6 | ||
|
|
f4d1874ac5 | ||
|
|
f3428929a2 | ||
|
|
263d6950a1 | ||
|
|
8024f8e31a | ||
|
|
3849b29594 | ||
|
|
0e4d4da0e5 | ||
|
|
ca3cd51f91 | ||
|
|
fda1e0d33d | ||
|
|
1a850392bc | ||
|
|
14a79eb142 | ||
|
|
271b809495 | ||
|
|
2363269c1c | ||
|
|
f1db473d11 | ||
|
|
e35d05a5e3 | ||
|
|
c61783546b | ||
|
|
c08794bdfb | ||
|
|
4905975f81 | ||
|
|
d53bfb9201 | ||
|
|
0dac47cb62 | ||
|
|
7b68552359 | ||
|
|
775495c7e7 | ||
|
|
1057f13cdc | ||
|
|
ce59a299cb | ||
|
|
8235e025d4 | ||
|
|
b301381f90 | ||
|
|
c62f930634 | ||
|
|
85eb44ac95 | ||
|
|
d5f8063900 | ||
|
|
ee66929465 | ||
|
|
1b044b8a40 | ||
|
|
f46f6d34d3 | ||
|
|
3a96e8826f | ||
|
|
84738668ca | ||
|
|
dbea311aa8 | ||
|
|
d9ce54dee3 | ||
|
|
7b056735ed | ||
|
|
33fde99138 | ||
|
|
4b486e87cc | ||
|
|
a07d1bca74 | ||
|
|
5e1ef90962 | ||
|
|
8fe214d915 | ||
|
|
bec9d1dfcd | ||
|
|
694d5d4638 | ||
|
|
a6ac7cd876 | ||
|
|
28751a097a | ||
|
|
19c795be0d | ||
|
|
dd82c26f87 | ||
|
|
c6f621d0dc | ||
|
|
e6add997eb | ||
|
|
a2baeb2fe2 | ||
|
|
a500946e50 | ||
|
|
b7c9c2679e | ||
|
|
bc8a14895a | ||
|
|
4ae68d0430 | ||
|
|
aabf97f885 | ||
|
|
a9b546cb0f | ||
|
|
5566c31458 | ||
|
|
ff96d6158e | ||
|
|
2aa9071aed | ||
|
|
adf2a030e6 | ||
|
|
0783aa99d7 | ||
|
|
5a848c98bb | ||
|
|
e98f9b9c4a | ||
|
|
faac2520c9 | ||
|
|
3d098416c6 | ||
|
|
7e53611e3a | ||
|
|
d8496160cb | ||
|
|
c7f10bc76d | ||
|
|
f8910caa59 | ||
|
|
b1d948daef | ||
|
|
4d4ddbd887 | ||
|
|
d205b47c08 | ||
|
|
2b7df1fcac | ||
|
|
53eccc0a3d | ||
|
|
951cf9d7b0 | ||
|
|
87136bb0d0 | ||
|
|
eb06ebe245 | ||
|
|
b06ca88cd4 | ||
|
|
5af2e30d9a | ||
|
|
ea3529e624 | ||
|
|
0209c11bc1 | ||
|
|
6a24660472 | ||
|
|
a3bc87d87d | ||
|
|
85493a2581 | ||
|
|
ad544565fe | ||
|
|
5e135a9daf |
3
.codespell.ignore
Normal file
3
.codespell.ignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
parm
|
||||||
|
parms
|
||||||
|
crate
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
[codespell]
|
[codespell]
|
||||||
ignore-words-list = parm,parms
|
ignore-words = .codespell.ignore
|
||||||
skip = ''
|
|
||||||
count = ''
|
count = ''
|
||||||
quiet-level = 3
|
quiet-level = 3
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ insert_final_newline = true
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
tab_width = 8
|
tab_width = 8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.rs]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
|
||||||
[*.sh]
|
[*.sh]
|
||||||
shell_variant = bash # used by `shfmt`
|
shell_variant = bash # used by `shfmt`
|
||||||
@@ -19,3 +25,9 @@ indent_size = 2
|
|||||||
[*.py]
|
[*.py]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|
||||||
|
[{Makefile,*.mak}]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[{COMMIT_EDITMSG,EDIT_DESCRIPTION}]
|
||||||
|
max_line_length = 72
|
||||||
|
|||||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -9,6 +9,10 @@
|
|||||||
tags
|
tags
|
||||||
TAGS
|
TAGS
|
||||||
|
|
||||||
|
# compile_commands.json
|
||||||
|
# (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
# clangd cache (https://clangd.llvm.org/design/indexing#backgroundindex)
|
# clangd cache (https://clangd.llvm.org/design/indexing#backgroundindex)
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
@@ -19,6 +23,8 @@ TAGS
|
|||||||
#
|
#
|
||||||
# Ignore generated executables and other generated files
|
# Ignore generated executables and other generated files
|
||||||
#
|
#
|
||||||
|
**/.detect-openssl.dep.c
|
||||||
|
*.debug
|
||||||
ap_tools/ap-check
|
ap_tools/ap-check
|
||||||
cmsfs-fuse/cmsfs-fuse
|
cmsfs-fuse/cmsfs-fuse
|
||||||
cpacfstats/cpacfstats
|
cpacfstats/cpacfstats
|
||||||
@@ -26,6 +32,7 @@ cpacfstats/cpacfstatsd
|
|||||||
cpumf/chcpumf
|
cpumf/chcpumf
|
||||||
cpumf/lscpumf
|
cpumf/lscpumf
|
||||||
cpumf/lshwc
|
cpumf/lshwc
|
||||||
|
cpumf/lspai
|
||||||
cpumf/pai
|
cpumf/pai
|
||||||
cpuplugd/cpuplugd
|
cpuplugd/cpuplugd
|
||||||
dasdfmt/dasdfmt
|
dasdfmt/dasdfmt
|
||||||
@@ -50,8 +57,8 @@ iucvterm/src/iucvconn
|
|||||||
iucvterm/src/iucvtty
|
iucvterm/src/iucvtty
|
||||||
iucvterm/src/ttyrun
|
iucvterm/src/ttyrun
|
||||||
iucvterm/test/test_afiucv
|
iucvterm/test/test_afiucv
|
||||||
libap/check-dep-lock
|
|
||||||
libap/check-dep-json
|
libap/check-dep-json
|
||||||
|
libap/check-dep-lock
|
||||||
libekmfweb/check-dep-libekmfweb
|
libekmfweb/check-dep-libekmfweb
|
||||||
libekmfweb/detect-openssl-version.dep
|
libekmfweb/detect-openssl-version.dep
|
||||||
libekmfweb/libekmfweb.so
|
libekmfweb/libekmfweb.so
|
||||||
@@ -85,6 +92,7 @@ vmcp/vmcp
|
|||||||
vmur/vmur
|
vmur/vmur
|
||||||
zconf/chp/chchp
|
zconf/chp/chchp
|
||||||
zconf/chp/lschp
|
zconf/chp/lschp
|
||||||
|
zconf/chp/chpstat/chpstat
|
||||||
zconf/css/lscss
|
zconf/css/lscss
|
||||||
zconf/qeth/lsqeth
|
zconf/qeth/lsqeth
|
||||||
zconf/scm/lsscm
|
zconf/scm/lsscm
|
||||||
@@ -96,6 +104,7 @@ zdev/src/chzdev
|
|||||||
zdev/src/chzdev_usage.c
|
zdev/src/chzdev_usage.c
|
||||||
zdev/src/lszdev
|
zdev/src/lszdev
|
||||||
zdev/src/lszdev_usage.c
|
zdev/src/lszdev_usage.c
|
||||||
|
zdev/src/zdev_id
|
||||||
zdsfs/zdsfs
|
zdsfs/zdsfs
|
||||||
zdump/.check_dep_fuse
|
zdump/.check_dep_fuse
|
||||||
zdump/.check_dep_zgetdump
|
zdump/.check_dep_zgetdump
|
||||||
@@ -115,10 +124,11 @@ zipl/boot/*.exec
|
|||||||
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
|
||||||
zdev/src/zdev_id
|
zipl/src/chreipl_helper.md
|
||||||
zipl/src/zipl
|
zipl/src/zipl
|
||||||
zipl/src/zipl-editenv
|
zipl/src/zipl-editenv
|
||||||
zipl/src/zipl_helper.device-mapper
|
zipl/src/zipl_helper.device-mapper
|
||||||
|
zipl/src/zipl_helper.md
|
||||||
zkey/check-dep-zkey
|
zkey/check-dep-zkey
|
||||||
zkey/check-dep-zkey-cryptsetup
|
zkey/check-dep-zkey-cryptsetup
|
||||||
zkey/detect-libcryptsetup.dep
|
zkey/detect-libcryptsetup.dep
|
||||||
@@ -129,4 +139,3 @@ zkey/kmip/zkey-kmip.so
|
|||||||
zkey/zkey
|
zkey/zkey
|
||||||
zkey/zkey-cryptsetup
|
zkey/zkey-cryptsetup
|
||||||
zpcictl/zpcictl
|
zpcictl/zpcictl
|
||||||
**/.detect-openssl.dep.c
|
|
||||||
|
|||||||
35
.pre-commit-config.yaml
Normal file
35
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
exclude: \.(bin|crl|crt|key)$
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.1.0
|
||||||
|
hooks:
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: mixed-line-ending
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: check-executables-have-shebangs
|
||||||
|
- id: check-shebang-scripts-are-executable
|
||||||
|
exclude_types: ['rust']
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: git-clang-format
|
||||||
|
name: git-clang-format
|
||||||
|
description: Run git-clang-format
|
||||||
|
entry: git
|
||||||
|
args: [clang-format, --staged, --]
|
||||||
|
pass_filenames: true
|
||||||
|
language: system
|
||||||
|
require_serial: true
|
||||||
|
minimum_pre_commit_version: "2.9.0"
|
||||||
|
types_or: [c++, c]
|
||||||
|
- repo: https://github.com/codespell-project/codespell
|
||||||
|
rev: v2.2.1
|
||||||
|
hooks:
|
||||||
|
- id: codespell
|
||||||
|
exclude_types: ['rust']
|
||||||
|
- repo: https://github.com/jumanjihouse/pre-commit-hooks
|
||||||
|
rev: 3.0.0
|
||||||
|
hooks:
|
||||||
|
- id: shellcheck
|
||||||
|
args: ["--external-sources"]
|
||||||
13
.rustfmt.toml
Normal file
13
.rustfmt.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
edition = "2021"
|
||||||
|
newline_style = "Unix"
|
||||||
|
|
||||||
|
# Unstable options that help catching some mistakes in formatting and that we may want to enable
|
||||||
|
# when they become stable.
|
||||||
|
#
|
||||||
|
# They are kept here since they are useful to run from time to time.
|
||||||
|
#comment_width = 100
|
||||||
|
#format_code_in_doc_comments = true
|
||||||
|
#group_imports = "StdExternalCrate"
|
||||||
|
#normalize_comments = true
|
||||||
|
#reorder_impl_items = true
|
||||||
|
#wrap_comments = true
|
||||||
5
.shellcheckrc
Normal file
5
.shellcheckrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Search in the current script's directory by default (since 0.7.0)
|
||||||
|
source-path=SCRIPTDIR
|
||||||
|
|
||||||
|
# Allow external-sources (since 0.8.0)
|
||||||
|
external-sources=true
|
||||||
@@ -27,6 +27,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Eberhard Pasch
|
- Eberhard Pasch
|
||||||
- Eduard Shishkin
|
- Eduard Shishkin
|
||||||
- Einar Lueck
|
- Einar Lueck
|
||||||
|
- Eric Farman
|
||||||
- Eric Sandeen
|
- Eric Sandeen
|
||||||
- Erwin Vicari
|
- Erwin Vicari
|
||||||
- Eugene Crosser
|
- Eugene Crosser
|
||||||
@@ -35,6 +36,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Farhan Ali
|
- Farhan Ali
|
||||||
- Fedor Loshakov
|
- Fedor Loshakov
|
||||||
- Felix Beck
|
- Felix Beck
|
||||||
|
- Finn Callies
|
||||||
- Frank Blaschka
|
- Frank Blaschka
|
||||||
- Frank Heimes
|
- Frank Heimes
|
||||||
- Frank Munzert
|
- Frank Munzert
|
||||||
@@ -56,6 +58,7 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Horst Hummel
|
- Horst Hummel
|
||||||
- Ingo Franzki
|
- Ingo Franzki
|
||||||
- Ingo Tuchscherer
|
- Ingo Tuchscherer
|
||||||
|
- Jakub Čajka
|
||||||
- Jan Glauber
|
- Jan Glauber
|
||||||
- Jan Höppner
|
- Jan Höppner
|
||||||
- Jan Willeke
|
- Jan Willeke
|
||||||
@@ -124,6 +127,8 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Thomas Richter
|
- Thomas Richter
|
||||||
- Thomas Spatzier
|
- Thomas Spatzier
|
||||||
- Thomas Weber
|
- Thomas Weber
|
||||||
|
- Thorsten Winkler
|
||||||
|
- Tobias Huschle
|
||||||
- Tuan Hoang
|
- Tuan Hoang
|
||||||
- Ursula Braun
|
- Ursula Braun
|
||||||
- Utz Bacher
|
- Utz Bacher
|
||||||
@@ -134,3 +139,4 @@ List of all individuals having contributed content to s390-tools
|
|||||||
- Volker Sameske
|
- Volker Sameske
|
||||||
- Wenjia Zhang
|
- Wenjia Zhang
|
||||||
- Wolfgang Taphorn
|
- Wolfgang Taphorn
|
||||||
|
- Yaakov Selkowitz
|
||||||
|
|||||||
166
CHANGELOG.md
166
CHANGELOG.md
@@ -1,6 +1,172 @@
|
|||||||
Release history for s390-tools (MIT version)
|
Release history for s390-tools (MIT version)
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
* __v2.35.0 (2024-10-01)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.11
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- cpacfstats: Add support for FULL XTS (MSA 10) and HMAC (MSA 11) PAI counter
|
||||||
|
- cpuplugd: Make cpuplugd compatible with hiperdispatch
|
||||||
|
- dbginfo.sh: Add network sockstat info
|
||||||
|
- pvapconfig: s390x exclusive build
|
||||||
|
- zdev: Add option to select IPL device
|
||||||
|
- zdump/dfo_s390: Support s390 DFO for vr-kernel dumps
|
||||||
|
- zipl: Add support of mirror devices
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- (genprotimg|zipl)/boot: discard .note.package ELF section to save memory
|
||||||
|
- netboot/mk-s390image: Fix size when argument is a symlink
|
||||||
|
- ziorep_config: Fix warning message when multipath device is not there.
|
||||||
|
- zipl: Fix problems when target parameters are specified by user
|
||||||
|
- zipl: Fix segfault when creating device-based dumps with '--dry-run'
|
||||||
|
|
||||||
|
* __v2.34.0 (2024-08-01)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.10
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- ap_tools/ap-check: Add support for vfio-ap dynamic configuration
|
||||||
|
- dbginfo.sh: Update/Add additional DASD data collection
|
||||||
|
- dumpconf: Add new parameter 'SCP_DATA' for SCSI/NVMe/ECKD dump devices
|
||||||
|
- libutil: Make formatted meta-data configurable
|
||||||
|
- s390-tools: Replace 'which' with built-in 'command -v'
|
||||||
|
- zdump/dfi_elf: Support core dumps of vr-kernels
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- chzdev: Fix warning about failed ATTR writes by udev
|
||||||
|
- rust/pv: Try again if first CRL-URI is invalid
|
||||||
|
- rust/pvattest: Add short option for --arpk
|
||||||
|
- zdump: Fix 'zgetdump -i' ioctl error on s390 formatted dump file
|
||||||
|
|
||||||
|
* __v2.33.1 (2024-05-28)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.9
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- s390-tools: Fix formatting and typos in README.md
|
||||||
|
- s390-tools: Fix release string
|
||||||
|
|
||||||
|
* __v2.33.0 (2024-05-27)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.9
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
- chpstat: New tool for displaying channel path statistics
|
||||||
|
- libutil: Add output format helpers(util_fmt: JSON, JSON-SEQ, CSV, text pairs)
|
||||||
|
|
||||||
|
Changes of existing tools / libraries:
|
||||||
|
- chzdev: Add --is-owner to identify files created by zdev
|
||||||
|
- dasdfmt: Change default mode to always use full-format (Note: affects ESE DASD)
|
||||||
|
- libap: Significantly reduce delay time between file lock retries
|
||||||
|
- pvattest: Rewrite from C to Rust
|
||||||
|
- pvattest: Support additional data & user-data
|
||||||
|
- rust/pv: Support for Attestation
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- chreipl: Improve disk type detection when running under QEMU
|
||||||
|
- dbginfo.sh: Use POSIX option with uname
|
||||||
|
- s390-tools: Fix missing hyphen escapes in the man page for many tools
|
||||||
|
- zipl/src: Fix bugs in disk_get_info() reproducible in corner cases
|
||||||
|
|
||||||
|
* __v2.32.0 (2024-04-03)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.8
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- cpumf/lscpumf: add support for machine type 3932
|
||||||
|
- genprotimg, pvattest, and pvsecret accept IBM signing key with Armonk as
|
||||||
|
subject locality
|
||||||
|
- zdump/zipl: Support for List-Directed dump from ECKD DASD
|
||||||
|
- zkey: Detect FIPS mode and generate PBKDF for luksFormat according to it
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- dbginfo.sh: dash compatible copy sequence
|
||||||
|
- rust/pv_core: Fix UvDeviceInfo::get() method
|
||||||
|
- zipl/src: Fix leak of files if run with a broken configuration
|
||||||
|
- zkey: Fix convert command to accept only keys of type CCA-AESDATA
|
||||||
|
|
||||||
|
* __v2.31.0 (2024-02-02)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.7
|
||||||
|
|
||||||
|
General:
|
||||||
|
- common.mak: Set default C/C++ standard to gnu11/gnu++11
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
- pvapconfig: Tool to automatically configure APQNs in SE KVM guests
|
||||||
|
- s390-tools: Provide pre-commit configuration
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- cpuplugd: Adjust to CPU 0 being no longer hotpluggable
|
||||||
|
- dbginfo.sh: Check for Dynamic Partition Mode
|
||||||
|
- dbginfo.sh: Update man page and copyright
|
||||||
|
- rust/pv: Add user-data signing and verifying
|
||||||
|
- rust/pvsecret: Add user defined signatures and verifications
|
||||||
|
- zdev/dracut: Consolidate device configuration
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- dbginfo.sh: Fix relative path on script copy
|
||||||
|
- libkmipclient: Fix build with libxml2-2.12.0
|
||||||
|
- pvsecret: Fix panic if empty file is used as host key document
|
||||||
|
- rust/pv: Fix 'elided_lifetimes_in_associated_constant' warning
|
||||||
|
|
||||||
|
* __v2.30.0 (2023-12-01)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.6
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
- lspai: Tool to display PAI counter sets
|
||||||
|
- s390-tools: Provide a ShellCheck configuration
|
||||||
|
|
||||||
|
Changes of existing tools / libraries:
|
||||||
|
- cpumf/pai: Add command line option for realtime scheduling
|
||||||
|
- dbginfo.sh: enhance ethtool collection for ROCE
|
||||||
|
- libutil/util_lockfile: add routine to return owning pid of file lock
|
||||||
|
- lszcrypt: Improve lszcrypt output on SE guests
|
||||||
|
- rust: Use a single workspace for all rust tools
|
||||||
|
- zdev: limit the derivation of ZDEV_SITE_ID
|
||||||
|
- zdump/df_s390: Update 'zgetdump -i' output with zlib info
|
||||||
|
- zdump/dfi_s390: Support reading compressed s390_ext dumps
|
||||||
|
- zipl/boot: Integrate zlib compression to single volume DASD dumper
|
||||||
|
- zipl/boot: compile the bootloaders only if HOST_ARCH is s390x
|
||||||
|
- zipl: Add --no-compress option to zipl command
|
||||||
|
- zkey: Also check for deconfigured and check-stopped cards
|
||||||
|
- dbginfo.sh: fix relative path on script copy
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- ap_tools/ap-check: handle get-attributes between pre and post event
|
||||||
|
- libutil: fix util_file_read_*() using wrong format specifiers
|
||||||
|
- rust/pv: fix Invalid write of size 1
|
||||||
|
|
||||||
|
* __v2.29.0 (2023-08-04)__
|
||||||
|
|
||||||
|
For Linux kernel version: 6.5
|
||||||
|
|
||||||
|
General:
|
||||||
|
- s390-tools now supports tools written in Rust.
|
||||||
|
- Add `compdb` Makefile target to create 'compile_commands.json' to LSP
|
||||||
|
backends in IDEs and editors
|
||||||
|
|
||||||
|
Add new tools / libraries:
|
||||||
|
- rust/pv: Library for pv tools written in rust
|
||||||
|
- rust/pvsecret: Tool to manage UV-secrets
|
||||||
|
|
||||||
|
Changes of existing tools:
|
||||||
|
- dbginfo.sh: Global IFS variable
|
||||||
|
- genprotimg: Add support for add-secret requests
|
||||||
|
- genprotimg: Build debuginfo files for bootloader
|
||||||
|
- hyptop: Add real SMT utilization field
|
||||||
|
- hyptop: Allow users to set speedup factor
|
||||||
|
- pvattest: Add yaml-output for verify command
|
||||||
|
- zipl: Build debuginfo files for bootloader
|
||||||
|
|
||||||
|
Bug Fixes:
|
||||||
|
- dump2tar: Fix truncated paths
|
||||||
|
- zdev/dracut: fix kdump build to integrate with site support
|
||||||
|
|
||||||
* __v2.28.0 (2023-07-11)__
|
* __v2.28.0 (2023-07-11)__
|
||||||
|
|
||||||
For Linux kernel version: 6.4
|
For Linux kernel version: 6.4
|
||||||
|
|||||||
5
Makefile
5
Makefile
@@ -15,11 +15,12 @@ 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 \
|
||||||
genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools pvattest
|
genprotimg lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust
|
||||||
|
|
||||||
else
|
else
|
||||||
BASELIB_DIRS =
|
BASELIB_DIRS =
|
||||||
LIB_DIRS = libpv
|
LIB_DIRS = libpv
|
||||||
TOOL_DIRS = genprotimg pvattest
|
TOOL_DIRS = genprotimg rust
|
||||||
endif
|
endif
|
||||||
|
|
||||||
SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS)
|
SUB_DIRS = $(BASELIB_DIRS) $(LIB_DIRS) $(TOOL_DIRS)
|
||||||
|
|||||||
53
README.md
53
README.md
@@ -15,6 +15,17 @@ The package also contains the following files:
|
|||||||
Package contents
|
Package contents
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
* rust:
|
||||||
|
all s390-tools that are written in rust and require external crates.
|
||||||
|
Disable the compilation of all tools in `rust/` using HAVE_CARGO=0
|
||||||
|
See the `rust/README.md` for Details
|
||||||
|
- pvattest:
|
||||||
|
Create, perform, and verify IBM Secure Execution attestation measurements.
|
||||||
|
- pvapconfig:
|
||||||
|
Automatic configure APQNs within an SE KVM guest
|
||||||
|
- pvsecret:
|
||||||
|
Manage secrets for IBM Secure Execution guests
|
||||||
|
|
||||||
* dasdfmt:
|
* dasdfmt:
|
||||||
Low-level format ECKD DASDs with the classical Linux disk layout or the new
|
Low-level format ECKD DASDs with the classical Linux disk layout or the new
|
||||||
z/OS compatible disk layout.
|
z/OS compatible disk layout.
|
||||||
@@ -33,9 +44,6 @@ Package contents
|
|||||||
* genprotimg:
|
* genprotimg:
|
||||||
Create a protected virtualization image.
|
Create a protected virtualization image.
|
||||||
|
|
||||||
* pvattest:
|
|
||||||
Create, perform, and verify protected virtualization attestation measurements.
|
|
||||||
|
|
||||||
* udev rules:
|
* udev rules:
|
||||||
- 59-dasd.rules: rules for unique DASD device nodes created in /dev/disk/.
|
- 59-dasd.rules: rules for unique DASD device nodes created in /dev/disk/.
|
||||||
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
- 57-osasnmpd.rules: udev rules for osasnmpd.
|
||||||
@@ -305,13 +313,14 @@ build options:
|
|||||||
| net-snmp | `HAVE_SNMP` | osasnmpd |
|
| net-snmp | `HAVE_SNMP` | osasnmpd |
|
||||||
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
|
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
|
||||||
| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb, |
|
| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb, |
|
||||||
| | | libkmipclient, pvattest, zgetdump |
|
| | | libkmipclient, pvattest, zgetdump, |
|
||||||
|
| | | rust/pvsecret, |
|
||||||
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
|
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
|
||||||
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, |
|
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, |
|
||||||
| | | libkmipclient |
|
| | | libkmipclient |
|
||||||
| glib2 | `HAVE_GLIB2` | genprotimg, pvattest, zgetdump |
|
| glib2 | `HAVE_GLIB2` | genprotimg, pvattest, zgetdump |
|
||||||
| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb, libkmipclient,|
|
| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb, libkmipclient,|
|
||||||
| | | pvattest |
|
| | | pvattest, rust/pvsecret, |
|
||||||
| libxml2 | `HAVE_LIBXML2` | libkmipclient |
|
| libxml2 | `HAVE_LIBXML2` | libkmipclient |
|
||||||
| systemd | `HAVE_SYSTEMD` | hsavmcore |
|
| systemd | `HAVE_SYSTEMD` | hsavmcore |
|
||||||
| libudev | `HAVE_LIBUDEV` | cpacfstatsd |
|
| libudev | `HAVE_LIBUDEV` | cpacfstatsd |
|
||||||
@@ -324,6 +333,7 @@ This table lists additional build or install options:
|
|||||||
| | | zipl |
|
| | | zipl |
|
||||||
| initramfs-tools | `HAVE_INITRAMFS` | zdev, zipl |
|
| initramfs-tools | `HAVE_INITRAMFS` | zdev, zipl |
|
||||||
| | `ZDEV_ALWAYS_UPDATE_INITRD` | zdev |
|
| | `ZDEV_ALWAYS_UPDATE_INITRD` | zdev |
|
||||||
|
| rust | `HAVE_CARGO` | rust/* |
|
||||||
|
|
||||||
The s390-tools build process uses "pkg-config" and therefore it must be
|
The s390-tools build process uses "pkg-config" and therefore it must be
|
||||||
available.
|
available.
|
||||||
@@ -334,6 +344,14 @@ Build and runtime requirements for specific tools
|
|||||||
In the following more details on the build an runtime requirements of
|
In the following more details on the build an runtime requirements of
|
||||||
the different tools are provided:
|
the different tools are provided:
|
||||||
|
|
||||||
|
* rust/pvsecret:
|
||||||
|
For building pvsecret you need OpenSSL version 1.1.1 or newer
|
||||||
|
installed (openssl-devel.rpm). Also required is cargo and libcurl.
|
||||||
|
Tip: you may skip the pvsecret build by adding
|
||||||
|
`HAVE_OPENSSL=0`, `HAVE_LIBCURL=0`, or `HAVE_CARGO=0`.
|
||||||
|
|
||||||
|
The runtime requirements are: openssl-libs (>= 1.1.1).
|
||||||
|
|
||||||
* dbginfo.sh:
|
* dbginfo.sh:
|
||||||
The tar package is required to archive collected data.
|
The tar package is required to archive collected data.
|
||||||
|
|
||||||
@@ -345,12 +363,11 @@ the different tools are provided:
|
|||||||
|
|
||||||
The runtime requirements are: openssl-libs (>= 1.1.0) and glib2.
|
The runtime requirements are: openssl-libs (>= 1.1.0) and glib2.
|
||||||
|
|
||||||
* pvattest:
|
* rust/pvattest:
|
||||||
For building pvattest you need OpenSSL version 1.1.1 or newer
|
For building pvattest you need OpenSSL version 1.1.1 or newer
|
||||||
installed (openssl-devel.rpm). Also required is glib2.56 or newer
|
installed (openssl-devel.rpm). Also required is cargo and libcurl.
|
||||||
(glib2-devel.rpm) and libcurl.
|
|
||||||
Tip: you may skip the pvattest build by adding
|
Tip: you may skip the pvattest build by adding
|
||||||
`HAVE_OPENSSL=0`, `HAVE_LIBCURL=0`, or `HAVE_GLIB2=0`.
|
`HAVE_OPENSSL=0`, `HAVE_LIBCURL=0`, or `HAVE_CARGO=0`.
|
||||||
|
|
||||||
The runtime requirements are: openssl-libs (>= 1.1.1) and
|
The runtime requirements are: openssl-libs (>= 1.1.1) and
|
||||||
glib2.56 or newer.
|
glib2.56 or newer.
|
||||||
@@ -371,6 +388,24 @@ the different tools are provided:
|
|||||||
- Packages: blktrace, multipath-tools, sg3-utils
|
- Packages: blktrace, multipath-tools, sg3-utils
|
||||||
- Tools: rsync, tar, lsscsi
|
- Tools: rsync, tar, lsscsi
|
||||||
|
|
||||||
|
* zipl
|
||||||
|
For CCW-type DASD dump, zlib compression can be used to compress the dump
|
||||||
|
data before writing it to the DASD partition. It can benefit from
|
||||||
|
s390 on-chip compression accelerator (DFLTCC) and provide a faster dumping
|
||||||
|
process, hence lower system downtime.
|
||||||
|
The zlib version integrated with zipl (zipl/boot/zlib) is based on the Linux
|
||||||
|
kernel zlib (kernel version 6.3) which represents zlib version 1.1.3 with a
|
||||||
|
limited number of functions and a number of updates on top including s390
|
||||||
|
hardware compression (DFLTCC) support. Also, all memory allocations are
|
||||||
|
performed in advance, which aligns with zipl requirements.
|
||||||
|
The CCW-type standalone dumper is built as a single binary and must be
|
||||||
|
loaded to stage2 during boot. Hence, all required zlib functions must be
|
||||||
|
integrated into it, and its size is restricted. To limit the size, only
|
||||||
|
deflate-related parts are integrated (no decompression is required during
|
||||||
|
dumping).
|
||||||
|
Removing the inflate modules and function prototypes are the only major
|
||||||
|
modifications made to the kernel version of zlib.
|
||||||
|
|
||||||
* 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
|
||||||
installed (openssl-devel.rpm). Also required is glib2
|
installed (openssl-devel.rpm). Also required is glib2
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <json-c/json.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -27,21 +28,33 @@
|
|||||||
|
|
||||||
#include "ap-check.h"
|
#include "ap-check.h"
|
||||||
|
|
||||||
|
/* The supported mdevctl callout version */
|
||||||
|
#define MDEVCTL_CAP_VERSION 2
|
||||||
|
|
||||||
static const struct mdevctl_action mdevctl_action_table[NUM_MDEVCTL_ACTIONS] = {
|
static const struct mdevctl_action mdevctl_action_table[NUM_MDEVCTL_ACTIONS] = {
|
||||||
{MDEVCTL_ACTION_DEFINE, "define"},
|
{MDEVCTL_ACTION_DEFINE, "define"},
|
||||||
{MDEVCTL_ACTION_LIST, "list"},
|
|
||||||
{MDEVCTL_ACTION_MODIFY, "modify"},
|
{MDEVCTL_ACTION_MODIFY, "modify"},
|
||||||
{MDEVCTL_ACTION_START, "start"},
|
{MDEVCTL_ACTION_START, "start"},
|
||||||
{MDEVCTL_ACTION_STOP, "stop"},
|
{MDEVCTL_ACTION_STOP, "stop"},
|
||||||
{MDEVCTL_ACTION_TYPES, "types"},
|
|
||||||
{MDEVCTL_ACTION_UNDEFINE, "undefine"},
|
{MDEVCTL_ACTION_UNDEFINE, "undefine"},
|
||||||
{MDEVCTL_ACTION_ATTRIBUTES, "attributes"}
|
{MDEVCTL_ACTION_ATTRIBUTES, "attributes"},
|
||||||
|
{MDEVCTL_ACTION_CAPABILITIES, "capabilities"}
|
||||||
|
/*
|
||||||
|
* Note: the following actions are known to exist but currently ignored:
|
||||||
|
* {MDEVCTL_ACTION_LIST, "list"},
|
||||||
|
* {MDEVCTL_ACTION_TYPES, "types"}
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mdevctl_event mdevctl_event_table[NUM_MDEVCTL_EVENTS] = {
|
static const struct mdevctl_event mdevctl_event_table[NUM_MDEVCTL_EVENTS] = {
|
||||||
{MDEVCTL_EVENT_PRE, "pre"},
|
{MDEVCTL_EVENT_PRE, "pre"},
|
||||||
{MDEVCTL_EVENT_POST, "post"},
|
{MDEVCTL_EVENT_POST, "post"},
|
||||||
{MDEVCTL_EVENT_GET, "get"}
|
{MDEVCTL_EVENT_GET, "get"},
|
||||||
|
{MDEVCTL_EVENT_LIVE, "live"}
|
||||||
|
/*
|
||||||
|
* Note: the following events are known to exist but currently ignored:
|
||||||
|
* {MDEVCTL_EVENT_NOTIFY, "notify"},
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -596,6 +609,94 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ap_check_active(struct ap_check_anchor *anc)
|
||||||
|
{
|
||||||
|
int rc, rc2;
|
||||||
|
|
||||||
|
/* Ensure device with control domains also has usage domains */
|
||||||
|
if (util_list_is_empty(anc->dev->domains) &&
|
||||||
|
!util_list_is_empty(anc->dev->controls)) {
|
||||||
|
fprintf(stderr, "At least one usage domain must be specified\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check against all other active vfio-ap devices */
|
||||||
|
rc = check_other_mdevs_sysfs(anc);
|
||||||
|
/* Check against the system sysfs values for apmask/aqmask */
|
||||||
|
rc2 = check_sysfs_mask_conflicts(anc);
|
||||||
|
/* If either hit an error, reflect this */
|
||||||
|
rc = rc != 0 ? rc : rc2;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ap_do_dynamic_config(struct ap_check_anchor *anc)
|
||||||
|
{
|
||||||
|
char *adapters, *domains, *controls, *path, *attr;
|
||||||
|
int asize, dsize, csize, size;
|
||||||
|
int rc = 0;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
adapters = vfio_ap_device_get_adapter_mask(anc->dev, &asize);
|
||||||
|
domains = vfio_ap_device_get_domain_mask(anc->dev, &dsize);
|
||||||
|
controls = vfio_ap_device_get_control_mask(anc->dev, &csize);
|
||||||
|
|
||||||
|
if (!adapters || !domains || !controls) {
|
||||||
|
fprintf(stderr, "Failed to read device config\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'ap_config' command takes a comma-delimited list of the 3 masks
|
||||||
|
* combined. Each mask size includes a terminating character, two of
|
||||||
|
* which will be replaced by commas and the final replaced by a
|
||||||
|
* newline, which ap_config seems to require at the end of the input.
|
||||||
|
* Add one to ensure room for a null termination.
|
||||||
|
*/
|
||||||
|
size = asize + dsize + csize + 1;
|
||||||
|
attr = util_zalloc(size);
|
||||||
|
|
||||||
|
/* Use the 3 masks to generate a 'ap_config' command */
|
||||||
|
rc = snprintf(attr, size, "%s,%s,%s\n", adapters, domains, controls);
|
||||||
|
|
||||||
|
if (rc < size - 1) {
|
||||||
|
fprintf(stderr, "Error creating ap_config command\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply the new configuration to the active device */
|
||||||
|
path = path_get_vfio_ap_attr(anc->uuid, "ap_config");
|
||||||
|
f = fopen(path, "w");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Error opening ap_config\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
rc = fputs(attr, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (rc == EOF)
|
||||||
|
fprintf(stderr, "Error writing to ap_config\n");
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (!adapters)
|
||||||
|
free(adapters);
|
||||||
|
if (!domains)
|
||||||
|
free(domains);
|
||||||
|
if (!controls)
|
||||||
|
free(controls);
|
||||||
|
if (!path)
|
||||||
|
free(path);
|
||||||
|
if (!attr)
|
||||||
|
free(attr);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if defining the specified device is a valid operation.
|
* Determine if defining the specified device is a valid operation.
|
||||||
* mdevctl can reach us for a DEFINE under the following circumstances:
|
* mdevctl can reach us for a DEFINE under the following circumstances:
|
||||||
@@ -647,6 +748,50 @@ static int ap_check_handle_modify(struct ap_check_anchor *anc)
|
|||||||
return ap_check_changes(anc);
|
return ap_check_changes(anc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if modifying the active device is a valid operation.
|
||||||
|
* This is similar to STARTing a device, in that the requested modifications
|
||||||
|
* cannot conflict with the active configuration. LIVE MODIFY can only be
|
||||||
|
* handled if the ap_config attribute is available in the vfio-ap driver.
|
||||||
|
*/
|
||||||
|
static int ap_check_handle_live_modify(struct ap_check_anchor *anc)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ap_get_lock_callout();
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr, "Failed to acquire configuration lock %d\n",
|
||||||
|
rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
anc->cleanup_lock = true;
|
||||||
|
|
||||||
|
if (vfio_ap_read_device_config(NULL, anc->dev) != 0) {
|
||||||
|
fprintf(stderr, "Failed to read device config\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(anc->dev->type, anc->type) != 0) {
|
||||||
|
fprintf(stderr, "Invalid mdev_type: %s\n", anc->dev->type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vfio_ap_need_dynamic_config(anc->dev)) {
|
||||||
|
fprintf(stderr, "vfio-ap module does not support ap_config for live modification");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the new configuration would cause conflicts */
|
||||||
|
rc = ap_check_active(anc);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Attempt to perform the dynamic configuration */
|
||||||
|
rc = ap_do_dynamic_config(anc);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if starting the specified device is a valid operation.
|
* Determine if starting the specified device is a valid operation.
|
||||||
* mdevctl can reach us for a START under the following circumstances:
|
* mdevctl can reach us for a START under the following circumstances:
|
||||||
@@ -665,7 +810,7 @@ static int ap_check_handle_modify(struct ap_check_anchor *anc)
|
|||||||
*/
|
*/
|
||||||
static int ap_check_handle_start(struct ap_check_anchor *anc)
|
static int ap_check_handle_start(struct ap_check_anchor *anc)
|
||||||
{
|
{
|
||||||
int rc = 0, rc2;
|
int rc = 0;
|
||||||
|
|
||||||
/* Can only start a device if vfio_ap is built-in or loaded */
|
/* Can only start a device if vfio_ap is built-in or loaded */
|
||||||
if (!util_path_is_dir(VFIO_AP_PATH)) {
|
if (!util_path_is_dir(VFIO_AP_PATH)) {
|
||||||
@@ -694,20 +839,7 @@ static int ap_check_handle_start(struct ap_check_anchor *anc)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure device with control domains also has usage domains */
|
rc = ap_check_active(anc);
|
||||||
if (util_list_is_empty(anc->dev->domains) &&
|
|
||||||
!util_list_is_empty(anc->dev->controls)) {
|
|
||||||
fprintf(stderr, "At least one usage domain must be specified\n");
|
|
||||||
rc = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check against all other active vfio-ap devices */
|
|
||||||
rc = check_other_mdevs_sysfs(anc);
|
|
||||||
/* Check against the system sysfs values for apmask/aqmask */
|
|
||||||
rc2 = check_sysfs_mask_conflicts(anc);
|
|
||||||
/* If either hit an error, reflect this */
|
|
||||||
rc = rc != 0 ? rc : rc2;
|
|
||||||
|
|
||||||
/* If successful, lock must remain held until post callout */
|
/* If successful, lock must remain held until post callout */
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@@ -798,12 +930,34 @@ static int ap_check_handle_get_attributes(struct ap_check_anchor *anc)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ap_get_lock_callout();
|
/*
|
||||||
if (rc) {
|
* For the get-attributes callout, we are typically called without the
|
||||||
fprintf(stderr, "Failed to acquire configuration lock %d\n", rc);
|
* callout lock held. However, there is a particular scenario (define
|
||||||
return -1;
|
* of an active mdev) where we may or may not be called with the lock
|
||||||
|
* already held on behalf of mdevctl, depending on the mdevctl version.
|
||||||
|
* Let's test for lock ownership first and, if already owned by the
|
||||||
|
* parent (mdevctl) proceed rather than waiting on the file lock.
|
||||||
|
*/
|
||||||
|
rc = ap_try_lock_callout();
|
||||||
|
switch (rc) {
|
||||||
|
case 0:
|
||||||
|
/* Lock acquired */
|
||||||
|
anc->cleanup_lock = true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* Lock held by parent -- trust the lock will remain held */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Lock not acquired or held by parent -- do a normal obtain */
|
||||||
|
rc = ap_get_lock_callout();
|
||||||
|
if (rc) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Failed to acquire configuration lock %d\n",
|
||||||
|
rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
anc->cleanup_lock = true;
|
||||||
}
|
}
|
||||||
anc->cleanup_lock = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the 'matrix' and 'control_domains' attributes to get the
|
* Read the 'matrix' and 'control_domains' attributes to get the
|
||||||
@@ -864,6 +1018,122 @@ static int ap_check_handle_get_attributes(struct ap_check_anchor *anc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the target 'attr' is in the 's' array, add it to the 't' array.
|
||||||
|
*/
|
||||||
|
static void json_add_attr(json_object *t, json_object *s, const char *attr)
|
||||||
|
{
|
||||||
|
size_t vlen, alen = strlen(attr);
|
||||||
|
const char *val;
|
||||||
|
json_object *o;
|
||||||
|
int i, num;
|
||||||
|
|
||||||
|
num = json_object_array_length(s);
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
o = json_object_array_get_idx(s, i);
|
||||||
|
val = json_object_get_string(o);
|
||||||
|
vlen = strlen(val);
|
||||||
|
if (alen == vlen && strncasecmp(attr, val, alen) == 0) {
|
||||||
|
json_object_array_add(t, json_object_new_string(val));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a JSON-formatted list of capability information that this script
|
||||||
|
* supports and return it to the caller via stdout. An example of what the
|
||||||
|
* output should look like (without the newlines):
|
||||||
|
* {
|
||||||
|
* "supports": {
|
||||||
|
* "version": 2,
|
||||||
|
* "actions": ["define",
|
||||||
|
* "modify",
|
||||||
|
* "start",
|
||||||
|
* "stop",
|
||||||
|
* "undefine",
|
||||||
|
* "attributes",
|
||||||
|
* "capabilities"],
|
||||||
|
* "events": ["pre",
|
||||||
|
* "post",
|
||||||
|
* "get",
|
||||||
|
* "live"]
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
static int ap_check_handle_get_capabilities(void)
|
||||||
|
{
|
||||||
|
json_object *root, *csup, *cver, *cact, *cev, *cap, *caps, *o;
|
||||||
|
int i, rc = 0;
|
||||||
|
|
||||||
|
root = json_object_from_fd(STDIN_FILENO);
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
fprintf(stderr, "No capabilities provided\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(root, "provides", &csup)) {
|
||||||
|
fprintf(stderr, "No supported capabilities provided\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(csup, "version", &cver)) {
|
||||||
|
fprintf(stderr, "No version provided in capabilities\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(csup, "actions", &cact)) {
|
||||||
|
fprintf(stderr, "No actions provided in capabilities\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_object_object_get_ex(csup, "events", &cev)) {
|
||||||
|
fprintf(stderr, "No events provided in capabilities\n");
|
||||||
|
rc = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Advertise the subset of supported capabilities from the list
|
||||||
|
* provided on stdin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cap = json_object_new_object();
|
||||||
|
caps = json_object_new_object();
|
||||||
|
json_object_object_add(cap, "supports", caps);
|
||||||
|
/*
|
||||||
|
* Currently we always advertise a fixed version, but we may need to
|
||||||
|
* revisit this if we increase MDEVCTL_CAP_VERSION in the future (e.g.
|
||||||
|
* how to handle ap-check having a greater supported version than
|
||||||
|
* what mdevctl reports)
|
||||||
|
*/
|
||||||
|
o = json_object_new_int(MDEVCTL_CAP_VERSION);
|
||||||
|
json_object_object_add(caps, "version", o);
|
||||||
|
|
||||||
|
o = json_object_new_array();
|
||||||
|
for (i = 0; i < NUM_MDEVCTL_ACTIONS; i++)
|
||||||
|
json_add_attr(o, cact, mdevctl_action_table[i].action);
|
||||||
|
json_object_object_add(caps, "actions", o);
|
||||||
|
|
||||||
|
o = json_object_new_array();
|
||||||
|
for (i = 0; i < NUM_MDEVCTL_EVENTS; i++)
|
||||||
|
json_add_attr(o, cev, mdevctl_event_table[i].event);
|
||||||
|
json_object_object_add(caps, "events", o);
|
||||||
|
|
||||||
|
/* Return supported capabilities JSON on stdout */
|
||||||
|
printf("%s\n", json_object_to_json_string(cap));
|
||||||
|
|
||||||
|
json_object_put(cap);
|
||||||
|
|
||||||
|
out:
|
||||||
|
json_object_put(root);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine which mdevctl action is being checked and handle accordingly.
|
* Determine which mdevctl action is being checked and handle accordingly.
|
||||||
*/
|
*/
|
||||||
@@ -889,8 +1159,6 @@ static int ap_check_handle_action(struct ap_check_anchor *anc)
|
|||||||
case MDEVCTL_ACTION_UNDEFINE:
|
case MDEVCTL_ACTION_UNDEFINE:
|
||||||
rc = ap_check_handle_undefine(anc);
|
rc = ap_check_handle_undefine(anc);
|
||||||
break;
|
break;
|
||||||
case MDEVCTL_ACTION_LIST:
|
|
||||||
case MDEVCTL_ACTION_TYPES:
|
|
||||||
default:
|
default:
|
||||||
/* Ignore some actions including unknown ones */
|
/* Ignore some actions including unknown ones */
|
||||||
break;
|
break;
|
||||||
@@ -915,6 +1183,19 @@ static int ap_check_handle_action(struct ap_check_anchor *anc)
|
|||||||
case MDEVCTL_ACTION_ATTRIBUTES:
|
case MDEVCTL_ACTION_ATTRIBUTES:
|
||||||
rc = ap_check_handle_get_attributes(anc);
|
rc = ap_check_handle_get_attributes(anc);
|
||||||
break;
|
break;
|
||||||
|
case MDEVCTL_ACTION_CAPABILITIES:
|
||||||
|
rc = ap_check_handle_get_capabilities();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Ignore some actions including unknown ones */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MDEVCTL_EVENT_LIVE:
|
||||||
|
switch (anc->action) {
|
||||||
|
case MDEVCTL_ACTION_MODIFY:
|
||||||
|
rc = ap_check_handle_live_modify(anc);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Ignore some actions including unknown ones */
|
/* Ignore some actions including unknown ones */
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ enum mdevctl_action_id {
|
|||||||
MDEVCTL_ACTION_TYPES,
|
MDEVCTL_ACTION_TYPES,
|
||||||
MDEVCTL_ACTION_UNDEFINE,
|
MDEVCTL_ACTION_UNDEFINE,
|
||||||
MDEVCTL_ACTION_ATTRIBUTES,
|
MDEVCTL_ACTION_ATTRIBUTES,
|
||||||
|
MDEVCTL_ACTION_CAPABILITIES,
|
||||||
/* UNKNOWN must always be the last in the list */
|
/* UNKNOWN must always be the last in the list */
|
||||||
MDEVCTL_ACTION_UNKNOWN,
|
MDEVCTL_ACTION_UNKNOWN,
|
||||||
};
|
};
|
||||||
@@ -38,6 +39,7 @@ enum mdevctl_event_id {
|
|||||||
MDEVCTL_EVENT_PRE = 0,
|
MDEVCTL_EVENT_PRE = 0,
|
||||||
MDEVCTL_EVENT_POST,
|
MDEVCTL_EVENT_POST,
|
||||||
MDEVCTL_EVENT_GET,
|
MDEVCTL_EVENT_GET,
|
||||||
|
MDEVCTL_EVENT_LIVE,
|
||||||
MDEVCTL_EVENT_UNKNOWN,
|
MDEVCTL_EVENT_UNKNOWN,
|
||||||
};
|
};
|
||||||
#define NUM_MDEVCTL_EVENTS MDEVCTL_EVENT_UNKNOWN
|
#define NUM_MDEVCTL_EVENTS MDEVCTL_EVENT_UNKNOWN
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
# GNU awk:
|
# GNU awk:
|
||||||
# - gawk
|
# - gawk
|
||||||
|
|
||||||
override SHELL := /bin/bash
|
|
||||||
override .SHELLFLAGS := -O globstar -O nullglob -O extglob -c
|
override .SHELLFLAGS := -O globstar -O nullglob -O extglob -c
|
||||||
|
|
||||||
# Include common s390-tools definitions
|
# Include common s390-tools definitions
|
||||||
|
|||||||
@@ -951,7 +951,7 @@ static void set_record_extension(struct file *f, int *record, off_t addr,
|
|||||||
|
|
||||||
if (f->record_scan_state != RSS_DATA_BLOCK_STARTED &&
|
if (f->record_scan_state != RSS_DATA_BLOCK_STARTED &&
|
||||||
f->record_scan_state != RSS_DATA_BLOCK_EXT)
|
f->record_scan_state != RSS_DATA_BLOCK_EXT)
|
||||||
DIE("%s: interal error\n", __func__);
|
DIE("%s: internal error\n", __func__);
|
||||||
|
|
||||||
BUG(*record >= f->fst->nr_records);
|
BUG(*record >= f->fst->nr_records);
|
||||||
|
|
||||||
|
|||||||
101
common.mak
101
common.mak
@@ -8,10 +8,14 @@ ASAN ?= 0
|
|||||||
ENABLE_WERROR ?= 0
|
ENABLE_WERROR ?= 0
|
||||||
OPT_FLAGS ?=
|
OPT_FLAGS ?=
|
||||||
MAKECMDGOALS ?=
|
MAKECMDGOALS ?=
|
||||||
|
CARGO ?= cargo
|
||||||
|
CARGOFLAGS ?=
|
||||||
|
|
||||||
ifeq ($(COMMON_INCLUDED),false)
|
ifeq ($(COMMON_INCLUDED),false)
|
||||||
COMMON_INCLUDED := true
|
COMMON_INCLUDED := true
|
||||||
|
|
||||||
|
override SHELL := /bin/bash
|
||||||
|
|
||||||
# 'BUILD_ARCH' is the architecture of the machine where the build takes place
|
# 'BUILD_ARCH' is the architecture of the machine where the build takes place
|
||||||
BUILD_ARCH := $(shell uname -m | sed -e 's/i.86/i386/' -e 's/sun4u/sparc64/' -e 's/arm.*/arm/' -e 's/sa110/arm/')
|
BUILD_ARCH := $(shell uname -m | sed -e 's/i.86/i386/' -e 's/sun4u/sparc64/' -e 's/arm.*/arm/' -e 's/sa110/arm/')
|
||||||
# 'HOST_ARCH' is the architecture of the machine that will run the compiled output
|
# 'HOST_ARCH' is the architecture of the machine that will run the compiled output
|
||||||
@@ -27,11 +31,11 @@ endif
|
|||||||
# Global definitions
|
# Global definitions
|
||||||
# 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 = 28
|
RELEASE := 35
|
||||||
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)
|
||||||
export S390_TOOLS_RELEASE
|
export S390_TOOLS_RELEASE
|
||||||
|
|
||||||
reldir = $(subst $(realpath $(dir $(filter %common.mak,$(MAKEFILE_LIST))))/,,$(CURDIR))
|
reldir = $(subst $(realpath $(dir $(filter %common.mak,$(MAKEFILE_LIST))))/,,$(CURDIR))
|
||||||
@@ -89,19 +93,19 @@ define cmd_define_and_export
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
define define_toolchain_variables
|
define define_toolchain_variables
|
||||||
$(eval $(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as))
|
$(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as)
|
||||||
$(eval $(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc))
|
$(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc)
|
||||||
$(eval $(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1))))
|
$(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1)))
|
||||||
$(eval $(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++))
|
$(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++)
|
||||||
$(eval $(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1))))
|
$(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1)))
|
||||||
$(eval $(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E))
|
$(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E)
|
||||||
$(eval $(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar))
|
$(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar)
|
||||||
$(eval $(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm))
|
$(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm)
|
||||||
$(eval $(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip))
|
$(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip)
|
||||||
$(eval $(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy))
|
$(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy)
|
||||||
$(eval $(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump))
|
$(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump)
|
||||||
$(eval PKG_CONFIG$(1) = pkg-config)
|
PKG_CONFIG$(1) = pkg-config
|
||||||
$(eval export PKG_CONFIG$(1))
|
export PKG_CONFIG$(1)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# If the host architecture is not the same as the build architecture
|
# If the host architecture is not the same as the build architecture
|
||||||
@@ -115,15 +119,19 @@ ifneq ($(HOST_ARCH),$(BUILD_ARCH))
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(call define_toolchain_variables,_FOR_BUILD,)
|
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
|
||||||
$(call define_toolchain_variables,,$(CROSS_COMPILE))
|
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
|
||||||
|
|
||||||
$(eval $(call cmd_define,RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest))
|
|
||||||
$(eval $(call cmd_define, CAT," CAT ",cat))
|
$(eval $(call cmd_define, RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest))
|
||||||
$(eval $(call cmd_define, SED," SED ",sed))
|
$(eval $(call cmd_define, CAT," CAT ",cat))
|
||||||
$(eval $(call cmd_define, GZIP," GZIP ",gzip))
|
$(eval $(call cmd_define, SED," SED ",sed))
|
||||||
$(eval $(call cmd_define, MV," MV ",mv))
|
$(eval $(call cmd_define, GZIP," GZIP ",gzip))
|
||||||
$(eval $(call cmd_define, PERLC," PERLC ",perl -c))
|
$(eval $(call cmd_define, MV," MV ",mv))
|
||||||
|
$(eval $(call cmd_define, PERLC," PERLC ",perl -c))
|
||||||
|
$(eval $(call cmd_define,CARGO_BUILD," CARGO BUILD ",$(CARGO) build))
|
||||||
|
$(eval $(call cmd_define,CARGO_TEST, " CARGO TEST ",$(CARGO) test))
|
||||||
|
$(eval $(call cmd_define,CARGO_CLEAN," CARGO CLEAN ",$(CARGO) clean))
|
||||||
|
|
||||||
CHECK = sparse
|
CHECK = sparse
|
||||||
CHECK_SILENT := $(CHECK)
|
CHECK_SILENT := $(CHECK)
|
||||||
@@ -133,8 +141,10 @@ SKIP = echo " SKIP $(call reldir) due to"
|
|||||||
|
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
CP = cp
|
CP = cp
|
||||||
|
ALL_CARGOFLAGS := $(CARGOFLAGS)
|
||||||
ifneq ("${V}","1")
|
ifneq ("${V}","1")
|
||||||
MAKEFLAGS += --quiet
|
MAKEFLAGS += --quiet
|
||||||
|
ALL_CARGOFLAGS += --quiet
|
||||||
echocmd=echo $1$(call reldir)$2;
|
echocmd=echo $1$(call reldir)$2;
|
||||||
RUNTEST += > /dev/null 2>&1
|
RUNTEST += > /dev/null 2>&1
|
||||||
else
|
else
|
||||||
@@ -283,8 +293,8 @@ INSTDIRS = $(USRSBINDIR) $(USRBINDIR) $(BINDIR) $(LIBDIR) $(MANDIR) \
|
|||||||
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR) \
|
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR) \
|
||||||
$(USRLIB64DIR) $(USRINCLUDEDIR) $(ZKEYKMSPLUGINDIR) \
|
$(USRLIB64DIR) $(USRINCLUDEDIR) $(ZKEYKMSPLUGINDIR) \
|
||||||
$(SOINSTALLDIR) $(USRLIBDIR)
|
$(SOINSTALLDIR) $(USRLIBDIR)
|
||||||
OWNER = $(shell id -un)
|
OWNER := $(shell id -un)
|
||||||
GROUP = $(shell id -gn)
|
GROUP := $(shell id -gn)
|
||||||
export INSTALLDIR BINDIR LIBDIR USRLIBDIR USRLIB64DIR MANDIR OWNER GROUP
|
export INSTALLDIR BINDIR LIBDIR USRLIBDIR USRLIB64DIR MANDIR OWNER GROUP
|
||||||
|
|
||||||
# Special defines for zfcpdump
|
# Special defines for zfcpdump
|
||||||
@@ -294,7 +304,7 @@ ZFCPDUMP_FLAVOR = zfcpdump
|
|||||||
export ZFCPDUMP_DIR ZFCPDUMP_IMAGE ZFCPDUMP_INITRD ZFCPDUMP_FLAVOR
|
export ZFCPDUMP_DIR ZFCPDUMP_IMAGE ZFCPDUMP_INITRD ZFCPDUMP_FLAVOR
|
||||||
|
|
||||||
CFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
CFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
||||||
CFLAGS_FOR_BUILD ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
CFLAGS_FOR_BUILD ?= -std=gnu11 $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
||||||
CPPFLAGS ?= $(DEFAULT_CPPFLAGS)
|
CPPFLAGS ?= $(DEFAULT_CPPFLAGS)
|
||||||
LDFLAGS ?= $(DEFAULT_LDFLAGS)
|
LDFLAGS ?= $(DEFAULT_LDFLAGS)
|
||||||
|
|
||||||
@@ -303,14 +313,14 @@ ALL_CFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
|
|||||||
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
|
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
|
||||||
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
|
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
|
||||||
-DS390_TOOLS_BINDIR=$(BINDIR) \
|
-DS390_TOOLS_BINDIR=$(BINDIR) \
|
||||||
$(CFLAGS)
|
-std=gnu11 $(CFLAGS)
|
||||||
CXXFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
CXXFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
|
||||||
ALL_CXXFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
|
ALL_CXXFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
|
||||||
-DS390_TOOLS_LIBDIR=$(TOOLS_LIBDIR) \
|
-DS390_TOOLS_LIBDIR=$(TOOLS_LIBDIR) \
|
||||||
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
|
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
|
||||||
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
|
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
|
||||||
-DS390_TOOLS_BINDIR=$(BINDIR) \
|
-DS390_TOOLS_BINDIR=$(BINDIR) \
|
||||||
$(CXXFLAGS)
|
-std=gnu++11 $(CXXFLAGS)
|
||||||
ALL_CPPFLAGS = -I $(rootdir)include $(CPPFLAGS)
|
ALL_CPPFLAGS = -I $(rootdir)include $(CPPFLAGS)
|
||||||
ALL_LDFLAGS = $(LDFLAGS)
|
ALL_LDFLAGS = $(LDFLAGS)
|
||||||
|
|
||||||
@@ -360,6 +370,7 @@ help:
|
|||||||
@echo ' all Build all tools (default target)'
|
@echo ' all Build all tools (default target)'
|
||||||
@echo ' install Install tools'
|
@echo ' install Install tools'
|
||||||
@echo ' clean Delete all generated files'
|
@echo ' clean Delete all generated files'
|
||||||
|
@echo ' compdb Generate compile_commands.json for clangd'
|
||||||
@echo ''
|
@echo ''
|
||||||
@echo 'OPTIONS'
|
@echo 'OPTIONS'
|
||||||
@echo ' D=1 Build with debugging option "-Og"'
|
@echo ' D=1 Build with debugging option "-Og"'
|
||||||
@@ -375,6 +386,32 @@ help:
|
|||||||
@echo ' # make C=1 CHECK=smatch'
|
@echo ' # make C=1 CHECK=smatch'
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
|
|
||||||
|
|
||||||
|
# 'compile_commands.json' generation
|
||||||
|
#
|
||||||
|
# Create the compilation database 'compile_commands.json'. See
|
||||||
|
# https://clang.llvm.org/docs/JSONCompilationDatabase.html for details.
|
||||||
|
#
|
||||||
|
.PHONY: compdb
|
||||||
|
compdb:
|
||||||
|
$(MAKE) clean
|
||||||
|
ifneq ($(shell command -v compiledb),)
|
||||||
|
compiledb $(MAKE)
|
||||||
|
else ifneq ($(shell command -v bear),)
|
||||||
|
ifeq ($(shell bear --help|grep -- '-- ...'),)
|
||||||
|
bear $(MAKE)
|
||||||
|
else
|
||||||
|
bear -- $(MAKE)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
$(error Please install either 'compiledb' or 'bear')
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Prints the s390-tools release string
|
||||||
|
version:
|
||||||
|
$(info $(S390_TOOLS_RELEASE))
|
||||||
|
.PHONY: version
|
||||||
|
|
||||||
# Automatic dependency generation
|
# Automatic dependency generation
|
||||||
#
|
#
|
||||||
# Create ".o.d" dependency files with the -MM compile option for all ".c" and
|
# Create ".o.d" dependency files with the -MM compile option for all ".c" and
|
||||||
@@ -485,7 +522,7 @@ install_echo:
|
|||||||
install: install_echo install_dirs
|
install: install_echo install_dirs
|
||||||
|
|
||||||
clean_echo:
|
clean_echo:
|
||||||
$(call echocmd," CLEAN ")
|
$(call echocmd," CLEAN ")
|
||||||
clean_gcov:
|
clean_gcov:
|
||||||
rm -f -- *.gcda *.gcno *.gcov
|
rm -f -- *.gcda *.gcno *.gcov
|
||||||
clean_dep:
|
clean_dep:
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ ALL_CPPFLAGS += -DVERSION=$(VERSION)
|
|||||||
|
|
||||||
all: check_dep cpacfstats cpacfstatsd
|
all: check_dep cpacfstats cpacfstatsd
|
||||||
|
|
||||||
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o
|
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \
|
||||||
|
$(rootdir)/libutil/libutil.a
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
|
||||||
|
|
||||||
cpacfstats: cpacfstats.o stats_sock.o
|
cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
|
|||||||
@@ -355,13 +355,13 @@ PCKMO DES,
|
|||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCKMO 2key TDES,
|
PCKMO 2key TDES,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCMKO TDES,
|
PCKMO TDES,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCKMO AES 128bit,
|
PCKMO AES 128bit,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCKMO AES 192bit,
|
PCKMO AES 192bit,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCMKO AES 256bit,
|
PCKMO AES 256bit,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
PCKMO ECC P256,
|
PCKMO ECC P256,
|
||||||
.IP \(bu
|
.IP \(bu
|
||||||
|
|||||||
@@ -55,168 +55,6 @@ static const char *const counter_str[] = {
|
|||||||
[PAI_KERNEL] = "pai_kernel"
|
[PAI_KERNEL] = "pai_kernel"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Strings for the pai counter details. Note that this is 0-based
|
|
||||||
* while PoP is 1-based.
|
|
||||||
*/
|
|
||||||
static const char *const pai_str[] = {
|
|
||||||
[ 0] = "KM DES",
|
|
||||||
[ 1] = "KM 2key TDES",
|
|
||||||
[ 2] = "KM TDES",
|
|
||||||
[ 3] = "KM DES protected key",
|
|
||||||
[ 4] = "KM 2key TDES protected key",
|
|
||||||
[ 5] = "KM TDES protected key",
|
|
||||||
[ 6] = "KM AES 128bit",
|
|
||||||
[ 7] = "KM AES 192bit",
|
|
||||||
[ 8] = "KM AES 256bit",
|
|
||||||
[ 9] = "KM AES 128bit protected key",
|
|
||||||
[ 10] = "KM AES 192bit protected key",
|
|
||||||
[ 11] = "KM AES 256bit protected key",
|
|
||||||
[ 12] = "KM AES-XTS 128bit",
|
|
||||||
[ 13] = "KM AES-XTS 256bit",
|
|
||||||
[ 14] = "KM AES-XTS 128bit protected key",
|
|
||||||
[ 15] = "KM AES-XTS 256bit protected key",
|
|
||||||
[ 16] = "KMC DES",
|
|
||||||
[ 17] = "KMC 2key TDES",
|
|
||||||
[ 18] = "KMC TDES",
|
|
||||||
[ 19] = "KMC DES protected key",
|
|
||||||
[ 20] = "KMC 2key TDES protected key",
|
|
||||||
[ 21] = "KMC TDES protected key",
|
|
||||||
[ 22] = "KMC AES 128bit",
|
|
||||||
[ 23] = "KMC AES 192bit",
|
|
||||||
[ 24] = "KMC AES 256bit",
|
|
||||||
[ 25] = "KMC AES 128bit protected key",
|
|
||||||
[ 26] = "KMC AES 192bit protected key",
|
|
||||||
[ 27] = "KMC AES 256bit protected key",
|
|
||||||
[ 28] = "KMC PRNG",
|
|
||||||
[ 29] = "KMA AES 128bit",
|
|
||||||
[ 30] = "KMA AES 192bit",
|
|
||||||
[ 31] = "KMA AES 256bit",
|
|
||||||
[ 32] = "KMA AES 128bit protected key",
|
|
||||||
[ 33] = "KMA AES 192bit protected key",
|
|
||||||
[ 34] = "KMA AES 256bit protected key",
|
|
||||||
[ 35] = "KMF DES",
|
|
||||||
[ 36] = "KMF 2key TDES",
|
|
||||||
[ 37] = "KMF TDES",
|
|
||||||
[ 38] = "KMF DES protected key",
|
|
||||||
[ 39] = "KMF 2key TDES protected key",
|
|
||||||
[ 40] = "KMF TDES protected key",
|
|
||||||
[ 41] = "KMF AES 128bit",
|
|
||||||
[ 42] = "KMF AES 192bit",
|
|
||||||
[ 43] = "KMF AES 256bit",
|
|
||||||
[ 44] = "KMF AES 128bit protected key",
|
|
||||||
[ 45] = "KMF AES 192bit protected key",
|
|
||||||
[ 46] = "KMF AES 256bit protected key",
|
|
||||||
[ 47] = "KMCTR DES",
|
|
||||||
[ 48] = "KMCTR 2key TDES",
|
|
||||||
[ 49] = "KMCTR TDES",
|
|
||||||
[ 50] = "KMCTR DES protected key",
|
|
||||||
[ 51] = "KMCTR 2key TDES protected key",
|
|
||||||
[ 52] = "KMCTR TDES protected key",
|
|
||||||
[ 53] = "KMCTR AES 128bit",
|
|
||||||
[ 54] = "KMCTR AES 192bit",
|
|
||||||
[ 55] = "KMCTR AES 256bit",
|
|
||||||
[ 56] = "KMCTR AES 128bit protected key",
|
|
||||||
[ 57] = "KMCTR AES 192bit protected key",
|
|
||||||
[ 58] = "KMCTR AES 256bit protected key",
|
|
||||||
[ 59] = "KMO DES",
|
|
||||||
[ 60] = "KMO 2key TDES",
|
|
||||||
[ 61] = "KMO TDES",
|
|
||||||
[ 62] = "KMO DES protected key",
|
|
||||||
[ 63] = "KMO 2key TDES protected key",
|
|
||||||
[ 64] = "KMO TDES protected key",
|
|
||||||
[ 65] = "KMO AES 128bit",
|
|
||||||
[ 66] = "KMO AES 192bit",
|
|
||||||
[ 67] = "KMO AES 256bit",
|
|
||||||
[ 68] = "KMO AES 128bit protected key",
|
|
||||||
[ 69] = "KMO AES 192bit protected key",
|
|
||||||
[ 70] = "KMO AES 256bit protected key",
|
|
||||||
[ 71] = "KIMD SHA1",
|
|
||||||
[ 72] = "KIMD SHA256",
|
|
||||||
[ 73] = "KIMD SHA512",
|
|
||||||
[ 74] = "KIMD SHA3-224",
|
|
||||||
[ 75] = "KIMD SHA3-256",
|
|
||||||
[ 76] = "KIMD SHA3-384",
|
|
||||||
[ 77] = "KIMD SHA3-512",
|
|
||||||
[ 78] = "KIMD SHAKE 128",
|
|
||||||
[ 79] = "KIMD SHAKE 256",
|
|
||||||
[ 80] = "KIMD GHASH",
|
|
||||||
[ 81] = "KLMD SHA1",
|
|
||||||
[ 82] = "KLMD SHA256",
|
|
||||||
[ 83] = "KLMD SHA512",
|
|
||||||
[ 84] = "KLMD SHA3-224",
|
|
||||||
[ 85] = "KLMD SHA3-256",
|
|
||||||
[ 86] = "KLMD SHA3-384",
|
|
||||||
[ 87] = "KLMD SHA3-512",
|
|
||||||
[ 88] = "KLMD SHAKE 128",
|
|
||||||
[ 89] = "KLMD SHAKE 256",
|
|
||||||
[ 90] = "KMAC DES",
|
|
||||||
[ 91] = "KMAC 2key TDES",
|
|
||||||
[ 92] = "KMAC TDES",
|
|
||||||
[ 93] = "KMAC DES protected key",
|
|
||||||
[ 94] = "KMAC 2key TDES protected key",
|
|
||||||
[ 95] = "KMAC TDES protected key",
|
|
||||||
[ 96] = "KMAC AES 128bit",
|
|
||||||
[ 97] = "KMAC AES 192bit",
|
|
||||||
[ 98] = "KMAC AES 256bit",
|
|
||||||
[ 99] = "KMAC AES 128bit protected key",
|
|
||||||
[100] = "KMAC AES 192bit protected key",
|
|
||||||
[101] = "KMAC AES 256bit protected key",
|
|
||||||
[102] = "PCC Last Block CMAC DES",
|
|
||||||
[103] = "PCC Last Block CMAC 2key TDES",
|
|
||||||
[104] = "PCC Last Block CMAC TDES",
|
|
||||||
[105] = "PCC Last Block CMAC DES protected key",
|
|
||||||
[106] = "PCC Last Block CMAC 2key TDES protected key",
|
|
||||||
[107] = "PCC Last Block CMAC TDES protected key",
|
|
||||||
[108] = "PCC Last Block CMAC AES 128bit",
|
|
||||||
[109] = "PCC Last Block CMAC AES 192bit",
|
|
||||||
[110] = "PCC Last Block CMAC AES 256bit",
|
|
||||||
[111] = "PCC Last Block CMAC AES 128bit protected key",
|
|
||||||
[112] = "PCC Last Block CMAC AES 192bit protected key",
|
|
||||||
[113] = "PCC Last Block CMAC AES 256bit protected key",
|
|
||||||
[114] = "PCC XTS Parameter AES 128bit",
|
|
||||||
[115] = "PCC XTS Parameter AES 256bit",
|
|
||||||
[116] = "PCC XTS Parameter AES 128bit protected key",
|
|
||||||
[117] = "PCC XTS Parameter AES 256bit protected key",
|
|
||||||
[118] = "PCC Scalar Mult P256",
|
|
||||||
[119] = "PCC Scalar Mult P384",
|
|
||||||
[120] = "PCC Scalar Mult P521",
|
|
||||||
[121] = "PCC Scalar Mult Ed25519",
|
|
||||||
[122] = "PCC Scalar Mult Ed448",
|
|
||||||
[123] = "PCC Scalar Mult X25519",
|
|
||||||
[124] = "PCC Scalar Mult X448",
|
|
||||||
[125] = "PRNO SHA512 DRNG",
|
|
||||||
[126] = "PRNO TRNG Query Ratio",
|
|
||||||
[127] = "PRNO TRNG",
|
|
||||||
[128] = "KDSA ECDSA Verify P256",
|
|
||||||
[129] = "KDSA ECDSA Verify P384",
|
|
||||||
[130] = "KDSA ECDSA Verify P521",
|
|
||||||
[131] = "KDSA ECDSA Sign P256",
|
|
||||||
[132] = "KDSA ECDSA Sign P384",
|
|
||||||
[133] = "KDSA ECDSA Sign P521",
|
|
||||||
[134] = "KDSA ECDSA Sign P256 protected key",
|
|
||||||
[135] = "KDSA ECDSA Sign P384 protected key",
|
|
||||||
[136] = "KDSA ECDSA Sign P521 protected key",
|
|
||||||
[137] = "KDSA EdDSA Verify Ed25519",
|
|
||||||
[138] = "KDSA EdDSA Verify Ed448",
|
|
||||||
[139] = "KDSA EdDSA Sign Ed25519",
|
|
||||||
[140] = "KDSA EdDSA Sign Ed448",
|
|
||||||
[141] = "KDSA EdDSA Sign Ed25519 protected key",
|
|
||||||
[142] = "KDSA EdDSA Sign Ed448 protected key",
|
|
||||||
[143] = "PCKMO DES",
|
|
||||||
[144] = "PCKMO 2key TDES",
|
|
||||||
[145] = "PCMKO TDES",
|
|
||||||
[146] = "PCKMO AES 128bit",
|
|
||||||
[147] = "PCKMO AES 192bit",
|
|
||||||
[148] = "PCMKO AES 256bit",
|
|
||||||
[149] = "PCKMO ECC P256",
|
|
||||||
[150] = "PCKMO ECC P384",
|
|
||||||
[151] = "PCKMO ECC P521",
|
|
||||||
[152] = "PCKMO ECC Ed25519",
|
|
||||||
[153] = "PCKMO ECC Ed448",
|
|
||||||
[154] = "Reserved 1",
|
|
||||||
[155] = "Reserved 2"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int paiprintnonzero;
|
static int paiprintnonzero;
|
||||||
|
|
||||||
@@ -275,7 +113,8 @@ static void json_print_virtual_counter_answer(int s, int ctr,
|
|||||||
int state, uint64_t value)
|
int state, uint64_t value)
|
||||||
{
|
{
|
||||||
int paictr = 0, paistate = 0, ec;
|
int paictr = 0, paistate = 0, ec;
|
||||||
uint64_t i, paivalue = 0, maxnum;
|
uint64_t i, paivalue = 0;
|
||||||
|
unsigned int maxnum;
|
||||||
const char *space;
|
const char *space;
|
||||||
|
|
||||||
switch (ctr) {
|
switch (ctr) {
|
||||||
@@ -288,11 +127,11 @@ static void json_print_virtual_counter_answer(int s, int ctr,
|
|||||||
printf("\"value\":%d}", !!value);
|
printf("\"value\":%d}", !!value);
|
||||||
return;
|
return;
|
||||||
case PAI_USER:
|
case PAI_USER:
|
||||||
maxnum = NUM_PAI_USER;
|
maxnum = get_num_user_space_ctrs();
|
||||||
space = "user";
|
space = "user";
|
||||||
break;
|
break;
|
||||||
case PAI_KERNEL:
|
case PAI_KERNEL:
|
||||||
maxnum = NUM_PAI_KERNEL;
|
maxnum = MAX_NUM_PAI;
|
||||||
space = "kernel";
|
space = "kernel";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -304,7 +143,7 @@ static void json_print_virtual_counter_answer(int s, int ctr,
|
|||||||
return;
|
return;
|
||||||
if (value > maxnum) {
|
if (value > maxnum) {
|
||||||
eprint("Incompatible versions detected!\n");
|
eprint("Incompatible versions detected!\n");
|
||||||
eprint("Expected %"PRIu64" counter space for %s, but got %"PRIu64"\n",
|
eprint("Expected %lu counter space for %s, but got %lu\n",
|
||||||
maxnum, space, value);
|
maxnum, space, value);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -315,18 +154,18 @@ static void json_print_virtual_counter_answer(int s, int ctr,
|
|||||||
/* No more data for this virtual event after error. */
|
/* No more data for this virtual event after error. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (paictr > NUM_PAI_KERNEL) {
|
if (paictr > MAX_NUM_PAI) {
|
||||||
eprint("Pai counter number too big: %d\n", paictr);
|
eprint("Pai counter number too big: %d\n", paictr);
|
||||||
} else {
|
} else {
|
||||||
printjsonsep();
|
printjsonsep();
|
||||||
printf("{\"counter\":\"%s\",\"space\":\"%s\",\"counterid\":%d,",
|
printf("{\"counter\":\"%s\",\"space\":\"%s\",\"counterid\":%d,",
|
||||||
pai_str[paictr], space, paictr + 1);
|
get_ctr_name(paictr), space, paictr + 1);
|
||||||
if (paistate < 0) {
|
if (paistate < 0) {
|
||||||
printf("\"error\":%d}", paistate);
|
printf("\"error\":%d}", paistate);
|
||||||
/* Protocol does not send further counters. */
|
/* Protocol does not send further counters. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("\"value\":%"PRIu64"}", paivalue);
|
printf("\"value\":%lu}", paivalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,7 +180,8 @@ static void print_virtual_counter_answer(int s,
|
|||||||
[UNSUPPORTED] = "unsupported"
|
[UNSUPPORTED] = "unsupported"
|
||||||
};
|
};
|
||||||
int paictr = 0, paistate = 0, ec;
|
int paictr = 0, paistate = 0, ec;
|
||||||
uint64_t i, paivalue = 0, maxnum;
|
uint64_t i, paivalue = 0;
|
||||||
|
unsigned int maxnum;
|
||||||
const char *ctrstr;
|
const char *ctrstr;
|
||||||
|
|
||||||
switch (ctr) {
|
switch (ctr) {
|
||||||
@@ -350,11 +190,11 @@ static void print_virtual_counter_answer(int s,
|
|||||||
printf(" hotplug detected\n");
|
printf(" hotplug detected\n");
|
||||||
return;
|
return;
|
||||||
case PAI_USER:
|
case PAI_USER:
|
||||||
maxnum = NUM_PAI_USER;
|
maxnum = get_num_user_space_ctrs();
|
||||||
ctrstr = "pai_user";
|
ctrstr = "pai_user";
|
||||||
break;
|
break;
|
||||||
case PAI_KERNEL:
|
case PAI_KERNEL:
|
||||||
maxnum = NUM_PAI_KERNEL;
|
maxnum = MAX_NUM_PAI;
|
||||||
ctrstr = "pai_kernel";
|
ctrstr = "pai_kernel";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -372,7 +212,7 @@ static void print_virtual_counter_answer(int s,
|
|||||||
return;
|
return;
|
||||||
if (value > maxnum) {
|
if (value > maxnum) {
|
||||||
eprint("Incompatible versions detected!\n");
|
eprint("Incompatible versions detected!\n");
|
||||||
eprint("Expected %"PRIu64" counters for %s, but got %"PRIu64"\n",
|
eprint("Expected %lu counters for %s, but got %lu\n",
|
||||||
maxnum, ctrstr, value);
|
maxnum, ctrstr, value);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@@ -383,10 +223,11 @@ static void print_virtual_counter_answer(int s,
|
|||||||
/* No more data for this virtual event after error. */
|
/* No more data for this virtual event after error. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (paictr > NUM_PAI_KERNEL)
|
if (paictr > MAX_NUM_PAI)
|
||||||
eprint("Pai counter number too big: %d\n", paictr);
|
eprint("Pai counter number too big: %d\n", paictr);
|
||||||
else if (!paiprintnonzero || paivalue > 0)
|
else if (!paiprintnonzero || paivalue > 0)
|
||||||
printf(" %-45s: %"PRIu64"\n", pai_str[paictr], paivalue);
|
printf(" (%3d) %-45s: %lu\n", paictr + 1,
|
||||||
|
get_ctr_name(paictr), paivalue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +243,7 @@ static void print_answer(int s, int ctr, int state, uint64_t value)
|
|||||||
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
|
else
|
||||||
printf(" %s counter: %"PRIu64"\n", counter_str[ctr], value);
|
printf(" %s counter: %lu\n", counter_str[ctr], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -417,7 +258,7 @@ static void json_print_answer(int s, int ctr, int state, uint64_t value)
|
|||||||
} else if (state == ENABLED) {
|
} else if (state == ENABLED) {
|
||||||
printjsonsep();
|
printjsonsep();
|
||||||
printf("{\"counter\":\"%s\",", counter_str[ctr]);
|
printf("{\"counter\":\"%s\",", counter_str[ctr]);
|
||||||
printf("\"value\":%"PRIu64"}", value);
|
printf("\"value\":%lu}", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,22 @@
|
|||||||
#define DEFAULT_RECV_TIMEOUT (30 * 1000)
|
#define DEFAULT_RECV_TIMEOUT (30 * 1000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of PAI counters for user space. This excludes PCKMO since
|
* Number of PAI counters. Contains all counters regardless of kernel or user
|
||||||
* this instruction is privileged.
|
* space
|
||||||
*/
|
*/
|
||||||
#define NUM_PAI_USER 143
|
#define MAX_NUM_PAI 172
|
||||||
/* Number of PAI counters for kernel space. Contains all counters. */
|
|
||||||
#define NUM_PAI_KERNEL 156
|
/*
|
||||||
|
* This is the sysfs directory from which cpacfstatsd daemon application loads
|
||||||
|
* the available PAI counters
|
||||||
|
*/
|
||||||
|
#define SYSFS_PAI_COUNTER "/sys/bus/event_source/devices/pai_crypto/events/"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that this is the first kernel only counter in the 1-based list of the
|
||||||
|
* architecture and NOT from the 0-based list in the cpacfstats code!
|
||||||
|
*/
|
||||||
|
#define FIRST_KERNEL_ONLY_COUNTER 144
|
||||||
|
|
||||||
int eprint(const char *format, ...);
|
int eprint(const char *format, ...);
|
||||||
|
|
||||||
@@ -67,6 +77,12 @@ enum state_e {
|
|||||||
UNSUPPORTED
|
UNSUPPORTED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum counter_type {
|
||||||
|
SUPPRESS_COUNTER = 0,
|
||||||
|
KERNEL_AND_USER_COUNTER,
|
||||||
|
KERNEL_ONLY_COUNTER,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* query send from client to daemon
|
* query send from client to daemon
|
||||||
* Consist of:
|
* Consist of:
|
||||||
@@ -122,15 +138,23 @@ int recv_msg(int sfd, struct msg *m, int timeout);
|
|||||||
|
|
||||||
/* perf_crypto.c */
|
/* perf_crypto.c */
|
||||||
|
|
||||||
int perf_init(void);
|
int perf_init(unsigned int *supported_counters);
|
||||||
void perf_stop(void);
|
void perf_stop(void);
|
||||||
void perf_close(void);
|
void perf_close(void);
|
||||||
int perf_enable_ctr(enum ctr_e ctr);
|
int perf_enable_ctr(enum ctr_e ctr, unsigned int *supported_counters);
|
||||||
int perf_disable_ctr(enum ctr_e ctr);
|
int perf_disable_ctr(enum ctr_e ctr, unsigned int *supported_counters);
|
||||||
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value);
|
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value, unsigned int
|
||||||
int perf_read_ctr(enum ctr_e ctr, uint64_t *value);
|
*supported_counters);
|
||||||
|
int perf_read_ctr(enum ctr_e ctr, uint64_t *value, unsigned int
|
||||||
|
*supported_counters);
|
||||||
int perf_ecc_supported(void);
|
int perf_ecc_supported(void);
|
||||||
int perf_ctr_state(enum ctr_e ctr);
|
int perf_ctr_state(enum ctr_e ctr);
|
||||||
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value);
|
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value);
|
||||||
|
|
||||||
|
/* cpacfstats_common.c */
|
||||||
|
|
||||||
|
enum counter_type is_user_space(unsigned int ctr);
|
||||||
|
const char *get_ctr_name(unsigned int ctr);
|
||||||
|
unsigned int get_num_user_space_ctrs(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
253
cpacfstats/cpacfstats_common.c
Normal file
253
cpacfstats/cpacfstats_common.c
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
/*
|
||||||
|
* cpacfstats_common.c - shared code by daemon and client
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "cpacfstats.h"
|
||||||
|
|
||||||
|
struct pai_counter {
|
||||||
|
const char *str;
|
||||||
|
const unsigned int counter_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strings for the pai counter details.
|
||||||
|
* Integer indicating if kernel space is needed (0 for user, KERNEL_ONLY_COUNTER for kernel)
|
||||||
|
* Note that this is 0-based while PoP is 1-based.
|
||||||
|
*
|
||||||
|
* When adding new items to this list add the counter number in the pai_idx
|
||||||
|
* list in cpacfstatsd.c and increase the number of total counters in
|
||||||
|
* cpacfstats.h.
|
||||||
|
*/
|
||||||
|
const struct pai_counter pai[] = {
|
||||||
|
[ 0] = {"KM DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 1] = {"KM 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 2] = {"KM TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 3] = {"KM DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 4] = {"KM 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 5] = {"KM TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 6] = {"KM AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 7] = {"KM AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 8] = {"KM AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 9] = {"KM AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 10] = {"KM AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 11] = {"KM AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 12] = {"KM AES-XTS 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 13] = {"KM AES-XTS 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 14] = {"KM AES-XTS 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 15] = {"KM AES-XTS 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 16] = {"KMC DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 17] = {"KMC 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 18] = {"KMC TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 19] = {"KMC DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 20] = {"KMC 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 21] = {"KMC TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 22] = {"KMC AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 23] = {"KMC AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 24] = {"KMC AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 25] = {"KMC AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 26] = {"KMC AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 27] = {"KMC AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 28] = {"KMC PRNG", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 29] = {"KMA AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 30] = {"KMA AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 31] = {"KMA AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 32] = {"KMA AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 33] = {"KMA AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 34] = {"KMA AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 35] = {"KMF DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 36] = {"KMF 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 37] = {"KMF TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 38] = {"KMF DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 39] = {"KMF 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 40] = {"KMF TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 41] = {"KMF AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 42] = {"KMF AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 43] = {"KMF AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 44] = {"KMF AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 45] = {"KMF AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 46] = {"KMF AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 47] = {"KMCTR DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 48] = {"KMCTR 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 49] = {"KMCTR TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 50] = {"KMCTR DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 51] = {"KMCTR 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 52] = {"KMCTR TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 53] = {"KMCTR AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 54] = {"KMCTR AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 55] = {"KMCTR AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 56] = {"KMCTR AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 57] = {"KMCTR AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 58] = {"KMCTR AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 59] = {"KMO DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 60] = {"KMO 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 61] = {"KMO TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 62] = {"KMO DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 63] = {"KMO 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 64] = {"KMO TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 65] = {"KMO AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 66] = {"KMO AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 67] = {"KMO AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 68] = {"KMO AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 69] = {"KMO AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 70] = {"KMO AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 71] = {"KIMD SHA1", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 72] = {"KIMD SHA256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 73] = {"KIMD SHA512", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 74] = {"KIMD SHA3-224", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 75] = {"KIMD SHA3-256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 76] = {"KIMD SHA3-384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 77] = {"KIMD SHA3-512", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 78] = {"KIMD SHAKE 128", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 79] = {"KIMD SHAKE 256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 80] = {"KIMD GHASH", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 81] = {"KLMD SHA1", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 82] = {"KLMD SHA256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 83] = {"KLMD SHA512", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 84] = {"KLMD SHA3-224", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 85] = {"KLMD SHA3-256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 86] = {"KLMD SHA3-384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 87] = {"KLMD SHA3-512", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 88] = {"KLMD SHAKE 128", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 89] = {"KLMD SHAKE 256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 90] = {"KMAC DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 91] = {"KMAC 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 92] = {"KMAC TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 93] = {"KMAC DES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 94] = {"KMAC 2key TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 95] = {"KMAC TDES protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 96] = {"KMAC AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 97] = {"KMAC AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 98] = {"KMAC AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[ 99] = {"KMAC AES 128bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[100] = {"KMAC AES 192bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[101] = {"KMAC AES 256bit protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[102] = {"PCC Last Block CMAC DES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[103] = {"PCC Last Block CMAC 2key TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[104] = {"PCC Last Block CMAC TDES", KERNEL_AND_USER_COUNTER},
|
||||||
|
[105] = {"PCC Last Block CMAC DES protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[106] = {"PCC Last Block CMAC 2key TDES protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[107] = {"PCC Last Block CMAC TDES protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[108] = {"PCC Last Block CMAC AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[109] = {"PCC Last Block CMAC AES 192bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[110] = {"PCC Last Block CMAC AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[111] = {"PCC Last Block CMAC AES 128bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[112] = {"PCC Last Block CMAC AES 192bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[113] = {"PCC Last Block CMAC AES 256bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[114] = {"PCC XTS Parameter AES 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[115] = {"PCC XTS Parameter AES 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[116] = {"PCC XTS Parameter AES 128bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[117] = {"PCC XTS Parameter AES 256bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[118] = {"PCC Scalar Mult P256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[119] = {"PCC Scalar Mult P384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[120] = {"PCC Scalar Mult P521", KERNEL_AND_USER_COUNTER},
|
||||||
|
[121] = {"PCC Scalar Mult Ed25519", KERNEL_AND_USER_COUNTER},
|
||||||
|
[122] = {"PCC Scalar Mult Ed448", KERNEL_AND_USER_COUNTER},
|
||||||
|
[123] = {"PCC Scalar Mult X25519", KERNEL_AND_USER_COUNTER},
|
||||||
|
[124] = {"PCC Scalar Mult X448", KERNEL_AND_USER_COUNTER},
|
||||||
|
[125] = {"PRNO SHA512 DRNG", KERNEL_AND_USER_COUNTER},
|
||||||
|
[126] = {"PRNO TRNG Query Ratio", KERNEL_AND_USER_COUNTER},
|
||||||
|
[127] = {"PRNO TRNG", KERNEL_AND_USER_COUNTER},
|
||||||
|
[128] = {"KDSA ECDSA Verify P256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[129] = {"KDSA ECDSA Verify P384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[130] = {"KDSA ECDSA Verify P521", KERNEL_AND_USER_COUNTER},
|
||||||
|
[131] = {"KDSA ECDSA Sign P256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[132] = {"KDSA ECDSA Sign P384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[133] = {"KDSA ECDSA Sign P521", KERNEL_AND_USER_COUNTER},
|
||||||
|
[134] = {"KDSA ECDSA Sign P256 protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[135] = {"KDSA ECDSA Sign P384 protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[136] = {"KDSA ECDSA Sign P521 protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[137] = {"KDSA EdDSA Verify Ed25519", KERNEL_AND_USER_COUNTER},
|
||||||
|
[138] = {"KDSA EdDSA Verify Ed448", KERNEL_AND_USER_COUNTER},
|
||||||
|
[139] = {"KDSA EdDSA Sign Ed25519", KERNEL_AND_USER_COUNTER},
|
||||||
|
[140] = {"KDSA EdDSA Sign Ed448", KERNEL_AND_USER_COUNTER},
|
||||||
|
[141] = {"KDSA EdDSA Sign Ed25519 protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[142] = {"KDSA EdDSA Sign Ed448 protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[143] = {"PCKMO DES", KERNEL_ONLY_COUNTER},
|
||||||
|
[144] = {"PCKMO 2key TDES", KERNEL_ONLY_COUNTER},
|
||||||
|
[145] = {"PCKMO TDES", KERNEL_ONLY_COUNTER},
|
||||||
|
[146] = {"PCKMO AES 128bit", KERNEL_ONLY_COUNTER},
|
||||||
|
[147] = {"PCKMO AES 192bit", KERNEL_ONLY_COUNTER},
|
||||||
|
[148] = {"PCKMO AES 256bit", KERNEL_ONLY_COUNTER},
|
||||||
|
[149] = {"PCKMO ECC P256", KERNEL_ONLY_COUNTER},
|
||||||
|
[150] = {"PCKMO ECC P384", KERNEL_ONLY_COUNTER},
|
||||||
|
[151] = {"PCKMO ECC P521", KERNEL_ONLY_COUNTER},
|
||||||
|
[152] = {"PCKMO ECC Ed25519", KERNEL_ONLY_COUNTER},
|
||||||
|
[153] = {"PCKMO ECC Ed448", KERNEL_ONLY_COUNTER},
|
||||||
|
[154] = {"Reserved 1", KERNEL_ONLY_COUNTER},
|
||||||
|
[155] = {"Reserved 2", KERNEL_ONLY_COUNTER},
|
||||||
|
[156] = {"KM AES-XTS (full) 128bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[157] = {"KM AES-XTS (full) 256bit", KERNEL_AND_USER_COUNTER},
|
||||||
|
[158] = {"KM AES-XTS (full) 128bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[159] = {"KM AES-XTS (full) 256bit protected key",
|
||||||
|
KERNEL_AND_USER_COUNTER},
|
||||||
|
[160] = {"KMAC HMAC SHA 224", KERNEL_AND_USER_COUNTER},
|
||||||
|
[161] = {"KMAC HMAC SHA 256", KERNEL_AND_USER_COUNTER},
|
||||||
|
[162] = {"KMAC HMAC SHA 384", KERNEL_AND_USER_COUNTER},
|
||||||
|
[163] = {"KMAC HMAC SHA 512", KERNEL_AND_USER_COUNTER},
|
||||||
|
[164] = {"KMAC HMAC SHA 224 protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[165] = {"KMAC HMAC SHA 256 protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[166] = {"KMAC HMAC SHA 384 protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[167] = {"KMAC HMAC SHA 512 protected key", KERNEL_AND_USER_COUNTER},
|
||||||
|
[168] = {"PCKMO HMAC 512 protected key", KERNEL_ONLY_COUNTER},
|
||||||
|
[169] = {"PCKMO HMAC 1024 protected key", KERNEL_ONLY_COUNTER},
|
||||||
|
[170] = {"PCKMO AES-XTS 128bit double key protected key",
|
||||||
|
KERNEL_ONLY_COUNTER},
|
||||||
|
[171] = {"PCKMO AES-XTS 256bit double key protected key",
|
||||||
|
KERNEL_ONLY_COUNTER}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns counter_type of pai_counter struct
|
||||||
|
*
|
||||||
|
* SUPPRESS_COUNTER
|
||||||
|
* KERNEL_AND_USER_COUNTER
|
||||||
|
* KERNEL_ONLY_COUNTER
|
||||||
|
*/
|
||||||
|
enum counter_type is_user_space(unsigned int ctr)
|
||||||
|
{
|
||||||
|
if (ctr >= MAX_NUM_PAI)
|
||||||
|
return SUPPRESS_COUNTER;
|
||||||
|
return pai[ctr].counter_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *get_ctr_name(unsigned int ctr)
|
||||||
|
{
|
||||||
|
if (ctr >= MAX_NUM_PAI)
|
||||||
|
return NULL;
|
||||||
|
return pai[ctr].str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns number of PAI counters for which no kernel space is needed
|
||||||
|
*/
|
||||||
|
unsigned int get_num_user_space_ctrs(void)
|
||||||
|
{
|
||||||
|
unsigned int counter = 0;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_NUM_PAI; i++) {
|
||||||
|
if (is_user_space(i) == KERNEL_AND_USER_COUNTER)
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
@@ -24,12 +24,54 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
#include "cpacfstats.h"
|
#include "cpacfstats.h"
|
||||||
|
|
||||||
static volatile int stopsig;
|
static volatile int stopsig;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This list contains the counter numbers sorted by instruction
|
||||||
|
*/
|
||||||
|
static const unsigned int pai_idx[] = {
|
||||||
|
// KM
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 156, 157, 158,
|
||||||
|
159,
|
||||||
|
// KMC
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||||
|
// KMA
|
||||||
|
29, 30, 31, 32, 33, 34,
|
||||||
|
// KMF
|
||||||
|
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
|
// KMCTR
|
||||||
|
47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
||||||
|
// KMO
|
||||||
|
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
|
||||||
|
// KIMD
|
||||||
|
71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
|
||||||
|
// KLMD
|
||||||
|
81, 82, 83, 84, 85, 86, 87, 88, 89,
|
||||||
|
// KMAC
|
||||||
|
90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 160, 161, 162, 163,
|
||||||
|
164, 165, 166, 167,
|
||||||
|
// PCC
|
||||||
|
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
|
||||||
|
114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
|
||||||
|
// PRNO
|
||||||
|
125, 126, 127,
|
||||||
|
// KDSA
|
||||||
|
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||||
|
140, 141, 142,
|
||||||
|
// PCKMO
|
||||||
|
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 168, 169, 170, 171,
|
||||||
|
// Reserved
|
||||||
|
154, 155
|
||||||
|
};
|
||||||
|
|
||||||
static const char *const name = "cpacfstatsd";
|
static const char *const name = "cpacfstatsd";
|
||||||
|
|
||||||
static const char *const usage =
|
static const char *const usage =
|
||||||
@@ -68,7 +110,6 @@ static int recv_query(int s, enum ctr_e *ctr, enum cmd_e *cmd)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int send_answer(int s, int ctr, int state, uint64_t value)
|
static int send_answer(int s, int ctr, int state, uint64_t value)
|
||||||
{
|
{
|
||||||
struct msg m;
|
struct msg m;
|
||||||
@@ -84,7 +125,6 @@ static int send_answer(int s, int ctr, int state, uint64_t value)
|
|||||||
return send_msg(s, &m, DEFAULT_SEND_TIMEOUT);
|
return send_msg(s, &m, DEFAULT_SEND_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print according to protocol for PAI:
|
* Print according to protocol for PAI:
|
||||||
* - first the state and the number of PAI counters that follow
|
* - first the state and the number of PAI counters that follow
|
||||||
@@ -93,34 +133,34 @@ static int send_answer(int s, int ctr, int state, uint64_t value)
|
|||||||
* Note that the PAI counters are 0-based, not 1 based as in PoP!
|
* Note that the PAI counters are 0-based, not 1 based as in PoP!
|
||||||
* Sending ends with the first error.
|
* Sending ends with the first error.
|
||||||
*/
|
*/
|
||||||
static int do_send_pai(int s, int user)
|
static int do_send_pai(int s, int user, unsigned int *counter)
|
||||||
{
|
{
|
||||||
int ctr, state, i, maxctr, rc = 0;
|
int ctr, state, i, rc = 0;
|
||||||
|
unsigned int current_ctr;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
|
|
||||||
if (user) {
|
ctr = user ? PAI_USER : PAI_KERNEL;
|
||||||
ctr = PAI_USER;
|
|
||||||
maxctr = NUM_PAI_USER;
|
|
||||||
} else {
|
|
||||||
ctr = PAI_KERNEL;
|
|
||||||
maxctr = NUM_PAI_KERNEL;
|
|
||||||
}
|
|
||||||
state = perf_ctr_state(ctr);
|
state = perf_ctr_state(ctr);
|
||||||
if (state != ENABLED)
|
if (state != ENABLED)
|
||||||
return rc;
|
return rc;
|
||||||
for (i = 0; i < maxctr; ++i) {
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
rc = perf_read_pai_ctr(i, user, &value);
|
current_ctr = pai_idx[i];
|
||||||
|
if ((user && is_user_space(current_ctr) != KERNEL_AND_USER_COUNTER) ||
|
||||||
|
(!user && is_user_space(current_ctr) == SUPPRESS_COUNTER) ||
|
||||||
|
counter[current_ctr] != 1)
|
||||||
|
continue;
|
||||||
|
rc = perf_read_pai_ctr(current_ctr, user, &value);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, current_ctr, rc, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
send_answer(s, i, state, value);
|
send_answer(s, current_ctr, state, value);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_enable(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
static int do_enable(int s, enum ctr_e ctr)
|
|
||||||
{
|
{
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
@@ -132,7 +172,7 @@ static int do_enable(int s, enum ctr_e ctr)
|
|||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
state = perf_ctr_state(i);
|
state = perf_ctr_state(i);
|
||||||
if (state == DISABLED) {
|
if (state == DISABLED) {
|
||||||
rc = perf_enable_ctr(i);
|
rc = perf_enable_ctr(i, supported_counters);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
break;
|
break;
|
||||||
@@ -140,7 +180,7 @@ static int do_enable(int s, enum ctr_e ctr)
|
|||||||
state = ENABLED;
|
state = ENABLED;
|
||||||
}
|
}
|
||||||
if (state != UNSUPPORTED) {
|
if (state != UNSUPPORTED) {
|
||||||
rc = perf_read_ctr(i, &value);
|
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);
|
||||||
break;
|
break;
|
||||||
@@ -148,20 +188,19 @@ static int do_enable(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
send_answer(s, i, state, value);
|
send_answer(s, i, state, value);
|
||||||
if (i == PAI_USER)
|
if (i == PAI_USER)
|
||||||
rc = do_send_pai(s, 1);
|
rc = do_send_pai(s, 1, supported_counters);
|
||||||
if (i == PAI_KERNEL)
|
if (i == PAI_KERNEL)
|
||||||
rc = do_send_pai(s, 0);
|
rc = do_send_pai(s, 0, supported_counters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
|
rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL);
|
||||||
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_disable(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
static int do_disable(int s, enum ctr_e ctr)
|
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
@@ -171,7 +210,7 @@ static int do_disable(int s, enum ctr_e ctr)
|
|||||||
continue;
|
continue;
|
||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
if (perf_ctr_state(i) == ENABLED) {
|
if (perf_ctr_state(i) == ENABLED) {
|
||||||
rc = perf_disable_ctr(i);
|
rc = perf_disable_ctr(i, supported_counters);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
break;
|
break;
|
||||||
@@ -181,14 +220,13 @@ static int do_disable(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
|
rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL);
|
||||||
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_reset(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
static int do_reset(int s, enum ctr_e ctr)
|
|
||||||
{
|
{
|
||||||
int i, rc = 0, state;
|
int i, rc = 0, state;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
@@ -199,7 +237,7 @@ static int do_reset(int s, enum ctr_e ctr)
|
|||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
state = perf_ctr_state(i);
|
state = perf_ctr_state(i);
|
||||||
if (state == ENABLED) {
|
if (state == ENABLED) {
|
||||||
rc = perf_reset_ctr(i, &value);
|
rc = perf_reset_ctr(i, &value, supported_counters);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
send_answer(s, i, rc, 0);
|
send_answer(s, i, rc, 0);
|
||||||
break;
|
break;
|
||||||
@@ -207,20 +245,19 @@ static int do_reset(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
send_answer(s, i, state, value);
|
send_answer(s, i, state, value);
|
||||||
if (i == PAI_USER)
|
if (i == PAI_USER)
|
||||||
rc = do_send_pai(s, 1);
|
rc = do_send_pai(s, 1, supported_counters);
|
||||||
if (i == PAI_KERNEL)
|
if (i == PAI_KERNEL)
|
||||||
rc = do_send_pai(s, 0);
|
rc = do_send_pai(s, 0, supported_counters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
|
rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL);
|
||||||
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_print(int s, enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
static int do_print(int s, enum ctr_e ctr)
|
|
||||||
{
|
{
|
||||||
int i, rc = 0, state;
|
int i, rc = 0, state;
|
||||||
uint64_t value = 0;
|
uint64_t value = 0;
|
||||||
@@ -231,7 +268,7 @@ static int do_print(int s, enum ctr_e ctr)
|
|||||||
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
if (i == (int) ctr || ctr == ALL_COUNTER) {
|
||||||
state = perf_ctr_state(i);
|
state = perf_ctr_state(i);
|
||||||
if (state == ENABLED) {
|
if (state == ENABLED) {
|
||||||
rc = perf_read_ctr(i, &value);
|
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);
|
||||||
break;
|
break;
|
||||||
@@ -239,19 +276,18 @@ static int do_print(int s, enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
send_answer(s, i, state, value);
|
send_answer(s, i, state, value);
|
||||||
if (i == PAI_USER)
|
if (i == PAI_USER)
|
||||||
rc = do_send_pai(s, 1);
|
rc = do_send_pai(s, 1, supported_counters);
|
||||||
if (i == PAI_KERNEL)
|
if (i == PAI_KERNEL)
|
||||||
rc = do_send_pai(s, 0);
|
rc = do_send_pai(s, 0, supported_counters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
|
rc = perf_read_ctr(HOTPLUG_DETECTED, &value, NULL);
|
||||||
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
send_answer(s, HOTPLUG_DETECTED, rc, value);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int become_daemon(int *startup_pipe)
|
static int become_daemon(int *startup_pipe)
|
||||||
{
|
{
|
||||||
int child_initialized = 0, fd;
|
int child_initialized = 0, fd;
|
||||||
@@ -344,7 +380,6 @@ static int become_daemon(int *startup_pipe)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void remove_sock(void)
|
static void remove_sock(void)
|
||||||
{
|
{
|
||||||
remove(SOCKET_FILE);
|
remove(SOCKET_FILE);
|
||||||
@@ -406,14 +441,12 @@ static void remove_pidfile(void)
|
|||||||
remove(PID_FILE);
|
remove(PID_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void signalhandler(int sig)
|
void signalhandler(int sig)
|
||||||
{
|
{
|
||||||
perf_stop();
|
perf_stop();
|
||||||
stopsig = sig;
|
stopsig = sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int eprint(const char *format, ...)
|
int eprint(const char *format, ...)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
@@ -435,10 +468,44 @@ int eprint(const char *format, ...)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns -1 on error
|
||||||
|
* returns X where X is the found counters in dir
|
||||||
|
*
|
||||||
|
* the supplied array supported_counters[] is filled in this function with the
|
||||||
|
* available PAI counters found in SYSFS_PAI_COUNTER
|
||||||
|
*/
|
||||||
|
static void supported_functions(unsigned int supported_counters[])
|
||||||
|
{
|
||||||
|
const char *dir = SYSFS_PAI_COUNTER;
|
||||||
|
struct dirent *dp = NULL;
|
||||||
|
char filepath[PATH_MAX];
|
||||||
|
unsigned int num;
|
||||||
|
DIR *dfd = NULL;
|
||||||
|
|
||||||
|
dfd = opendir(dir);
|
||||||
|
if (dfd == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((dp = readdir(dfd)) != NULL) {
|
||||||
|
if ((strcmp(dp->d_name, ".") != 0) &&
|
||||||
|
(strcmp(dp->d_name, "..") != 0)) {
|
||||||
|
snprintf(filepath, sizeof(filepath), "%s%s", dir, dp->d_name);
|
||||||
|
if (util_file_read_va(filepath, "event=0x10%x", &num) != 1)
|
||||||
|
continue;
|
||||||
|
if (num > 0 && num <= MAX_NUM_PAI)
|
||||||
|
supported_counters[num - 1] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dfd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int rc, sfd, foreground = 0, startup_pipe = -1, initialized = 0;
|
int rc, sfd, foreground = 0, startup_pipe = -1, initialized = 0;
|
||||||
|
unsigned int supported_counters[MAX_NUM_PAI] = { 0 };
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
@@ -485,7 +552,9 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perf_init() != 0) {
|
supported_functions(supported_counters);
|
||||||
|
|
||||||
|
if (perf_init(supported_counters) != 0) {
|
||||||
eprint("Couldn't initialize perf lib\n");
|
eprint("Couldn't initialize perf lib\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -548,13 +617,13 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == ENABLE)
|
if (cmd == ENABLE)
|
||||||
rc = do_enable(s, ctr);
|
rc = do_enable(s, ctr, supported_counters);
|
||||||
else if (cmd == DISABLE)
|
else if (cmd == DISABLE)
|
||||||
rc = do_disable(s, ctr);
|
rc = do_disable(s, ctr, supported_counters);
|
||||||
else if (cmd == RESET)
|
else if (cmd == RESET)
|
||||||
rc = do_reset(s, ctr);
|
rc = do_reset(s, ctr, supported_counters);
|
||||||
else if (cmd == PRINT)
|
else if (cmd == PRINT)
|
||||||
rc = do_print(s, ctr);
|
rc = do_print(s, ctr, supported_counters);
|
||||||
else {
|
else {
|
||||||
eprint("Received unknown command %d, ignoring\n",
|
eprint("Received unknown command %d, ignoring\n",
|
||||||
(int) cmd);
|
(int) cmd);
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ static struct pmf_data {
|
|||||||
|
|
||||||
struct percpucounter {
|
struct percpucounter {
|
||||||
int ctr_fds[ALL_COUNTER];
|
int ctr_fds[ALL_COUNTER];
|
||||||
int pai_user[NUM_PAI_USER];
|
int pai_user[MAX_NUM_PAI];
|
||||||
int pai_kernel[NUM_PAI_KERNEL];
|
int pai_kernel[MAX_NUM_PAI];
|
||||||
unsigned int cpunum;
|
unsigned int cpunum;
|
||||||
struct percpucounter *next;
|
struct percpucounter *next;
|
||||||
};
|
};
|
||||||
@@ -84,10 +84,10 @@ static struct percpucounter *allocpercpucounter(unsigned int cpunum)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; ++i)
|
for (i = 0; i < ALL_COUNTER; ++i)
|
||||||
ppc->ctr_fds[i] = -1;
|
ppc->ctr_fds[i] = -1;
|
||||||
for (i = 0; i < NUM_PAI_USER; ++i)
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
ppc->pai_user[i] = -1;
|
ppc->pai_user[i] = -1;
|
||||||
for (i = 0; i < NUM_PAI_KERNEL; ++i)
|
|
||||||
ppc->pai_kernel[i] = -1;
|
ppc->pai_kernel[i] = -1;
|
||||||
|
}
|
||||||
ppc->cpunum = cpunum;
|
ppc->cpunum = cpunum;
|
||||||
ppc->next = NULL;
|
ppc->next = NULL;
|
||||||
}
|
}
|
||||||
@@ -100,10 +100,10 @@ static void freepercpucounter(struct percpucounter *pcpu)
|
|||||||
|
|
||||||
for (i = 0; i < ALL_COUNTER; ++i)
|
for (i = 0; i < ALL_COUNTER; ++i)
|
||||||
(void)close(pcpu->ctr_fds[i]);
|
(void)close(pcpu->ctr_fds[i]);
|
||||||
for (i = 0; i < NUM_PAI_USER; ++i)
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
(void)close(pcpu->pai_user[i]);
|
(void)close(pcpu->pai_user[i]);
|
||||||
for (i = 0; i < NUM_PAI_KERNEL; ++i)
|
|
||||||
(void)close(pcpu->pai_kernel[i]);
|
(void)close(pcpu->pai_kernel[i]);
|
||||||
|
}
|
||||||
free(pcpu);
|
free(pcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ static int perf_event_encode(int *pmutype, int *eventid,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int activatecpu(unsigned int cpu)
|
static int activatecpu(unsigned int cpu, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
struct perf_event_attr pfm_event;
|
struct perf_event_attr pfm_event;
|
||||||
struct percpucounter *ppc;
|
struct percpucounter *ppc;
|
||||||
@@ -273,7 +273,10 @@ static int activatecpu(unsigned int cpu)
|
|||||||
(ctr_state[PAI_USER] == UNSUPPORTED) ==
|
(ctr_state[PAI_USER] == UNSUPPORTED) ==
|
||||||
(ctr_state[PAI_KERNEL] == UNSUPPORTED) */
|
(ctr_state[PAI_KERNEL] == UNSUPPORTED) */
|
||||||
if (ctr_state[PAI_USER] != UNSUPPORTED) {
|
if (ctr_state[PAI_USER] != UNSUPPORTED) {
|
||||||
for (i = 1; i <= NUM_PAI_USER; ++i) {
|
for (i = 1; i <= MAX_NUM_PAI; ++i) {
|
||||||
|
if (is_user_space(i - 1) != KERNEL_AND_USER_COUNTER ||
|
||||||
|
supported_counters[i - 1] != 1)
|
||||||
|
continue;
|
||||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||||
pfm_event.size = sizeof(pfm_event);
|
pfm_event.size = sizeof(pfm_event);
|
||||||
pfm_event.type = paipmutype;
|
pfm_event.type = paipmutype;
|
||||||
@@ -307,7 +310,14 @@ static int activatecpu(unsigned int cpu)
|
|||||||
ppc->pai_kernel[i - 1] = fd;
|
ppc->pai_kernel[i - 1] = fd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; i <= NUM_PAI_KERNEL; ++i) {
|
/*
|
||||||
|
* i can start at the index of the first PAI counter
|
||||||
|
* for which kernel space is needed
|
||||||
|
*/
|
||||||
|
for (i = FIRST_KERNEL_ONLY_COUNTER; i <= MAX_NUM_PAI; ++i) {
|
||||||
|
if (is_user_space(i - 1) == SUPPRESS_COUNTER ||
|
||||||
|
supported_counters[i - 1] != 1)
|
||||||
|
continue;
|
||||||
memset(&pfm_event, 0, sizeof(pfm_event));
|
memset(&pfm_event, 0, sizeof(pfm_event));
|
||||||
pfm_event.size = sizeof(pfm_event);
|
pfm_event.size = sizeof(pfm_event);
|
||||||
pfm_event.type = paipmutype;
|
pfm_event.type = paipmutype;
|
||||||
@@ -348,10 +358,10 @@ static void deactivatecpu(unsigned int cpunum)
|
|||||||
if (pcpu != NULL) {
|
if (pcpu != NULL) {
|
||||||
for (i = 0; i < ALL_COUNTER; ++i)
|
for (i = 0; i < ALL_COUNTER; ++i)
|
||||||
(void)close(pcpu->ctr_fds[i]);
|
(void)close(pcpu->ctr_fds[i]);
|
||||||
for (i = 0; i < NUM_PAI_USER; ++i)
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
(void)close(pcpu->pai_user[i]);
|
(void)close(pcpu->pai_user[i]);
|
||||||
for (i = 0; i < NUM_PAI_KERNEL; ++i)
|
|
||||||
(void)close(pcpu->pai_kernel[i]);
|
(void)close(pcpu->pai_kernel[i]);
|
||||||
|
}
|
||||||
free(pcpu);
|
free(pcpu);
|
||||||
if (enabledcounter)
|
if (enabledcounter)
|
||||||
hotplugdetected = 1;
|
hotplugdetected = 1;
|
||||||
@@ -359,7 +369,7 @@ static void deactivatecpu(unsigned int cpunum)
|
|||||||
pthread_mutex_unlock(&rootmux);
|
pthread_mutex_unlock(&rootmux);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int addallcpus(void)
|
static int addallcpus(unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
unsigned int start, end;
|
unsigned int start, end;
|
||||||
int scanned, rc = 0;
|
int scanned, rc = 0;
|
||||||
@@ -379,7 +389,7 @@ static int addallcpus(void)
|
|||||||
if (scanned == 1)
|
if (scanned == 1)
|
||||||
end = start;
|
end = start;
|
||||||
for (; start <= end; ++start) {
|
for (; start <= end; ++start) {
|
||||||
if (activatecpu(start)) {
|
if (activatecpu(start, supported_counters)) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -409,7 +419,7 @@ static int perf_load_counter_data(void)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *hotplughandler(void *UNUSED(unused))
|
static void *hotplughandler(void *supported_counters)
|
||||||
{
|
{
|
||||||
struct udev *hotplug;
|
struct udev *hotplug;
|
||||||
struct udev_monitor *monitor;
|
struct udev_monitor *monitor;
|
||||||
@@ -452,7 +462,7 @@ static void *hotplughandler(void *UNUSED(unused))
|
|||||||
path = udev_device_get_devpath(dev);
|
path = udev_device_get_devpath(dev);
|
||||||
if (sscanf(path, "/devices/system/cpu/cpu%u", &cpunum) != 1)
|
if (sscanf(path, "/devices/system/cpu/cpu%u", &cpunum) != 1)
|
||||||
continue;
|
continue;
|
||||||
if (on && activatecpu(cpunum))
|
if (on && activatecpu(cpunum, (unsigned int *) supported_counters))
|
||||||
eprint("Failed to attach to hotplugged CPU %u\n", cpunum);
|
eprint("Failed to attach to hotplugged CPU %u\n", cpunum);
|
||||||
if (off)
|
if (off)
|
||||||
deactivatecpu(cpunum);
|
deactivatecpu(cpunum);
|
||||||
@@ -462,11 +472,18 @@ static void *hotplughandler(void *UNUSED(unused))
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int perf_init(void)
|
int perf_init(unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
int ecc_supported, i, num;
|
static const char *cpum_cf[] = {
|
||||||
|
"DEA_FUNCTIONS",
|
||||||
|
"AES_FUNCTIONS",
|
||||||
|
"SHA_FUNCTIONS",
|
||||||
|
"PRNG_FUNCTIONS",
|
||||||
|
"ECC_FUNCTION_COUNT"
|
||||||
|
};
|
||||||
unsigned long maxfd;
|
unsigned long maxfd;
|
||||||
struct rlimit rlim;
|
struct rlimit rlim;
|
||||||
|
int i, num;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
/* initialize performance monitoring library */
|
/* initialize performance monitoring library */
|
||||||
@@ -478,16 +495,18 @@ int perf_init(void)
|
|||||||
/* We currently support all cpumf counters plus two virtual
|
/* We currently support all cpumf counters plus two virtual
|
||||||
* counters for PAI. */
|
* counters for PAI. */
|
||||||
num = ALL_COUNTER + 2;
|
num = ALL_COUNTER + 2;
|
||||||
/* Check if ECC is supported on current hardware */
|
|
||||||
ecc_supported = perf_counter_supported("cpum_cf", "ECC_FUNCTION_COUNT");
|
|
||||||
|
|
||||||
if (!cpumf_authorized()) {
|
if (!cpumf_authorized()) {
|
||||||
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 (!ecc_supported) {
|
} else {
|
||||||
ctr_state[ECC_FUNCTIONS] = UNSUPPORTED;
|
for (i = 0; i < ALL_COUNTER; i++) {
|
||||||
--num;
|
if (!perf_counter_supported("cpum_cf", cpum_cf[i])) {
|
||||||
|
ctr_state[i] = UNSUPPORTED;
|
||||||
|
num--;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!perf_counter_supported("pai_crypto", "CRYPTO_ALL")) {
|
if (!perf_counter_supported("pai_crypto", "CRYPTO_ALL")) {
|
||||||
@@ -523,11 +542,12 @@ int perf_init(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pthread_create(&hotplugthread, NULL, hotplughandler, NULL)) {
|
if (pthread_create(&hotplugthread, NULL, hotplughandler,
|
||||||
|
supported_counters)) {
|
||||||
eprint("Failed to start hotplug handler thread\n");
|
eprint("Failed to start hotplug handler thread\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return addallcpus();
|
return addallcpus(supported_counters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -552,11 +572,14 @@ void perf_close(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int enable_array(int *arr, int size)
|
static int enable_array(int *arr, int user, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
int i, ec, rc = 0;
|
int i, ec, rc = 0;
|
||||||
|
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
|
if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) ||
|
||||||
|
supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER)
|
||||||
|
continue;
|
||||||
ec = ioctl(arr[i], PERF_EVENT_IOC_ENABLE, 0);
|
ec = ioctl(arr[i], PERF_EVENT_IOC_ENABLE, 0);
|
||||||
if (ec < 0) {
|
if (ec < 0) {
|
||||||
eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n",
|
eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n",
|
||||||
@@ -568,14 +591,14 @@ static int enable_array(int *arr, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int perf_enable_ctr(enum ctr_e ctr)
|
int perf_enable_ctr(enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
struct percpucounter *pcpu;
|
struct percpucounter *pcpu;
|
||||||
int ec, rc = 0;
|
int ec, rc = 0;
|
||||||
|
|
||||||
if (ctr == ALL_COUNTER) {
|
if (ctr == ALL_COUNTER) {
|
||||||
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
||||||
rc = perf_enable_ctr(ctr);
|
rc = perf_enable_ctr(ctr, supported_counters);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -593,7 +616,7 @@ int perf_enable_ctr(enum ctr_e ctr)
|
|||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_USER) {
|
} else if (ctr == PAI_USER) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = enable_array(pcpu->pai_user, NUM_PAI_USER);
|
ec = enable_array(pcpu->pai_user, 1, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
@@ -602,7 +625,7 @@ int perf_enable_ctr(enum ctr_e ctr)
|
|||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_KERNEL) {
|
} else if (ctr == PAI_KERNEL) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = enable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
ec = enable_array(pcpu->pai_kernel, 0, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
@@ -617,11 +640,14 @@ int perf_enable_ctr(enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int disable_array(int *arr, int size)
|
static int disable_array(int *arr, int user, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
int i, ec, rc = 0;
|
int i, ec, rc = 0;
|
||||||
|
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
|
if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) ||
|
||||||
|
supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER)
|
||||||
|
continue;
|
||||||
ec = ioctl(arr[i], PERF_EVENT_IOC_DISABLE, 0);
|
ec = ioctl(arr[i], PERF_EVENT_IOC_DISABLE, 0);
|
||||||
if (ec < 0) {
|
if (ec < 0) {
|
||||||
eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n",
|
eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n",
|
||||||
@@ -633,14 +659,14 @@ static int disable_array(int *arr, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int perf_disable_ctr(enum ctr_e ctr)
|
int perf_disable_ctr(enum ctr_e ctr, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
struct percpucounter *pcpu;
|
struct percpucounter *pcpu;
|
||||||
int ec, rc = 0;
|
int ec, rc = 0;
|
||||||
|
|
||||||
if (ctr == ALL_COUNTER) {
|
if (ctr == ALL_COUNTER) {
|
||||||
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
||||||
rc = perf_disable_ctr(ctr);
|
rc = perf_disable_ctr(ctr, supported_counters);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -660,7 +686,7 @@ int perf_disable_ctr(enum ctr_e ctr)
|
|||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_USER) {
|
} else if (ctr == PAI_USER) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = disable_array(pcpu->pai_user, NUM_PAI_USER);
|
ec = disable_array(pcpu->pai_user, 1, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
@@ -671,7 +697,7 @@ int perf_disable_ctr(enum ctr_e ctr)
|
|||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_KERNEL) {
|
} else if (ctr == PAI_KERNEL) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = disable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
ec = disable_array(pcpu->pai_kernel, 0, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
@@ -688,11 +714,14 @@ int perf_disable_ctr(enum ctr_e ctr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int reset_array(int *arr, int size)
|
static int reset_array(int *arr, int user, unsigned int *supported_counters)
|
||||||
{
|
{
|
||||||
int ec, rc = 0, i;
|
int ec, rc = 0, i;
|
||||||
|
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < MAX_NUM_PAI; ++i) {
|
||||||
|
if ((user && is_user_space(i) != KERNEL_AND_USER_COUNTER) ||
|
||||||
|
supported_counters[i] != 1 || is_user_space(i) == SUPPRESS_COUNTER)
|
||||||
|
continue;
|
||||||
ec = ioctl(arr[i], PERF_EVENT_IOC_RESET, 0);
|
ec = ioctl(arr[i], PERF_EVENT_IOC_RESET, 0);
|
||||||
if (ec < 0) {
|
if (ec < 0) {
|
||||||
eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n",
|
eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n",
|
||||||
@@ -704,14 +733,15 @@ static int reset_array(int *arr, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value)
|
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value, unsigned int
|
||||||
|
*supported_counters)
|
||||||
{
|
{
|
||||||
struct percpucounter *pcpu;
|
struct percpucounter *pcpu;
|
||||||
int ec, rc = 0;
|
int ec, rc = 0;
|
||||||
|
|
||||||
if (ctr == ALL_COUNTER) {
|
if (ctr == ALL_COUNTER) {
|
||||||
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
|
||||||
rc = perf_reset_ctr(ctr, value);
|
rc = perf_reset_ctr(ctr, value, supported_counters);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -727,14 +757,14 @@ int perf_reset_ctr(enum ctr_e ctr, uint64_t *value)
|
|||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_USER) {
|
} else if (ctr == PAI_USER) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = reset_array(pcpu->pai_user, NUM_PAI_USER);
|
ec = reset_array(pcpu->pai_user, 1, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
endforeachcpu();
|
endforeachcpu();
|
||||||
} else if (ctr == PAI_KERNEL) {
|
} else if (ctr == PAI_KERNEL) {
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
ec = reset_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
|
ec = reset_array(pcpu->pai_kernel, 0, supported_counters);
|
||||||
if (ec < 0)
|
if (ec < 0)
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
@@ -743,12 +773,13 @@ int perf_reset_ctr(enum ctr_e ctr, uint64_t *value)
|
|||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = perf_read_ctr(ctr, value);
|
rc = perf_read_ctr(ctr, value, supported_counters);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
int perf_read_ctr(enum ctr_e ctr, uint64_t *value, unsigned int
|
||||||
|
*supported_counters)
|
||||||
{
|
{
|
||||||
struct percpucounter *pcpu;
|
struct percpucounter *pcpu;
|
||||||
int ec, rc = 0;
|
int ec, rc = 0;
|
||||||
@@ -761,11 +792,26 @@ int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ctr == PAI_USER) {
|
if (ctr == PAI_USER) {
|
||||||
*value = NUM_PAI_USER;
|
int c = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_PAI; i++) {
|
||||||
|
if (is_user_space(i) == KERNEL_AND_USER_COUNTER &&
|
||||||
|
supported_counters[i] == 1)
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = c;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ctr == PAI_KERNEL) {
|
if (ctr == PAI_KERNEL) {
|
||||||
*value = NUM_PAI_KERNEL;
|
int c = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_NUM_PAI; i++) {
|
||||||
|
if (supported_counters[i] == 1)
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = c;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ctr >= ALL_COUNTER)
|
if (ctr >= ALL_COUNTER)
|
||||||
@@ -802,14 +848,15 @@ int perf_ctr_state(enum ctr_e ctr) {
|
|||||||
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value)
|
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value)
|
||||||
{
|
{
|
||||||
struct percpucounter *pcpu;
|
struct percpucounter *pcpu;
|
||||||
unsigned int maxctr;
|
|
||||||
int *arr, ec, rc = 0;
|
int *arr, ec, rc = 0;
|
||||||
uint64_t val;
|
uint64_t val;
|
||||||
|
|
||||||
*value = 0;
|
*value = 0;
|
||||||
maxctr = user ? NUM_PAI_USER : NUM_PAI_KERNEL;
|
|
||||||
if (ctrnum >= maxctr)
|
if (is_user_space(ctrnum) == SUPPRESS_COUNTER ||
|
||||||
|
(user && is_user_space(ctrnum) == KERNEL_ONLY_COUNTER))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
foreachcpu(pcpu) {
|
foreachcpu(pcpu) {
|
||||||
arr = user ? pcpu->pai_user : pcpu->pai_kernel;
|
arr = user ? pcpu->pai_user : pcpu->pai_kernel;
|
||||||
ec = read(arr[ctrnum], &val, sizeof(val));
|
ec = read(arr[ctrnum], &val, sizeof(val));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
include ../common.mak
|
include ../common.mak
|
||||||
|
|
||||||
BIN_FILES = lscpumf chcpumf lshwc pai
|
BIN_FILES = lscpumf chcpumf lshwc pai lspai
|
||||||
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8
|
MAN_FILES = lscpumf.8 chcpumf.8 lshwc.8 pai.8 lspai.8
|
||||||
|
|
||||||
all: $(BIN_FILES)
|
all: $(BIN_FILES)
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ lscpumf: lscpumf.o $(libs)
|
|||||||
chcpumf: chcpumf.o $(libs)
|
chcpumf: chcpumf.o $(libs)
|
||||||
lshwc: lshwc.o $(libs)
|
lshwc: lshwc.o $(libs)
|
||||||
pai: pai.o $(libs)
|
pai: pai.o $(libs)
|
||||||
|
lspai: lspai.o $(libs)
|
||||||
|
|
||||||
install: all install-man
|
install: all install-man
|
||||||
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR)/man8
|
||||||
|
|||||||
@@ -3473,6 +3473,7 @@ static struct counters *get_counter(int ctrset, size_t *len)
|
|||||||
read_ccerror(cp, *len);
|
read_ccerror(cp, *len);
|
||||||
break;
|
break;
|
||||||
case UTIL_ARCH_MACHINE_TYPE_Z16:
|
case UTIL_ARCH_MACHINE_TYPE_Z16:
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
352
cpumf/lspai.c
Normal file
352
cpumf/lspai.c
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
/* Copyright IBM Corp. 2023
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* List available Processor Assist Instrumentation (PAI) counters. */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lib/util_opt.h"
|
||||||
|
#include "lib/util_prg.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_list.h"
|
||||||
|
#include "lib/libcpumf.h"
|
||||||
|
|
||||||
|
static struct util_opt opt_vec[] = {
|
||||||
|
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 = {
|
||||||
|
.desc = "List Processor Assist Information counter sets",
|
||||||
|
.copyright_vec = {
|
||||||
|
{
|
||||||
|
.owner = "IBM Corp.",
|
||||||
|
.pub_first = 2023,
|
||||||
|
.pub_last = 2023,
|
||||||
|
},
|
||||||
|
UTIL_PRG_COPYRIGHT_END
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool numsort; /* If true sort counter numerically */
|
||||||
|
|
||||||
|
#define PAI_PATH "/bus/event_source/devices/%s"
|
||||||
|
|
||||||
|
enum pai_types { /* Bit mask for supported PAI counters */
|
||||||
|
pai_type_crypto = 0, /* PAI Crypto Counters */
|
||||||
|
pai_type_nnpa = 1, /* PAI NNPA Counters */
|
||||||
|
pai_type_max = 2, /* PAI maximum value, must be last */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pai_types_show;
|
||||||
|
|
||||||
|
struct pai_ctrname { /* List of defined counters */
|
||||||
|
char *name; /* Counter name */
|
||||||
|
unsigned long nr; /* Counter number */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pai_node { /* Head for PAI counter sets */
|
||||||
|
struct util_list_node node; /* Successor in PAI counter set list */
|
||||||
|
enum pai_types type; /* PAI type */
|
||||||
|
int pmu; /* Assigned PMU type number */
|
||||||
|
const char *name; /* Counter set name */
|
||||||
|
char *name_uc; /* Counter set name upper case */
|
||||||
|
const char *sysfs_name; /* Counter set name in /sysfs tree */
|
||||||
|
const char *filter_name; /* Counter set name for scandir filter */
|
||||||
|
struct pai_ctrname *ctrlist; /* List of counter names & numbers */
|
||||||
|
size_t ctrsize; /* Total size in bytes of ctrlist */
|
||||||
|
int ctridx; /* Index of last entry used in ctrlist */
|
||||||
|
unsigned long base; /* Base number for counter set */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct util_list pai_list;
|
||||||
|
|
||||||
|
/* Return base of counter set, this is the first counter of this set. */
|
||||||
|
static unsigned long pai_type_base(enum pai_types t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case pai_type_crypto:
|
||||||
|
return 0x1000;
|
||||||
|
case pai_type_nnpa:
|
||||||
|
return 0x1800;
|
||||||
|
case pai_type_max:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test PAI counter name from command line option. */
|
||||||
|
static const char *pai_type_name(enum pai_types t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case pai_type_crypto:
|
||||||
|
return "crypto";
|
||||||
|
case pai_type_nnpa:
|
||||||
|
return "nnpa";
|
||||||
|
case pai_type_max:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert PAI counter type to sysfs directory name. Only validated
|
||||||
|
* input at this time.
|
||||||
|
*/
|
||||||
|
static const char *pai_type_sysfs(enum pai_types t)
|
||||||
|
{
|
||||||
|
if (t == pai_type_crypto)
|
||||||
|
return "pai_crypto";
|
||||||
|
return "pai_ext";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert PAI counter type to sysfs directory name filter for scandir(). */
|
||||||
|
static const char *pai_type_filter(enum pai_types t)
|
||||||
|
{
|
||||||
|
if (t == pai_type_nnpa)
|
||||||
|
return "^NNPA";
|
||||||
|
return "[^.]"; /* Matches anything but . and .. in sysfs */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sort PAI counter names by assigned counter number. */
|
||||||
|
static int pai_ctrcmp(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
struct pai_ctrname *l = (struct pai_ctrname *)p1;
|
||||||
|
struct pai_ctrname *r = (struct pai_ctrname *)p2;
|
||||||
|
|
||||||
|
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.
|
||||||
|
* Exit when sysfs directory can not be scanned.
|
||||||
|
*/
|
||||||
|
static void read_counternames(struct pai_node *node)
|
||||||
|
{
|
||||||
|
int i, more = 0, ctr = 0, count = 0;
|
||||||
|
struct dirent **namelist = NULL;
|
||||||
|
char *path, *ctrpath;
|
||||||
|
|
||||||
|
/* Read counter names and assigned event number. */
|
||||||
|
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
|
||||||
|
count = util_scandir(&namelist, alphasort, path, node->filter_name);
|
||||||
|
if (count <= 0)
|
||||||
|
errx(EXIT_FAILURE, "Cannot open %s", path);
|
||||||
|
|
||||||
|
node->ctrsize = count * sizeof(*node->ctrlist);
|
||||||
|
node->ctrlist = util_malloc(node->ctrsize);
|
||||||
|
for (i = 0; i < count && ctr >= 0; i++) {
|
||||||
|
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
|
||||||
|
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1) {
|
||||||
|
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
|
||||||
|
node->ctrlist[node->ctridx++].nr = ctr;
|
||||||
|
more++;
|
||||||
|
} else {
|
||||||
|
warnx("Cannot parse %s", ctrpath);
|
||||||
|
}
|
||||||
|
free(ctrpath);
|
||||||
|
}
|
||||||
|
util_scandir_free(namelist, count);
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
if (numsort && more > 1)
|
||||||
|
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void show_painode(void)
|
||||||
|
{
|
||||||
|
struct pai_node *node;
|
||||||
|
int indent = 0;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i)
|
||||||
|
indent = MAX((size_t)indent, strlen(node->ctrlist[i].name));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("RAW %*s NAME %*s DESCRIPTION\n", 3, "", indent - 5, "");
|
||||||
|
util_list_iterate(&pai_list, node) {
|
||||||
|
for (int i = 0; i < node->ctridx; ++i) {
|
||||||
|
printf("%d:%ld %s", node->pmu,
|
||||||
|
node->ctrlist[i].nr, node->ctrlist[i].name);
|
||||||
|
|
||||||
|
offset = indent - strlen(node->ctrlist[i].name) + 1;
|
||||||
|
printf("%*s", offset, "");
|
||||||
|
|
||||||
|
printf("Counter %ld / PAI %s counter set\n",
|
||||||
|
node->ctrlist[i].nr - node->base, node->name_uc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release all memory allocated at make_painode(). */
|
||||||
|
static void free_painode(void)
|
||||||
|
{
|
||||||
|
struct pai_node *next, *node;
|
||||||
|
|
||||||
|
util_list_iterate_safe(&pai_list, node, next) {
|
||||||
|
free(node->name_uc);
|
||||||
|
for (int i = 0; i < node->ctridx; ++i)
|
||||||
|
free(node->ctrlist[i].name);
|
||||||
|
free(node->ctrlist);
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_painode(enum pai_types t)
|
||||||
|
{
|
||||||
|
struct pai_node *node = util_zalloc(sizeof(*node));
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
node->type = t;
|
||||||
|
node->sysfs_name = pai_type_sysfs(t);
|
||||||
|
node->name = pai_type_name(t);
|
||||||
|
node->name_uc = str2uc(node->name);
|
||||||
|
node->filter_name = pai_type_filter(t);
|
||||||
|
node->base = pai_type_base(t);
|
||||||
|
|
||||||
|
/* Read PMU type number. */
|
||||||
|
path = util_path_sysfs(PAI_PATH, node->sysfs_name);
|
||||||
|
node->pmu = libcpumf_pmutype(path);
|
||||||
|
if (node->pmu < 0)
|
||||||
|
errx(EXIT_FAILURE, "Cannot open %s", path);
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
read_counternames(node);
|
||||||
|
|
||||||
|
util_list_add_tail(&pai_list, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int painode_cmp(void *a, void *b, void *UNUSED(data))
|
||||||
|
{
|
||||||
|
struct pai_node *n1 = (struct pai_node *)a;
|
||||||
|
struct pai_node *n2 = (struct pai_node *)b;
|
||||||
|
|
||||||
|
return n1->pmu < n2->pmu ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sort_painode(void)
|
||||||
|
{
|
||||||
|
util_list_sort(&pai_list, painode_cmp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for hardware support and return false if not available. */
|
||||||
|
static bool have_support(enum pai_types t)
|
||||||
|
{
|
||||||
|
const char *sysfn = pai_type_sysfs(t);
|
||||||
|
char *path = util_path_sysfs(PAI_PATH, sysfn);
|
||||||
|
bool rc = true;
|
||||||
|
|
||||||
|
if (!util_path_is_dir(path)) {
|
||||||
|
warnx("No support for PAI %s facility", pai_type_name(t));
|
||||||
|
rc = false;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the argument for option -t. It must be a valid PAI counter set.
|
||||||
|
* Exit when an invalid PAI counter set name has been specified.
|
||||||
|
*/
|
||||||
|
static void check_type_name(const char *type)
|
||||||
|
{
|
||||||
|
bool no_match = true;
|
||||||
|
enum pai_types i;
|
||||||
|
const char *fn;
|
||||||
|
|
||||||
|
for (i = pai_type_crypto; i < pai_type_max; ++i) {
|
||||||
|
fn = pai_type_name(i);
|
||||||
|
if (!strcasecmp(fn, type)) {
|
||||||
|
pai_types_show |= (1 << i);
|
||||||
|
no_match = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (no_match)
|
||||||
|
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
|
||||||
|
util_list_init(&pai_list, struct pai_node, node);
|
||||||
|
util_prg_init(&prg);
|
||||||
|
util_opt_init(opt_vec, NULL);
|
||||||
|
|
||||||
|
while ((ch = util_opt_getopt_long(argc, argv)) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
default:
|
||||||
|
util_opt_print_parse_error(ch, argv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
case 'h':
|
||||||
|
util_prg_print_help();
|
||||||
|
util_opt_print_help();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case 'v':
|
||||||
|
util_prg_print_version();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
case 'n':
|
||||||
|
numsort = true;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
check_type_name(optarg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing specified, show all PAI counters */
|
||||||
|
if (!pai_types_show)
|
||||||
|
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
|
||||||
|
|
||||||
|
/* Check for hardware support */
|
||||||
|
for (enum pai_types i = pai_type_crypto; i < pai_type_max; ++i) {
|
||||||
|
if ((pai_types_show & (1 << i))) {
|
||||||
|
if (!have_support(i))
|
||||||
|
pai_types_show &= ~(1 << i);
|
||||||
|
else
|
||||||
|
make_painode(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort_painode();
|
||||||
|
show_painode();
|
||||||
|
free_painode();
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
80
cpumf/man/lspai.8
Normal file
80
cpumf/man/lspai.8
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
.\" lspai.8
|
||||||
|
.\"
|
||||||
|
.\"
|
||||||
|
.\" Copyright IBM Corp. 2021
|
||||||
|
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
.\" ----------------------------------------------------------------------
|
||||||
|
.ds c \fBlspai\fP
|
||||||
|
.
|
||||||
|
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
|
||||||
|
.
|
||||||
|
.SH NAME
|
||||||
|
\*c \- list Processor Activity Instrumentation (PAI) counters
|
||||||
|
.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
\*c
|
||||||
|
.RB [ \-n ]
|
||||||
|
.RB [ \-t
|
||||||
|
.IR "\ TYPE" ]
|
||||||
|
.br
|
||||||
|
\*c
|
||||||
|
.BR \-h | \-\-help
|
||||||
|
.br
|
||||||
|
\*c
|
||||||
|
.BR \-v | \-\-version
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.SH DESCRIPTION
|
||||||
|
\*c displays the Processor Activity Instrumentation (PAI) counters
|
||||||
|
for Linux on IBM Z.
|
||||||
|
The output is a human-readable list of available PAI counter
|
||||||
|
names and numbers.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.BR \-h ", " \-\-help
|
||||||
|
Displays help information, then exits.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-v ", " \-\-version
|
||||||
|
Displays version information, then exits.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-t ", " \-\-type "\ TYPE"
|
||||||
|
Specifies the PAI counter set to list.
|
||||||
|
Valid counter set values are
|
||||||
|
.I crypto
|
||||||
|
and
|
||||||
|
.IR nnpa .
|
||||||
|
By default, the command lists all available PAI counter sets.
|
||||||
|
NNPA refers to the Neural Network Processing Assist facility counter set.
|
||||||
|
Crypto refers to the Cryptografic Processing Assist facility counter set.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-n ", " \-\-numeric
|
||||||
|
Shows the PAI counter sets sorted by counter number.
|
||||||
|
Default sort order is PAI counter name.
|
||||||
|
.
|
||||||
|
.SH "EXAMPLE"
|
||||||
|
The \*c invocation lists all PAI Neural Network Processing Assist Facility
|
||||||
|
(NNPA) counters in numeric order:
|
||||||
|
.nf
|
||||||
|
# lspai -t nnpa -n
|
||||||
|
RAW NAME DESCRIPTION
|
||||||
|
13:6144 NNPA_ALL Counter 0 / PAI NNPA counter set
|
||||||
|
13:6145 NNPA_ADD Counter 1 / PAI NNPA counter set
|
||||||
|
13:6146 NNPA_SUB Counter 2 / PAI NNPA counter set
|
||||||
|
13:6147 NNPA_MUL Counter 3 / PAI NNPA counter set
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
The first column shows the raw event number suitable for
|
||||||
|
.IR perf "(8)"
|
||||||
|
raw event specification.
|
||||||
|
The second column shows the PAI NNPA counter name,
|
||||||
|
suitable for
|
||||||
|
.IR perf "(8)"
|
||||||
|
event specification by name.
|
||||||
|
The third gives a short explanation, if available.
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.BR pai (8)
|
||||||
|
.BR lscpumf (8)
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
.IR size ]
|
.IR size ]
|
||||||
.RB [ \-i | \-\-interval
|
.RB [ \-i | \-\-interval
|
||||||
.IR ms ]
|
.IR ms ]
|
||||||
|
.RB [ \-R | \-\-realtime
|
||||||
|
.IR prio ]
|
||||||
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
@@ -25,6 +27,8 @@
|
|||||||
.IR size ]
|
.IR size ]
|
||||||
.RB [ \-i | \-\-interval
|
.RB [ \-i | \-\-interval
|
||||||
.IR ms ]
|
.IR ms ]
|
||||||
|
.RB [ \-R | \-\-realtime
|
||||||
|
.IR prio ]
|
||||||
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
|
||||||
.br
|
.br
|
||||||
\*c
|
\*c
|
||||||
@@ -191,6 +195,14 @@ The ring buffer is created with the
|
|||||||
.IR mmap (2)
|
.IR mmap (2)
|
||||||
system call.
|
system call.
|
||||||
.
|
.
|
||||||
|
.TP
|
||||||
|
.BR \-R ", " \-\-realtime "\ prio"
|
||||||
|
Collect data using the RT SCHED_FIFO priority specified by
|
||||||
|
.BR prio .
|
||||||
|
Valid values are integers in the range 1 (low) to 99 (high).
|
||||||
|
Use this option when gathering data from multiple CPUs
|
||||||
|
to prevent data loss.
|
||||||
|
.
|
||||||
.SH ARGUMENT
|
.SH ARGUMENT
|
||||||
The command line options determine how command line
|
The command line options determine how command line
|
||||||
arguments are interpreted.
|
arguments are interpreted.
|
||||||
|
|||||||
39
cpumf/pai.c
39
cpumf/pai.c
@@ -320,7 +320,7 @@ static void readmap(int fd)
|
|||||||
* ring buffer per event, sleep some short time and always read all
|
* ring buffer per event, sleep some short time and always read all
|
||||||
* ring buffer for new contents.
|
* ring buffer for new contents.
|
||||||
*/
|
*/
|
||||||
static void collect(unsigned long cnt)
|
static int collect(unsigned long cnt)
|
||||||
{
|
{
|
||||||
fd_set r_fds, e_fds, a_fds;
|
fd_set r_fds, e_fds, a_fds;
|
||||||
struct pai_event *p;
|
struct pai_event *p;
|
||||||
@@ -328,6 +328,7 @@ static void collect(unsigned long cnt)
|
|||||||
int rc, max_fd;
|
int rc, max_fd;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
rc = -1;
|
||||||
max_fd = -1;
|
max_fd = -1;
|
||||||
tv.tv_sec = read_interval / 1000;
|
tv.tv_sec = read_interval / 1000;
|
||||||
tv.tv_usec = (1000 * read_interval) % 1000000;
|
tv.tv_usec = (1000 * read_interval) % 1000000;
|
||||||
@@ -357,6 +358,7 @@ static void collect(unsigned long cnt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (rc != -1 && --cnt > 0);
|
} while (rc != -1 && --cnt > 0);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lookup_event(__u64 evtnum, __u16 ctr, __u64 value)
|
static void lookup_event(__u64 evtnum, __u16 ctr, __u64 value)
|
||||||
@@ -449,6 +451,11 @@ static void evt_show(__u64 evtnum, const char *evtsel, struct pai_event_out *ev)
|
|||||||
ev->u.s_comm.tid);
|
ev->u.s_comm.tid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PERF_RECORD_SWITCH:
|
||||||
|
printf("cs-%s",
|
||||||
|
(ev->misc & PERF_RECORD_MISC_SWITCH_OUT) ? "out" : "in");
|
||||||
|
break;
|
||||||
|
|
||||||
case PERF_RECORD_SWITCH_CPU_WIDE:
|
case PERF_RECORD_SWITCH_CPU_WIDE:
|
||||||
if (ev->misc & PERF_RECORD_MISC_SWITCH_OUT) {
|
if (ev->misc & PERF_RECORD_MISC_SWITCH_OUT) {
|
||||||
short p = PERF_RECORD_MISC_SWITCH_OUT_PREEMPT;
|
short p = PERF_RECORD_MISC_SWITCH_OUT_PREEMPT;
|
||||||
@@ -549,6 +556,9 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
|||||||
offset -= sizeof(__u64);
|
offset -= sizeof(__u64);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PERF_RECORD_SWITCH:
|
||||||
|
break;
|
||||||
|
|
||||||
case PERF_RECORD_SWITCH_CPU_WIDE:
|
case PERF_RECORD_SWITCH_CPU_WIDE:
|
||||||
memcpy(&ev.u, buf + offset, sizeof(ev.u.s_cs));
|
memcpy(&ev.u, buf + offset, sizeof(ev.u.s_cs));
|
||||||
offset += sizeof(ev.u.s_cs);
|
offset += sizeof(ev.u.s_cs);
|
||||||
@@ -583,7 +593,7 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("unknown header-type %d ", hdr->type);
|
printf("unknown header-type %d\n", hdr->type);
|
||||||
offset += hdr->size - sizeof(*hdr);
|
offset += hdr->size - sizeof(*hdr);
|
||||||
goto bypass;
|
goto bypass;
|
||||||
}
|
}
|
||||||
@@ -944,6 +954,11 @@ static struct util_opt opt_vec[] = {
|
|||||||
.option = { "report", no_argument, NULL, 'r' },
|
.option = { "report", no_argument, NULL, 'r' },
|
||||||
.desc = "Report file contents"
|
.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' },
|
.option = { "interval", required_argument, NULL, 'i' },
|
||||||
.argument = "NUMBER",
|
.argument = "NUMBER",
|
||||||
@@ -1007,6 +1022,19 @@ static unsigned long check_mapsize(unsigned long n)
|
|||||||
return cnt == 1 ? n : 0;
|
return cnt == 1 ? n : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setprio(const char *prio)
|
||||||
|
{
|
||||||
|
struct sched_param param;
|
||||||
|
char *endstr;
|
||||||
|
|
||||||
|
memset(¶m, 0, sizeof(param));
|
||||||
|
param.sched_priority = strtoul(prio, &endstr, 0);
|
||||||
|
if (*endstr)
|
||||||
|
errno = EINVAL;
|
||||||
|
if (*endstr || sched_setscheduler(0, SCHED_FIFO, ¶m))
|
||||||
|
err(EXIT_FAILURE, "Could not set realtime priority");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
bool crypto_record = false, report = false;
|
bool crypto_record = false, report = false;
|
||||||
@@ -1061,6 +1089,9 @@ int main(int argc, char **argv)
|
|||||||
record_cpus_nnpa(optarg);
|
record_cpus_nnpa(optarg);
|
||||||
nnpa_record = true;
|
nnpa_record = true;
|
||||||
break;
|
break;
|
||||||
|
case 'R':
|
||||||
|
setprio(optarg);
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
report = true;
|
report = true;
|
||||||
break;
|
break;
|
||||||
@@ -1094,12 +1125,12 @@ int main(int argc, char **argv)
|
|||||||
ev_install(group);
|
ev_install(group);
|
||||||
ev_enable();
|
ev_enable();
|
||||||
|
|
||||||
collect(loop_count);
|
ch = collect(loop_count);
|
||||||
|
|
||||||
ev_disable();
|
ev_disable();
|
||||||
ev_deinstall();
|
ev_deinstall();
|
||||||
ev_dealloc();
|
ev_dealloc();
|
||||||
return EXIT_SUCCESS;
|
return ch < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be reporting */
|
/* Must be reporting */
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ all: cpuplugd
|
|||||||
|
|
||||||
LDLIBS += -lm
|
LDLIBS += -lm
|
||||||
|
|
||||||
|
libs = $(rootdir)/libutil/libutil.a
|
||||||
|
|
||||||
OBJECTS = daemon.o cpu.o info.o terms.o config.o main.o getopt.o mem.o
|
OBJECTS = daemon.o cpu.o info.o terms.o config.o main.o getopt.o mem.o
|
||||||
|
|
||||||
cpuplugd: $(OBJECTS)
|
cpuplugd: $(OBJECTS) $(libs)
|
||||||
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -204,6 +204,45 @@ void parse_configfile(char *file)
|
|||||||
fclose(filp);
|
fclose(filp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apply_cpu_config(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Check that the initial number of cpus is not below the
|
||||||
|
* minimum
|
||||||
|
*/
|
||||||
|
if (num_cpu_start < cfg.cpu_min &&
|
||||||
|
get_numcpus() >= cfg.cpu_min) {
|
||||||
|
cpuplugd_debug("The number of online cpus is below ");
|
||||||
|
cpuplugd_debug("the minimum and will be increased.\n");
|
||||||
|
while (get_num_online_cpus() < cfg.cpu_min) {
|
||||||
|
if (hotplug_one_cpu())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (get_num_online_cpus() > cfg.cpu_max) {
|
||||||
|
cpuplugd_debug("The number of online cpus is above the maximum");
|
||||||
|
cpuplugd_debug(" and will be decreased.\n");
|
||||||
|
while (get_num_online_cpus() > cfg.cpu_max) {
|
||||||
|
if (hotunplug_one_cpu())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cfg.cpu_min > get_numcpus()) {
|
||||||
|
/*
|
||||||
|
* This check only works if nobody used the
|
||||||
|
* additional_cpus in the boot parameter section
|
||||||
|
*/
|
||||||
|
cpuplugd_debug("The minimum amount of cpus is above the ");
|
||||||
|
cpuplugd_debug("number of available cpus.\n");
|
||||||
|
cpuplugd_exit("Detected %d available cpus\n", get_numcpus());
|
||||||
|
}
|
||||||
|
if (get_num_online_cpus() < cfg.cpu_min) {
|
||||||
|
cpuplugd_debug("Failed to set the number of online cpus to ");
|
||||||
|
cpuplugd_debug("the minimum. ");
|
||||||
|
cpuplugd_exit("Aborting.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the required settings are found in the configuration file.
|
* Check if the required settings are found in the configuration file.
|
||||||
* "Autodetect" if cpu and/or memory hotplug configuration entries
|
* "Autodetect" if cpu and/or memory hotplug configuration entries
|
||||||
@@ -211,7 +250,6 @@ void parse_configfile(char *file)
|
|||||||
*/
|
*/
|
||||||
void check_config()
|
void check_config()
|
||||||
{
|
{
|
||||||
int cpuid;
|
|
||||||
int lpar_status;
|
int lpar_status;
|
||||||
|
|
||||||
lpar_status = check_lpar();
|
lpar_status = check_lpar();
|
||||||
@@ -262,60 +300,23 @@ void check_config()
|
|||||||
/*
|
/*
|
||||||
* Save the number of online cpus and the cmm_pagesize at startup,
|
* Save the number of online cpus and the cmm_pagesize at startup,
|
||||||
* so that we can enable exactly the same amount when the daemon ends
|
* so that we can enable exactly the same amount when the daemon ends
|
||||||
|
*
|
||||||
|
* Don't adjust cpus if system is on vertical polarization
|
||||||
*/
|
*/
|
||||||
if (cpu) {
|
saved_polarization = get_polarization();
|
||||||
num_cpu_start = get_num_online_cpus();
|
num_cpu_start = get_num_online_cpus();
|
||||||
cpuplugd_debug("Daemon started with %d active cpus.\n",
|
cpuplugd_debug("Daemon started with %d active cpus.\n",
|
||||||
num_cpu_start);
|
num_cpu_start);
|
||||||
/*
|
if (saved_polarization < 0) {
|
||||||
* Check that the initial number of cpus is not below the
|
cpuplugd_debug("Daemon couldn't determine system polarization\n");
|
||||||
* minimum
|
cpuplugd_debug("Starting without evaluating cpu rules\n");
|
||||||
*/
|
} else if (saved_polarization == PLR_VERTICAL) {
|
||||||
if (num_cpu_start < cfg.cpu_min &&
|
cpuplugd_debug("Daemon started with vertical polarization.\n");
|
||||||
get_numcpus() >= cfg.cpu_min) {
|
cpuplugd_debug("Cpu adjustments won't be made until system ");
|
||||||
cpuplugd_debug("The number of online cpus is below "
|
cpuplugd_debug("is in horizontal polarization\n");
|
||||||
"the minimum and will be increased.\n");
|
} else if (saved_polarization == PLR_HORIZONTAL &&
|
||||||
cpuid = 0;
|
cpu == 1) {
|
||||||
while (get_num_online_cpus() < cfg.cpu_min &&
|
apply_cpu_config();
|
||||||
cpuid < get_numcpus()) {
|
|
||||||
if (is_online(cpuid) == 1) {
|
|
||||||
cpuid++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cpuplugd_debug("cpu with id %d is currently offline "
|
|
||||||
"and will be enabled\n", cpuid);
|
|
||||||
hotplug(cpuid);
|
|
||||||
cpuid++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (get_num_online_cpus() > cfg.cpu_max) {
|
|
||||||
cpuplugd_debug("The number of online cpus is above the maximum"
|
|
||||||
" and will be decreased.\n");
|
|
||||||
cpuid = 0;
|
|
||||||
while (get_num_online_cpus() > cfg.cpu_max &&
|
|
||||||
cpuid < get_numcpus()) {
|
|
||||||
if (is_online(cpuid) != 1) {
|
|
||||||
cpuid++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cpuplugd_debug("cpu with id %d is currently online "
|
|
||||||
"and will be disabled\n", cpuid);
|
|
||||||
hotunplug(cpuid);
|
|
||||||
cpuid++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cfg.cpu_min > get_numcpus())
|
|
||||||
/*
|
|
||||||
* This check only works if nobody used the
|
|
||||||
* additional_cpus in the boot parameter section
|
|
||||||
*/
|
|
||||||
cpuplugd_exit("The minimum amount of cpus is above "
|
|
||||||
"the number of available cpus.\n"
|
|
||||||
"Detected %d available cpus\n",
|
|
||||||
get_numcpus());
|
|
||||||
if (get_num_online_cpus() < cfg.cpu_min)
|
|
||||||
cpuplugd_exit("Failed to set the number of online "
|
|
||||||
"cpus to the minimum. Aborting.\n");
|
|
||||||
}
|
}
|
||||||
if (memory == 1) {
|
if (memory == 1) {
|
||||||
/*
|
/*
|
||||||
|
|||||||
361
cpuplugd/cpu.c
361
cpuplugd/cpu.c
@@ -12,216 +12,241 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include "cpuplugd.h"
|
#include "cpuplugd.h"
|
||||||
|
|
||||||
|
#define NUM_BASE (10)
|
||||||
|
#define CPU_OFFLINE (0)
|
||||||
|
#define CPU_ONLINE (1)
|
||||||
|
#define CPU_DECONFIGURED (0)
|
||||||
|
#define CPU_CONFIGURED (1)
|
||||||
|
#define CPU_LIST_LEN (4096)
|
||||||
|
|
||||||
/*
|
static int get_sysfs_attribute_cpu_count(char *path)
|
||||||
* Return overall number of available cpus. This does not necessarily
|
|
||||||
* mean that those are currently online
|
|
||||||
*/
|
|
||||||
int get_numcpus()
|
|
||||||
{
|
{
|
||||||
int i;
|
char cpu_list[CPU_LIST_LEN];
|
||||||
char path[PATH_MAX];
|
int number, start, end;
|
||||||
int number = 0;
|
char *sub_list;
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
if (util_file_read_line(cpu_list, sizeof(cpu_list), path))
|
||||||
/* check whether file exists and is readable */
|
cpuplugd_exit("Cannot open %s file: %s\n", path, strerror(errno));
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", i);
|
number = 0;
|
||||||
if (access(path, R_OK) == 0)
|
sub_list = strtok(cpu_list, ",");
|
||||||
|
while (sub_list) {
|
||||||
|
if (strchr(sub_list, '-')) {
|
||||||
|
if (sscanf(sub_list, "%d-%d", &start, &end) != 2)
|
||||||
|
cpuplugd_exit("Malformed content of %s: %s\n", path, sub_list);
|
||||||
|
number += (end - start) + 1;
|
||||||
|
} else {
|
||||||
number++;
|
number++;
|
||||||
else
|
}
|
||||||
break;
|
sub_list = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return number of online cpus
|
* get_numcpus() - return number of present cpus by sysfs'
|
||||||
|
* cpu/present attribute.
|
||||||
|
* This number represents the total number of usable cpus,
|
||||||
|
* this includes offline or deconfigured cpus as well.
|
||||||
*/
|
*/
|
||||||
int get_num_online_cpus()
|
int get_numcpus(void)
|
||||||
{
|
{
|
||||||
FILE *filp;
|
int number;
|
||||||
int i;
|
char *path;
|
||||||
char path[PATH_MAX];
|
|
||||||
int status = 0;
|
|
||||||
int value_of_onlinefile, rc;
|
|
||||||
|
|
||||||
for (i = 0; i <= get_numcpus(); i++) {
|
path = util_path_sysfs("devices/system/cpu/present");
|
||||||
/* check wether file exists and is readable */
|
number = get_sysfs_attribute_cpu_count(path);
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", i);
|
free(path);
|
||||||
if (access(path, R_OK) != 0)
|
if (number <= 0)
|
||||||
continue;
|
cpuplugd_exit("number of present cpus (%d) <= 0\n", number);
|
||||||
filp = fopen(path, "r");
|
return number;
|
||||||
if (!filp)
|
}
|
||||||
cpuplugd_exit("Cannot open cpu online file: "
|
|
||||||
"%s\n", strerror(errno));
|
/*
|
||||||
else {
|
* get_num_online_cpus() - return number of online cpus
|
||||||
rc = fscanf(filp, "%d", &value_of_onlinefile);
|
* by parsing sysfs cpu/online attribute
|
||||||
if (rc != 1)
|
*/
|
||||||
cpuplugd_exit("Cannot read cpu online file: "
|
int get_num_online_cpus(void)
|
||||||
"%s\n", strerror(errno));
|
{
|
||||||
if (value_of_onlinefile == 1)
|
int number;
|
||||||
status++;
|
char *path;
|
||||||
}
|
|
||||||
fclose(filp);
|
path = util_path_sysfs("devices/system/cpu/online");
|
||||||
|
number = get_sysfs_attribute_cpu_count(path);
|
||||||
|
free(path);
|
||||||
|
if (number <= 0)
|
||||||
|
cpuplugd_exit("number of online cpus (%d) <= 0\n", number);
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_polarization() - return system polarization
|
||||||
|
*/
|
||||||
|
int get_polarization(void)
|
||||||
|
{
|
||||||
|
int polarization;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
path = util_path_sysfs("devices/system/cpu/dispatching");
|
||||||
|
if (util_file_read_i(&polarization, NUM_BASE, path) < 0) {
|
||||||
|
polarization = -1;
|
||||||
|
cpuplugd_debug("failed to read system polarization\n");
|
||||||
}
|
}
|
||||||
|
free(path);
|
||||||
|
return polarization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_cpu_hotpluggable() - check if cpuhotplug operations are supported
|
||||||
|
* for the given cpu.
|
||||||
|
*/
|
||||||
|
static int is_cpu_hotpluggable(int cpuid)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
path = util_path_sysfs("devices/system/cpu/cpu%d/online", cpuid);
|
||||||
|
rc = util_path_exists(path);
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hotplug() - perform cpu hotplug on given cpuid
|
||||||
|
*/
|
||||||
|
static int hotplug(int cpuid)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
path = util_path_sysfs("devices/system/cpu/cpu%d/online", cpuid);
|
||||||
|
rc = util_file_write_l(CPU_ONLINE, NUM_BASE, path);
|
||||||
|
if (rc < 0)
|
||||||
|
cpuplugd_debug("failed to enable cpu with id %d\n", cpuid);
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hotunplug() - perform cpu hotunplug on given cpuid
|
||||||
|
*/
|
||||||
|
static int hotunplug(int cpuid)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
path = util_path_sysfs("devices/system/cpu/cpu%d/online", cpuid);
|
||||||
|
rc = util_file_write_l(CPU_OFFLINE, NUM_BASE, path);
|
||||||
|
if (rc < 0)
|
||||||
|
cpuplugd_debug("failed to disable cpu with id %d\n", cpuid);
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_cpu_attribute() - get a certain cpu's selected attribute
|
||||||
|
*/
|
||||||
|
static int get_cpu_attribute(int cpuid, char *attribute)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
path = util_path_sysfs("devices/system/cpu/cpu%d/%s", cpuid, attribute);
|
||||||
|
if (util_file_read_i(&status, NUM_BASE, path) < 0) {
|
||||||
|
status = -1;
|
||||||
|
cpuplugd_debug("failed to read %s status of cpu with id %d\n", attribute, cpuid);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable a certain cpu
|
* hotplug_one_cpu() - perform hotplugging on the first available cpu
|
||||||
*/
|
*/
|
||||||
int hotplug(int cpuid)
|
int hotplug_one_cpu(void)
|
||||||
{
|
{
|
||||||
FILE *filp;
|
struct dirent **cpu_dir;
|
||||||
char path[PATH_MAX];
|
int cpuid, count, i, rc;
|
||||||
int status, rc;
|
char *path;
|
||||||
|
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", cpuid);
|
rc = -1;
|
||||||
if (access(path, W_OK) == 0) {
|
path = util_path_sysfs("devices/system/cpu/");
|
||||||
filp = fopen(path, "w");
|
count = util_scandir(&cpu_dir, alphasort, path, "cpu[0-9]*");
|
||||||
if (!filp)
|
for (i = 0; (i < count) && (rc != 0); i++) {
|
||||||
cpuplugd_exit("Cannot open cpu online file: %s\n",
|
if (sscanf(cpu_dir[i]->d_name, "cpu%d", &cpuid) != 1)
|
||||||
strerror(errno));
|
cpuplugd_exit("Malformed content of %s: %s\n", path, cpu_dir[i]->d_name);
|
||||||
fprintf(filp, "1");
|
if (!is_cpu_hotpluggable(cpuid))
|
||||||
fclose(filp);
|
continue;
|
||||||
/*
|
if (get_cpu_attribute(cpuid, "configure") == CPU_CONFIGURED &&
|
||||||
* check if the attempt to enable the cpus really worked
|
get_cpu_attribute(cpuid, "online") == CPU_OFFLINE) {
|
||||||
*/
|
cpuplugd_debug("cpu%d will be enabled", cpuid);
|
||||||
filp = fopen(path, "r");
|
rc = hotplug(cpuid);
|
||||||
rc = fscanf(filp, "%d", &status);
|
|
||||||
if (rc != 1)
|
|
||||||
cpuplugd_exit("Cannot open cpu online file: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
fclose(filp);
|
|
||||||
if (status == 1) {
|
|
||||||
cpuplugd_debug("cpu with id %d enabled\n", cpuid);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
cpuplugd_debug("failed to enable cpu with id %d\n",
|
|
||||||
cpuid);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cpuplugd_error("hotplugging cpu with id %d failed\n", cpuid);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
return -1;
|
util_scandir_free(cpu_dir, count);
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable a certain cpu
|
* hotunplug_one_cpu() - perform hotunplugging on the first available cpu
|
||||||
*/
|
*/
|
||||||
int hotunplug(int cpuid)
|
int hotunplug_one_cpu(void)
|
||||||
{
|
{
|
||||||
FILE *filp;
|
struct dirent **cpu_dir;
|
||||||
int state, rc;
|
int cpuid, count, i, rc;
|
||||||
int retval = -1;
|
char *path;
|
||||||
char path[PATH_MAX];
|
|
||||||
|
|
||||||
state = -1;
|
rc = -1;
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", cpuid);
|
path = util_path_sysfs("devices/system/cpu/");
|
||||||
if (access(path, W_OK) == 0) {
|
count = util_scandir(&cpu_dir, alphasort, path, "cpu[0-9]*");
|
||||||
filp = fopen(path, "w");
|
for (i = 0; (i < count) && (rc != 0); i++) {
|
||||||
fprintf(filp, "0");
|
if (sscanf(cpu_dir[i]->d_name, "cpu%d", &cpuid) != 1)
|
||||||
fclose(filp);
|
cpuplugd_exit("Malformed content of %s: %s\n", path, cpu_dir[i]->d_name);
|
||||||
/*
|
if (!is_cpu_hotpluggable(cpuid))
|
||||||
* Check if the attempt to enable the cpus really worked
|
continue;
|
||||||
*/
|
if (get_cpu_attribute(cpuid, "online") == CPU_ONLINE) {
|
||||||
filp = fopen(path, "r");
|
cpuplugd_debug("cpu%d will be disabled\n", cpuid);
|
||||||
rc = fscanf(filp, "%d", &state);
|
rc = hotunplug(cpuid);
|
||||||
if (rc != 1)
|
|
||||||
cpuplugd_error("Failed to disable cpu with id %d\n",
|
|
||||||
cpuid);
|
|
||||||
fclose(filp);
|
|
||||||
if (state == 0)
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
cpuplugd_error("unplugging cpu with id %d failed\n", cpuid);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if a certain cpu is currently online
|
|
||||||
*/
|
|
||||||
int is_online(int cpuid)
|
|
||||||
{
|
|
||||||
FILE *filp;
|
|
||||||
int state;
|
|
||||||
int retval, rc;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
|
|
||||||
retval = -1;
|
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", cpuid);
|
|
||||||
if (access(path, R_OK) == 0) {
|
|
||||||
filp = fopen(path, "r");
|
|
||||||
rc = fscanf(filp, "%d", &state);
|
|
||||||
if (rc == 1) {
|
|
||||||
if (state == 1)
|
|
||||||
retval = 1;
|
|
||||||
if (state == 0)
|
|
||||||
retval = 0;
|
|
||||||
}
|
}
|
||||||
fclose(filp);
|
|
||||||
}
|
}
|
||||||
return retval;
|
util_scandir_free(cpu_dir, count);
|
||||||
|
free(path);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cleanup method. If the daemon is stopped, we (re)activate all cpus
|
* Cleanup method. If the daemon is stopped, we (re)activate all cpus
|
||||||
*/
|
*/
|
||||||
void reactivate_cpus()
|
void reactivate_cpus(void)
|
||||||
{
|
{
|
||||||
/*
|
struct dirent **cpu_dir;
|
||||||
* Only enable the number of cpus which where
|
int cpuid, nc, count, i;
|
||||||
* available at daemon startup time
|
char *path;
|
||||||
*/
|
|
||||||
int cpuid, nc;
|
|
||||||
|
|
||||||
cpuid = 0;
|
/*
|
||||||
/* suppress verbose messages on exit */
|
* Only enable the number of cpus which where available at
|
||||||
debug = 0;
|
* daemon startup time by checking num_cpu_start.
|
||||||
/*
|
* We check for num_cpu_start != 0 because we might want to
|
||||||
* We check for num_cpu_start != 0 because we might want to
|
* clean up, before we queried for the number on cpus at
|
||||||
* clean up, before we queried for the number on cpus at
|
* startup
|
||||||
* startup
|
*/
|
||||||
*/
|
|
||||||
if (num_cpu_start == 0)
|
if (num_cpu_start == 0)
|
||||||
return;
|
return;
|
||||||
while (get_num_online_cpus() != num_cpu_start && cpuid < get_numcpus()) {
|
nc = 0;
|
||||||
|
path = util_path_sysfs("devices/system/cpu/");
|
||||||
|
count = util_scandir(&cpu_dir, alphasort, path, "cpu[0-9]*");
|
||||||
|
for (i = 0; (i < count) && (nc != num_cpu_start); i++) {
|
||||||
nc = get_num_online_cpus();
|
nc = get_num_online_cpus();
|
||||||
if (nc == num_cpu_start)
|
if (sscanf(cpu_dir[i]->d_name, "cpu%d", &cpuid) != 1)
|
||||||
return;
|
cpuplugd_exit("Malformed content of %s: %s\n", path, cpu_dir[i]->d_name);
|
||||||
if (nc > num_cpu_start && is_online(cpuid) == 1)
|
if (nc > num_cpu_start &&
|
||||||
|
get_cpu_attribute(cpuid, "online") == CPU_ONLINE)
|
||||||
hotunplug(cpuid);
|
hotunplug(cpuid);
|
||||||
if (nc < num_cpu_start && is_online(cpuid) == 0)
|
if (nc < num_cpu_start &&
|
||||||
|
get_cpu_attribute(cpuid, "online") == CPU_OFFLINE)
|
||||||
hotplug(cpuid);
|
hotplug(cpuid);
|
||||||
cpuid++;
|
|
||||||
}
|
}
|
||||||
|
util_scandir_free(cpu_dir, count);
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* In kernels > 2.6.24 cpus can be deconfigured. The following functions is used
|
|
||||||
* to check if a certain cpus is in a deconfigured state.
|
|
||||||
*/
|
|
||||||
int cpu_is_configured(int cpuid)
|
|
||||||
{
|
|
||||||
FILE *filp;
|
|
||||||
int retval, state, rc;
|
|
||||||
char path[4096];
|
|
||||||
|
|
||||||
retval = -1;
|
|
||||||
sprintf(path, "/sys/devices/system/cpu/cpu%d/configure", cpuid);
|
|
||||||
if (access(path, R_OK) == 0) {
|
|
||||||
filp = fopen(path, "r");
|
|
||||||
rc = fscanf(filp, "%d", &state);
|
|
||||||
if (rc == 1) {
|
|
||||||
if (state == 1)
|
|
||||||
retval = 1;
|
|
||||||
if (state == 0)
|
|
||||||
retval = 0;
|
|
||||||
}
|
|
||||||
fclose(filp);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,6 +23,9 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lib/util_base.h"
|
#include "lib/util_base.h"
|
||||||
|
#include "lib/util_path.h"
|
||||||
|
#include "lib/util_file.h"
|
||||||
|
#include "lib/util_scandir.h"
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
#define NAME "cpuplugd"
|
#define NAME "cpuplugd"
|
||||||
@@ -35,6 +38,8 @@
|
|||||||
#define MAX_VARNAME 128
|
#define MAX_VARNAME 128
|
||||||
#define MAX_LINESIZE 2048
|
#define MAX_LINESIZE 2048
|
||||||
#define CPUSTATS 10
|
#define CPUSTATS 10
|
||||||
|
#define PLR_HORIZONTAL 0
|
||||||
|
#define PLR_VERTICAL 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Precedence of C operators
|
* Precedence of C operators
|
||||||
@@ -173,9 +178,11 @@ extern unsigned int history_max;
|
|||||||
extern unsigned int history_current;
|
extern unsigned int history_current;
|
||||||
extern struct symbol_names sym_names[];
|
extern struct symbol_names sym_names[];
|
||||||
extern unsigned int sym_names_count;
|
extern unsigned int sym_names_count;
|
||||||
|
extern int saved_polarization;
|
||||||
|
|
||||||
int get_numcpus();
|
int get_numcpus();
|
||||||
int get_num_online_cpus();
|
int get_num_online_cpus();
|
||||||
|
int get_polarization(void);
|
||||||
void get_loadavg_runnable(double *loadavg, double *runnable);
|
void get_loadavg_runnable(double *loadavg, double *runnable);
|
||||||
void clean_up();
|
void clean_up();
|
||||||
void reactivate_cpus();
|
void reactivate_cpus();
|
||||||
@@ -190,9 +197,8 @@ void proc_cpu_read(char *procinfo);
|
|||||||
unsigned long proc_read_size(char *path);
|
unsigned long proc_read_size(char *path);
|
||||||
char *get_var_rvalue(char *var_name);
|
char *get_var_rvalue(char *var_name);
|
||||||
void cleanup_cmm(void);
|
void cleanup_cmm(void);
|
||||||
int hotplug(int cpuid);
|
int hotplug_one_cpu(void);
|
||||||
int hotunplug(int cpuid);
|
int hotunplug_one_cpu(void);
|
||||||
int is_online(int cpuid);
|
|
||||||
long get_cmmpages_size();
|
long get_cmmpages_size();
|
||||||
void parse_options(int argc, char **argv);
|
void parse_options(int argc, char **argv);
|
||||||
void check_if_started_twice();
|
void check_if_started_twice();
|
||||||
@@ -202,9 +208,9 @@ void reload_daemon(void);
|
|||||||
int daemonize(void);
|
int daemonize(void);
|
||||||
int check_cmmfiles(void);
|
int check_cmmfiles(void);
|
||||||
void check_config();
|
void check_config();
|
||||||
|
void apply_cpu_config(void);
|
||||||
void set_cmm_pages(long size);
|
void set_cmm_pages(long size);
|
||||||
int check_lpar();
|
int check_lpar();
|
||||||
int cpu_is_configured(int cpuid);
|
|
||||||
void setup_history(void);
|
void setup_history(void);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ void clean_up()
|
|||||||
cpuplugd_info("terminated\n");
|
cpuplugd_info("terminated\n");
|
||||||
remove(pid_file);
|
remove(pid_file);
|
||||||
remove(LOCKFILE);
|
remove(LOCKFILE);
|
||||||
|
/* suppress verbose messages on exit */
|
||||||
|
debug = 0;
|
||||||
reactivate_cpus();
|
reactivate_cpus();
|
||||||
if (memory)
|
if (memory)
|
||||||
cleanup_cmm();
|
cleanup_cmm();
|
||||||
@@ -163,6 +165,8 @@ void kill_daemon(int UNUSED(a))
|
|||||||
cpuplugd_info("shutting down\n");
|
cpuplugd_info("shutting down\n");
|
||||||
remove(pid_file);
|
remove(pid_file);
|
||||||
remove(LOCKFILE);
|
remove(LOCKFILE);
|
||||||
|
/* suppress verbose messages on exit */
|
||||||
|
debug = 0;
|
||||||
reactivate_cpus();
|
reactivate_cpus();
|
||||||
if (memory)
|
if (memory)
|
||||||
cleanup_cmm();
|
cleanup_cmm();
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ struct config cfg = {
|
|||||||
.hotunplug = NULL,
|
.hotunplug = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
int num_cpu_start, memory, cpu, reload_pending;
|
|
||||||
long cmm_pagesize_start;
|
|
||||||
unsigned long meminfo_size, vmstat_size, cpustat_size, varinfo_size;
|
|
||||||
char *meminfo, *vmstat, *cpustat, *varinfo;
|
|
||||||
double *timestamps;
|
|
||||||
unsigned int history_max, history_current, history_prev, sym_names_count;
|
unsigned int history_max, history_current, history_prev, sym_names_count;
|
||||||
|
unsigned long meminfo_size, vmstat_size, cpustat_size, varinfo_size;
|
||||||
|
int num_cpu_start, memory, cpu, reload_pending, saved_polarization;
|
||||||
|
char *meminfo, *vmstat, *cpustat, *varinfo;
|
||||||
|
long cmm_pagesize_start;
|
||||||
|
double *timestamps;
|
||||||
|
|
||||||
static struct symbols symbols;
|
static struct symbols symbols;
|
||||||
static jmp_buf jmpenv;
|
static jmp_buf jmpenv;
|
||||||
@@ -77,8 +77,29 @@ static void eval_cpu_rules(void)
|
|||||||
{
|
{
|
||||||
double diffs[CPUSTATS], diffs_total, percent_factor;
|
double diffs[CPUSTATS], diffs_total, percent_factor;
|
||||||
char *procinfo_current, *procinfo_prev;
|
char *procinfo_current, *procinfo_prev;
|
||||||
int cpu, nr_cpus, on_off;
|
int nr_cpus, on_off, polarization;
|
||||||
|
|
||||||
|
polarization = get_polarization();
|
||||||
|
if (polarization < 0) {
|
||||||
|
cpuplugd_debug("couldn't determine system polarization\n");
|
||||||
|
cpuplugd_debug("skipping cpu rule evaluation\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (saved_polarization != polarization) {
|
||||||
|
saved_polarization = polarization;
|
||||||
|
if (polarization == PLR_VERTICAL) {
|
||||||
|
/* revert cpu hotplug adjustments after switching from horizontal */
|
||||||
|
reactivate_cpus();
|
||||||
|
} else if (polarization == PLR_HORIZONTAL) {
|
||||||
|
/* reapply cpu config after switching from vertical */
|
||||||
|
apply_cpu_config();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (polarization == PLR_VERTICAL) {
|
||||||
|
cpuplugd_debug("system is running vertical polarization\n");
|
||||||
|
cpuplugd_debug("cpuplugd won't make cpu adjustments\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
nr_cpus = get_numcpus();
|
nr_cpus = get_numcpus();
|
||||||
procinfo_current = cpustat + history_current * cpustat_size;
|
procinfo_current = cpustat + history_current * cpustat_size;
|
||||||
procinfo_prev = cpustat + history_prev * cpustat_size;
|
procinfo_prev = cpustat + history_prev * cpustat_size;
|
||||||
@@ -157,7 +178,6 @@ static void eval_cpu_rules(void)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
printf("---------------------------------------------\n");
|
printf("---------------------------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
on_off = 0;
|
on_off = 0;
|
||||||
/* Evaluate the hotplug rule */
|
/* Evaluate the hotplug rule */
|
||||||
if (eval_term(cfg.hotplug, &symbols))
|
if (eval_term(cfg.hotplug, &symbols))
|
||||||
@@ -172,40 +192,16 @@ static void eval_cpu_rules(void)
|
|||||||
cpuplugd_debug("maximum cpu limit is reached\n");
|
cpuplugd_debug("maximum cpu limit is reached\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* try to find a offline cpu */
|
if (hotplug_one_cpu())
|
||||||
for (cpu = 0; cpu < nr_cpus; cpu++)
|
cpuplugd_debug("unable to find a cpu which can be enabled\n");
|
||||||
if (is_online(cpu) == 0 && cpu_is_configured(cpu) != 0)
|
|
||||||
break;
|
|
||||||
if (cpu < nr_cpus) {
|
|
||||||
cpuplugd_debug("cpu with id %d is currently offline "
|
|
||||||
"and will be enabled\n", cpu);
|
|
||||||
if (hotplug(cpu) == -1)
|
|
||||||
cpuplugd_debug("unable to find a cpu which "
|
|
||||||
"can be enabled\n");
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* In case we tried to enable a cpu but this failed.
|
|
||||||
* This is the case if a cpu is deconfigured
|
|
||||||
*/
|
|
||||||
cpuplugd_debug("unable to find a cpu which can "
|
|
||||||
"be enabled\n");
|
|
||||||
}
|
|
||||||
} else if (on_off < 0) {
|
} else if (on_off < 0) {
|
||||||
/* check cpu nr limit */
|
/* check cpu nr limit */
|
||||||
if (symbols.onumcpus <= cfg.cpu_min) {
|
if (symbols.onumcpus <= cfg.cpu_min) {
|
||||||
cpuplugd_debug("minimum cpu limit is reached\n");
|
cpuplugd_debug("minimum cpu limit is reached\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* try to find a online cpu */
|
if (hotunplug_one_cpu())
|
||||||
for (cpu = get_numcpus() - 1; cpu >= 0; cpu--) {
|
cpuplugd_debug("unable to find a cpu which can be disabled\n");
|
||||||
if (is_online(cpu) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cpu > 0) {
|
|
||||||
cpuplugd_debug("cpu with id %d is currently online "
|
|
||||||
"and will be disabled\n", cpu);
|
|
||||||
hotunplug(cpu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ of active CPUs are reset to the values they had before the cpuplugd was started.
|
|||||||
This program can be used to control the number of CPUs for Linux on z/VM
|
This program can be used to control the number of CPUs for Linux on z/VM
|
||||||
and for Linux in LPAR mode. The memory hotplug feature (CMM page pool) applies
|
and for Linux in LPAR mode. The memory hotplug feature (CMM page pool) applies
|
||||||
to Linux on z/VM only.
|
to Linux on z/VM only.
|
||||||
|
|
||||||
|
The cpuplugd daemon stops any CPU hot-plug operations when the system switches
|
||||||
|
to vertical polarization, thus avoiding possible performance penalties.
|
||||||
.
|
.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
dasdfmt \- formatting of DASD (ECKD) disk drives.
|
dasdfmt \- formatting of DASD (ECKD) disk drives.
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\fBdasdfmt\fR [-h] [-t] [-v] [-y] [-p] [-P] [-m \fIstep\fR]
|
\fBdasdfmt\fR [\-h] [\-t] [\-v] [\-y] [\-p] [\-P] [\-m \fIstep\fR]
|
||||||
.br
|
.br
|
||||||
[-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
|
[\-r \fIcylinder\fR] [\-b \fIblksize\fR] [\-l \fIvolser\fR] [\-d \fIlayout\fR]
|
||||||
.br
|
.br
|
||||||
[-L] [-V] [-F] [-k] [-C] [-M \fImode\fR] \fIdevice\fR
|
[\-L] [\-V] [\-F] [\-k] [\-C] [\-M \fImode\fR] \fIdevice\fR
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
|
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
|
||||||
@@ -26,26 +26,26 @@ Any device node created by udev for kernel 2.6 can be used
|
|||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB-h\fR or \fB--help\fR
|
\fB\-h\fR or \fB\-\-help\fR
|
||||||
Print usage and exit.
|
Print usage and exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-t\fR or \fB--test\fR
|
\fB\-t\fR or \fB\-\-test\fR
|
||||||
Disables any modification of the disk drive.
|
Disables any modification of the disk drive.
|
||||||
.br
|
.br
|
||||||
\fBdasdfmt\fR just prints
|
\fBdasdfmt\fR just prints
|
||||||
out, what it \fBwould\fR do.
|
out, what it \fBwould\fR do.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-v\fR
|
\fB\-v\fR
|
||||||
Increases verbosity.
|
Increases verbosity.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-y\fR
|
\fB\-y\fR
|
||||||
Start formatting without further user-confirmation.
|
Start formatting without further user-confirmation.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB--norecordzero\fR
|
\fB\-\-norecordzero\fR
|
||||||
Remove permission for subsystem to format write record zero.
|
Remove permission for subsystem to format write record zero.
|
||||||
.br
|
.br
|
||||||
This is an expert option: Per default in recent dasd drivers, subsystems are
|
This is an expert option: Per default in recent dasd drivers, subsystems are
|
||||||
@@ -54,32 +54,32 @@ to remove this permission.
|
|||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-L\fR or \fB--no_label\fR
|
\fB\-L\fR or \fB\-\-no_label\fR
|
||||||
Omit the writing of a disk label after formatting.
|
Omit the writing of a disk label after formatting.
|
||||||
.br
|
.br
|
||||||
This makes only sense for the 'ldl' disk layout.
|
This makes only sense for the 'ldl' disk layout.
|
||||||
.br
|
.br
|
||||||
The '-L' option has to be specified after the '-d ldl' option.
|
The '\-L' option has to be specified after the '\-d ldl' option.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
e.g. dasdfmt -d ldl -L /dev/...
|
e.g. dasdfmt \-d ldl \-L /dev/...
|
||||||
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-V\fR or \fB--version\fR
|
\fB\-V\fR or \fB\-\-version\fR
|
||||||
Print version number and exit.
|
Print version number and exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-F\fR or \fB--force\fR
|
\fB\-F\fR or \fB\-\-force\fR
|
||||||
Formats the device without performing sanity checking.
|
Formats the device without performing sanity checking.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-C\fR or \fB--check_host_count\fR
|
\fB\-C\fR or \fB\-\-check_host_count\fR
|
||||||
Force dasdfmt to check the host access open count to ensure the device
|
Force dasdfmt to check the host access open count to ensure the device
|
||||||
is not online on another operating system instance
|
is not online on another operating system instance
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-d\fR \fIlayout\fR or \fB--disk_layout\fR=\fIlayout\fR
|
\fB\-d\fR \fIlayout\fR or \fB\-\-disk_layout\fR=\fIlayout\fR
|
||||||
Formats the device with compatible disk layout or linux disk layout.
|
Formats the device with compatible disk layout or linux disk layout.
|
||||||
\fIlayout\fR is either \fIcdl\fR for the compatible disk layout
|
\fIlayout\fR is either \fIcdl\fR for the compatible disk layout
|
||||||
(default) or \fIldl\fR for the linux disk layout.
|
(default) or \fIldl\fR for the linux disk layout.
|
||||||
@@ -95,39 +95,39 @@ Do not use this option if you are using a 3270 console,
|
|||||||
running in background or redirecting the output to a file.
|
running in background or redirecting the output to a file.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-P\fR or \fB--percentage\fR
|
\fB\-P\fR or \fB\-\-percentage\fR
|
||||||
Print one line for each formatted cylinder showing the number of the
|
Print one line for each formatted cylinder showing the number of the
|
||||||
cylinder and percentage of formatting process.
|
cylinder and percentage of formatting process.
|
||||||
Intended to be used by higher level interfaces.
|
Intended to be used by higher level interfaces.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-m\fR \fIstep\fR or \fB--hashmarks\fR=\fIstep\fR
|
\fB\-m\fR \fIstep\fR or \fB\-\-hashmarks\fR=\fIstep\fR
|
||||||
Print a hashmark every \fIstep\fR cylinders. The value \fIstep\fR has to be within range [1,1000], otherwise it will be set to the default, which is 10.
|
Print a hashmark every \fIstep\fR cylinders. The value \fIstep\fR has to be within range [1,1000], otherwise it will be set to the default, which is 10.
|
||||||
.br
|
.br
|
||||||
You can use this option to see the progress of formatting in case you
|
You can use this option to see the progress of formatting in case you
|
||||||
are not able to use the progress bar option -p, e.g. with a 3270
|
are not able to use the progress bar option \-p, e.g. with a 3270
|
||||||
terminal.
|
terminal.
|
||||||
.br
|
.br
|
||||||
The value will be at least as big as the -r or --requestsize value.
|
The value will be at least as big as the \-r or \-\-requestsize value.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-M\fR \fImode\fR or \fB--mode\fR=\fImode\fR
|
\fB\-M\fR \fImode\fR or \fB\-\-mode\fR=\fImode\fR
|
||||||
Specify the \fImode\fR to be used to format the device. Valid modes are:
|
Specify the \fImode\fR to be used to format the device. Valid modes are:
|
||||||
.RS
|
.RS
|
||||||
.IP full
|
.IP full
|
||||||
Format the entire disk with the specified blocksize. (default)
|
Format the entire disk with the specified blocksize. (default)
|
||||||
.IP quick
|
.IP quick
|
||||||
Format the first two tracks and write label and partition information. Use this
|
Format the first two tracks and write label and partition information.
|
||||||
option only if you are sure that the target DASD already contains a regular
|
|
||||||
format with the specified blocksize. A blocksize can optionally be specified
|
|
||||||
using \fB-b\fR (\fB--blocksize\fR).
|
|
||||||
.br
|
.br
|
||||||
For thin-provisioned DASD ESE volumes, quick is the default mode. A full space
|
Use this option for DASD ESE volumes to take the benefits of thin provisioning.
|
||||||
release then precedes the formatting step. If this space release fails, dasdfmt
|
In this case, a full space release precedes the formatting step. If this space
|
||||||
falls back to a full-format mode. Formatting stops if the space release fails
|
release fails, then the formatting also fails. Specify the \fB\-\-no\-discard\fR
|
||||||
and quick mode was specified explicitly using \fB-M\fR. Specify the
|
option to omit the space release.
|
||||||
\fB--no-discard\fR option to omit the space release.
|
.br
|
||||||
|
For non-ESE volumes use this option only if you are sure that the target DASD
|
||||||
|
already contains a regular format with the specified blocksize. A blocksize can
|
||||||
|
optionally be specified using \fB\-b\fR (\fB\-\-blocksize\fR).
|
||||||
|
|
||||||
.IP expand
|
.IP expand
|
||||||
Format all unformatted tracks at the end of the target DASD. This mode assumes
|
Format all unformatted tracks at the end of the target DASD. This mode assumes
|
||||||
@@ -135,20 +135,20 @@ that tracks at the beginning of the DASD volume have already been correctly
|
|||||||
formatted, while a consecutive set of tracks at the end are unformatted. You can
|
formatted, while a consecutive set of tracks at the end are unformatted. You can
|
||||||
use this mode to make added space available for Linux use after dynamically
|
use this mode to make added space available for Linux use after dynamically
|
||||||
increasing the size of a DASD volume. A blocksize can optionally be specified
|
increasing the size of a DASD volume. A blocksize can optionally be specified
|
||||||
using \fB-b\fR (\fB--blocksize\fR).
|
using \fB\-b\fR (\fB\-\-blocksize\fR).
|
||||||
.RE
|
.RE
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB--check\fR
|
\fB\-\-check\fR
|
||||||
Perform a complete format check on a DASD volume. A blocksize can be specified
|
Perform a complete format check on a DASD volume. A blocksize can be specified
|
||||||
with \fB-b\fR (\fB--blocksize\fR).
|
with \fB\-b\fR (\fB\-\-blocksize\fR).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB--no-discard\fR
|
\fB\-\-no\-discard\fR
|
||||||
Omit a full space release when formatting a thin-provisioned DASD ESE volume.
|
Omit a full space release when formatting a thin-provisioned DASD ESE volume.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
|
\fB\-r\fR \fIcylindercount\fR or \fB\-\-requestsize\fR=\fIcylindercount\fR
|
||||||
Number of cylinders to be processed in one formatting step.
|
Number of cylinders to be processed in one formatting step.
|
||||||
The value must be an integer in the range 1 - 255.
|
The value must be an integer in the range 1 - 255.
|
||||||
.br
|
.br
|
||||||
@@ -158,19 +158,19 @@ devices, counting the base device and all alias devices.
|
|||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-b\fR \fIblksize\fR or \fB--blocksize\fR=\fIblksize\fR
|
\fB\-b\fR \fIblksize\fR or \fB\-\-blocksize\fR=\fIblksize\fR
|
||||||
Specify blocksize to be used. \fIblksize\fR must be a positive integer
|
Specify blocksize to be used. \fIblksize\fR must be a positive integer
|
||||||
and always be a power of two. The recommended blocksize is 4096 bytes.
|
and always be a power of two. The recommended blocksize is 4096 bytes.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-l\fR \fIvolser\fR or \fB--label\fR=\fIvolser\fR
|
\fB\-l\fR \fIvolser\fR or \fB\-\-label\fR=\fIvolser\fR
|
||||||
Specify the volume serial number or volume identifier to be written
|
Specify the volume serial number or volume identifier to be written
|
||||||
to disk after formatting. If no label is specified, a sensible default
|
to disk after formatting. If no label is specified, a sensible default
|
||||||
is used. \fIvolser\fR is interpreted as ASCII string and is automatically
|
is used. \fIvolser\fR is interpreted as ASCII string and is automatically
|
||||||
converted to uppercase and then to EBCDIC.
|
converted to uppercase and then to EBCDIC.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
e.g. -l LNX001 or --label=DASD01
|
e.g. \-l LNX001 or \-\-label=DASD01
|
||||||
.br
|
.br
|
||||||
|
|
||||||
The \fIvolser\fR identifies by serial number the volume. A volume serial
|
The \fIvolser\fR identifies by serial number the volume. A volume serial
|
||||||
@@ -192,14 +192,13 @@ NOTE: Try to avoid using special characters in the volume serial. This may cause
|
|||||||
In case you really have to use special characters, make sure you are using quotes. In addition there is a special handling for the '$' sign. Please specify it using '\\$' if necessary.
|
In case you really have to use special characters, make sure you are using quotes. In addition there is a special handling for the '$' sign. Please specify it using '\\$' if necessary.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
e.g. -l 'a@b\\$c#' to get A@B$C#
|
e.g. \-l 'a@b\\$c#' to get A@B$C#
|
||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-k\fR or \fB--keep_volser\fR
|
\fB\-k\fR or \fB\-\-keep_volser\fR
|
||||||
Keeps the Volume Serial Number, when writing the Volume Label. This is
|
Keeps the Volume Serial Number when writing the Volume Label. This is useful if
|
||||||
useful, if the Serial Number has been written with a VM Tool and should not
|
the volume already has a Serial Number that should not be overwritten.
|
||||||
be overwritten.
|
|
||||||
.br
|
.br
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
|||||||
@@ -1230,7 +1230,7 @@ static void dasdfmt_find_start(unsigned int cylinders, unsigned int heads,
|
|||||||
format_params->start_unit = first;
|
format_params->start_unit = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dasdfmt_release_space(void)
|
static void dasdfmt_release_space(void)
|
||||||
{
|
{
|
||||||
format_data_t r = {
|
format_data_t r = {
|
||||||
.start_unit = 0,
|
.start_unit = 0,
|
||||||
@@ -1240,21 +1240,12 @@ static int dasdfmt_release_space(void)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (!g.ese || g.no_discard)
|
if (!g.ese || g.no_discard)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
printf("Releasing space for the entire device...\n");
|
printf("Releasing space for the entire device...\n");
|
||||||
err = dasd_release_space(g.dev_node, &r);
|
err = dasd_release_space(g.dev_node, &r);
|
||||||
/*
|
if (err)
|
||||||
* Warn or Error on failing RAS depending on QUICK mode set explicitly or automatically
|
|
||||||
*/
|
|
||||||
if (err && !g.mode_specified) {
|
|
||||||
warnx("Could not release space. Falling back to full format.");
|
|
||||||
return 1;
|
|
||||||
} else if (err && g.mode_specified) {
|
|
||||||
error("Could not release space: %s", strerror(err));
|
error("Could not release space: %s", strerror(err));
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dasdfmt_prepare_and_format(unsigned int cylinders, unsigned int heads,
|
static void dasdfmt_prepare_and_format(unsigned int cylinders, unsigned int heads,
|
||||||
@@ -1454,12 +1445,8 @@ static void do_format_dasd(volume_label_t *vlabel, format_data_t *p,
|
|||||||
dasdfmt_prepare_and_format(cylinders, heads, p);
|
dasdfmt_prepare_and_format(cylinders, heads, p);
|
||||||
break;
|
break;
|
||||||
case QUICK:
|
case QUICK:
|
||||||
if (dasdfmt_release_space()) {
|
dasdfmt_release_space();
|
||||||
p->stop_unit = (cylinders * heads) - 1;
|
dasdfmt_quick_format(cylinders, heads, p);
|
||||||
dasdfmt_prepare_and_format(cylinders, heads, p);
|
|
||||||
} else {
|
|
||||||
dasdfmt_quick_format(cylinders, heads, p);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case EXPAND:
|
case EXPAND:
|
||||||
dasdfmt_expand_format(cylinders, heads, p);
|
dasdfmt_expand_format(cylinders, heads, p);
|
||||||
@@ -1491,7 +1478,7 @@ static void eval_format_mode(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!g.mode_specified)
|
if (!g.mode_specified)
|
||||||
mode = g.ese ? QUICK : FULL;
|
mode = FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -7,28 +7,28 @@
|
|||||||
.B "dasdinfo "
|
.B "dasdinfo "
|
||||||
\- tool to read unique id from s390 DASD device
|
\- tool to read unique id from s390 DASD device
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.BI "dasdinfo [-a] [-l] [-u] [-x] [-e] {-i " <busid>
|
.BI "dasdinfo [\-a] [\-l] [\-u] [\-x] [\-e] {\-i " <busid>
|
||||||
.BI "| -b " <blockdev>
|
.BI "| \-b " <blockdev>
|
||||||
.BI " | -d " <devnode>
|
.BI " | \-d " <devnode>
|
||||||
.BI "}"
|
.BI "}"
|
||||||
.sp
|
.sp
|
||||||
.BI "dasdinfo [-h] [-v]"
|
.BI "dasdinfo [\-h] [\-v]"
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B dasdinfo
|
.B dasdinfo
|
||||||
displays specific information about a specified DASD device.
|
displays specific information about a specified DASD device.
|
||||||
It is normally called from a udev rule, to provide udev with a unique id string and
|
It is normally called from a udev rule, to provide udev with a unique id string and
|
||||||
additional information (type, serial) for an S390 DASD drive. Udev can use this
|
additional information (type, serial) for an S390 DASD drive. Udev can use this
|
||||||
information to create symlinks in /dev/disk/by-id and /dev/disk/by-label
|
information to create symlinks in /dev/disk/by\-id and /dev/disk/by\-label
|
||||||
to the real device node.
|
to the real device node.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-a|--all"
|
.BI "\-a|\-\-all"
|
||||||
Same as -u -x -l
|
Same as -u -x -l
|
||||||
.TP
|
.TP
|
||||||
.BI "-x|--extended-uid"
|
.BI "\-x|\-\-extended\-uid"
|
||||||
Print DASD uid
|
Print DASD uid
|
||||||
|
|
||||||
This option prints the full uid of the DASD. When z/VM provides two
|
This option prints the full uid of the DASD. When z/VM provides two
|
||||||
@@ -42,13 +42,13 @@ For z/VM: VM support for the hypervisor injected Special Node Element
|
|||||||
Qualifier (SNEQ) (or hypervisor injected self-description data) is
|
Qualifier (SNEQ) (or hypervisor injected self-description data) is
|
||||||
available by applying the PTFs for VM APAR VM64273 on z/VM 5.2.0 and higher.
|
available by applying the PTFs for VM APAR VM64273 on z/VM 5.2.0 and higher.
|
||||||
.TP
|
.TP
|
||||||
.BI "-u|--uid"
|
.BI "\-u|\-\-uid"
|
||||||
Print DASD uid without z/VM minidisk token
|
Print DASD uid without z/VM minidisk token
|
||||||
|
|
||||||
z/VM may provide an additional token that can be used to distinguish
|
z/VM may provide an additional token that can be used to distinguish
|
||||||
between different minidisks (see --extended-uid option). To remain
|
between different minidisks (see \-\-extended\-uid option). To remain
|
||||||
compatible with systems that were installed on older Linux or z/VM
|
compatible with systems that were installed on older Linux or z/VM
|
||||||
levels, the -u option will print the uid excluding any z/VM-provided
|
levels, the \-u option will print the uid excluding any z/VM-provided
|
||||||
minidisk token.
|
minidisk token.
|
||||||
|
|
||||||
For example, if the extended uid is
|
For example, if the extended uid is
|
||||||
@@ -57,33 +57,33 @@ uid is IBM.75000000092461.e900.10. If the extended uid contains no
|
|||||||
minidisk token, e.g. in an LPAR environment, then both uids are the
|
minidisk token, e.g. in an LPAR environment, then both uids are the
|
||||||
same.
|
same.
|
||||||
.TP
|
.TP
|
||||||
.BI "-l|--label"
|
.BI "\-l|\-\-label"
|
||||||
Print DASD volume label (volser).
|
Print DASD volume label (volser).
|
||||||
.TP
|
.TP
|
||||||
.BI "-i|--busid " <busid>
|
.BI "\-i|\-\-busid " <busid>
|
||||||
Use the bus ID as input parameter, e.g. 0.0.e910.
|
Use the bus ID as input parameter, e.g. 0.0.e910.
|
||||||
.TP
|
.TP
|
||||||
.BI "-b|--block " <blockdev>
|
.BI "\-b|\-\-block " <blockdev>
|
||||||
Use the block device name as input parameter, e.g. dasdb.
|
Use the block device name as input parameter, e.g. dasdb.
|
||||||
.TP
|
.TP
|
||||||
.BI "-d|--devnode " <devnode>
|
.BI "\-d|\-\-devnode " <devnode>
|
||||||
Use a device node as input parameter, e.g. /dev/dasdb.
|
Use a device node as input parameter, e.g. /dev/dasdb.
|
||||||
.TP
|
.TP
|
||||||
.BI "-e|--export"
|
.BI "\-e|\-\-export"
|
||||||
Print all values (ID_BUS, ID_TYPE, ID_SERIAL).
|
Print all values (ID_BUS, ID_TYPE, ID_SERIAL).
|
||||||
.TP
|
.TP
|
||||||
.BI "-h|--help"
|
.BI "\-h|\-\-help"
|
||||||
Print usage text.
|
Print usage text.
|
||||||
.TP
|
.TP
|
||||||
.BI "-v|--version"
|
.BI "\-v|\-\-version"
|
||||||
Print version number.
|
Print version number.
|
||||||
|
|
||||||
.SH EXAMPLES
|
.SH EXAMPLES
|
||||||
dasdinfo -u -i 0.0.e910
|
dasdinfo \-u \-i 0.0.e910
|
||||||
|
|
||||||
dasdinfo -u -b dasdb
|
dasdinfo \-u \-b dasdb
|
||||||
|
|
||||||
dasdinfo -u -d /dev/dasdb
|
dasdinfo \-u \-d /dev/dasdb
|
||||||
|
|
||||||
All three examples should return the same unique ID for
|
All three examples should return the same unique ID for
|
||||||
the same DASD device, e.g. IBM.75000000092461.e900.10.
|
the same DASD device, e.g. IBM.75000000092461.e900.10.
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
dasdview \- Display DASD and VTOC information and dump the content of a DASD
|
dasdview \- Display DASD and VTOC information and dump the content of a DASD
|
||||||
to the console.
|
to the console.
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
\fBdasdview\fR [-h] [-v]
|
\fBdasdview\fR [\-h] [\-v]
|
||||||
.br
|
.br
|
||||||
[-b \fIbegin\fR] [-s \fIsize\fR] [-1|-2]
|
[\-b \fIbegin\fR] [\-s \fIsize\fR] [\-1|\-2]
|
||||||
.br
|
.br
|
||||||
[-i] [-x] [-j] [-c]
|
[\-i] [\-x] [\-j] [\-c]
|
||||||
.br
|
.br
|
||||||
[-l] [-t {\fIinfo\fR|\fIf1\fR|\fIf3\fR|\fIf4\fR|\fIf5\fR|\fIf7\fR|\fIf8\fR|\fIf9\fR}]
|
[\-l] [\-t {\fIinfo\fR|\fIf1\fR|\fIf3\fR|\fIf4\fR|\fIf5\fR|\fIf7\fR|\fIf8\fR|\fIf9\fR}]
|
||||||
.br
|
.br
|
||||||
\fIdevice\fR
|
\fIdevice\fR
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
@@ -29,27 +29,27 @@ automatically. When in raw_track_access mode, the same basic
|
|||||||
functions are available as in the regular mode, but the output may
|
functions are available as in the regular mode, but the output may
|
||||||
have a slightly different layout:
|
have a slightly different layout:
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
The disk dump functions (\fB-b\fR and \fB-s\fR) print the count,
|
The disk dump functions (\fB\-b\fR and \fB\-s\fR) print the count,
|
||||||
key and data information for the whole track, and not just the
|
key and data information for the whole track, and not just the
|
||||||
contents of the data areas.
|
contents of the data areas.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
The VTOC listing (\fB-t\fR) print all specified DSCBs in the same
|
The VTOC listing (\fB\-t\fR) print all specified DSCBs in the same
|
||||||
format as in the regular mode, but in the sequence as they appear in
|
format as in the regular mode, but in the sequence as they appear in
|
||||||
the VTOC. The \fB-t info\fR overview contains more details for each
|
the VTOC. The \fB\-t info\fR overview contains more details for each
|
||||||
data set than in the regular mode, to support the larger variety of
|
data set than in the regular mode, to support the larger variety of
|
||||||
data set layouts.
|
data set layouts.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB-h\fR or \fB--help\fR
|
\fB\-h\fR or \fB\-\-help\fR
|
||||||
Print usage and exit.
|
Print usage and exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-v\fR or \fB--version\fR
|
\fB\-v\fR or \fB\-\-version\fR
|
||||||
Print version number and exit.
|
Print version number and exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-b\fR \fIbegin\fR or \fB--begin=\fR\fIbegin\fR
|
\fB\-b\fR \fIbegin\fR or \fB\-\-begin=\fR\fIbegin\fR
|
||||||
Print a disk dump to the console, starting with \fIbegin\fR. The content of
|
Print a disk dump to the console, starting with \fIbegin\fR. The content of
|
||||||
the disk will be displayed in hexadecimal numbers, ASCII text and EBCDIC text.
|
the disk will be displayed in hexadecimal numbers, ASCII text and EBCDIC text.
|
||||||
If no size is specified dasdview will take the default size. The variable
|
If no size is specified dasdview will take the default size. The variable
|
||||||
@@ -76,22 +76,22 @@ cylinder as starting point.
|
|||||||
|
|
||||||
examples:
|
examples:
|
||||||
.br
|
.br
|
||||||
-b 32 --> start printing at Byte 32
|
\-b 32 --> start printing at Byte 32
|
||||||
.br
|
.br
|
||||||
-b 32k --> start printing at kByte 32
|
\-b 32k --> start printing at kByte 32
|
||||||
.br
|
.br
|
||||||
-b 32m --> start printing at MByte 32
|
\-b 32m --> start printing at MByte 32
|
||||||
.br
|
.br
|
||||||
-b 32b --> start printing at block 32
|
\-b 32b --> start printing at block 32
|
||||||
.br
|
.br
|
||||||
-b 32t --> start printing at track 32
|
\-b 32t --> start printing at track 32
|
||||||
.br
|
.br
|
||||||
-b 32c --> start printing at cylinder 32
|
\-b 32c --> start printing at cylinder 32
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-s\fR \fIsize\fR or \fB--size=\fR\fIsize\fR
|
\fB\-s\fR \fIsize\fR or \fB\-\-size=\fR\fIsize\fR
|
||||||
Print a disk dump to the console, starting with \fIbegin\fR, specified with
|
Print a disk dump to the console, starting with \fIbegin\fR, specified with
|
||||||
the \fB-b\fR option and size \fIsize\fR. The content of the disk will be
|
the \fB\-b\fR option and size \fIsize\fR. The content of the disk will be
|
||||||
displayed in hexadecimal numbers, ASCII text and EBCDIC text. If no start
|
displayed in hexadecimal numbers, ASCII text and EBCDIC text. If no start
|
||||||
value is specified dasdview will take the default start value. The variable
|
value is specified dasdview will take the default start value. The variable
|
||||||
\fIsize\fR can be specified in one of the following ways:
|
\fIsize\fR can be specified in one of the following ways:
|
||||||
@@ -111,63 +111,63 @@ in raw_track_access mode.
|
|||||||
|
|
||||||
examples:
|
examples:
|
||||||
.br
|
.br
|
||||||
-s 16 --> use a 16 Byte size
|
\-s 16 --> use a 16 Byte size
|
||||||
.br
|
.br
|
||||||
-s 16k --> use a 16 kByte size
|
\-s 16k --> use a 16 kByte size
|
||||||
.br
|
.br
|
||||||
-s 16m --> use a 16 MByte size
|
\-s 16m --> use a 16 MByte size
|
||||||
.br
|
.br
|
||||||
-s 16b --> use a 16 block size
|
\-s 16b --> use a 16 block size
|
||||||
.br
|
.br
|
||||||
-s 16t --> use a 16 track size
|
\-s 16t --> use a 16 track size
|
||||||
.br
|
.br
|
||||||
-s 16c --> use a 16 cylinder size
|
\-s 16c --> use a 16 cylinder size
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-1\fR
|
\fB\-1\fR
|
||||||
This option tells dasdview to print the disk dump using format 1. This means
|
This option tells dasdview to print the disk dump using format 1. This means
|
||||||
you will get 16 Bytes per line in hex, ascii and ebcdic. There is no line
|
you will get 16 Bytes per line in hex, ascii and ebcdic. There is no line
|
||||||
number.
|
number.
|
||||||
.br
|
.br
|
||||||
The \fB-1\fR option makes only sense with the \fB-b\fR and/or the \fB-s\fR
|
The \fB\-1\fR option makes only sense with the \fB\-b\fR and/or the \fB\-s\fR
|
||||||
options.
|
options.
|
||||||
.br
|
.br
|
||||||
This is the default.
|
This is the default.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-2\fR
|
\fB\-2\fR
|
||||||
This option tells dasdview to print the disk dump using format 2. This means
|
This option tells dasdview to print the disk dump using format 2. This means
|
||||||
you will get 8 Bytes per line in hex, ascii and ebcdic. And in addition a line
|
you will get 8 Bytes per line in hex, ascii and ebcdic. And in addition a line
|
||||||
number and a decimal and hexadecimal byte count will be printed.
|
number and a decimal and hexadecimal byte count will be printed.
|
||||||
.br
|
.br
|
||||||
The \fB-2\fR option makes only sense with the \fB-b\fR and/or the \fB-s\fR
|
The \fB\-2\fR option makes only sense with the \fB\-b\fR and/or the \fB\-s\fR
|
||||||
options. In raw_track_access mode this format is not supported and the
|
options. In raw_track_access mode this format is not supported and the
|
||||||
option will be ignored.
|
option will be ignored.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-i\fR or \fB--info\fR
|
\fB\-i\fR or \fB\-\-info\fR
|
||||||
Print some useful information (e.g. device node/number/type or geometry data).
|
Print some useful information (e.g. device node/number/type or geometry data).
|
||||||
When running dasdview on a kernel 2.6 based distribution the busid
|
When running dasdview on a kernel 2.6 based distribution the busid
|
||||||
is printed instead of the device number.
|
is printed instead of the device number.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-x\fR or \fB--extended\fR
|
\fB\-x\fR or \fB\-\-extended\fR
|
||||||
Print some more DASD information (e.g. open count, subchannel identifier).
|
Print some more DASD information (e.g. open count, subchannel identifier).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-j\fR or \fB--volser\fR
|
\fB\-j\fR or \fB\-\-volser\fR
|
||||||
Print volume serial number (volume identifier).
|
Print volume serial number (volume identifier).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-l\fR or \fB--label\fR
|
\fB\-l\fR or \fB\-\-label\fR
|
||||||
Print the volume label.
|
Print the volume label.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-c\fR or \fB--characteristic\fR
|
\fB\-c\fR or \fB\-\-characteristic\fR
|
||||||
Print some information about the device e.g. if it is encrypted.
|
Print some information about the device e.g. if it is encrypted.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-t\fR \fIspec\fR or \fB--vtoc=\fR\fIspec\fR
|
\fB\-t\fR \fIspec\fR or \fB\-\-vtoc=\fR\fIspec\fR
|
||||||
Print the VTOC (table of content) or single VTOC entries to the console.
|
Print the VTOC (table of content) or single VTOC entries to the console.
|
||||||
\fIspec\fR can be one of the following strings:
|
\fIspec\fR can be one of the following strings:
|
||||||
.br
|
.br
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Common definitions
|
# Common definitions
|
||||||
include ../../common.mak
|
include ../../common.mak
|
||||||
|
|
||||||
ALL_CPPFLAGS += -I../include -std=gnu99 -Wno-unused-parameter
|
ALL_CPPFLAGS += -I../include -Wno-unused-parameter
|
||||||
LDLIBS += -lpthread -lrt
|
LDLIBS += -lpthread -lrt
|
||||||
ifneq ($(HAVE_ZLIB),0)
|
ifneq ($(HAVE_ZLIB),0)
|
||||||
ALL_CPPFLAGS += -DHAVE_ZLIB
|
ALL_CPPFLAGS += -DHAVE_ZLIB
|
||||||
|
|||||||
@@ -23,9 +23,16 @@
|
|||||||
|
|
||||||
#define BLOCKSIZE 512
|
#define BLOCKSIZE 512
|
||||||
|
|
||||||
|
#if __has_attribute(nonstring)
|
||||||
|
# define __nonstring __attribute__ ((nonstring))
|
||||||
|
#else
|
||||||
|
# define __nonstring
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Basic TAR header */
|
/* Basic TAR header */
|
||||||
struct tar_header {
|
struct tar_header {
|
||||||
char name[100];
|
char name[100] __nonstring;
|
||||||
char mode[8];
|
char mode[8];
|
||||||
char uid[8];
|
char uid[8];
|
||||||
char gid[8];
|
char gid[8];
|
||||||
@@ -33,7 +40,7 @@ struct tar_header {
|
|||||||
char mtime[12];
|
char mtime[12];
|
||||||
char chksum[8];
|
char chksum[8];
|
||||||
char typeflag;
|
char typeflag;
|
||||||
char linkname[100];
|
char linkname[100] __nonstring;
|
||||||
char magic[6];
|
char magic[6];
|
||||||
char version[2];
|
char version[2];
|
||||||
char uname[32];
|
char uname[32];
|
||||||
@@ -78,7 +85,7 @@ static void set_time(char *dest, size_t len, time_t value)
|
|||||||
#define SET_TIME_FIELD(obj, name, value) \
|
#define SET_TIME_FIELD(obj, name, value) \
|
||||||
set_time((obj)->name, sizeof((obj)->name), (time_t) (value))
|
set_time((obj)->name, sizeof((obj)->name), (time_t) (value))
|
||||||
#define SET_STR_FIELD(obj, name, value) \
|
#define SET_STR_FIELD(obj, name, value) \
|
||||||
util_strlcpy((obj)->name, (value), sizeof((obj)->name))
|
strncpy((obj)->name, (value), sizeof((obj)->name))
|
||||||
|
|
||||||
/* Initialize the tar file @header with the provided data */
|
/* Initialize the tar file @header with the provided data */
|
||||||
static void init_header(struct tar_header *header, const char *filename,
|
static void init_header(struct tar_header *header, const char *filename,
|
||||||
|
|||||||
@@ -28,6 +28,15 @@
|
|||||||
# DEVICE=0.0.4e13
|
# DEVICE=0.0.4e13
|
||||||
# DELAY_MINUTES=5
|
# DELAY_MINUTES=5
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dump on ECKD device (DASD)
|
||||||
|
#
|
||||||
|
# ON_PANIC=dump
|
||||||
|
# DUMP_TYPE=eckd
|
||||||
|
# DEVICE=0.0.1004
|
||||||
|
# BOOTPROG=0
|
||||||
|
# BR_CHR=auto
|
||||||
|
|
||||||
#
|
#
|
||||||
# Dump on fcp device (SCSI Disk)
|
# Dump on fcp device (SCSI Disk)
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -8,16 +8,16 @@ fdasd \- partitioning tool.
|
|||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
interactive mode:
|
interactive mode:
|
||||||
.br
|
.br
|
||||||
\fBfdasd\fR [-s] [-r] [-C] \fIdevice\fR
|
\fBfdasd\fR [\-s] [\-r] [\-C] \fIdevice\fR
|
||||||
.br
|
.br
|
||||||
command line mode:
|
command line mode:
|
||||||
.br
|
.br
|
||||||
\fBfdasd\fR [-s] [-r] [-C] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
|
\fBfdasd\fR [\-s] [\-r] [\-C] {\-a[\-k|\-l \fIvolser\fR]|\-i|\-p|\-c \fIconf_file\fR}
|
||||||
[-f \fI[type,blocksize]\fR] \fIdevice\fR
|
[-f \fI[type,blocksize]\fR] \fIdevice\fR
|
||||||
.br
|
.br
|
||||||
help:
|
help:
|
||||||
.br
|
.br
|
||||||
\fBfdasd\fR {-h|-v}
|
\fBfdasd\fR {\-h|\-v}
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
\fBfdasd\fR writes a partition table to a cdl (compatible disk layout)
|
\fBfdasd\fR writes a partition table to a cdl (compatible disk layout)
|
||||||
formatted DASD, in the form of
|
formatted DASD, in the form of
|
||||||
@@ -30,35 +30,35 @@ will use it, otherwise it asks to write a new one.
|
|||||||
\fBfdasd\fR can result in loss of data.
|
\fBfdasd\fR can result in loss of data.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
\fB-h\fR or \fB--help\fR
|
\fB\-h\fR or \fB\-\-help\fR
|
||||||
Print usage information, then exit.
|
Print usage information, then exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-v\fR or \fB--version\fR
|
\fB\-v\fR or \fB\-\-version\fR
|
||||||
Print version information, then exit.
|
Print version information, then exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-s\fR or \fB--silent\fR
|
\fB\-s\fR or \fB\-\-silent\fR
|
||||||
Suppress messages in non-interactive mode.
|
Suppress messages in non-interactive mode.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-r\fR or \fB--verbose\fR
|
\fB\-r\fR or \fB\-\-verbose\fR
|
||||||
Provide more verbose output.
|
Provide more verbose output.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-a\fR or \fB--auto\fR
|
\fB\-a\fR or \fB\-\-auto\fR
|
||||||
Automatically create a partition using the entire disk in non-interactive
|
Automatically create a partition using the entire disk in non-interactive
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-k\fR or \fB--keep_volser\fR
|
\fB\-k\fR or \fB\-\-keep_volser\fR
|
||||||
Keeps the volume serial when writing the volume label.
|
Keeps the Volume Serial Number when writing the Volume Label.
|
||||||
.br
|
.br
|
||||||
This is useful, if the volume serial has been written before and should not
|
This is useful if the volume already has a Serial Number that should not be
|
||||||
be overwritten. This option is only applicable in non-interactive mode.
|
overwritten. This option is only applicable in non-interactive mode.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-l\fR \fIvolser\fR or \fB--label\fR \fIvolser\fR
|
\fB\-l\fR \fIvolser\fR or \fB\-\-label\fR \fIvolser\fR
|
||||||
Specify the volume serial.
|
Specify the volume serial.
|
||||||
.br
|
.br
|
||||||
\fIvolser\fR is interpreted as ASCII string and is automatically converted to
|
\fIvolser\fR is interpreted as ASCII string and is automatically converted to
|
||||||
@@ -82,14 +82,14 @@ quotes. In addition there is a special handling for the '$' sign.
|
|||||||
Please specify it using '\\$' if necessary.
|
Please specify it using '\\$' if necessary.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
e.g. -l 'a@b\\$c#' to get A@B$C#
|
e.g. \-l 'a@b\\$c#' to get A@B$C#
|
||||||
.br
|
.br
|
||||||
|
|
||||||
Omitting this parameter causes fdasd to ask for it in case it is needed.
|
Omitting this parameter causes fdasd to ask for it in case it is needed.
|
||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-c\fR \fIconf_file\fR or \fB--config\fR \fIconf_file\fR
|
\fB\-c\fR \fIconf_file\fR or \fB\-\-config\fR \fIconf_file\fR
|
||||||
Use this option to create multiple partitions according to
|
Use this option to create multiple partitions according to
|
||||||
specifications in a configuration file, \fIconf_file\fR.
|
specifications in a configuration file, \fIconf_file\fR.
|
||||||
.br
|
.br
|
||||||
@@ -124,37 +124,37 @@ partitions that use the entire disk:
|
|||||||
.br
|
.br
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-i\fR or \fB--volser\fR
|
\fB\-i\fR or \fB\-\-volser\fR
|
||||||
Print the volume serial, then exit.
|
Print the volume serial, then exit.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-p\fR or \fB--table\fR
|
\fB\-p\fR or \fB\-\-table\fR
|
||||||
Print partition table, then exit.
|
Print partition table, then exit.
|
||||||
.br
|
.br
|
||||||
In combination with the -s option fdasd will display a short version of the
|
In combination with the \-s option fdasd will display a short version of the
|
||||||
partition table.
|
partition table.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-C\fR or \fB--check_host_count\fR
|
\fB\-C\fR or \fB\-\-check_host_count\fR
|
||||||
Force fdasd to check the host access open count to ensure the device
|
Force fdasd to check the host access open count to ensure the device
|
||||||
is not online on another operating system instance
|
is not online on another operating system instance
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB-f\fR \fI[type,blocksize]\fR or \fB--force\fR \fI[type,blocksize]\fR
|
\fB\-f\fR \fI[type,blocksize]\fR or \fB\-\-force\fR \fI[type,blocksize]\fR
|
||||||
Force fdasd to work on non DASD devices.
|
Force fdasd to work on non DASD devices.
|
||||||
.br
|
.br
|
||||||
If fdasd is to be used on a block device that is neither a native DASD
|
If fdasd is to be used on a block device that is neither a native DASD
|
||||||
nor exposes the proper disk geometry of a DASD of type 3390,
|
nor exposes the proper disk geometry of a DASD of type 3390,
|
||||||
then the --force option can be used to assume the geometry of a
|
then the \-\-force option can be used to assume the geometry of a
|
||||||
given device type. The default device type is 3390 and the default
|
given device type. The default device type is 3390 and the default
|
||||||
block size is 4096. An optional argument of <device type>,<blocksize>
|
block size is 4096. An optional argument of <device type>,<blocksize>
|
||||||
can be used to specify type and blocksize explicitly. For example:
|
can be used to specify type and blocksize explicitly. For example:
|
||||||
|
|
||||||
-f
|
\-f
|
||||||
|
|
||||||
has the same effect as
|
has the same effect as
|
||||||
|
|
||||||
-f3390,4096 or --force=3390,4096
|
\-f3390,4096 or \-\-force=3390,4096
|
||||||
|
|
||||||
Valid device types are: 3390, 3380, 9345
|
Valid device types are: 3390, 3380, 9345
|
||||||
.br
|
.br
|
||||||
|
|||||||
@@ -3,16 +3,16 @@ include ../common.mak
|
|||||||
|
|
||||||
.DEFAULT_GOAL := all
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
PKGDATADIR := "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
|
PKGDATADIR := "$(TOOLS_DATADIR)/genprotimg"
|
||||||
TESTS :=
|
TESTS :=
|
||||||
SUBDIRS := boot src man
|
SUBDIRS := boot src man
|
||||||
RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
|
RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
|
||||||
|
|
||||||
all: all-recursive
|
all: all-recursive
|
||||||
|
|
||||||
install: all install-recursive
|
install: install-recursive
|
||||||
$(INSTALL) -d -m 755 "$(PKGDATADIR)"
|
$(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(PKGDATADIR)"
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(DESTDIR)$(PKGDATADIR)"
|
||||||
|
|
||||||
clean: clean-recursive
|
clean: clean-recursive
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
include ../../common.mak
|
include ../../common.mak
|
||||||
|
|
||||||
FILES := stage3a.bin stage3b.bin stage3b_reloc.bin
|
FILES := stage3a.bin stage3b.bin stage3b_reloc.bin
|
||||||
|
DEBUG_FILES := $(addsuffix .debug,$(FILES))
|
||||||
|
|
||||||
ifeq ($(HOST_ARCH),s390x)
|
ifeq ($(HOST_ARCH),s390x)
|
||||||
ZIPL_DIR := $(rootdir)/zipl
|
ZIPL_DIR := $(rootdir)/zipl
|
||||||
ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
|
ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
|
||||||
PKGDATADIR := $(DESTDIR)$(TOOLS_DATADIR)/genprotimg
|
PKGDATADIR := $(TOOLS_DATADIR)/genprotimg
|
||||||
|
|
||||||
INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
|
INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
|
||||||
INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
|
INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
|
||||||
@@ -71,25 +72,30 @@ stage3b_reloc.o: stage3b.bin
|
|||||||
stage3a.elf: head.o stage3a_init.o $(ZIPL_OBJS)
|
stage3a.elf: head.o stage3a_init.o $(ZIPL_OBJS)
|
||||||
stage3b.elf: head.o $(ZIPL_OBJS)
|
stage3b.elf: head.o $(ZIPL_OBJS)
|
||||||
|
|
||||||
|
.SECONDARY: $(FILES:.bin=.lds)
|
||||||
%.elf: %.lds %.o
|
%.elf: %.lds %.o
|
||||||
$(LINK) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,-T,$< -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
$(LINK) $(NO_PIE_LDFLAGS) $(NO_WARN_RWX_SEGMENTS_LDFLAGS) -Wl,-T,$< -Wl,--build-id=none -m64 -static -nostdlib $(filter %.o, $^) -o $@
|
||||||
@chmod a-x $@
|
@chmod a-x $@
|
||||||
|
|
||||||
|
%.bin.debug: %.elf
|
||||||
|
$(OBJCOPY) --only-keep-debug $< $@
|
||||||
|
@chmod a-x $@
|
||||||
|
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(OBJCOPY) -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
@chmod a-x $@
|
@chmod a-x $@
|
||||||
|
|
||||||
install: stage3a.bin stage3b_reloc.bin
|
install: stage3a.bin stage3b_reloc.bin
|
||||||
$(INSTALL) -d -m 755 "$(PKGDATADIR)"
|
$(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(PKGDATADIR)"
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(DESTDIR)$(PKGDATADIR)"
|
||||||
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(PKGDATADIR)"
|
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(DESTDIR)$(PKGDATADIR)"
|
||||||
|
|
||||||
else
|
else
|
||||||
# Don't generate the dependency files (see `common.mak` for the
|
# Don't generate the dependency files (see `common.mak` for the
|
||||||
# `-include $(dependencies_c)` statement).
|
# `-include $(dependencies_c)` statement).
|
||||||
.PHONY: $(dependencies_c)
|
.PHONY: $(dependencies_c)
|
||||||
|
|
||||||
$(FILES):
|
$(FILES) $(DEBUG_FILES):
|
||||||
echo " SKIP $@ due to HOST_ARCH != s390x"
|
echo " SKIP $@ due to HOST_ARCH != s390x"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@@ -97,9 +103,9 @@ install:
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
.DEFAULT_GOAL := all
|
.DEFAULT_GOAL := all
|
||||||
all: $(FILES)
|
all: $(FILES) $(DEBUG_FILES)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.elf *.bin *.map .*.d *.lds
|
rm -f -- *.o *.elf *.bin *.map .*.d *.lds *.debug
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
#include "stage3a.h"
|
#include "stage3a.h"
|
||||||
|
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
|
#include "boot/error.h"
|
||||||
|
#include "boot/s390.h"
|
||||||
#include "boot/ipl.h"
|
#include "boot/ipl.h"
|
||||||
#include "sclp.h"
|
#include "sclp.h"
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
|
|
||||||
static volatile struct stage3a_args __section(".loader_parms") loader_parms;
|
static volatile struct stage3a_args __section(".loader_parms") loader_parms;
|
||||||
|
|||||||
@@ -93,5 +93,6 @@ SECTIONS
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.interp)
|
*(.interp)
|
||||||
*(.note.GNU-stack)
|
*(.note.GNU-stack)
|
||||||
|
*(.note.package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,11 @@
|
|||||||
|
|
||||||
#include "lib/zt_common.h"
|
#include "lib/zt_common.h"
|
||||||
#include "boot/psw.h"
|
#include "boot/psw.h"
|
||||||
|
#include "boot/error.h"
|
||||||
|
#include "boot/s390.h"
|
||||||
#include "boot/linux_layout.h"
|
#include "boot/linux_layout.h"
|
||||||
#include "boot/loaders_layout.h"
|
#include "boot/loaders_layout.h"
|
||||||
#include "sclp.h"
|
#include "sclp.h"
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
|
|
||||||
static volatile struct stage3b_args __section(".loader_parms") loader_parms;
|
static volatile struct stage3b_args __section(".loader_parms") loader_parms;
|
||||||
@@ -60,13 +61,17 @@ void __noreturn start(void)
|
|||||||
if (cmdline->size > get_kernel_cmdline_size())
|
if (cmdline->size > get_kernel_cmdline_size())
|
||||||
panic(EINTERNAL, "Command line is too large\n");
|
panic(EINTERNAL, "Command line is too large\n");
|
||||||
|
|
||||||
/* move the kernel cmdline */
|
if (cmdline->size > 0) {
|
||||||
memmove((void *)COMMAND_LINE,
|
/* make sure the cmdline is a null-terminated string */
|
||||||
(void *)cmdline->src,
|
if (((char *)cmdline->src)[cmdline->size - 1] != '\0')
|
||||||
cmdline->size);
|
panic(EINTERNAL, "Command line needs to be null-terminated\n");
|
||||||
|
|
||||||
|
/* move the kernel cmdline */
|
||||||
|
memmove((void *)COMMAND_LINE, (void *)cmdline->src, cmdline->size);
|
||||||
|
}
|
||||||
/* the initrd does not need to be moved */
|
/* the initrd does not need to be moved */
|
||||||
|
|
||||||
if (initrd->size != 0) {
|
if (initrd->size > 0) {
|
||||||
/* copy initrd start address and size into new kernel space */
|
/* copy initrd start address and size into new kernel space */
|
||||||
*(unsigned long long *)INITRD_START = initrd->src;
|
*(unsigned long long *)INITRD_START = initrd->src;
|
||||||
*(unsigned long long *)INITRD_SIZE = initrd->size;
|
*(unsigned long long *)INITRD_SIZE = initrd->size;
|
||||||
|
|||||||
@@ -79,5 +79,6 @@ SECTIONS
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.interp)
|
*(.interp)
|
||||||
*(.note.GNU-stack)
|
*(.note.GNU-stack)
|
||||||
|
*(.note.package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,6 @@ SECTIONS
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.interp)
|
*(.interp)
|
||||||
*(.note.GNU-stack)
|
*(.note.GNU-stack)
|
||||||
|
*(.note.package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,18 +97,29 @@ Do not use for a production image unless you verified
|
|||||||
the host-key document before. Optional.
|
the host-key document before. Optional.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-comm\-key\fR=\fI\,FILE\/\fR
|
\fB\-\-comm\-key\fR=\fI\,FILE\/\fR
|
||||||
Specifies the encryption key you want to use for the PV guest dump. Use a
|
Specifies the customer communication key (CCK). This key is used for the
|
||||||
secure, random, plaintext AES-256 GCM key. Optional.
|
PV guest dump encryption and to derive the CCK-derived extension secret
|
||||||
|
used for add-secret requests. Use a secure, random, plaintext AES-256
|
||||||
|
GCM key. Optional.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-enable\-dump\fR
|
\fB\-\-enable\-dump\fR
|
||||||
Enable PV guest dumps. Requires the \fB\-\-comm-key\fR option. Optional.
|
Enable PV guest dumps. Requires the \fB\-\-comm\-key\fR option. Optional.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-disable\-dump\fR
|
\fB\-\-disable\-dump\fR
|
||||||
Disable PV guest dumps. This is the default. Optional.
|
Disable PV guest dumps. This is the default.
|
||||||
|
.TP
|
||||||
|
\fB\-\-enable\-cck\-extension\-secret\fR
|
||||||
|
Add-secret requests must provide an extension secret that matches the
|
||||||
|
CCK-derived extension secret. Requires the \fB\-\-comm\-key\fR option.
|
||||||
|
Optional.
|
||||||
|
.TP
|
||||||
|
\fB\-\-disable\-cck\-extension\-secret\fR
|
||||||
|
Add-secret requests don't have to provide an extension secret. This is
|
||||||
|
the default.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-enable\-pckmo\fR
|
\fB\-\-enable\-pckmo\fR
|
||||||
Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption
|
Enable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption
|
||||||
functions. This is the default. Optional.
|
functions. This is the default.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-disable\-pckmo\fR
|
\fB\-\-disable\-pckmo\fR
|
||||||
Disable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption
|
Disable the support for the DEA, TDEA, AES, and ECC PCKMO key encryption
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Sample script to verify that a host key document is genuine by
|
# Sample script to verify that a host key document is genuine by
|
||||||
# verifying the issuer, the validity date and the signature.
|
# verifying the issuer, the validity date and the signature.
|
||||||
# Optionally verify the full trust chain using a CA certficate.
|
# Optionally verify the full trust chain using a CA certificate.
|
||||||
#
|
#
|
||||||
# Sample invocation:
|
# Sample invocation:
|
||||||
#
|
#
|
||||||
@@ -15,31 +15,33 @@
|
|||||||
# 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.
|
||||||
|
|
||||||
|
|
||||||
# Allocate temporary files
|
# Allocate temporary files
|
||||||
ISSUER_PUBKEY_FILE=$(mktemp)
|
ISSUER_PUBKEY_FILE=$(mktemp)
|
||||||
SIGNATURE_FILE=$(mktemp)
|
SIGNATURE_FILE=$(mktemp)
|
||||||
BODY_FILE=$(mktemp)
|
BODY_FILE=$(mktemp)
|
||||||
ISSUER_DN_FILE=$(mktemp)
|
ISSUER_DN_FILE=$(mktemp)
|
||||||
SUBJECT_DN_FILE=$(mktemp)
|
SUBJECT_DN_FILE=$(mktemp)
|
||||||
DEF_ISSUER_DN_FILE=$(mktemp)
|
DEF_ISSUER_ARMONK_DN_FILE=$(mktemp)
|
||||||
|
DEF_ISSUER_POUGHKEEPSIE_DN_FILE=$(mktemp)
|
||||||
CANONICAL_ISSUER_DN_FILE=$(mktemp)
|
CANONICAL_ISSUER_DN_FILE=$(mktemp)
|
||||||
CRL_SERIAL_FILE=$(mktemp)
|
CRL_SERIAL_FILE=$(mktemp)
|
||||||
|
|
||||||
# Cleanup on exit
|
# Cleanup on exit
|
||||||
cleanup()
|
cleanup()
|
||||||
{
|
{
|
||||||
rm -f $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE \
|
rm -f "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" \
|
||||||
$ISSUER_DN_FILE $SUBJECT_DN_FILE $DEF_ISSUER_DN_FILE \
|
"$ISSUER_DN_FILE" "$SUBJECT_DN_FILE" "$DEF_ISSUER_ARMONK_DN_FILE" "$DEF_ISSUER_POUGHKEEPSIE_DN_FILE" \
|
||||||
$CANONICAL_ISSUER_DN_FILE $CRL_SERIAL_FILE
|
"$CANONICAL_ISSUER_DN_FILE" "$CRL_SERIAL_FILE"
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
# Enhanced error checking for bash
|
# Enhanced error checking for bash
|
||||||
if [ -n "${BASH}" ]
|
if [ -n "${BASH}" ]; then
|
||||||
then
|
# shellcheck disable=SC3040
|
||||||
set -o posix
|
set -o posix
|
||||||
|
# shellcheck disable=SC3040
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
# shellcheck disable=SC3040
|
||||||
set -o nounset
|
set -o nounset
|
||||||
fi
|
fi
|
||||||
set -e
|
set -e
|
||||||
@@ -47,8 +49,8 @@ set -e
|
|||||||
# Usage
|
# Usage
|
||||||
usage()
|
usage()
|
||||||
{
|
{
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
Usage: `basename $1` [-d] [-c CA-cert] [-r CRL] host-key-doc signing-key-cert
|
Usage: $(basename "$1") [-d] [-c CA-cert] [-r CRL] host-key-doc signing-key-cert
|
||||||
|
|
||||||
Verify an IBM Secure Execution host key document against
|
Verify an IBM Secure Execution host key document against
|
||||||
a signing key.
|
a signing key.
|
||||||
@@ -71,8 +73,7 @@ check_verify_chain()
|
|||||||
{
|
{
|
||||||
# Verify certificate chain in case a CA certificate file/bundle
|
# Verify certificate chain in case a CA certificate file/bundle
|
||||||
# was specified on the command line.
|
# was specified on the command line.
|
||||||
if [ $# = 1 ]
|
if [ -z "$2" ]; then
|
||||||
then
|
|
||||||
cat >&2 <<-EOF
|
cat >&2 <<-EOF
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
No CA certificate specified! Skipping trust chain verification.
|
No CA certificate specified! Skipping trust chain verification.
|
||||||
@@ -80,37 +81,37 @@ Make sure that '$1' is a valid certificate.
|
|||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
EOF
|
EOF
|
||||||
else
|
else
|
||||||
openssl verify -crl_download -crl_check $2 &&
|
openssl verify -crl_download -crl_check "$2" &&
|
||||||
openssl verify -crl_download -crl_check -untrusted $2 $1 ||
|
openssl verify -crl_download -crl_check -untrusted "$2" "$1" ||
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_pubkey()
|
extract_pubkey()
|
||||||
{
|
{
|
||||||
openssl x509 -in $1 -pubkey -noout > $2
|
openssl x509 -in "$1" -pubkey -noout >"$2"
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_signature()
|
extract_signature()
|
||||||
{
|
{
|
||||||
# Assuming that the last field is the signature
|
# Assuming that the last field is the signature
|
||||||
SIGOFFSET=$(openssl asn1parse -in $1 | tail -1 | cut -d : -f 1)
|
SIGOFFSET=$(openssl asn1parse -in "$1" | tail -1 | cut -d : -f 1)
|
||||||
|
|
||||||
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
|
openssl asn1parse -in "$1" -out "$2" -strparse "$SIGOFFSET" -noout
|
||||||
}
|
}
|
||||||
|
|
||||||
extract_body()
|
extract_body()
|
||||||
{
|
{
|
||||||
# Assuming that the first field is the full cert body
|
# Assuming that the first field is the full cert body
|
||||||
SIGOFFSET=$(openssl asn1parse -in $1 | head -2 | tail -1 | cut -d : -f 1)
|
SIGOFFSET=$(openssl asn1parse -in "$1" | head -2 | tail -1 | cut -d : -f 1)
|
||||||
|
|
||||||
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
|
openssl asn1parse -in "$1" -out "$2" -strparse "$SIGOFFSET" -noout
|
||||||
}
|
}
|
||||||
|
|
||||||
verify_signature()
|
verify_signature()
|
||||||
{
|
{
|
||||||
# Assuming that the signature algorithm is SHA512 with RSA
|
# Assuming that the signature algorithm is SHA512 with RSA
|
||||||
openssl sha512 -verify $1 -signature $2 $3
|
openssl sha512 -verify "$1" -signature "$2" "$3"
|
||||||
}
|
}
|
||||||
|
|
||||||
canonical_dn()
|
canonical_dn()
|
||||||
@@ -120,18 +121,30 @@ canonical_dn()
|
|||||||
DNTYPE=$3
|
DNTYPE=$3
|
||||||
OUTPUT=$4
|
OUTPUT=$4
|
||||||
|
|
||||||
openssl $OBJTYPE -in $OBJ -$DNTYPE -noout -nameopt multiline \
|
openssl "$OBJTYPE" -in "$OBJ" -"$DNTYPE" -noout -nameopt multiline |
|
||||||
| sort | grep -v $DNTYPE= > $OUTPUT
|
LC_ALL=C sort | grep -v "$DNTYPE"= >"$OUTPUT"
|
||||||
}
|
}
|
||||||
|
|
||||||
default_issuer()
|
default_issuer_armonk()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
commonName = International Business Machines Corporation
|
||||||
|
countryName = US
|
||||||
|
localityName = Armonk
|
||||||
|
organizationName = International Business Machines Corporation
|
||||||
|
organizationalUnitName = Key Signing Service
|
||||||
|
stateOrProvinceName = New York
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
default_issuer_pougkeepsie()
|
||||||
{
|
{
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
commonName = International Business Machines Corporation
|
commonName = International Business Machines Corporation
|
||||||
countryName = US
|
countryName = US
|
||||||
localityName = Poughkeepsie
|
localityName = Poughkeepsie
|
||||||
organizationalUnitName = Key Signing Service
|
|
||||||
organizationName = International Business Machines Corporation
|
organizationName = International Business Machines Corporation
|
||||||
|
organizationalUnitName = Key Signing Service
|
||||||
stateOrProvinceName = New York
|
stateOrProvinceName = New York
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@@ -141,42 +154,37 @@ EOF
|
|||||||
# stripping off the prefix
|
# stripping off the prefix
|
||||||
verify_default_issuer()
|
verify_default_issuer()
|
||||||
{
|
{
|
||||||
default_issuer > $DEF_ISSUER_DN_FILE
|
default_issuer_pougkeepsie >"$DEF_ISSUER_POUGHKEEPSIE_DN_FILE"
|
||||||
|
default_issuer_armonk >"$DEF_ISSUER_ARMONK_DN_FILE"
|
||||||
|
|
||||||
sed "s/\(^[ ]*organizationalUnitName[ ]*=[ ]*\).*\(Key Signing Service$\)/\1\2/" \
|
sed "s/\(^[ ]*organizationalUnitName[ ]*=[ ]*\).*\(Key Signing Service$\)/\1\2/" \
|
||||||
$ISSUER_DN_FILE > $CANONICAL_ISSUER_DN_FILE
|
"$ISSUER_DN_FILE" >"$CANONICAL_ISSUER_DN_FILE"
|
||||||
|
|
||||||
if ! diff $CANONICAL_ISSUER_DN_FILE $DEF_ISSUER_DN_FILE
|
if ! {
|
||||||
then
|
diff "$CANONICAL_ISSUER_DN_FILE" "$DEF_ISSUER_POUGHKEEPSIE_DN_FILE" ||
|
||||||
|
diff "$CANONICAL_ISSUER_DN_FILE" "$DEF_ISSUER_ARMONK_DN_FILE"
|
||||||
|
} >/dev/null 2>&1; then
|
||||||
echo Incorrect default issuer >&2 && exit 1
|
echo Incorrect default issuer >&2 && exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
verify_issuer_files()
|
verify_issuer_files()
|
||||||
{
|
{
|
||||||
if [ $1 -eq 1 ]
|
if [ "$1" -eq 1 ]; then
|
||||||
then
|
verify_default_issuer
|
||||||
verify_default_issuer
|
|
||||||
fi
|
|
||||||
|
|
||||||
if diff $ISSUER_DN_FILE $SUBJECT_DN_FILE
|
|
||||||
then
|
|
||||||
echo Issuer verification OK
|
|
||||||
else
|
|
||||||
echo Issuer verification failed >&2 && exit 1
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
cert_time()
|
cert_time()
|
||||||
{
|
{
|
||||||
DATE=$(openssl x509 -in $1 -$2 -noout | sed "s/^.*=//")
|
DATE=$(openssl x509 -in "$1" -"$2" -noout | sed "s/^.*=//")
|
||||||
|
|
||||||
date -d "$DATE" +%s
|
date -d "$DATE" +%s
|
||||||
}
|
}
|
||||||
|
|
||||||
crl_time()
|
crl_time()
|
||||||
{
|
{
|
||||||
DATE=$(openssl crl -in $1 -$2 -noout | sed "s/^.*=//")
|
DATE=$(openssl crl -in "$1" -"$2" -noout | sed "s/^.*=//")
|
||||||
|
|
||||||
date -d "$DATE" +%s
|
date -d "$DATE" +%s
|
||||||
}
|
}
|
||||||
@@ -188,8 +196,7 @@ verify_dates()
|
|||||||
MSG="${3:-Certificate}"
|
MSG="${3:-Certificate}"
|
||||||
NOW=$(date +%s)
|
NOW=$(date +%s)
|
||||||
|
|
||||||
if [ $START -le $NOW -a $NOW -le $END ]
|
if [ "$START" -le "$NOW" ] && [ "$NOW" -le "$END" ]; then
|
||||||
then
|
|
||||||
echo "${MSG} dates are OK"
|
echo "${MSG} dates are OK"
|
||||||
else
|
else
|
||||||
echo "${MSG} date verification failed" >&2 && exit 1
|
echo "${MSG} date verification failed" >&2 && exit 1
|
||||||
@@ -198,22 +205,21 @@ verify_dates()
|
|||||||
|
|
||||||
crl_serials()
|
crl_serials()
|
||||||
{
|
{
|
||||||
openssl crl -in $1 -text -noout | \
|
openssl crl -in "$1" -text -noout |
|
||||||
grep "Serial Number" > $CRL_SERIAL_FILE
|
grep "Serial Number" >"$CRL_SERIAL_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_serial()
|
check_serial()
|
||||||
{
|
{
|
||||||
CERT_SERIAL=$(openssl x509 -in $1 -noout -serial | cut -d = -f 2)
|
CERT_SERIAL=$(openssl x509 -in "$1" -noout -serial | cut -d = -f 2)
|
||||||
|
|
||||||
grep -q $CERT_SERIAL $CRL_SERIAL_FILE
|
grep -q "$CERT_SERIAL" "$CRL_SERIAL_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_file()
|
check_file()
|
||||||
{
|
{
|
||||||
[ $# = 0 ] ||
|
|
||||||
[ -e "$1" ] ||
|
[ -e "$1" ] ||
|
||||||
(echo "File '$1' not found" >&2 && exit 1)
|
(echo "File '$1' not found" >&2 && exit 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
# check args
|
# check args
|
||||||
@@ -221,28 +227,25 @@ CRL_FILE=
|
|||||||
CA_FILE=
|
CA_FILE=
|
||||||
CHECK_DEFAULT_ISSUER=1
|
CHECK_DEFAULT_ISSUER=1
|
||||||
|
|
||||||
args=$(getopt -qu "dr:c:h" $*)
|
while getopts 'dr:c:h' opt; do
|
||||||
if [ $? = 0 ]
|
case $opt in
|
||||||
then
|
d) CHECK_DEFAULT_ISSUER=0 ;;
|
||||||
set -- $args
|
r) CRL_FILE=$OPTARG ;;
|
||||||
while [ $1 != "" ]
|
c) CA_FILE=$OPTARG ;;
|
||||||
do
|
h)
|
||||||
case $1 in
|
usage "$0"
|
||||||
-d) CHECK_DEFAULT_ISSUER=0; shift;;
|
exit 0
|
||||||
-r) CRL_FILE=$2; shift 2;;
|
;;
|
||||||
-c) CA_FILE=$2; shift 2;;
|
?)
|
||||||
-h) usage $0; exit 0;;
|
usage "$0"
|
||||||
--) shift; break;;
|
exit 1
|
||||||
esac
|
;;
|
||||||
done
|
esac
|
||||||
else
|
done
|
||||||
usage $0 >&2
|
shift "$((OPTIND - 1))"
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $# -ne 2 ]
|
if [ $# -ne 2 ]; then
|
||||||
then
|
usage "$0" >&2
|
||||||
usage $0 >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -250,51 +253,51 @@ HKD_FILE=$1
|
|||||||
HKSK_FILE=$2
|
HKSK_FILE=$2
|
||||||
|
|
||||||
# Check whether all specified files exist
|
# Check whether all specified files exist
|
||||||
check_file $HKD_FILE
|
check_file "$HKD_FILE"
|
||||||
check_file $HKSK_FILE
|
check_file "$HKSK_FILE"
|
||||||
check_file $CA_FILE
|
# CA and CRL are optional arguments
|
||||||
check_file $CRL_FILE
|
[ -n "$CA_FILE" ] && check_file "$CA_FILE"
|
||||||
|
[ -n "$CRL_FILE" ] && check_file "$CRL_FILE"
|
||||||
|
|
||||||
# Check trust chain
|
# Check trust chain
|
||||||
check_verify_chain $HKSK_FILE $CA_FILE
|
check_verify_chain "$HKSK_FILE" "$CA_FILE"
|
||||||
|
|
||||||
# Verify host key document signature
|
# Verify host key document signature
|
||||||
echo -n "Checking host key document signature: "
|
printf "Checking host key document signature: "
|
||||||
extract_pubkey $HKSK_FILE $ISSUER_PUBKEY_FILE &&
|
extract_pubkey "$HKSK_FILE" "$ISSUER_PUBKEY_FILE" &&
|
||||||
extract_signature $HKD_FILE $SIGNATURE_FILE &&
|
extract_signature "$HKD_FILE" "$SIGNATURE_FILE" &&
|
||||||
extract_body $HKD_FILE $BODY_FILE &&
|
extract_body "$HKD_FILE" "$BODY_FILE" &&
|
||||||
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
|
verify_signature "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" ||
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
# Verify the issuer
|
# Verify the issuer
|
||||||
canonical_dn x509 $HKD_FILE issuer $ISSUER_DN_FILE
|
canonical_dn x509 "$HKD_FILE" issuer "$ISSUER_DN_FILE"
|
||||||
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
|
canonical_dn x509 "$HKSK_FILE" subject "$SUBJECT_DN_FILE"
|
||||||
verify_issuer_files $CHECK_DEFAULT_ISSUER
|
verify_issuer_files $CHECK_DEFAULT_ISSUER
|
||||||
|
|
||||||
# Verify dates
|
# Verify dates
|
||||||
verify_dates $(cert_time $HKD_FILE startdate) $(cert_time $HKD_FILE enddate)
|
verify_dates "$(cert_time "$HKD_FILE" startdate)" "$(cert_time "$HKD_FILE" enddate)"
|
||||||
|
|
||||||
# Check CRL if specified
|
# Check CRL if specified
|
||||||
if [ -n "$CRL_FILE" ]
|
if [ -n "$CRL_FILE" ]; then
|
||||||
then
|
printf "Checking CRL signature: "
|
||||||
echo -n "Checking CRL signature: "
|
extract_signature "$CRL_FILE" "$SIGNATURE_FILE" &&
|
||||||
extract_signature $CRL_FILE $SIGNATURE_FILE &&
|
extract_body "$CRL_FILE" "$BODY_FILE" &&
|
||||||
extract_body $CRL_FILE $BODY_FILE &&
|
verify_signature "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" ||
|
||||||
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
|
exit 1
|
||||||
exit 1
|
|
||||||
|
|
||||||
echo -n "CRL "
|
printf "CRL "
|
||||||
canonical_dn crl $CRL_FILE issuer $ISSUER_DN_FILE
|
canonical_dn crl "$CRL_FILE" issuer "$ISSUER_DN_FILE"
|
||||||
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
|
canonical_dn x509 "$HKSK_FILE" subject "$SUBJECT_DN_FILE"
|
||||||
verify_issuer_files $CHECK_DEFAULT_ISSUER
|
verify_issuer_files $CHECK_DEFAULT_ISSUER
|
||||||
|
|
||||||
verify_dates $(crl_time $CRL_FILE lastupdate) $(crl_time $CRL_FILE nextupdate) 'CRL'
|
verify_dates "$(crl_time "$CRL_FILE" lastupdate)" "$(crl_time "$CRL_FILE" nextupdate)" 'CRL'
|
||||||
|
|
||||||
crl_serials $CRL_FILE
|
crl_serials "$CRL_FILE"
|
||||||
check_serial $HKD_FILE &&
|
check_serial "$HKD_FILE" &&
|
||||||
echo "Certificate is revoked, do not use it anymore!" >&2 &&
|
echo "Certificate is revoked, do not use it anymore!" >&2 &&
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We made it
|
# We made it
|
||||||
echo All checks reqested for \'$HKD_FILE\' were successful
|
echo All checks requested for \'"$HKD_FILE"\' were successful
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ include ../../common.mak
|
|||||||
|
|
||||||
bin_PROGRAM = genprotimg
|
bin_PROGRAM = genprotimg
|
||||||
|
|
||||||
PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
|
PKGDATADIR ?= "$(TOOLS_DATADIR)/genprotimg"
|
||||||
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
|
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||||
TOP_SRCDIR := $(SRC_DIR)/../
|
TOP_SRCDIR := $(SRC_DIR)/../
|
||||||
ROOT_DIR = $(TOP_SRC_DIR)/../../
|
ROOT_DIR = $(TOP_SRC_DIR)/../../
|
||||||
@@ -27,7 +27,7 @@ $(bin_PROGRAM)_SRCS := $(bin_PROGRAM).c pv/pv_stage3.c pv/pv_image.c \
|
|||||||
$(NULL)
|
$(NULL)
|
||||||
$(bin_PROGRAM)_OBJS := $($(bin_PROGRAM)_SRCS:.c=.o)
|
$(bin_PROGRAM)_OBJS := $($(bin_PROGRAM)_SRCS:.c=.o)
|
||||||
|
|
||||||
ALL_CFLAGS += -std=gnu11 -DPKGDATADIR=$(PKGDATADIR) \
|
ALL_CFLAGS += -DPKGDATADIR=$(PKGDATADIR) \
|
||||||
$(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBCURL_CFLAGS) \
|
$(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBCURL_CFLAGS) \
|
||||||
-DOPENSSL_API_COMPAT=0x10100000L \
|
-DOPENSSL_API_COMPAT=0x10100000L \
|
||||||
$(WARNINGS) \
|
$(WARNINGS) \
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
/* IBM signing key subject */
|
/* IBM signing key subject */
|
||||||
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
|
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
|
||||||
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
|
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
|
||||||
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
|
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
|
||||||
|
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
|
||||||
#define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service"
|
#define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service"
|
||||||
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
|
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
|
||||||
#define PV_IBM_Z_SUBJECT_STATE "New York"
|
#define PV_IBM_Z_SUBJECT_STATE "New York"
|
||||||
|
|||||||
@@ -34,6 +34,10 @@
|
|||||||
#define PV_PCF_PCKMO_AES __PV_BIT(57) /* PCKMO encrypt-AES-key functions allowed */
|
#define PV_PCF_PCKMO_AES __PV_BIT(57) /* PCKMO encrypt-AES-key functions allowed */
|
||||||
#define PV_PCF_PCKM_ECC __PV_BIT(58) /* PCKMO encrypt-ECC-key functions allowed */
|
#define PV_PCF_PCKM_ECC __PV_BIT(58) /* PCKMO encrypt-ECC-key functions allowed */
|
||||||
|
|
||||||
|
/* Secret control flags */
|
||||||
|
#define PV_SCF_CCK_EXTENSION_SECRET_ENFORCMENT \
|
||||||
|
__PV_BIT(1) /* All add-secret requests must provide an extension secret */
|
||||||
|
|
||||||
/* maxima for the PV version 1 */
|
/* maxima for the PV version 1 */
|
||||||
#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE
|
#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE
|
||||||
#define PV_V1_PV_HDR_MAX_SIZE (2 * PAGE_SIZE)
|
#define PV_V1_PV_HDR_MAX_SIZE (2 * PAGE_SIZE)
|
||||||
|
|||||||
@@ -62,11 +62,12 @@ static gint pv_args_set_defaults(PvArgs *args, GError **err G_GNUC_UNUSED)
|
|||||||
|
|
||||||
static gint pv_args_validate_options(PvArgs *args, GError **err)
|
static gint pv_args_validate_options(PvArgs *args, GError **err)
|
||||||
{
|
{
|
||||||
|
const PvControlFlagsArgs *cf_args = &args->cf_args;
|
||||||
PvComponentType KERNEL = PV_COMP_TYPE_KERNEL;
|
PvComponentType KERNEL = PV_COMP_TYPE_KERNEL;
|
||||||
|
|
||||||
/* Check for mutually exclusive arguments */
|
/* Check for mutually exclusive arguments */
|
||||||
if (args->pcf && !(args->allow_pckmo == PV_NOT_SET &&
|
if (cf_args->pcf &&
|
||||||
args->allow_dump == PV_NOT_SET)) {
|
!(cf_args->enable_pckmo == PV_NOT_SET && cf_args->enable_dump == PV_NOT_SET)) {
|
||||||
g_set_error(
|
g_set_error(
|
||||||
err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
|
err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
|
||||||
_("The '--x-pcf' option cannot be used with the '--(enable|disable)-pckmo' or"
|
_("The '--x-pcf' option cannot be used with the '--(enable|disable)-pckmo' or"
|
||||||
@@ -74,6 +75,13 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cf_args->scf && !(cf_args->enable_cck_extension_secret_enforcement == PV_NOT_SET)) {
|
||||||
|
g_set_error(
|
||||||
|
err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
|
||||||
|
_("The '--x-scf' option cannot be used with the '--(enable|disable)-extension-secret-required' flags.\nUse 'genprotimg --help' for more information"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for unused arguments */
|
/* Check for unused arguments */
|
||||||
if (args->unused_values->len > 0) {
|
if (args->unused_values->len > 0) {
|
||||||
g_autofree gchar *unused = NULL;
|
g_autofree gchar *unused = NULL;
|
||||||
@@ -93,12 +101,20 @@ static gint pv_args_validate_options(PvArgs *args, GError **err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for mandatory arguments */
|
/* Check for mandatory arguments */
|
||||||
if (args->allow_dump == PV_TRUE && !args->cust_comm_key_path) {
|
if (cf_args->enable_dump == PV_TRUE && !args->cust_comm_key_path) {
|
||||||
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
|
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
|
||||||
_("Option '--allow-dump' requires the '--comm-key' option.\nUse 'genprotimg "
|
_("Option '--enable-dump' requires the '--comm-key' option.\nUse 'genprotimg "
|
||||||
"--help' for more information"));
|
"--help' for more information"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (cf_args->enable_cck_extension_secret_enforcement == PV_TRUE &&
|
||||||
|
!args->cust_comm_key_path) {
|
||||||
|
g_set_error(
|
||||||
|
err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
|
||||||
|
_("Option '--enable-cck-extension-secret' requires the '--comm-key' option.\nUse 'genprotimg "
|
||||||
|
"--help' for more information"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!args->output_path) {
|
if (!args->output_path) {
|
||||||
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
|
g_set_error(err, PV_PARSE_ERROR, PR_PARSE_ERROR_MISSING_ARGUMENT,
|
||||||
@@ -178,11 +194,11 @@ static gboolean cb_set_string_option(const gchar *option, const gchar *value,
|
|||||||
if (g_str_equal(option, "--x-header-key"))
|
if (g_str_equal(option, "--x-header-key"))
|
||||||
args_option = &args->cust_root_key_path;
|
args_option = &args->cust_root_key_path;
|
||||||
if (g_str_equal(option, "--x-pcf"))
|
if (g_str_equal(option, "--x-pcf"))
|
||||||
args_option = &args->pcf;
|
args_option = &args->cf_args.pcf;
|
||||||
if (g_str_equal(option, "--x-psw"))
|
if (g_str_equal(option, "--x-psw"))
|
||||||
args_option = &args->psw_addr;
|
args_option = &args->psw_addr;
|
||||||
if (g_str_equal(option, "--x-scf"))
|
if (g_str_equal(option, "--x-scf"))
|
||||||
args_option = &args->scf;
|
args_option = &args->cf_args.scf;
|
||||||
|
|
||||||
if (!args_option) {
|
if (!args_option) {
|
||||||
g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
|
g_set_error(err, PV_PARSE_ERROR, PV_PARSE_ERROR_SYNTAX,
|
||||||
@@ -217,49 +233,48 @@ static gboolean cb_remaining_values(const gchar *option G_GNUC_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE) (cb_##FLAG##_##VALUE)
|
#define MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE) (cb_##FLAG##_##VALUE)
|
||||||
#define DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, VALUE) \
|
#define DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, VALUE) \
|
||||||
static gboolean MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE)( \
|
static gboolean MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, VALUE)(const gchar *option G_GNUC_UNUSED, \
|
||||||
const gchar *option G_GNUC_UNUSED, const gchar *value G_GNUC_UNUSED, \
|
const gchar *value G_GNUC_UNUSED, \
|
||||||
PvArgs *args, GError **err) \
|
PvArgs *args, GError **err) \
|
||||||
{ \
|
{ \
|
||||||
if (!(args->allow_##FLAG == PV_NOT_SET || \
|
if (!(args->cf_args.enable_##FLAG == PV_NOT_SET || \
|
||||||
args->allow_##FLAG == VALUE)) { \
|
args->cf_args.enable_##FLAG == VALUE)) { \
|
||||||
g_set_error(err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, \
|
g_set_error(err, G_OPTION_ERROR, G_OPTION_ERROR_FAILED, \
|
||||||
"'--enable-" #FLAG "' and '--disable-" #FLAG \
|
"'--enable-" #FLAG "' and '--disable-" #FLAG \
|
||||||
"' are mutually exclusive"); \
|
"' are mutually exclusive"); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
} \
|
} \
|
||||||
args->allow_##FLAG = VALUE; \
|
args->cf_args.enable_##FLAG = VALUE; \
|
||||||
return TRUE; \
|
return TRUE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_MUT_EXCL_BOOL_FLAG_CBS(FLAG) \
|
#define DEFINE_MUT_EXCL_BOOL_FLAG_CBS(FLAG) \
|
||||||
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_TRUE) \
|
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_TRUE) \
|
||||||
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_FALSE)
|
DEFINE_MUT_EXCL_BOOL_FLAG_CB(FLAG, PV_FALSE)
|
||||||
|
|
||||||
#define MUT_EXCL_BOOL_FLAG(FLAG, ENABLE_DESC, DISABLE_DESC) \
|
#define MUT_EXCL_BOOL_FLAG(NAME, FLAG, ENABLE_DESC, DISABLE_DESC) \
|
||||||
{ \
|
{ \
|
||||||
.long_name = "enable-" #FLAG, \
|
.long_name = "enable-" #NAME, \
|
||||||
.short_name = 0, \
|
.short_name = 0, \
|
||||||
.flags = G_OPTION_FLAG_NO_ARG, \
|
.flags = G_OPTION_FLAG_NO_ARG, \
|
||||||
.arg = G_OPTION_ARG_CALLBACK, \
|
.arg = G_OPTION_ARG_CALLBACK, \
|
||||||
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_TRUE), \
|
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_TRUE), \
|
||||||
.description = ENABLE_DESC, \
|
.description = ENABLE_DESC, \
|
||||||
}, \
|
}, \
|
||||||
{ \
|
{ \
|
||||||
.long_name = "disable-" #FLAG, \
|
.long_name = "disable-" #NAME, .short_name = 0, .flags = G_OPTION_FLAG_NO_ARG, \
|
||||||
.short_name = 0, \
|
.arg = G_OPTION_ARG_CALLBACK, \
|
||||||
.flags = G_OPTION_FLAG_NO_ARG, \
|
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_FALSE), \
|
||||||
.arg = G_OPTION_ARG_CALLBACK, \
|
.description = DISABLE_DESC, \
|
||||||
.arg_data = MUT_EXCL_BOOL_FLAG_CB_NAME(FLAG, PV_FALSE), \
|
|
||||||
.description = DISABLE_DESC, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INDENT " "
|
#define INDENT " "
|
||||||
|
|
||||||
/* Define the callbacks for mutually exclusive command line flags */
|
/* Define the callbacks for mutually exclusive command line flags */
|
||||||
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(dump)
|
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(dump);
|
||||||
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(pckmo)
|
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(pckmo);
|
||||||
|
DEFINE_MUT_EXCL_BOOL_FLAG_CBS(cck_extension_secret_enforcement);
|
||||||
|
|
||||||
gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
|
gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
|
||||||
GError **err)
|
GError **err)
|
||||||
@@ -280,7 +295,7 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
|
|||||||
.arg_data = &args->host_keys,
|
.arg_data = &args->host_keys,
|
||||||
.description =
|
.description =
|
||||||
_("FILE specifies a host-key document. At least\n" INDENT
|
_("FILE specifies a host-key document. At least\n" INDENT
|
||||||
"one is required Specify this option multiple times\n" INDENT
|
"one is required. Specify this option multiple times\n" INDENT
|
||||||
"to enable the image to run on more than one host."),
|
"to enable the image to run on more than one host."),
|
||||||
.arg_description = _("FILE") },
|
.arg_description = _("FILE") },
|
||||||
{ .long_name = "cert",
|
{ .long_name = "cert",
|
||||||
@@ -325,27 +340,31 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
|
|||||||
.description = _("Use the kernel parameters stored in PARMFILE\n" INDENT
|
.description = _("Use the kernel parameters stored in PARMFILE\n" INDENT
|
||||||
"(optional)."),
|
"(optional)."),
|
||||||
.arg_description = _("PARMFILE") },
|
.arg_description = _("PARMFILE") },
|
||||||
|
MUT_EXCL_BOOL_FLAG(dump, dump,
|
||||||
|
_("Enable PV guest dumps (optional). This option\n" INDENT
|
||||||
|
"requires the '--comm-key' option."),
|
||||||
|
_("Disable PV guest dumps (default).")),
|
||||||
MUT_EXCL_BOOL_FLAG(
|
MUT_EXCL_BOOL_FLAG(
|
||||||
dump,
|
cck-extension-secret, cck_extension_secret_enforcement,
|
||||||
_("Enable PV guest dumps (optional). This option\n" INDENT
|
_("Add-secret requests must provide an extension\n" INDENT
|
||||||
"requires the '--comm-key' option."),
|
"secret that matches the CCK-derived extension\n" INDENT
|
||||||
_("Disable PV guest dumps (default) (optional).")),
|
"secret (optional). This option requires the\n" INDENT
|
||||||
MUT_EXCL_BOOL_FLAG(
|
"'--comm-key' option."),
|
||||||
pckmo,
|
_("Add-secret requests don't have to provide\n" INDENT
|
||||||
_("Enable the support for the DEA, TDEA, AES, and\n" INDENT
|
"the CCK-derived extension secret (default).")),
|
||||||
"ECC PCKMO key encryption functions (default)\n" INDENT
|
MUT_EXCL_BOOL_FLAG(pckmo, pckmo,
|
||||||
"(optional)."),
|
_("Enable the support for the DEA, TDEA, AES, and\n" INDENT
|
||||||
_("Disable the support for the DEA, TDEA, AES, and\n" INDENT
|
"ECC PCKMO key encryption functions (default)."),
|
||||||
"ECC PCKMO key encryption functions (optional).")),
|
_("Disable the support for the DEA, TDEA, AES, and\n" INDENT
|
||||||
|
"ECC PCKMO key encryption functions (optional).")),
|
||||||
{ .long_name = "comm-key",
|
{ .long_name = "comm-key",
|
||||||
.short_name = 0,
|
.short_name = 0,
|
||||||
.flags = G_OPTION_FLAG_FILENAME,
|
.flags = G_OPTION_FLAG_FILENAME,
|
||||||
.arg = G_OPTION_ARG_CALLBACK,
|
.arg = G_OPTION_ARG_CALLBACK,
|
||||||
.arg_data = cb_set_string_option,
|
.arg_data = cb_set_string_option,
|
||||||
.description = _(
|
.description = _(
|
||||||
"FILE contains the key with which you encrypt\n" INDENT
|
"FILE contains the customer communication key\n" INDENT
|
||||||
"the PV guest dump (optional). Required by\n" INDENT
|
"(CCK) (optional)."),
|
||||||
"the '--enable-dump' option."),
|
|
||||||
.arg_description = _("FILE") },
|
.arg_description = _("FILE") },
|
||||||
{ .long_name = "crl",
|
{ .long_name = "crl",
|
||||||
.short_name = 0,
|
.short_name = 0,
|
||||||
@@ -450,6 +469,8 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
|
|||||||
.arg_data = cb_set_string_option,
|
.arg_data = cb_set_string_option,
|
||||||
.description = _("Specify the secret control flags\n" INDENT
|
.description = _("Specify the secret control flags\n" INDENT
|
||||||
"as a hexadecimal value.\n" INDENT
|
"as a hexadecimal value.\n" INDENT
|
||||||
|
"Optional; mutually exclusive with\n" INDENT
|
||||||
|
"'--(enable|disable)-cck-extension-secret';\n" INDENT
|
||||||
"Optional; default: '0x0'."),
|
"Optional; default: '0x0'."),
|
||||||
.arg_description = _("VALUE") },
|
.arg_description = _("VALUE") },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
@@ -487,8 +508,10 @@ PvArgs *pv_args_new(void)
|
|||||||
g_autoptr(PvArgs) args = g_new0(PvArgs, 1);
|
g_autoptr(PvArgs) args = g_new0(PvArgs, 1);
|
||||||
|
|
||||||
args->unused_values = g_ptr_array_new_with_free_func(g_free);
|
args->unused_values = g_ptr_array_new_with_free_func(g_free);
|
||||||
args->allow_dump = PV_NOT_SET;
|
/* `args->cf_args` is implicitly initialized with zeros since
|
||||||
args->allow_pckmo = PV_NOT_SET;
|
* `g_new0` is used. So there is no reason to explicitly
|
||||||
|
* initialize the values as PV_NOT_SET == 0.
|
||||||
|
*/
|
||||||
return g_steal_pointer(&args);
|
return g_steal_pointer(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,8 +520,8 @@ void pv_args_free(PvArgs *args)
|
|||||||
if (!args)
|
if (!args)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_free(args->pcf);
|
g_free(args->cf_args.pcf);
|
||||||
g_free(args->scf);
|
g_free(args->cf_args.scf);
|
||||||
g_free(args->psw_addr);
|
g_free(args->psw_addr);
|
||||||
g_free(args->cust_root_key_path);
|
g_free(args->cust_root_key_path);
|
||||||
g_free(args->cust_comm_key_path);
|
g_free(args->cust_comm_key_path);
|
||||||
|
|||||||
@@ -23,19 +23,27 @@ PvArg *pv_arg_new(PvComponentType type, const gchar *path);
|
|||||||
void pv_arg_free(PvArg *arg);
|
void pv_arg_free(PvArg *arg);
|
||||||
|
|
||||||
typedef enum pv_tristate {
|
typedef enum pv_tristate {
|
||||||
PV_NOT_SET = 0,
|
PV_NOT_SET = 0,
|
||||||
PV_TRUE,
|
PV_TRUE,
|
||||||
PV_FALSE,
|
PV_FALSE,
|
||||||
} PvTristate;
|
} PvTristate;
|
||||||
|
/* The value of PV_NOT_SET is not allowed to be changed */
|
||||||
|
STATIC_ASSERT(PV_NOT_SET == 0)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gchar *pcf;
|
||||||
|
gchar *scf;
|
||||||
|
/* Add-secret requests do require CCK-extension secrets */
|
||||||
|
PvTristate enable_cck_extension_secret_enforcement;
|
||||||
|
PvTristate enable_dump;
|
||||||
|
PvTristate enable_pckmo;
|
||||||
|
} PvControlFlagsArgs;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
gint log_level;
|
gint log_level;
|
||||||
gint no_verify;
|
gint no_verify;
|
||||||
gboolean offline;
|
gboolean offline;
|
||||||
gchar *pcf;
|
PvControlFlagsArgs cf_args;
|
||||||
gchar *scf;
|
|
||||||
PvTristate allow_dump;
|
|
||||||
PvTristate allow_pckmo;
|
|
||||||
gchar *psw_addr; /* PSW address which will be used for the start of
|
gchar *psw_addr; /* PSW address which will be used for the start of
|
||||||
* the actual component (e.g. Linux kernel)
|
* the actual component (e.g. Linux kernel)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -228,37 +228,40 @@ static gint pv_img_set_psw_addr(PvImage *img, const gchar *psw_addr_s,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint pv_img_set_control_flags(PvImage *img, const gchar *pcf_s,
|
static void pv_img_set_control_flag(uint64_t *flags, const PvTristate option, const uint64_t flag)
|
||||||
const gchar *scf_s,
|
{
|
||||||
PvTristate allow_dump,
|
if (option == PV_TRUE)
|
||||||
PvTristate allow_pckmo, GError **err)
|
*flags |= flag;
|
||||||
|
else if (option == PV_FALSE)
|
||||||
|
*flags &= ~flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint pv_img_set_control_flags(PvImage *img, const PvControlFlagsArgs *cf_args, GError **err)
|
||||||
{
|
{
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
if (pcf_s) {
|
/* Set plain control flags */
|
||||||
if (hex_str_toull(pcf_s, &flags, err) < 0)
|
if (cf_args->pcf) {
|
||||||
|
if (hex_str_toull(cf_args->pcf, &flags, err) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
img->pcf = flags;
|
img->pcf = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scf_s) {
|
pv_img_set_control_flag(&img->pcf, cf_args->enable_dump, PV_PCF_ALLOW_DUMPING);
|
||||||
if (hex_str_toull(scf_s, &flags, err) < 0)
|
pv_img_set_control_flag(&img->pcf, cf_args->enable_pckmo,
|
||||||
|
PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA);
|
||||||
|
|
||||||
|
/* Set secret control flags */
|
||||||
|
if (cf_args->scf) {
|
||||||
|
if (hex_str_toull(cf_args->scf, &flags, err) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
img->scf = flags;
|
img->scf = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allow_dump == PV_TRUE)
|
pv_img_set_control_flag(&img->scf, cf_args->enable_cck_extension_secret_enforcement,
|
||||||
img->pcf |= PV_PCF_ALLOW_DUMPING;
|
PV_SCF_CCK_EXTENSION_SECRET_ENFORCMENT);
|
||||||
else if (allow_dump == PV_FALSE)
|
|
||||||
img->pcf &= ~PV_PCF_ALLOW_DUMPING;
|
|
||||||
|
|
||||||
if (allow_pckmo == PV_TRUE)
|
|
||||||
img->pcf |= PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA;
|
|
||||||
else if (allow_pckmo == PV_FALSE)
|
|
||||||
img->pcf &= ~(PV_PCF_PCKM_ECC | PV_PCF_PCKMO_AES | PV_PCF_PCKMO_DEA_TDEA);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,9 +613,7 @@ PvImage *pv_img_new(PvArgs *args, const gchar *stage3a_path, GError **err)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* set the control flags: PCF and SCF */
|
/* set the control flags: PCF and SCF */
|
||||||
if (pv_img_set_control_flags(ret, args->pcf, args->scf,
|
if (pv_img_set_control_flags(ret, &args->cf_args, err) < 0)
|
||||||
args->allow_dump, args->allow_pckmo,
|
|
||||||
err) < 0)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* read in the keys */
|
/* read in the keys */
|
||||||
@@ -683,7 +684,26 @@ gint pv_img_add_component(PvImage *img, const PvArg *arg, GError **err)
|
|||||||
{
|
{
|
||||||
g_autoptr(PvComponent) comp = NULL;
|
g_autoptr(PvComponent) comp = NULL;
|
||||||
|
|
||||||
comp = pv_component_new_file(arg->type, arg->path, err);
|
switch (arg->type) {
|
||||||
|
case PV_COMP_TYPE_INITRD:
|
||||||
|
case PV_COMP_TYPE_KERNEL:
|
||||||
|
case PV_COMP_TYPE_STAGE3B:
|
||||||
|
comp = pv_component_new_file(arg->type, arg->path, err);
|
||||||
|
break;
|
||||||
|
case PV_COMP_TYPE_CMDLINE: {
|
||||||
|
g_autoptr(PvBuffer) buf = NULL;
|
||||||
|
g_autofree char *data = NULL;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
if (!g_file_get_contents(arg->path, &data, &length, err))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Add one for the null terminator */
|
||||||
|
buf = pv_buffer_take(g_steal_pointer(&data), length + 1);
|
||||||
|
comp = pv_component_new_buf(arg->type, buf, err);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!comp)
|
if (!comp)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ static gint pv_ipib_init(IplParameterBlock *ipib, GSList *comps,
|
|||||||
ipib_size = MAX(ipl_pl_hdr_size + blk0_len, (uint32_t)PAGE_SIZE);
|
ipib_size = MAX(ipl_pl_hdr_size + blk0_len, (uint32_t)PAGE_SIZE);
|
||||||
g_assert(pv_ipib_get_size(comps_length) == ipib_size);
|
g_assert(pv_ipib_get_size(comps_length) == ipib_size);
|
||||||
|
|
||||||
pv->pbt = IPL_TYPE_PV;
|
pv->pbt = IPL_PBT_PV;
|
||||||
pv->len = GUINT32_TO_BE(blk0_len);
|
pv->len = GUINT32_TO_BE(blk0_len);
|
||||||
pv->num_comp = GUINT32_TO_BE(comps_length);
|
pv->num_comp = GUINT32_TO_BE(comps_length);
|
||||||
/* both values will be overwritten during the IPL process by
|
/* both values will be overwritten during the IPL process by
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ PvBuffer *pv_buffer_alloc(gsize size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PvBuffer *pv_buffer_take(char *data, gsize size)
|
||||||
|
{
|
||||||
|
PvBuffer *ret = g_new0(PvBuffer, 1);
|
||||||
|
|
||||||
|
ret->data = data;
|
||||||
|
ret->size = size;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
PvBuffer *pv_buffer_dup(const PvBuffer *buf, gboolean page_aligned)
|
PvBuffer *pv_buffer_dup(const PvBuffer *buf, gboolean page_aligned)
|
||||||
{
|
{
|
||||||
PvBuffer *ret;
|
PvBuffer *ret;
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ typedef struct PvBuffer {
|
|||||||
} PvBuffer;
|
} PvBuffer;
|
||||||
|
|
||||||
PvBuffer *pv_buffer_alloc(gsize size);
|
PvBuffer *pv_buffer_alloc(gsize size);
|
||||||
|
/* After this call @data belongs to the PvBuffer and must no longer be modified
|
||||||
|
* by the caller.
|
||||||
|
*/
|
||||||
|
PvBuffer *pv_buffer_take(char *data, gsize size);
|
||||||
void pv_buffer_free(PvBuffer *buf);
|
void pv_buffer_free(PvBuffer *buf);
|
||||||
void pv_buffer_clear(PvBuffer **buf);
|
void pv_buffer_clear(PvBuffer **buf);
|
||||||
gint pv_buffer_write(const PvBuffer *buf, FILE *file, GError **err);
|
gint pv_buffer_write(const PvBuffer *buf, FILE *file, GError **err);
|
||||||
|
|||||||
@@ -664,62 +664,9 @@ static gboolean x509_name_data_by_nid_equal(X509_NAME *name, gint nid,
|
|||||||
return memcmp(data, y, data_len) == 0;
|
return memcmp(data, y, data_len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean own_X509_NAME_ENTRY_equal(const X509_NAME_ENTRY *x,
|
|
||||||
const X509_NAME_ENTRY *y)
|
|
||||||
{
|
|
||||||
const ASN1_OBJECT *x_obj = X509_NAME_ENTRY_get_object(x);
|
|
||||||
const ASN1_STRING *x_data = X509_NAME_ENTRY_get_data(x);
|
|
||||||
const ASN1_OBJECT *y_obj = X509_NAME_ENTRY_get_object(y);
|
|
||||||
const ASN1_STRING *y_data = X509_NAME_ENTRY_get_data(y);
|
|
||||||
gint x_len = ASN1_STRING_length(x_data);
|
|
||||||
gint y_len = ASN1_STRING_length(y_data);
|
|
||||||
|
|
||||||
if (x_len < 0 || x_len != y_len)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* ASN1_STRING_cmp(x_data, y_data) == 0 doesn't work because it also
|
|
||||||
* compares the type, which is sometimes different.
|
|
||||||
*/
|
|
||||||
return OBJ_cmp(x_obj, y_obj) == 0 &&
|
|
||||||
memcmp(ASN1_STRING_get0_data(x_data),
|
|
||||||
ASN1_STRING_get0_data(y_data),
|
|
||||||
(unsigned long)x_len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean own_X509_NAME_equal(const X509_NAME *x, const X509_NAME *y)
|
|
||||||
{
|
|
||||||
gint x_count = X509_NAME_entry_count(x);
|
|
||||||
gint y_count = X509_NAME_entry_count(y);
|
|
||||||
|
|
||||||
if (x != y && (!x || !y))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (x_count != y_count)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
for (gint i = 0; i < x_count; i++) {
|
|
||||||
const X509_NAME_ENTRY *entry_i = X509_NAME_get_entry(x, i);
|
|
||||||
gboolean entry_found = FALSE;
|
|
||||||
|
|
||||||
for (gint j = 0; j < y_count; j++) {
|
|
||||||
const X509_NAME_ENTRY *entry_j =
|
|
||||||
X509_NAME_get_entry(y, j);
|
|
||||||
|
|
||||||
if (own_X509_NAME_ENTRY_equal(entry_i, entry_j)) {
|
|
||||||
entry_found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!entry_found)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
|
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
|
||||||
* must check that the subject is equal to: 'C = US, ST = New York, L =
|
* must check that the subject is equal to: 'C = US, ST = New York, L =
|
||||||
* Poughkeepsie, O = International Business Machines Corporation, CN =
|
* Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
|
||||||
* International Business Machines Corporation' and the organization unit (OUT)
|
* International Business Machines Corporation' and the organization unit (OUT)
|
||||||
* must end with the suffix ' Key Signing Service'.
|
* must end with the suffix ' Key Signing Service'.
|
||||||
*/
|
*/
|
||||||
@@ -743,8 +690,10 @@ static gboolean has_ibm_signing_subject(X509 *cert)
|
|||||||
PV_IBM_Z_SUBJECT_STATE))
|
PV_IBM_Z_SUBJECT_STATE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!x509_name_data_by_nid_equal(subject, NID_localityName,
|
if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
|
||||||
PV_IBM_Z_SUBJECT_LOCALITY_NAME))
|
PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
|
||||||
|
x509_name_data_by_nid_equal(subject, NID_localityName,
|
||||||
|
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
|
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
|
||||||
@@ -806,6 +755,39 @@ static X509_NAME *x509_name_reorder_attributes(const X509_NAME *name, const gint
|
|||||||
return g_steal_pointer(&ret);
|
return g_steal_pointer(&ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
|
||||||
|
* `NULL`.
|
||||||
|
*/
|
||||||
|
static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
|
||||||
|
{
|
||||||
|
g_autoptr(X509_NAME) ret = NULL;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
/* Check if ``L=Armonk`` */
|
||||||
|
if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
|
||||||
|
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = X509_NAME_dup((X509_NAME *)name);
|
||||||
|
if (!ret)
|
||||||
|
g_abort();
|
||||||
|
|
||||||
|
pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
|
||||||
|
if (pos == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
|
||||||
|
|
||||||
|
/* Create a new name entry at the same position as before */
|
||||||
|
if (X509_NAME_add_entry_by_NID(
|
||||||
|
ret, NID_localityName, MBSTRING_UTF8,
|
||||||
|
(const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
|
||||||
|
sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return g_steal_pointer(&ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory
|
/* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory
|
||||||
* ordered. The problem is that our certificates are not consistent in the order
|
* ordered. The problem is that our certificates are not consistent in the order
|
||||||
* (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details).
|
* (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details).
|
||||||
@@ -828,24 +810,10 @@ X509_NAME *c2b_name(const X509_NAME *name)
|
|||||||
return X509_NAME_dup((X509_NAME *)name);
|
return X509_NAME_dup((X509_NAME *)name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
|
/* Verify that SKID(issuer) == AKID(crl) if available */
|
||||||
static gint check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **err)
|
static gint check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **err)
|
||||||
{
|
{
|
||||||
const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
|
g_autoptr(AUTHORITY_KEYID) akid = NULL;
|
||||||
const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
|
|
||||||
AUTHORITY_KEYID *akid = NULL;
|
|
||||||
|
|
||||||
if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
|
|
||||||
g_autofree char *issuer_subject_str = X509_NAME_oneline(issuer_subject,
|
|
||||||
NULL, 0);
|
|
||||||
g_autofree char *crl_issuer_str = X509_NAME_oneline(crl_issuer, NULL, 0);
|
|
||||||
|
|
||||||
g_set_error(err, PV_CRYPTO_ERROR,
|
|
||||||
PV_CRYPTO_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
|
|
||||||
_("issuer mismatch:\n%s\n%s"),
|
|
||||||
issuer_subject_str, crl_issuer_str);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
|
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
|
||||||
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
|
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
|
||||||
@@ -881,7 +849,6 @@ gint check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check that the @crl issuer matches with the subject name of @cert*/
|
|
||||||
if (check_crl_issuer(crl, cert, err) < 0)
|
if (check_crl_issuer(crl, cert, err) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -910,6 +877,60 @@ gint check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
|
||||||
|
* issues.
|
||||||
|
*/
|
||||||
|
static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
|
||||||
|
const X509_NAME *subject, GError **err)
|
||||||
|
{
|
||||||
|
g_autoptr(X509_NAME) fixed_subject = NULL;
|
||||||
|
g_autoptr(STACK_OF_X509_CRL) ret = NULL;
|
||||||
|
|
||||||
|
ret = Pv_X509_STORE_CTX_get1_crls(ctx, subject);
|
||||||
|
if (ret && sk_X509_CRL_num(ret) > 0)
|
||||||
|
return g_steal_pointer(&ret);
|
||||||
|
|
||||||
|
/* Workaround to fix the mismatch between issuer name of the * IBM
|
||||||
|
* signing CRLs and the IBM signing key subject name. Locality name has
|
||||||
|
* changed from Poughkeepsie to Armonk.
|
||||||
|
*/
|
||||||
|
fixed_subject = x509_armonk_locality_fixup(subject);
|
||||||
|
/* Was the locality replaced? */
|
||||||
|
if (fixed_subject) {
|
||||||
|
X509_NAME *tmp;
|
||||||
|
|
||||||
|
sk_X509_CRL_free(ret);
|
||||||
|
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||||||
|
if (ret && sk_X509_CRL_num(ret) > 0)
|
||||||
|
return g_steal_pointer(&ret);
|
||||||
|
|
||||||
|
/* Workaround to fix the ordering mismatch between issuer name
|
||||||
|
* of the IBM signing CRLs and the IBM signing key subject name.
|
||||||
|
*/
|
||||||
|
tmp = fixed_subject;
|
||||||
|
fixed_subject = c2b_name(fixed_subject);
|
||||||
|
X509_NAME_free(tmp);
|
||||||
|
sk_X509_CRL_free(ret);
|
||||||
|
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||||||
|
if (ret && sk_X509_CRL_num(ret) > 0)
|
||||||
|
return g_steal_pointer(&ret);
|
||||||
|
X509_NAME_free(fixed_subject);
|
||||||
|
fixed_subject = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround to fix the ordering mismatch between issuer name of the
|
||||||
|
* IBM signing CRLs and the IBM signing key subject name.
|
||||||
|
*/
|
||||||
|
fixed_subject = c2b_name(subject);
|
||||||
|
sk_X509_CRL_free(ret);
|
||||||
|
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
|
||||||
|
if (ret && sk_X509_CRL_num(ret) > 0)
|
||||||
|
return g_steal_pointer(&ret);
|
||||||
|
|
||||||
|
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL, _("no CRL found"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
|
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
|
||||||
* valid CRL was found NULL is returned.
|
* valid CRL was found NULL is returned.
|
||||||
*/
|
*/
|
||||||
@@ -927,20 +948,9 @@ STACK_OF_X509_CRL *store_ctx_find_valid_crls(X509_STORE_CTX *ctx, X509 *cert,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = X509_STORE_CTX_get1_crls(ctx, subject);
|
ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, err);
|
||||||
if (!ret) {
|
if (!ret)
|
||||||
/* Workaround to fix the mismatch between issuer name of the
|
return NULL;
|
||||||
* IBM Z signing CRLs and the IBM Z signing key subject name.
|
|
||||||
*/
|
|
||||||
g_autoptr(X509_NAME) broken_subject = c2b_name(subject);
|
|
||||||
|
|
||||||
ret = X509_STORE_CTX_get1_crls(ctx, broken_subject);
|
|
||||||
if (!ret) {
|
|
||||||
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL,
|
|
||||||
_("no CRL found"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Filter out non-valid CRLs for @cert */
|
/* Filter out non-valid CRLs for @cert */
|
||||||
for (gint i = 0; i < sk_X509_CRL_num(ret); i++) {
|
for (gint i = 0; i < sk_X509_CRL_num(ret); i++) {
|
||||||
@@ -1328,32 +1338,14 @@ gint check_chain_parameters(const STACK_OF_X509 *chain,
|
|||||||
|
|
||||||
/* It's almost the same as X509_check_issed from OpenSSL does except that we
|
/* It's almost the same as X509_check_issed from OpenSSL does except that we
|
||||||
* don't check the key usage of the potential issuer. This means we check:
|
* don't check the key usage of the potential issuer. This means we check:
|
||||||
* 1. issuer_name(cert) == subject_name(issuer)
|
* 1. Check whether the akid(cert) (if available) matches the issuer skid
|
||||||
* 2. Check whether the akid(cert) (if available) matches the issuer skid
|
* 2. Check that the cert algrithm matches the subject algorithm
|
||||||
* 3. Check that the cert algrithm matches the subject algorithm
|
* 3. Verify the signature of certificate @cert is using the public key of
|
||||||
* 4. Verify the signature of certificate @cert is using the public key of
|
|
||||||
* @issuer.
|
* @issuer.
|
||||||
*/
|
*/
|
||||||
static gint check_host_key_issued(X509 *cert, X509 *issuer, GError **err)
|
static gint check_host_key_issued(X509 *cert, X509 *issuer, GError **err)
|
||||||
{
|
{
|
||||||
const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
|
g_autoptr(AUTHORITY_KEYID) akid = NULL;
|
||||||
const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
|
|
||||||
AUTHORITY_KEYID *akid = NULL;
|
|
||||||
|
|
||||||
/* We cannot use X509_NAME_cmp() because it considers the order of the
|
|
||||||
* X509_NAME_Entries.
|
|
||||||
*/
|
|
||||||
if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
|
|
||||||
g_autofree char *issuer_subject_str =
|
|
||||||
X509_NAME_oneline(issuer_subject, NULL, 0);
|
|
||||||
g_autofree char *cert_issuer_str =
|
|
||||||
X509_NAME_oneline(cert_issuer, NULL, 0);
|
|
||||||
g_set_error(err, PV_CRYPTO_ERROR,
|
|
||||||
PV_CRYPTO_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
|
|
||||||
_("Subject issuer mismatch:\n'%s'\n'%s'"),
|
|
||||||
issuer_subject_str, cert_issuer_str);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
|
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
|
||||||
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
|
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
|
||||||
@@ -1834,14 +1826,12 @@ static gint __encrypt_decrypt_bio(const struct cipher_parms *parms, BIO *b_in,
|
|||||||
g_assert(out_len >= 0);
|
g_assert(out_len >= 0);
|
||||||
|
|
||||||
num_bytes_written = BIO_write(b_out, out_buf, out_len);
|
num_bytes_written = BIO_write(b_out, out_buf, out_len);
|
||||||
if (num_bytes_written < 0) {
|
if (num_bytes_written != out_len) {
|
||||||
g_set_error(err, PV_CRYPTO_ERROR,
|
g_set_error(err, PV_CRYPTO_ERROR,
|
||||||
PV_CRYPTO_ERROR_INTERNAL,
|
PV_CRYPTO_ERROR_INTERNAL,
|
||||||
_("Failed to write"));
|
_("Failed to write"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
g_assert(num_bytes_written == out_len);
|
|
||||||
|
|
||||||
tmp_size_out += (guint)num_bytes_written;
|
tmp_size_out += (guint)num_bytes_written;
|
||||||
|
|
||||||
/* Set new tweak value. Please keep in mind that the
|
/* Set new tweak value. Please keep in mind that the
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ void x509_pair_free(x509_pair *pair);
|
|||||||
/* Register auto cleanup functions */
|
/* Register auto cleanup functions */
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
|
||||||
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(AUTHORITY_KEYID, AUTHORITY_KEYID_free)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ static void l_sd_cpu_fill(struct sd_cpu *cpu, struct l_x_cpu_info *cpu_info,
|
|||||||
int threads)
|
int threads)
|
||||||
{
|
{
|
||||||
sd_cpu_cpu_time_us_set(cpu, cpu_info->lp_time);
|
sd_cpu_cpu_time_us_set(cpu, cpu_info->lp_time);
|
||||||
|
sd_cpu_threads_per_core_set(cpu, threads);
|
||||||
if (threads > 1)
|
if (threads > 1)
|
||||||
sd_cpu_thread_time_us_set(cpu,
|
sd_cpu_thread_time_us_set(cpu,
|
||||||
cpu_info->lp_time * threads - cpu_info->mt_idle_time);
|
cpu_info->lp_time * threads - cpu_info->mt_idle_time);
|
||||||
@@ -297,6 +298,7 @@ static struct sd_sys_item *l_sys_item_vec[] = {
|
|||||||
&sd_sys_item_thread_cnt,
|
&sd_sys_item_thread_cnt,
|
||||||
&sd_sys_item_core_diff,
|
&sd_sys_item_core_diff,
|
||||||
&sd_sys_item_thread_diff,
|
&sd_sys_item_thread_diff,
|
||||||
|
&sd_sys_item_smt_diff,
|
||||||
&sd_sys_item_mgm_diff,
|
&sd_sys_item_mgm_diff,
|
||||||
&sd_sys_item_core,
|
&sd_sys_item_core,
|
||||||
&sd_sys_item_thread,
|
&sd_sys_item_thread,
|
||||||
@@ -326,6 +328,7 @@ static struct sd_cpu_item *l_cpu_item_vec[] = {
|
|||||||
&sd_cpu_item_type,
|
&sd_cpu_item_type,
|
||||||
&sd_cpu_item_core_diff,
|
&sd_cpu_item_core_diff,
|
||||||
&sd_cpu_item_thread_diff,
|
&sd_cpu_item_thread_diff,
|
||||||
|
&sd_cpu_item_smt_diff,
|
||||||
&sd_cpu_item_mgm_diff,
|
&sd_cpu_item_mgm_diff,
|
||||||
&sd_cpu_item_core,
|
&sd_cpu_item_core,
|
||||||
&sd_cpu_item_thread,
|
&sd_cpu_item_thread,
|
||||||
|
|||||||
@@ -391,3 +391,24 @@ void hyptop_helper_init(void)
|
|||||||
if (l_iconv_ebcdic_ascii == (iconv_t) -1)
|
if (l_iconv_ebcdic_ascii == (iconv_t) -1)
|
||||||
ERR_EXIT("Could not initialize iconv\n");
|
ERR_EXIT("Could not initialize iconv\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate real SMT utilization
|
||||||
|
* @core_us: core utilization in us
|
||||||
|
* @thr_us: thread utilization in us
|
||||||
|
* @mgm_us: management utilization in us
|
||||||
|
* @thread_per_core: SMT thread count per core
|
||||||
|
*/
|
||||||
|
s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core)
|
||||||
|
{
|
||||||
|
s64 component1, component2, smt_us;
|
||||||
|
double smt_factor = g.o.smt_factor;
|
||||||
|
|
||||||
|
component1 = thread_per_core * core_us - thr_us;
|
||||||
|
if (thread_per_core > 1)
|
||||||
|
component1 /= smt_factor;
|
||||||
|
component2 = thr_us - core_us;
|
||||||
|
smt_us = G0(component1 + component2 + mgm_us);
|
||||||
|
|
||||||
|
return smt_us;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ extern void ht_ebcdic_to_ascii(char *in, char *out, size_t len);
|
|||||||
extern char *ht_mount_point_get(const char *fs_type);
|
extern char *ht_mount_point_get(const char *fs_type);
|
||||||
extern u64 ht_ext_tod_2_us(void *tod_ext);
|
extern u64 ht_ext_tod_2_us(void *tod_ext);
|
||||||
extern void ht_print_time(void);
|
extern void ht_print_time(void);
|
||||||
|
extern s64 ht_calculate_smt_util(u64 core_us, u64 thr_us, u64 mgm_us, int thread_per_core);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory alloc functions
|
* Memory alloc functions
|
||||||
|
|||||||
@@ -74,6 +74,18 @@ In this mode no user input is accepted.
|
|||||||
.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>"
|
||||||
|
Specifies a workload dependent SMT speedup factor.
|
||||||
|
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, specifying lower values results in more accurate reports of
|
||||||
|
real CPU SMT utilization field for LPARs. There is no hard boundary except
|
||||||
|
that it must be a positive value. Example ranges to select a sensible value
|
||||||
|
from:
|
||||||
|
|
||||||
|
For IBM z13: [0.8, 1.3]
|
||||||
|
For IBM z15: [1.1, 1.5]
|
||||||
|
.TP
|
||||||
.BR "\-n <ITERATIONS>" " or " "\-\-iterations=<ITERATIONS>"
|
.BR "\-n <ITERATIONS>" " or " "\-\-iterations=<ITERATIONS>"
|
||||||
Specifies the maximum number of iterations before ending.
|
Specifies the maximum number of iterations before ending.
|
||||||
|
|
||||||
@@ -119,6 +131,7 @@ The following fields are available under LPAR:
|
|||||||
In "sys_list" and "sys" window:
|
In "sys_list" and "sys" window:
|
||||||
'c' - Core dispatch time per second
|
'c' - Core dispatch time per second
|
||||||
'e' - Thread time per second
|
'e' - Thread time per second
|
||||||
|
'S' - Real CPU SMT utilization
|
||||||
'm' - Management time per second
|
'm' - Management time per second
|
||||||
'C' - Total core dispatch time
|
'C' - Total core dispatch time
|
||||||
'E' - Total thread time
|
'E' - Total thread time
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
|
||||||
#define HYPTOP_OPT_DEFAULT_DELAY 2
|
#define HYPTOP_OPT_DEFAULT_DELAY 2
|
||||||
|
#define HYPTOP_OPT_DEFAULT_SMT_SCALE 1.3
|
||||||
#define HYPTOP_MAX_WIN_DEPTH 4
|
#define HYPTOP_MAX_WIN_DEPTH 4
|
||||||
#define HYPTOP_MAX_LINE 512
|
#define HYPTOP_MAX_LINE 512
|
||||||
#define PROG_NAME "hyptop"
|
#define PROG_NAME "hyptop"
|
||||||
@@ -60,6 +61,8 @@ struct hyptop_opts {
|
|||||||
|
|
||||||
int delay_s;
|
int delay_s;
|
||||||
int delay_us;
|
int delay_us;
|
||||||
|
|
||||||
|
double smt_factor;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ static char HELP_TEXT[] =
|
|||||||
"-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"
|
||||||
"-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"
|
||||||
"-n, --iterations NUMBER Number of iterations before ending\n";
|
"-n, --iterations NUMBER Number of iterations before ending\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -48,6 +49,7 @@ static void l_init_defaults(void)
|
|||||||
{
|
{
|
||||||
g.prog_name = PROG_NAME;
|
g.prog_name = PROG_NAME;
|
||||||
g.o.delay_s = HYPTOP_OPT_DEFAULT_DELAY;
|
g.o.delay_s = HYPTOP_OPT_DEFAULT_DELAY;
|
||||||
|
g.o.smt_factor = HYPTOP_OPT_DEFAULT_SMT_SCALE;
|
||||||
g.w.cur = &win_sys_list;
|
g.w.cur = &win_sys_list;
|
||||||
g.o.cur_win = &win_sys_list;
|
g.o.cur_win = &win_sys_list;
|
||||||
}
|
}
|
||||||
@@ -108,6 +110,20 @@ static void l_delay_set(char *delay_string)
|
|||||||
g.o.delay_us = 0;
|
g.o.delay_us = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set SMT factor option
|
||||||
|
*/
|
||||||
|
static void l_factor_set(char *value_string)
|
||||||
|
{
|
||||||
|
double factor;
|
||||||
|
|
||||||
|
if (sscanf(value_string, "%lf", &factor) != 1)
|
||||||
|
ERR_EXIT("The SMT factor \"%s\" is invalid\n", value_string);
|
||||||
|
if (factor <= 0)
|
||||||
|
ERR_EXIT("The SMT factor \"%s\" is <= 0\n", value_string);
|
||||||
|
g.o.smt_factor = factor;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get number of occurrences of character 'c' in "str"
|
* Get number of occurrences of character 'c' in "str"
|
||||||
*/
|
*/
|
||||||
@@ -299,6 +315,7 @@ void opts_parse(int argc, char *argv[])
|
|||||||
{ "help", no_argument, NULL, 'h'},
|
{ "help", no_argument, NULL, 'h'},
|
||||||
{ "batch_mode", no_argument, NULL, 'b'},
|
{ "batch_mode", no_argument, NULL, 'b'},
|
||||||
{ "delay", required_argument, NULL, 'd'},
|
{ "delay", required_argument, NULL, 'd'},
|
||||||
|
{ "smt_factor", required_argument, NULL, 'm'},
|
||||||
{ "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'},
|
||||||
@@ -307,7 +324,7 @@ void opts_parse(int argc, char *argv[])
|
|||||||
{ "cpu_types", required_argument, NULL, 't'},
|
{ "cpu_types", required_argument, NULL, 't'},
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
static const char option_string[] = "vhbd:w:s:n:f:t:S:";
|
static const char option_string[] = "vhbd:m:w:s:n:f:t:S:";
|
||||||
|
|
||||||
l_init_defaults();
|
l_init_defaults();
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -328,6 +345,9 @@ void opts_parse(int argc, char *argv[])
|
|||||||
case 'd':
|
case 'd':
|
||||||
l_delay_set(optarg);
|
l_delay_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
l_factor_set(optarg);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
l_window_set(optarg);
|
l_window_set(optarg);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ struct sd_cpu {
|
|||||||
struct sd_cpu_info *d_cur;
|
struct sd_cpu_info *d_cur;
|
||||||
struct sd_cpu_info *d_prev;
|
struct sd_cpu_info *d_prev;
|
||||||
u16 cnt;
|
u16 cnt;
|
||||||
|
int threads_per_core;
|
||||||
enum sd_cpu_state state;
|
enum sd_cpu_state state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -232,6 +233,11 @@ static inline void sd_cpu_cpu_time_us_set(struct sd_cpu *cpu, u64 value)
|
|||||||
cpu->d_cur->cpu_time_us = value;
|
cpu->d_cur->cpu_time_us = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void sd_cpu_threads_per_core_set(struct sd_cpu *cpu, int value)
|
||||||
|
{
|
||||||
|
cpu->threads_per_core = value;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void sd_cpu_thread_time_us_set(struct sd_cpu *cpu, u64 value)
|
static inline void sd_cpu_thread_time_us_set(struct sd_cpu *cpu, u64 value)
|
||||||
{
|
{
|
||||||
cpu->d_cur->thread_time_us = value;
|
cpu->d_cur->thread_time_us = value;
|
||||||
@@ -335,6 +341,7 @@ extern struct sd_cpu_item sd_cpu_item_state;
|
|||||||
extern struct sd_cpu_item sd_cpu_item_cpu_diff;
|
extern struct sd_cpu_item sd_cpu_item_cpu_diff;
|
||||||
extern struct sd_cpu_item sd_cpu_item_core_diff;
|
extern struct sd_cpu_item sd_cpu_item_core_diff;
|
||||||
extern struct sd_cpu_item sd_cpu_item_thread_diff;
|
extern struct sd_cpu_item sd_cpu_item_thread_diff;
|
||||||
|
extern struct sd_cpu_item sd_cpu_item_smt_diff;
|
||||||
extern struct sd_cpu_item sd_cpu_item_mgm_diff;
|
extern struct sd_cpu_item sd_cpu_item_mgm_diff;
|
||||||
extern struct sd_cpu_item sd_cpu_item_wait_diff;
|
extern struct sd_cpu_item sd_cpu_item_wait_diff;
|
||||||
extern struct sd_cpu_item sd_cpu_item_steal_diff;
|
extern struct sd_cpu_item sd_cpu_item_steal_diff;
|
||||||
@@ -398,6 +405,7 @@ static inline char *sd_sys_item_str(struct sd_sys *sys,
|
|||||||
extern struct sd_sys_item sd_sys_item_cpu_cnt;
|
extern struct sd_sys_item sd_sys_item_cpu_cnt;
|
||||||
extern struct sd_sys_item sd_sys_item_core_cnt;
|
extern struct sd_sys_item sd_sys_item_core_cnt;
|
||||||
extern struct sd_sys_item sd_sys_item_thread_cnt;
|
extern struct sd_sys_item sd_sys_item_thread_cnt;
|
||||||
|
extern struct sd_sys_item sd_sys_item_smt_diff;
|
||||||
extern struct sd_sys_item sd_sys_item_cpu_oper_cnt;
|
extern struct sd_sys_item sd_sys_item_cpu_oper_cnt;
|
||||||
extern struct sd_sys_item sd_sys_item_cpu_deconf_cnt;
|
extern struct sd_sys_item sd_sys_item_cpu_deconf_cnt;
|
||||||
extern struct sd_sys_item sd_sys_item_cpu_stop_cnt;
|
extern struct sd_sys_item sd_sys_item_cpu_stop_cnt;
|
||||||
|
|||||||
@@ -98,6 +98,18 @@ static u64 l_cpu_item_64(struct sd_cpu_item *item, struct sd_cpu *cpu)
|
|||||||
return l_cpu_info_u64(cpu->d_cur, item->offset) / cpu->cnt;
|
return l_cpu_info_u64(cpu->d_cur, item->offset) / cpu->cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 l_cpu_smt_util(struct sd_cpu_item *item, struct sd_cpu *cpu)
|
||||||
|
{
|
||||||
|
u64 core_us, thr_us, mgm_us;
|
||||||
|
(void)item;
|
||||||
|
|
||||||
|
core_us = sd_cpu_item_u64(&sd_cpu_item_core_diff, cpu);
|
||||||
|
thr_us = sd_cpu_item_u64(&sd_cpu_item_thread_diff, cpu);
|
||||||
|
mgm_us = sd_cpu_item_u64(&sd_cpu_item_mgm_diff, cpu);
|
||||||
|
|
||||||
|
return ht_calculate_smt_util(core_us, thr_us, mgm_us, cpu->threads_per_core);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CPU item definitions
|
* CPU item definitions
|
||||||
*/
|
*/
|
||||||
@@ -139,6 +151,13 @@ struct sd_cpu_item sd_cpu_item_thread_diff = {
|
|||||||
.fn_u64 = l_cpu_diff_u64,
|
.fn_u64 = l_cpu_diff_u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sd_cpu_item sd_cpu_item_smt_diff = {
|
||||||
|
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'S', "smt"),
|
||||||
|
.type = SD_TYPE_U64,
|
||||||
|
.desc = "Real CPU SMT utilization",
|
||||||
|
.fn_u64 = l_cpu_smt_util,
|
||||||
|
};
|
||||||
|
|
||||||
struct sd_cpu_item sd_cpu_item_mgm_diff = {
|
struct sd_cpu_item sd_cpu_item_mgm_diff = {
|
||||||
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
||||||
.type = SD_TYPE_U64,
|
.type = SD_TYPE_U64,
|
||||||
|
|||||||
@@ -208,6 +208,18 @@ static s64 l_sys_cpu_info_diff_s64(struct sd_sys_item *item, struct sd_sys *sys)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u64 l_sys_smt_util(struct sd_sys_item *item, struct sd_sys *sys)
|
||||||
|
{
|
||||||
|
u64 core_us, thr_us, mgm_us;
|
||||||
|
(void)item;
|
||||||
|
|
||||||
|
core_us = sd_sys_item_u64(sys, &sd_sys_item_core_diff);
|
||||||
|
thr_us = sd_sys_item_u64(sys, &sd_sys_item_thread_diff);
|
||||||
|
mgm_us = sd_sys_item_u64(sys, &sd_sys_item_mgm_diff);
|
||||||
|
|
||||||
|
return ht_calculate_smt_util(core_us, thr_us, mgm_us, sys->threads_per_core);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* System item definitions
|
* System item definitions
|
||||||
*/
|
*/
|
||||||
@@ -277,6 +289,13 @@ struct sd_sys_item sd_sys_item_thread_diff = {
|
|||||||
.fn_u64 = l_sys_cpu_info_diff_u64,
|
.fn_u64 = l_sys_cpu_info_diff_u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sd_sys_item sd_sys_item_smt_diff = {
|
||||||
|
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'S', "smt"),
|
||||||
|
.type = SD_TYPE_U64,
|
||||||
|
.desc = "Real CPU SMT utilization",
|
||||||
|
.fn_u64 = l_sys_smt_util,
|
||||||
|
};
|
||||||
|
|
||||||
struct sd_sys_item sd_sys_item_mgm_diff = {
|
struct sd_sys_item sd_sys_item_mgm_diff = {
|
||||||
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
.table_col = TABLE_COL_TIME_DIFF_SUM(table_col_unit_perc, 'm', "mgm"),
|
||||||
.offset = SD_CPU_INFO_OFFSET(mgm_time_us),
|
.offset = SD_CPU_INFO_OFFSET(mgm_time_us),
|
||||||
|
|||||||
@@ -34,10 +34,10 @@
|
|||||||
/* Secure IPL error */
|
/* Secure IPL error */
|
||||||
#define ESECUREBOOT 0x00004512
|
#define ESECUREBOOT 0x00004512
|
||||||
|
|
||||||
/* kdump: No operating system information was found */
|
/* os_info error: No operating system information was found */
|
||||||
#define EOS_INFO_MISSING 0x00004520
|
#define EOS_INFO_MISSING 0x00004520
|
||||||
|
|
||||||
/* kdump: The checksum of the operating system information is incorrect */
|
/* os_info error: The checksum of the operating system information is incorrect */
|
||||||
#define EOS_INFO_CSUM_FAILED 0x00004521
|
#define EOS_INFO_CSUM_FAILED 0x00004521
|
||||||
|
|
||||||
/* kdump: The major version of the operating system information is too high */
|
/* kdump: The major version of the operating system information is too high */
|
||||||
@@ -21,10 +21,6 @@
|
|||||||
#define IPL_MAX_SUPPORTED_VERSION 0
|
#define IPL_MAX_SUPPORTED_VERSION 0
|
||||||
#define IPL_PARM_BLOCK_VERSION 0x1
|
#define IPL_PARM_BLOCK_VERSION 0x1
|
||||||
|
|
||||||
/* IPL Types */
|
|
||||||
#define IPL_TYPE_PV 0x5
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -43,6 +39,16 @@ struct ipl_pb_hdr {
|
|||||||
uint8_t pbt;
|
uint8_t pbt;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
/* IPL Parameter Block types */
|
||||||
|
enum ipl_pbt {
|
||||||
|
IPL_PBT_FCP = 0,
|
||||||
|
IPL_PBT_SCP_DATA = 1,
|
||||||
|
IPL_PBT_CCW = 2,
|
||||||
|
IPL_PBT_ECKD = 3,
|
||||||
|
IPL_PBT_NVME = 4,
|
||||||
|
IPL_PBT_PV = 5,
|
||||||
|
};
|
||||||
|
|
||||||
/* IPL Parameter Block 0 with common fields */
|
/* IPL Parameter Block 0 with common fields */
|
||||||
struct ipl_pb0_common {
|
struct ipl_pb0_common {
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|||||||
@@ -22,11 +22,19 @@
|
|||||||
#define STAGE2_DESC _AC(0x78, UL)
|
#define STAGE2_DESC _AC(0x78, UL)
|
||||||
#define STAGE2_ENTRY _AC(0x2018, UL)
|
#define STAGE2_ENTRY _AC(0x2018, UL)
|
||||||
#define STAGE2_HEAP_ADDRESS _AC(0x6000, UL)
|
#define STAGE2_HEAP_ADDRESS _AC(0x6000, UL)
|
||||||
|
#define ECKD2DUMP_SV_HEAP_ADDRESS _AC(0xb000, UL)
|
||||||
#define STAGE2_HEAP_SIZE _AC(0x3000, UL)
|
#define STAGE2_HEAP_SIZE _AC(0x3000, UL)
|
||||||
#define STAGE2_STACK_ADDRESS _AC(0xe400, UL)
|
#define STAGE2_STACK_ADDRESS _AC(0xe400, UL)
|
||||||
#define STAGE2_STACK_SIZE _AC(0x1c00, UL)
|
#define STAGE2_STACK_SIZE _AC(0x1c00, UL)
|
||||||
|
#define ECKD2DUMP_SV_STACK_ADDRESS _AC(0xe000, UL)
|
||||||
|
#define ECKD2DUMP_SV_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_V2 _AC(0x2000, UL)
|
||||||
|
#define STAGE2_DUMPER_SIZE_V3 _AC(0x3000, UL)
|
||||||
|
#define STAGE2_DUMPER_SIZE_ZLIB _AC(0x8000, UL)
|
||||||
|
|
||||||
#define STAGE3_ENTRY _AC(0xa000, UL)
|
#define STAGE3_ENTRY _AC(0xa000, UL)
|
||||||
|
|
||||||
#define STAGE2_LOAD_ADDRESS _AC(0x2000, UL)
|
#define STAGE2_LOAD_ADDRESS _AC(0x2000, UL)
|
||||||
|
|||||||
94
include/boot/os_info.h
Normal file
94
include/boot/os_info.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* zipl - zSeries Initial Program Loader tool
|
||||||
|
*
|
||||||
|
* os-info definitions
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2013, 2023
|
||||||
|
*
|
||||||
|
* 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 OS_INFO_H
|
||||||
|
#define OS_INFO_H
|
||||||
|
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
#include "boot/error.h"
|
||||||
|
#include "boot/s390.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define OS_INFO_MAGIC 0x4f53494e464f535aULL /* OSINFOSZ */
|
||||||
|
#define OS_INFO_CSUM_SIZE (sizeof(struct os_info) - offsetof(struct os_info, version_major))
|
||||||
|
#define OS_INFO_FLAGS_ENTRY_SIZE (sizeof(unsigned long))
|
||||||
|
|
||||||
|
#define OS_INFO_VMCOREINFO 0
|
||||||
|
#define OS_INFO_REIPL_BLOCK 1
|
||||||
|
#define OS_INFO_FLAGS_ENTRY 2
|
||||||
|
#define OS_INFO_RESERVED 3
|
||||||
|
#define OS_INFO_IDENTITY_BASE 4
|
||||||
|
#define OS_INFO_KASLR_OFFSET 5
|
||||||
|
#define OS_INFO_KASLR_OFF_PHYS 6
|
||||||
|
#define OS_INFO_VMEMMAP 7
|
||||||
|
#define OS_INFO_AMODE31_START 8
|
||||||
|
#define OS_INFO_AMODE31_END 9
|
||||||
|
#define OS_INFO_IMAGE_START 10
|
||||||
|
#define OS_INFO_IMAGE_END 11
|
||||||
|
#define OS_INFO_IMAGE_PHYS 12
|
||||||
|
#define OS_INFO_MAX 13
|
||||||
|
|
||||||
|
#define OS_INFO_FLAG_REIPL_CLEAR (1UL << 0)
|
||||||
|
|
||||||
|
struct os_info_entry {
|
||||||
|
union {
|
||||||
|
uint64_t addr;
|
||||||
|
uint64_t val;
|
||||||
|
};
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t csum;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct os_info {
|
||||||
|
uint64_t magic;
|
||||||
|
uint32_t csum;
|
||||||
|
uint16_t version_major;
|
||||||
|
uint16_t version_minor;
|
||||||
|
uint64_t crashkernel_addr;
|
||||||
|
uint64_t crashkernel_size;
|
||||||
|
struct os_info_entry entry[OS_INFO_MAX];
|
||||||
|
uint8_t reserved[3804];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
STATIC_ASSERT(sizeof(struct os_info) == 4096)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 0 in case of valid os_info
|
||||||
|
* Return -EOS_INFO_MISSING if os_info address is not page aligned or page is
|
||||||
|
* not accessible or os_info magic value is missing.
|
||||||
|
* Return -EOS_INFO_CSUM_FAILED if os_info checksum is invalid.
|
||||||
|
*/
|
||||||
|
static inline int os_info_check(const struct os_info *os_info)
|
||||||
|
{
|
||||||
|
if (!os_info ||
|
||||||
|
(unsigned long)os_info % PAGE_SIZE ||
|
||||||
|
!page_is_valid((unsigned long)os_info) ||
|
||||||
|
os_info->magic != OS_INFO_MAGIC)
|
||||||
|
return -EOS_INFO_MISSING;
|
||||||
|
if (os_info->csum != csum_partial(&os_info->version_major, OS_INFO_CSUM_SIZE, 0))
|
||||||
|
return -EOS_INFO_CSUM_FAILED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return 1 in case of valid os_info_entry, otherwise 0
|
||||||
|
* Make sure that the entire os_info structure is checked first with os_info_check().
|
||||||
|
*/
|
||||||
|
static inline int os_info_entry_is_valid(const struct os_info_entry *entry)
|
||||||
|
{
|
||||||
|
return (entry &&
|
||||||
|
entry->addr &&
|
||||||
|
entry->size &&
|
||||||
|
page_is_valid(entry->addr) &&
|
||||||
|
entry->csum == csum_partial((void *)entry->addr, entry->size, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* OS_INFO_H */
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#define STACK_FRAME_OVERHEAD _AC(160, U)
|
#define STACK_FRAME_OVERHEAD _AC(160, U)
|
||||||
|
|
||||||
/* Facilities */
|
/* Facilities */
|
||||||
|
#define DFLTCC_FACILITY _AC(151, U)
|
||||||
#define UNPACK_FACILITY _AC(161, U)
|
#define UNPACK_FACILITY _AC(161, U)
|
||||||
|
|
||||||
#ifndef __ASSEMBLER__
|
#ifndef __ASSEMBLER__
|
||||||
@@ -285,18 +286,21 @@ static __always_inline void __ctl_set_bit(unsigned int cr, unsigned int bit)
|
|||||||
* DIAG 308 support
|
* DIAG 308 support
|
||||||
*/
|
*/
|
||||||
enum diag308_subcode {
|
enum diag308_subcode {
|
||||||
DIAG308_REL_HSA = 2,
|
DIAG308_CLEAR_RESET = 0,
|
||||||
DIAG308_IPL = 3,
|
DIAG308_LOAD_NORMAL_RESET = 1,
|
||||||
DIAG308_DUMP = 4,
|
DIAG308_REL_HSA = 2,
|
||||||
DIAG308_SET = 5,
|
DIAG308_LOAD_CLEAR = 3,
|
||||||
DIAG308_STORE = 6,
|
DIAG308_LOAD_NORMAL_DUMP = 4,
|
||||||
|
DIAG308_SET = 5,
|
||||||
|
DIAG308_STORE = 6,
|
||||||
|
DIAG308_LOAD_NORMAL = 7,
|
||||||
DIAG308_SET_PV = 8,
|
DIAG308_SET_PV = 8,
|
||||||
DIAG308_UNPACK_PV = 10,
|
DIAG308_UNPACK_PV = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum diag308_rc {
|
enum diag308_rc {
|
||||||
DIAG308_RC_OK = 0x0001,
|
DIAG308_RC_OK = 0x0001,
|
||||||
DIAG308_RC_NO_CONF = 0x0102,
|
DIAG308_RC_NOCONFIG = 0x0102,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
|
static __always_inline unsigned long diag308(unsigned long subcode, void *addr)
|
||||||
|
|||||||
145
include/dump/s390_dump.h
Normal file
145
include/dump/s390_dump.h
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* s390 related definitions and functions.
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2013, 2023
|
||||||
|
*
|
||||||
|
* 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 S390_DUMP_H
|
||||||
|
#define S390_DUMP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "boot/page.h"
|
||||||
|
#include "lib/zt_common.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* S390 dump format defines
|
||||||
|
*/
|
||||||
|
#define DF_S390_MAGIC 0xa8190173618f23fdULL
|
||||||
|
#define DF_S390_MAGIC_EXT 0xa8190173618f23feULL
|
||||||
|
#define DF_S390_HDR_SIZE 0x1000
|
||||||
|
#define DF_S390_EM_SIZE 16
|
||||||
|
#define DF_S390_EM_MAGIC 0x44554d505f454e44ULL
|
||||||
|
#define DF_S390_EM_STR "DUMP_END"
|
||||||
|
#define DF_S390_CPU_MAX 512
|
||||||
|
#define DF_S390_MAGIC_BLK_ECKD 3
|
||||||
|
#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_MAGIC32_FBA "ZDFBA31"
|
||||||
|
#define DF_S390_DUMPER_MAGIC64_FBA "ZDFBA64"
|
||||||
|
#define DF_S390_DUMPER_MAGIC_FBA_EXT "XDFBA64"
|
||||||
|
#define DF_S390_DUMPER_MAGIC_MV "ZMULT64"
|
||||||
|
#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
|
||||||
|
*/
|
||||||
|
enum df_s390_arch {
|
||||||
|
DF_S390_ARCH_32 = 1,
|
||||||
|
DF_S390_ARCH_64 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* zipl parameters passed at tail of dump tools
|
||||||
|
*/
|
||||||
|
struct stage2dump_parm_tail {
|
||||||
|
char reserved[6];
|
||||||
|
uint8_t no_compress;
|
||||||
|
uint8_t mvdump_force;
|
||||||
|
uint64_t mem_upper_limit;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* s390 dump header format
|
||||||
|
*/
|
||||||
|
struct df_s390_hdr {
|
||||||
|
uint64_t magic; /* 0x000 */
|
||||||
|
uint32_t version; /* 0x008 */
|
||||||
|
uint32_t hdr_size; /* 0x00c */
|
||||||
|
uint32_t dump_level; /* 0x010 */
|
||||||
|
uint32_t page_size; /* 0x014 */
|
||||||
|
uint64_t mem_size; /* 0x018 */
|
||||||
|
uint64_t mem_start; /* 0x020 */
|
||||||
|
uint64_t mem_end; /* 0x028 */
|
||||||
|
uint32_t num_pages; /* 0x030 */
|
||||||
|
uint32_t pad; /* 0x034 */
|
||||||
|
uint64_t tod; /* 0x038 */
|
||||||
|
uint64_t cpu_id; /* 0x040 */
|
||||||
|
uint32_t arch; /* 0x048 */
|
||||||
|
uint32_t volnr; /* 0x04c */
|
||||||
|
uint32_t build_arch; /* 0x050 */
|
||||||
|
uint64_t mem_size_real; /* 0x054 */
|
||||||
|
uint8_t mvdump; /* 0x05c */
|
||||||
|
uint16_t cpu_cnt; /* 0x05d */
|
||||||
|
uint16_t real_cpu_cnt; /* 0x05f */
|
||||||
|
uint8_t zlib_version_s390; /* 0x061 */
|
||||||
|
uint32_t zlib_entry_size; /* 0x062 */
|
||||||
|
uint8_t end_pad1[0x200 - 0x066]; /* 0x066 */
|
||||||
|
uint64_t mvdump_sign; /* 0x200 */
|
||||||
|
uint64_t mvdump_zipl_time; /* 0x208 */
|
||||||
|
uint8_t end_pad2[0x800 - 0x210]; /* 0x210 */
|
||||||
|
uint32_t lc_vec[DF_S390_CPU_MAX]; /* 0x800 */
|
||||||
|
} __packed __aligned(16);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* End marker: Should be at the end of every valid s390 crash dump
|
||||||
|
*/
|
||||||
|
struct df_s390_em {
|
||||||
|
union {
|
||||||
|
uint64_t magic;
|
||||||
|
char str[8];
|
||||||
|
};
|
||||||
|
uint64_t tod;
|
||||||
|
} __packed __aligned(16);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump segment header
|
||||||
|
*/
|
||||||
|
struct df_s390_dump_segm_hdr {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint64_t start; /* 0x000 */
|
||||||
|
uint64_t len; /* 0x008 */
|
||||||
|
uint64_t stop_marker; /* 0x010 */
|
||||||
|
/* Size in blocks of compressed dump segment written to disk */
|
||||||
|
uint32_t size_on_disk; /* 0x018 */
|
||||||
|
uint8_t reserved_pad[0x30 - 0x1c]; /* 0x01c */
|
||||||
|
/*
|
||||||
|
* Number of compressed entries in this dump segment (up to
|
||||||
|
* 1011 entries)
|
||||||
|
*/
|
||||||
|
uint32_t entry_count; /* 0x030 */
|
||||||
|
/*
|
||||||
|
* Offsets in blocks to compressed entries written to disk
|
||||||
|
* from the start of the dump segment.
|
||||||
|
* High-order bit is set if the entry has been written
|
||||||
|
* uncompressed.
|
||||||
|
*/
|
||||||
|
uint32_t entry_offset[]; /* 0x034 */
|
||||||
|
} __packed;
|
||||||
|
uint8_t padding[PAGE_SIZE];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Data compression granularity (size of input data chunk for zlib deflate) */
|
||||||
|
#define DUMP_SEGM_ZLIB_ENTSIZE (1 * MIB)
|
||||||
|
/* Maximum number of compressed entries in one dump segment */
|
||||||
|
#define DUMP_SEGM_ZLIB_MAXENTS ((sizeof(struct df_s390_dump_segm_hdr) \
|
||||||
|
- offsetof(struct df_s390_dump_segm_hdr, entry_offset)) \
|
||||||
|
/ sizeof(uint32_t))
|
||||||
|
/*
|
||||||
|
* Maximum length of compressed dump segment considering the size of
|
||||||
|
* a single input chunk
|
||||||
|
*/
|
||||||
|
#define DUMP_SEGM_ZLIB_MAXLEN (DUMP_SEGM_ZLIB_MAXENTS * DUMP_SEGM_ZLIB_ENTSIZE)
|
||||||
|
/* Bitmask to mark uncompressed chunks */
|
||||||
|
#define DUMP_SEGM_ENTRY_UNCOMPRESSED 0x80000000
|
||||||
|
|
||||||
|
#endif /* S390_DUMP_H */
|
||||||
@@ -21,7 +21,9 @@
|
|||||||
#define AP_UDEV_FILE "/etc/udev/rules.d/41-ap.rules"
|
#define AP_UDEV_FILE "/etc/udev/rules.d/41-ap.rules"
|
||||||
#define AP_LOCKFILE "/run/lock/s390apconfig.lock"
|
#define AP_LOCKFILE "/run/lock/s390apconfig.lock"
|
||||||
|
|
||||||
#define AP_LOCK_RETRIES 15
|
#define AP_LOCK_RETRIES 3000
|
||||||
|
#define AP_LOCK_DELAY_US 30000 /* wait at least 30ms between lock retries */
|
||||||
|
#define AP_LOCK_VARIANCE_US 3000 /* or as much as 33ms */
|
||||||
|
|
||||||
/* apmask and aqmask are each represented as 67 character strings with:
|
/* apmask and aqmask are each represented as 67 character strings with:
|
||||||
* '0x' leading characters
|
* '0x' leading characters
|
||||||
@@ -70,6 +72,7 @@ char *path_get_ap_udev(void);
|
|||||||
void vfio_ap_parse_matrix(struct vfio_ap_device *dev, char *matrix);
|
void vfio_ap_parse_matrix(struct vfio_ap_device *dev, char *matrix);
|
||||||
void vfio_ap_sort_matrix_results(struct vfio_ap_device *dev);
|
void vfio_ap_sort_matrix_results(struct vfio_ap_device *dev);
|
||||||
void vfio_ap_parse_control(struct vfio_ap_device *dev, char *control);
|
void vfio_ap_parse_control(struct vfio_ap_device *dev, char *control);
|
||||||
|
bool vfio_ap_need_dynamic_config(struct vfio_ap_device *dev);
|
||||||
|
|
||||||
/* Functions for reading JSON device config */
|
/* Functions for reading JSON device config */
|
||||||
int vfio_ap_read_device_config(const char *path, struct vfio_ap_device *dev);
|
int vfio_ap_read_device_config(const char *path, struct vfio_ap_device *dev);
|
||||||
@@ -85,10 +88,14 @@ bool ap_read_udev_masks(char *path, char *ap, char *aq, bool *read_ap,
|
|||||||
bool *read_aq);
|
bool *read_aq);
|
||||||
void ap_mask_to_list(char *mask, struct util_list *list);
|
void ap_mask_to_list(char *mask, struct util_list *list);
|
||||||
void ap_list_remove_all(struct util_list *list);
|
void ap_list_remove_all(struct util_list *list);
|
||||||
|
char *vfio_ap_device_get_adapter_mask(struct vfio_ap_device *dev, int *size);
|
||||||
|
char *vfio_ap_device_get_domain_mask(struct vfio_ap_device *dev, int *size);
|
||||||
|
char *vfio_ap_device_get_control_mask(struct vfio_ap_device *dev, int *size);
|
||||||
|
|
||||||
/* Lock Functions */
|
/* Lock Functions */
|
||||||
int ap_get_lock(void);
|
int ap_get_lock(void);
|
||||||
int ap_get_lock_callout(void);
|
int ap_get_lock_callout(void);
|
||||||
|
int ap_try_lock_callout(void);
|
||||||
int ap_release_lock(void);
|
int ap_release_lock(void);
|
||||||
int ap_release_lock_callout(void);
|
int ap_release_lock_callout(void);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ enum util_arch_machine_type {
|
|||||||
UTIL_ARCH_MACHINE_TYPE_Z15 = 8561,
|
UTIL_ARCH_MACHINE_TYPE_Z15 = 8561,
|
||||||
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,
|
||||||
};
|
};
|
||||||
|
|
||||||
int util_arch_machine_type(void);
|
int util_arch_machine_type(void);
|
||||||
|
|||||||
@@ -14,7 +14,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "zt_common.h"
|
#include "zt_common.h"
|
||||||
|
#include "lib/util_libc.h"
|
||||||
|
|
||||||
void util_hexdump(FILE *fh, const char *tag, const void *data, int cnt);
|
void util_hexdump(FILE *fh, const char *tag, const void *data, int cnt);
|
||||||
void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group,
|
void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group,
|
||||||
@@ -37,4 +40,30 @@ static inline void util_ptr_vec_free(void **ptr_vec, int count)
|
|||||||
free(ptr_vec);
|
free(ptr_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expand size of dynamic array (element_t *) by one element
|
||||||
|
*
|
||||||
|
* @param[in,out] array Pointer to array (element_t **)
|
||||||
|
* @param[in,out] num Pointer to integer containing number of elements
|
||||||
|
*/
|
||||||
|
#define util_expand_array(array, num) \
|
||||||
|
do { \
|
||||||
|
unsigned int __size = sizeof(*(*(array))); \
|
||||||
|
*(array) = util_realloc(*(array), ++(*(num)) * __size); \
|
||||||
|
memset(&((*(array))[*(num) - 1]), 0, __size); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append one element to dynamic array (element_t *)
|
||||||
|
*
|
||||||
|
* @param[in,out] array Pointer to array (element_t **)
|
||||||
|
* @param[in,out] num Pointer to integer containing number of elements
|
||||||
|
* @param[in] element Element to add (element_t)
|
||||||
|
*/
|
||||||
|
#define util_add_array(array, num, element) \
|
||||||
|
do { \
|
||||||
|
util_expand_array(array, num); \
|
||||||
|
(*(array))[*(num) - 1] = (element) ; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif /* LIB_UTIL_BASE_H */
|
#endif /* LIB_UTIL_BASE_H */
|
||||||
|
|||||||
235
include/lib/util_fmt.h
Normal file
235
include/lib/util_fmt.h
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* util_fmt - Format structured key-value data as JSON, text pairs, or CSV
|
||||||
|
*
|
||||||
|
* Copyright IBM Corp. 2024
|
||||||
|
*
|
||||||
|
* s390-tools is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the MIT license. See LICENSE for details.
|
||||||
|
*
|
||||||
|
* This module provides helper functions for converting structured key-value
|
||||||
|
* data into different output formats.
|
||||||
|
*
|
||||||
|
* Benefits:
|
||||||
|
* - Output format can be dynamically configured at run-time
|
||||||
|
* - Callers do not need to add extra code for each output format
|
||||||
|
* - Some format-specific requirements such as quoting, indentation, and
|
||||||
|
* comma-placement are automated
|
||||||
|
*
|
||||||
|
* Basic API calling sequence:
|
||||||
|
*
|
||||||
|
* util_fmt_init() => Select output format
|
||||||
|
* util_fmt_obj_start() => Start a new object or list
|
||||||
|
* util_fmt_pair() => Emit a key-value pair
|
||||||
|
* util_fmt_obj_end() => End the latest object or list
|
||||||
|
* util_fmt_exit() => Cleanup
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* - Supported data elements are objects, lists and key-value pairs (mappings)
|
||||||
|
* - Scalars are only supported as part of a mapping
|
||||||
|
* - For CSV output and key filtering, mapping keys must be unique - this can
|
||||||
|
* be achieved either by choosing unique key names or by including object
|
||||||
|
* names via the FMT_PREFIX flag
|
||||||
|
* - For CSV output, at least one object or list with the FMT_ROW flag must be
|
||||||
|
* emitted
|
||||||
|
* - Common tool-specific meta-information such as API-level, tool version,
|
||||||
|
* etc. is automatically added to the output
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIB_UTIL_FMT_H
|
||||||
|
#define LIB_UTIL_FMT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* Flag value for default behavior (all flag types). */
|
||||||
|
#define FMT_DEFAULT 0
|
||||||
|
|
||||||
|
/* Names of supported output format types. */
|
||||||
|
#define FMT_TYPE_NAMES "json json-seq pairs csv"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum util_fmt_t - Output format types.
|
||||||
|
* @FMT_JSON: JavaScript Object Notation output data structure
|
||||||
|
* @FMT_JSONSEQ: Sequence of JSON data structures according to RFC7464
|
||||||
|
* @FMT_PAIRS: Textual key=value pairs
|
||||||
|
* @FMT_CSV: Comma-separated-values output
|
||||||
|
*
|
||||||
|
* Use these types with util_fmt_init() to control the output format.
|
||||||
|
*/
|
||||||
|
enum util_fmt_t {
|
||||||
|
FMT_JSON,
|
||||||
|
FMT_JSONSEQ,
|
||||||
|
FMT_PAIRS,
|
||||||
|
FMT_CSV,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum util_fmt_flags_t - Format control flags.
|
||||||
|
* @FMT_NOPREFIX: (pairs) Remove object hierarchy prefix from keys
|
||||||
|
* @FMT_KEEPINVAL: (all) Print mappings even if value is marked as invalid
|
||||||
|
* Values will be replaced with null (JSON) or an empty
|
||||||
|
* string
|
||||||
|
* @FMT_QUOTEALL: (all) Add quotes to all mapping values
|
||||||
|
* @FMT_FILTER: (all) Ignore keys not announced via util_fmt_add_key()
|
||||||
|
* @FMT_HANDLEINT: (json) Ensure correct JSON closure when interrupted
|
||||||
|
* @FMT_NOMETA: (all) Do not emit tool meta-data
|
||||||
|
* @FMT_WARN: (all) Warn about incorrect API usage
|
||||||
|
*
|
||||||
|
* Use these flags with util_fmt_init() to control generic aspects.
|
||||||
|
*/
|
||||||
|
enum util_fmt_flags_t {
|
||||||
|
FMT_NOPREFIX = (1 << 0),
|
||||||
|
FMT_KEEPINVAL = (1 << 1),
|
||||||
|
FMT_QUOTEALL = (1 << 2),
|
||||||
|
FMT_FILTER = (1 << 3),
|
||||||
|
FMT_HANDLEINT = (1 << 4),
|
||||||
|
FMT_NOMETA = (1 << 5),
|
||||||
|
FMT_WARN = (1 << 6),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum util_fmt_oflags_t - Object flags.
|
||||||
|
* @FMT_LIST: (all) Object is a list
|
||||||
|
* @FMT_ROW: (csv) Start a new CSV row with this object
|
||||||
|
* @FMT_PREFIX: (all) Include object name in key prefix for CSV headings
|
||||||
|
* and filter keys
|
||||||
|
*
|
||||||
|
* Use these flags with util_fmt_obj_start() to control object related
|
||||||
|
* aspects.
|
||||||
|
*/
|
||||||
|
enum util_fmt_oflags_t {
|
||||||
|
FMT_LIST = (1 << 0),
|
||||||
|
FMT_ROW = (1 << 1),
|
||||||
|
FMT_PREFIX = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum util_fmt_mflags_t - Mapping flags.
|
||||||
|
* @FMT_QUOTE: (all) Quote value
|
||||||
|
* @FMT_INVAL: (all) Mark value as invalid
|
||||||
|
* @FMT_PERSIST: (csv) Keep value across CSV rows until overwritten
|
||||||
|
*
|
||||||
|
* Use these flags with util_fmt_pair() to control mapping related aspects.
|
||||||
|
*/
|
||||||
|
enum util_fmt_mflags_t {
|
||||||
|
FMT_QUOTE = (1 << 0),
|
||||||
|
FMT_INVAL = (1 << 1),
|
||||||
|
FMT_PERSIST = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_init() - Initialize output formatter.
|
||||||
|
* @fd : Output file descriptor
|
||||||
|
* @type : Output format type
|
||||||
|
* @flags: Formatting parameters
|
||||||
|
* @api_level: Output format level indicator
|
||||||
|
*
|
||||||
|
* Prepare for writing formatted output with the given @type to @fd. Additional
|
||||||
|
* @flags can be specified to control certain output aspects (see &enum
|
||||||
|
* util_fmt_flags_t).
|
||||||
|
*
|
||||||
|
* @api_level represents an application-specific output format version number:
|
||||||
|
* this number starts at 1 and must be increased whenever an incompatible format
|
||||||
|
* change is introduced, e.g. when a non-optional object or mapping is removed
|
||||||
|
* or used for different data.
|
||||||
|
*/
|
||||||
|
void util_fmt_init(FILE *fd, enum util_fmt_t type, unsigned int flags,
|
||||||
|
int api_level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_exit() - Release resources used by output formatter.
|
||||||
|
*
|
||||||
|
* Release all resources currently in use by the output formatter.
|
||||||
|
*/
|
||||||
|
void util_fmt_exit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_name_to_type() - Convert format name to type identifier.
|
||||||
|
* @name: Format name
|
||||||
|
* @type: Pointer to resulting format type identifier
|
||||||
|
*
|
||||||
|
* Search supported output format types for a type with associated @name. If
|
||||||
|
* found, store resulting type identifier in @type.
|
||||||
|
*
|
||||||
|
* Return: %true if type is found, %false otherwise.
|
||||||
|
*/
|
||||||
|
bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_set_indent() - Set indentation parameters.
|
||||||
|
* @base : Base indentation level to apply to all output lines (default 0)
|
||||||
|
* @width : Number of indentation characters per intendation level (default 2)
|
||||||
|
* @ind_char: Indentation characters to use (default space).
|
||||||
|
*/
|
||||||
|
void util_fmt_set_indent(unsigned int base, unsigned int width, char ind_char);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_add_key() - Register expected mapping keys.
|
||||||
|
* @fmt: Format string to generate key
|
||||||
|
*
|
||||||
|
* Register a mapping key before the associated key-value pair is emitted.
|
||||||
|
*
|
||||||
|
* Use this function together with format control flag @FMT_FILTER to ignore all
|
||||||
|
* key-value pairs for which the key has not been registered. This can be
|
||||||
|
* useful to allow for dynamically configured filtering of output based on
|
||||||
|
* a static list of emitted mappings.
|
||||||
|
*
|
||||||
|
* When creating CSV output, use this function to register all column keys
|
||||||
|
* in advance to enable a stable column list in case of rows that do not
|
||||||
|
* provide data for all columns.
|
||||||
|
*/
|
||||||
|
void util_fmt_add_key(const char *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_obj_start() - Start a new data object.
|
||||||
|
* @oflags: Flags controlling aspects of this object.
|
||||||
|
* @fmt : Format string for generating an object name or %NULL.
|
||||||
|
*
|
||||||
|
* Use this function to start a new object in output data. Depending on
|
||||||
|
* @oflags, the new object represents either a normal object or a list. @oflags
|
||||||
|
* can also be used to indicated that an object corresponds to a new row of
|
||||||
|
* CSV data. If @fmt is non-%NULL, the resulting name is used in a format
|
||||||
|
* type specified way:
|
||||||
|
*
|
||||||
|
* Pairs:
|
||||||
|
* - Object names are reflected as dot-separated component in the mapping
|
||||||
|
* prefix, e.g. 'a.b.key=value'
|
||||||
|
* - An index is generated for mappings and objects that are part of list,
|
||||||
|
* e.g. 'a.b[1].key=value'
|
||||||
|
* JSON:
|
||||||
|
* - Object names are reflected as key-object mappings, e.g.
|
||||||
|
* <name>: { }
|
||||||
|
* - Required commas between objects and mappings are automatically generated
|
||||||
|
* CSV:
|
||||||
|
* - Object names and the list type flag have no effect
|
||||||
|
* - When flag @FMT_ROW is specified, a CSV row will be emitted when
|
||||||
|
* util_fmt_obj_end() is called for the associated object
|
||||||
|
*/
|
||||||
|
void util_fmt_obj_start(unsigned int oflags, const char *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_obj_end() - Announce the end of the latest data object started.
|
||||||
|
*
|
||||||
|
* Each object started with util_fmt_obj_start() must be ended with an
|
||||||
|
* associated util_fmt_obj_end() call.
|
||||||
|
*/
|
||||||
|
void util_fmt_obj_end(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* util_fmt_pair() - Emit a key-value pair.
|
||||||
|
* @mflags: Flags controlling this pair.
|
||||||
|
* @key : Key for this pair, excluding prefix.
|
||||||
|
* @fmt : Format string used to generated the pair value.
|
||||||
|
*
|
||||||
|
* Emit a key-value pair with the specified @key and the value that results
|
||||||
|
* from format string @fmt.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - For JSON, a mapping can only occur after util_fmt_obj_start()
|
||||||
|
* - For CSV, each @key must be unique, either by choosing unique key names
|
||||||
|
* or by including object names as prefix via the use of FMT_PREFIX in
|
||||||
|
* parent objects
|
||||||
|
*/
|
||||||
|
void util_fmt_pair(unsigned int mflags, const char *key, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif /* LIB_UTIL_FMT_H */
|
||||||
@@ -127,6 +127,7 @@ do { \
|
|||||||
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);
|
||||||
|
void util_concatf(char **str1, const char *fmt, ...);
|
||||||
void util_str_toupper(char *str);
|
void util_str_toupper(char *str);
|
||||||
|
|
||||||
char *util_strstrip(char *s);
|
char *util_strstrip(char *s);
|
||||||
|
|||||||
@@ -18,9 +18,15 @@
|
|||||||
#define UTIL_LOCKFILE_ERR 4 /* Other, unexpected error conditions */
|
#define UTIL_LOCKFILE_ERR 4 /* Other, unexpected error conditions */
|
||||||
|
|
||||||
int util_lockfile_lock(char *lockfile, int retries);
|
int util_lockfile_lock(char *lockfile, int retries);
|
||||||
|
int util_lockfile_lock_cw(char *lockfile, int retries, unsigned int waitinc,
|
||||||
|
unsigned int maxwait);
|
||||||
int util_lockfile_parent_lock(char *lockfile, int retries);
|
int util_lockfile_parent_lock(char *lockfile, int retries);
|
||||||
|
int util_lockfile_parent_lock_cw(char *lockfile, int retries,
|
||||||
|
unsigned int waitinc, unsigned int maxwait);
|
||||||
|
|
||||||
int util_lockfile_release(char *lockfile);
|
int util_lockfile_release(char *lockfile);
|
||||||
int util_lockfile_parent_release(char *lockfile);
|
int util_lockfile_parent_release(char *lockfile);
|
||||||
|
|
||||||
|
int util_lockfile_peek_owner(char *lockfile, int *pid);
|
||||||
|
|
||||||
#endif /** LIB_UTIL_LOCKFILE_H @} */
|
#endif /** LIB_UTIL_LOCKFILE_H @} */
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#define LV_COMPAT_CYL 0xFFFE
|
#define LV_COMPAT_CYL 0xFFFE
|
||||||
|
|
||||||
#define VTOC_ERROR "VTOC error:"
|
#define VTOC_ERROR "VTOC error:"
|
||||||
|
#define MAX_VTOC_ENTRIES 9 /* max number of VTOC labels for cdl formatted DASD */
|
||||||
|
|
||||||
typedef struct ttr
|
typedef struct ttr
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,439 +0,0 @@
|
|||||||
/*
|
|
||||||
* Certificate functions and definitions.
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2022
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef LIBPV_CERT_H
|
|
||||||
#define LIBPV_CERT_H
|
|
||||||
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
|
|
||||||
#include "libpv/common.h"
|
|
||||||
|
|
||||||
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
|
|
||||||
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
|
|
||||||
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
|
|
||||||
#define PV_IBM_Z_SUBJECT_ORGANIZATIONAL_UNIT_NAME_SUFFIX "Key Signing Service"
|
|
||||||
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
|
|
||||||
#define PV_IBM_Z_SUBJECT_STATE "New York"
|
|
||||||
#define PV_IMB_Z_SUBJECT_ENTRY_COUNT 6
|
|
||||||
|
|
||||||
/* Minimum security level for the keys/certificates used to establish a chain of
|
|
||||||
* trust (see https://www.openssl.org/docs/man1.1.1/man3/X509_VERIFY_PARAM_set_auth_level.html
|
|
||||||
* for details).
|
|
||||||
*/
|
|
||||||
#define PV_CERTS_SECURITY_LEVEL 2
|
|
||||||
|
|
||||||
/** pv_cert_init:
|
|
||||||
*
|
|
||||||
* Should not be called by user.
|
|
||||||
* Use pv_init() instead which
|
|
||||||
* calls this function during creation.
|
|
||||||
*
|
|
||||||
* Sets up data structures for caching CRLs.
|
|
||||||
*/
|
|
||||||
void pv_cert_init(void);
|
|
||||||
|
|
||||||
/** pv_cert_cleanup:
|
|
||||||
*
|
|
||||||
* Should not be called by user.
|
|
||||||
* Use pv_cleanup() instead which
|
|
||||||
* calls this function during creation.
|
|
||||||
*
|
|
||||||
* Cleans up data structures for caching CRLs.
|
|
||||||
*/
|
|
||||||
void pv_cert_cleanup(void);
|
|
||||||
|
|
||||||
#define PV_CERT_ERROR g_quark_from_static_string("pv-cert-error-quark")
|
|
||||||
typedef enum {
|
|
||||||
PV_CERT_ERROR_CERT_REVOKED,
|
|
||||||
PV_CERT_ERROR_CERT_SIGNATURE_INVALID,
|
|
||||||
PV_CERT_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
|
|
||||||
PV_CERT_ERROR_CRL_DOWNLOAD_FAILED,
|
|
||||||
PV_CERT_ERROR_CRL_SIGNATURE_INVALID,
|
|
||||||
PV_CERT_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
|
|
||||||
PV_CERT_ERROR_FAILED_DOWNLOAD_CRL,
|
|
||||||
PV_CERT_ERROR_INTERNAL,
|
|
||||||
PV_CERT_ERROR_INVALID_PARM,
|
|
||||||
PV_CERT_ERROR_INVALID_SIGNATURE_ALGORITHM,
|
|
||||||
PV_CERT_ERROR_INVALID_VALIDITY_PERIOD,
|
|
||||||
PV_CERT_ERROR_LOAD_CRL,
|
|
||||||
PV_CERT_ERROR_LOAD_DEFAULT_CA,
|
|
||||||
PV_CERT_ERROR_LOAD_ROOT_CA,
|
|
||||||
PV_CERT_ERROR_MALFORMED_CERTIFICATE,
|
|
||||||
PV_CERT_ERROR_MALFORMED_ROOT_CA,
|
|
||||||
PV_CERT_ERROR_NO_CRL,
|
|
||||||
PV_CERT_ERROR_NO_CRLDP,
|
|
||||||
PV_CERT_ERROR_NO_IBM_Z_SIGNING_KEY,
|
|
||||||
PV_CERT_ERROR_NO_ISSUER_IBM_Z_FOUND,
|
|
||||||
PV_CERT_ERROR_NO_PUBLIC_KEY,
|
|
||||||
PV_CERT_ERROR_READ_CERTIFICATE,
|
|
||||||
PV_CERT_ERROR_READ_CRL,
|
|
||||||
PV_CERT_ERROR_SIGNATURE_ALGORITHM_MISMATCH,
|
|
||||||
PV_CERT_ERROR_SKID_AKID_MISMATCH,
|
|
||||||
PV_CERT_ERROR_VERIFICATION_FAILED,
|
|
||||||
PV_CERT_ERROR_WRONG_CA_USED,
|
|
||||||
} PvCertErrors;
|
|
||||||
|
|
||||||
/** PvX509WithPath - X509 certificate associated with a path
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
X509 *cert;
|
|
||||||
char *path;
|
|
||||||
} PvX509WithPath;
|
|
||||||
|
|
||||||
/** pv_x509_with_path_new:
|
|
||||||
*
|
|
||||||
* @cert: X509 certificate
|
|
||||||
* @path: Path of that X509 certificate
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): new X509 with path
|
|
||||||
*/
|
|
||||||
PvX509WithPath *pv_x509_with_path_new(X509 *cert, const char *path);
|
|
||||||
|
|
||||||
/** pv_x509_with_path_free:
|
|
||||||
*
|
|
||||||
* Frees the path and the PvX509WithPath; Decreases the refcount of the X509
|
|
||||||
*/
|
|
||||||
void pv_x509_with_path_free(PvX509WithPath *cert);
|
|
||||||
|
|
||||||
typedef STACK_OF(DIST_POINT) STACK_OF_DIST_POINT;
|
|
||||||
typedef STACK_OF(X509) STACK_OF_X509;
|
|
||||||
typedef STACK_OF(X509_CRL) STACK_OF_X509_CRL;
|
|
||||||
typedef GSList PvCertWithPathList;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
X509 *cert;
|
|
||||||
STACK_OF_X509_CRL *crls;
|
|
||||||
} PvX509Pair;
|
|
||||||
|
|
||||||
/** pv_x509_pair_new_take:
|
|
||||||
* @cert: ptr to X509
|
|
||||||
* @crls: ptr to CRLs
|
|
||||||
*
|
|
||||||
* Takes a X509 and the associated CRLs and builds a pair.
|
|
||||||
* Both, *cert and *crls will be NULL afterwards, and owned by the pair.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): New PvX509Pair
|
|
||||||
*/
|
|
||||||
PvX509Pair *pv_x509_pair_new_take(X509 **cert, STACK_OF_X509_CRL **crls);
|
|
||||||
|
|
||||||
/** pv_x509_pair_free:
|
|
||||||
*
|
|
||||||
* Decreases the refcount of the X509 and crls.
|
|
||||||
* Frees the PvX509Pair.
|
|
||||||
*/
|
|
||||||
void pv_x509_pair_free(PvX509Pair *pair);
|
|
||||||
|
|
||||||
void STACK_OF_DIST_POINT_free(STACK_OF_DIST_POINT *stack);
|
|
||||||
void STACK_OF_X509_free(STACK_OF_X509 *stack);
|
|
||||||
void STACK_OF_X509_CRL_free(STACK_OF_X509_CRL *stack);
|
|
||||||
|
|
||||||
/** pv_x509_from_pem_der_data:
|
|
||||||
*
|
|
||||||
* @data: GBytes containing the cert in PEM format
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): X509 cert
|
|
||||||
*/
|
|
||||||
X509 *pv_x509_from_pem_der_data(GBytes *data, GError **error);
|
|
||||||
|
|
||||||
/** pv_x509_get_ec_pubkey:
|
|
||||||
*
|
|
||||||
* @cert: X509 to extract elliptic curve pubkey from
|
|
||||||
* @nid: numerical identifier of the expected curve
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): corresponding pupkey for the given certificate
|
|
||||||
*/
|
|
||||||
EVP_PKEY *pv_x509_get_ec_pubkey(X509 *cert, int nid, GError **error);
|
|
||||||
|
|
||||||
/** pv_get_ec_pubkeys:
|
|
||||||
*
|
|
||||||
* @certs_with_path: List of PvX509WithPath
|
|
||||||
* @nid: numerical identifier of the expected curve
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): List of corresponding public keys for the given certificate
|
|
||||||
*/
|
|
||||||
GSList *pv_get_ec_pubkeys(PvCertWithPathList *certs_with_path, int nid, GError **error);
|
|
||||||
|
|
||||||
/* pv_load_certificates:
|
|
||||||
*
|
|
||||||
* @cert_paths: list of cert paths.
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* @cert_paths must contain at least one element, otherwise an error is
|
|
||||||
* reported.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): List of PvX509WithPath corresponding to the given paths
|
|
||||||
*/
|
|
||||||
PvCertWithPathList *pv_load_certificates(char **cert_paths, GError **error);
|
|
||||||
|
|
||||||
/* pv_load_first_cert_from_file:
|
|
||||||
*
|
|
||||||
* @path: location of the x509
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* This function reads in only the first certificate and ignores all other. This
|
|
||||||
* is only relevant for the PEM file format. For the host-key document and the
|
|
||||||
* root CA this behavior is expected.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): PvX509WithPath corresponding to the given path
|
|
||||||
*/
|
|
||||||
X509 *pv_load_first_cert_from_file(const char *path, GError **error);
|
|
||||||
|
|
||||||
/* pv_load_first_crl_from_file:
|
|
||||||
*
|
|
||||||
* @path: location of the x509 CRL
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* This function reads in only the first CRL and ignores all other. This
|
|
||||||
* is only relevant for the PEM file format.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): X509_CRL corresponding to the given path
|
|
||||||
*/
|
|
||||||
X509_CRL *pv_load_first_crl_from_file(const char *path, GError **error);
|
|
||||||
|
|
||||||
/** pv_store_setup_crl_download:
|
|
||||||
*
|
|
||||||
* @st: X509_STORE
|
|
||||||
*/
|
|
||||||
void pv_store_setup_crl_download(X509_STORE *st);
|
|
||||||
|
|
||||||
/** pv_load_first_crl_by_cert:
|
|
||||||
* @cert: X509 to specify the download location.
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* This function returns the first X509_CRL found from the CRL distribution
|
|
||||||
* points specified in @cert.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): x509 CRL corresponding to the given X509
|
|
||||||
*/
|
|
||||||
X509_CRL *pv_load_first_crl_by_cert(X509 *cert, GError **error);
|
|
||||||
|
|
||||||
/** pv_try_load_crls_by_certs:
|
|
||||||
*
|
|
||||||
* @certs_with_path: List of PvX509WithPath
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): Stack of CRLs corresponding to the given X509
|
|
||||||
*/
|
|
||||||
STACK_OF_X509_CRL *pv_try_load_crls_by_certs(PvCertWithPathList *certs_with_path);
|
|
||||||
|
|
||||||
/** pv_store_setup:
|
|
||||||
*
|
|
||||||
* @root_ca_path: Location of the rootCA or NULL if SystemRoot CA shall be used
|
|
||||||
* @crl_paths: List of CRL paths or NULL
|
|
||||||
* @cert_with_crl_paths: List of (untrusted) X509 paths
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* The untrusted certs need to be verified before actually verifying a Host Key Document.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): X509_store with given input data.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
X509_STORE *pv_store_setup(char *root_ca_path, char **crl_paths, char **cert_with_crl_paths,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
/** pv_get_x509_stack:
|
|
||||||
*
|
|
||||||
* x509_with_path_list: list of PvX509WithPath
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): Stack of X509 corresponding to the given x509 with path
|
|
||||||
*/
|
|
||||||
STACK_OF_X509 *pv_get_x509_stack(const GSList *x509_with_path_list);
|
|
||||||
|
|
||||||
/** pv_init_store_ctx:
|
|
||||||
*
|
|
||||||
* @ctx: a uninitialized Store CTX
|
|
||||||
* @trusted: X509_STORE with a trusted rootCA
|
|
||||||
* @chain: untrusted X509s
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Can be called multiple times on the same context if X509_STORE_CTX_cleanup(ctx)
|
|
||||||
* was called before.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 on success
|
|
||||||
* -1 in failure
|
|
||||||
*/
|
|
||||||
int pv_init_store_ctx(X509_STORE_CTX *ctx, X509_STORE *trusted, STACK_OF_X509 *chain,
|
|
||||||
GError **error) PV_NONNULL(1, 2, 3);
|
|
||||||
|
|
||||||
/** pv_init_store_ctx:
|
|
||||||
*
|
|
||||||
* @trusted: X509_STORE with a trusted rootCA
|
|
||||||
* @chain: untrusted X509s
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): X509_STORE_CTX setup with the input data
|
|
||||||
*/
|
|
||||||
X509_STORE_CTX *pv_create_store_ctx(X509_STORE *trusted, STACK_OF_X509 *chain, GError **error)
|
|
||||||
PV_NONNULL(1, 2);
|
|
||||||
/** pv_remove_ibm_signing_certs:
|
|
||||||
*
|
|
||||||
* @certs: Stack of X509s
|
|
||||||
*
|
|
||||||
* Returns: (transfer full):
|
|
||||||
* List of all IBM Z signing key certificates in @certs and remove them
|
|
||||||
* from the chain.
|
|
||||||
* Empty stack if no IBM Z signing key is found.
|
|
||||||
*/
|
|
||||||
STACK_OF_X509 *pv_remove_ibm_signing_certs(STACK_OF_X509 *certs);
|
|
||||||
|
|
||||||
/** pv_c2b_name:
|
|
||||||
*
|
|
||||||
* Workaround to fix the mismatch between issuer name of the
|
|
||||||
* IBM Z signing CRLs and the IBM Z signing key subject name.
|
|
||||||
*
|
|
||||||
* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory
|
|
||||||
* ordered. The problem is that our certificates are not consistent in the order
|
|
||||||
* (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details).
|
|
||||||
*
|
|
||||||
* This function tries to reorder the name attributes such that
|
|
||||||
* further OpenSSL calls can work with it. The caller is
|
|
||||||
* responsible to free the returned value.
|
|
||||||
*/
|
|
||||||
X509_NAME *pv_c2b_name(const X509_NAME *name);
|
|
||||||
|
|
||||||
/** pv_verify_host_key:
|
|
||||||
*
|
|
||||||
* @host_key: X509 to be verified
|
|
||||||
* @issuer_pairs: IBM signing key X509+CRLs Pairs used for verification
|
|
||||||
* @level: Security level. see PV_CERTS_SECURITY_LEVEL
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 if Host key could be verified with one of the IBM signing keys
|
|
||||||
* -1 if no IBM signing key could verify the authenticity of the given host key
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int pv_verify_host_key(X509 *host_key, GSList *issuer_pairs, int verify_flags, int level,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
/** pv_verify_cert:
|
|
||||||
*
|
|
||||||
* @ctx: trusted store ctx used for verification
|
|
||||||
* @cert: X509 to be verified
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Cannot be used to verify host keys with IBM signing keys, as IBM signing
|
|
||||||
* keys are no intermediate CAs. Use pv_verify_host_key() instead.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 if @cert could be verified
|
|
||||||
* -1 if @cert could not be verified
|
|
||||||
*/
|
|
||||||
int pv_verify_cert(X509_STORE_CTX *ctx, X509 *cert, GError **error) PV_NONNULL(1, 2);
|
|
||||||
|
|
||||||
/** pv_check_crl_valid_for_cert:
|
|
||||||
*
|
|
||||||
* @crl: CRL to be verified
|
|
||||||
* @cert: Cert that probably issued the given CRL
|
|
||||||
* @verify_flags: X509 Verification flags (X509_V_FLAG_<TYPE>)
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Verify whether a revocation list @crl is valid and is issued by @cert. For
|
|
||||||
* this multiple steps must be done:
|
|
||||||
*
|
|
||||||
* 1. verify issuer of the CRL matches with the suject name of @cert
|
|
||||||
* 2. verify the validity period of the CRL
|
|
||||||
* 3. verify the signature of the CRL
|
|
||||||
*
|
|
||||||
* Important: This function does not verify whether @cert is allowed to issue a
|
|
||||||
* CRL.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 if @crl is valid and issued by @cert
|
|
||||||
* -1 otherwise
|
|
||||||
*/
|
|
||||||
int pv_verify_crl(X509_CRL *crl, X509 *cert, int verify_flags, GError **error);
|
|
||||||
|
|
||||||
/** pv_check_chain_parameters:
|
|
||||||
*
|
|
||||||
* @chain: chain of trust to be validated
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Verifies that chain has at least a RootCA ans intermediate CA
|
|
||||||
* and logs the used ROD CA subject
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 @chain is valid
|
|
||||||
* -1 otherwise
|
|
||||||
*/
|
|
||||||
int pv_check_chain_parameters(const STACK_OF_X509 *chain, GError **error);
|
|
||||||
|
|
||||||
/** pv_store_set_verify_param:
|
|
||||||
*
|
|
||||||
* @store: X509_STORE to set parameters
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 on success
|
|
||||||
* -1 on failure
|
|
||||||
*/
|
|
||||||
int pv_store_set_verify_param(X509_STORE *store, GError **error);
|
|
||||||
|
|
||||||
/** pv_store_ctx_find_valid_crls:
|
|
||||||
*
|
|
||||||
* @ctx: STORE_CTX for searching CRLs
|
|
||||||
* @cert: X509 to match CRLs aggainst
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): STACK of CRLs related to given @crl fin @ctx
|
|
||||||
*/
|
|
||||||
STACK_OF_X509_CRL *pv_store_ctx_find_valid_crls(X509_STORE_CTX *ctx, X509 *cert, GError **error)
|
|
||||||
PV_NONNULL(1, 2);
|
|
||||||
|
|
||||||
/** pv_verify_host_key_doc:
|
|
||||||
*
|
|
||||||
* @host_key_certs_with_path: X509s to be verified
|
|
||||||
* @trusted. X509_STORE with a rusted RootCA
|
|
||||||
* @untrusted_certs: STACK OF untrusted X509s
|
|
||||||
* @online: true if CRLs shall be downloaded
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 if all given HKDs could be verified using the chain of trust.
|
|
||||||
* -1 otherwise
|
|
||||||
*/
|
|
||||||
int pv_verify_host_key_doc(PvCertWithPathList *host_key_certs_with_path, X509_STORE *trusted,
|
|
||||||
STACK_OF_X509 *untrusted_certs, gboolean online, GError **error)
|
|
||||||
PV_NONNULL(1, 2, 3);
|
|
||||||
|
|
||||||
/** pv_verify_host_key_docs_by_path:
|
|
||||||
*
|
|
||||||
* @host_key_paths: locations of X509 to be verified
|
|
||||||
* @optional_root_ca_path: rootCA location or NULL if Default shall be used
|
|
||||||
* @optional_crl_paths: locations of CRLs or NULL
|
|
||||||
* @untrusted_cert_paths: locations of IntermediateCAs including the IBM signing key
|
|
||||||
* @online: true if CRLs shall be downloaded
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* 0 if all given HKDs could be verfied using the chain of trust.
|
|
||||||
* -1 otherwise
|
|
||||||
*/
|
|
||||||
int pv_verify_host_key_docs_by_path(char **host_key_paths, char *optional_root_ca_path,
|
|
||||||
char **optional_crl_paths, char **untrusted_cert_paths,
|
|
||||||
gboolean online, GError **error) PV_NONNULL(1, 4);
|
|
||||||
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(AUTHORITY_KEYID, AUTHORITY_KEYID_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvX509WithPath, pv_x509_with_path_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_DIST_POINT, STACK_OF_DIST_POINT_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_X509, STACK_OF_X509_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(STACK_OF_X509_CRL, STACK_OF_X509_CRL_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509, X509_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_CRL, X509_CRL_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_LOOKUP, X509_LOOKUP_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_NAME, X509_NAME_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(PvX509Pair, pv_x509_pair_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE, X509_STORE_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(X509_STORE_CTX, X509_STORE_CTX_free)
|
|
||||||
|
|
||||||
#endif /* LIBPV_CERT_H */
|
|
||||||
@@ -14,22 +14,6 @@
|
|||||||
* the glib version is supported
|
* the glib version is supported
|
||||||
*/
|
*/
|
||||||
#include "libpv/glib-helper.h"
|
#include "libpv/glib-helper.h"
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
#include "libpv/openssl-compat.h"
|
|
||||||
#include "libpv/macros.h"
|
|
||||||
|
|
||||||
/** pv_init:
|
|
||||||
*
|
|
||||||
* Must be called before any libpv call.
|
|
||||||
*/
|
|
||||||
int pv_init(void);
|
|
||||||
|
|
||||||
/** pv_cleanup:
|
|
||||||
*
|
|
||||||
* Must be called when done with using libpv.
|
|
||||||
*/
|
|
||||||
void pv_cleanup(void);
|
|
||||||
|
|
||||||
#endif /* LIBPV_COMMON_H */
|
#endif /* LIBPV_COMMON_H */
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#include "libpv/common.h"
|
#include "libpv/common.h"
|
||||||
|
#define PV_NONNULL(...)
|
||||||
|
|
||||||
typedef struct pv_cipher_parms {
|
typedef struct pv_cipher_parms {
|
||||||
const EVP_CIPHER *cipher;
|
const EVP_CIPHER *cipher;
|
||||||
@@ -26,17 +27,6 @@ typedef struct pv_cipher_parms {
|
|||||||
};
|
};
|
||||||
} PvCipherParms;
|
} PvCipherParms;
|
||||||
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
uint8_t x[80];
|
|
||||||
uint8_t y[80];
|
|
||||||
};
|
|
||||||
uint8_t data[160];
|
|
||||||
} PvEcdhPubKey;
|
|
||||||
G_STATIC_ASSERT(sizeof(PvEcdhPubKey) == 160);
|
|
||||||
|
|
||||||
typedef GSList PvEvpKeyList;
|
|
||||||
|
|
||||||
enum PvCryptoMode {
|
enum PvCryptoMode {
|
||||||
PV_ENCRYPT,
|
PV_ENCRYPT,
|
||||||
PV_DECRYPT,
|
PV_DECRYPT,
|
||||||
@@ -61,42 +51,6 @@ char *pv_get_openssl_errors(void);
|
|||||||
*/
|
*/
|
||||||
int pv_BIO_reset(BIO *b);
|
int pv_BIO_reset(BIO *b);
|
||||||
|
|
||||||
/**
|
|
||||||
* pv_generate_rand_data:
|
|
||||||
* @size: number of generated random bytes using a crypographically secure pseudo random generator
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Creates a new #GBytes with @size random bytes using a cryptographically
|
|
||||||
* secure pseudo random generator.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): a new #GBytes, or %NULL in case of an error
|
|
||||||
*/
|
|
||||||
GBytes *pv_generate_rand_data(size_t size, GError **error);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pv_generate_key:
|
|
||||||
* @cipher: specifies the OpenSSL cipher for which a cryptographically secure key should be generated
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Creates a random key for @cipher using a cryptographically secure pseudo
|
|
||||||
* random generator.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): a new #GBytes, or %NULL in case of an error
|
|
||||||
*/
|
|
||||||
GBytes *pv_generate_key(const EVP_CIPHER *cipher, GError **error) PV_NONNULL(1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pv_generate_iv:
|
|
||||||
* @cipher: specifies the OpenSSL cipher for which a cryptographically secure IV should be generated
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Creates a random IV for @cipher using a cryptographically secure pseudo
|
|
||||||
* random generator.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): a new #GBytes, or %NULL in case of an error
|
|
||||||
*/
|
|
||||||
GBytes *pv_generate_iv(const EVP_CIPHER *cipher, GError **error) PV_NONNULL(1);
|
|
||||||
|
|
||||||
/* Symmetric en/decryption functions */
|
/* Symmetric en/decryption functions */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,7 +89,7 @@ int64_t pv_gcm_decrypt(GBytes *cipher, GBytes *aad, GBytes *tag, const PvCipherP
|
|||||||
* @derived_key_len: size of the output key
|
* @derived_key_len: size of the output key
|
||||||
* @key: input key
|
* @key: input key
|
||||||
* @salt: salt for the extraction
|
* @salt: salt for the extraction
|
||||||
* @info: infor for the expansion
|
* @info: info for the expansion
|
||||||
* @md: EVP mode of operation
|
* @md: EVP mode of operation
|
||||||
* @error: return location for a #GError
|
* @error: return location for a #GError
|
||||||
*
|
*
|
||||||
@@ -147,54 +101,15 @@ int64_t pv_gcm_decrypt(GBytes *cipher, GBytes *aad, GBytes *tag, const PvCipherP
|
|||||||
GBytes *pv_hkdf_extract_and_expand(size_t derived_key_len, GBytes *key, GBytes *salt, GBytes *info,
|
GBytes *pv_hkdf_extract_and_expand(size_t derived_key_len, GBytes *key, GBytes *salt, GBytes *info,
|
||||||
const EVP_MD *md, GError **error) PV_NONNULL(2, 3, 4, 5);
|
const EVP_MD *md, GError **error) PV_NONNULL(2, 3, 4, 5);
|
||||||
|
|
||||||
/** pv_generate_ec_key:
|
|
||||||
*
|
|
||||||
* @nid: Numerical identifier of the curve
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): new random key based on the given curve
|
|
||||||
*/
|
|
||||||
EVP_PKEY *pv_generate_ec_key(int nid, GError **error);
|
|
||||||
|
|
||||||
/** pv_evp_pkey_to_ecdh_pub_key:
|
|
||||||
*
|
|
||||||
* @key: input key in EVP_PKEY format
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: the public part of the input @key in ECDH format.
|
|
||||||
*/
|
|
||||||
PvEcdhPubKey *pv_evp_pkey_to_ecdh_pub_key(EVP_PKEY *key, GError **error) PV_NONNULL(1);
|
|
||||||
|
|
||||||
/** pv_derive_exchange_key:
|
|
||||||
* @cust: Customer Key
|
|
||||||
* @host: Host key
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): Shared Secret of @cust and @host
|
|
||||||
*/
|
|
||||||
GBytes *pv_derive_exchange_key(EVP_PKEY *cust, EVP_PKEY *host, GError **error) PV_NONNULL(1, 2);
|
|
||||||
|
|
||||||
GQuark pv_crypto_error_quark(void);
|
GQuark pv_crypto_error_quark(void);
|
||||||
#define PV_CRYPTO_ERROR pv_crypto_error_quark()
|
#define PV_CRYPTO_ERROR pv_crypto_error_quark()
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PV_CRYPTO_ERROR_DERIVE,
|
|
||||||
PV_CRYPTO_ERROR_HKDF_FAIL,
|
PV_CRYPTO_ERROR_HKDF_FAIL,
|
||||||
PV_CRYPTO_ERROR_INTERNAL,
|
PV_CRYPTO_ERROR_INTERNAL,
|
||||||
PV_CRYPTO_ERROR_INVALID_KEY_SIZE,
|
|
||||||
PV_CRYPTO_ERROR_KEYGENERATION,
|
|
||||||
PV_CRYPTO_ERROR_RANDOMIZATION,
|
|
||||||
PV_CRYPTO_ERROR_READ_FILE,
|
|
||||||
PV_CRYPTO_ERROR_NO_MATCH_TAG,
|
PV_CRYPTO_ERROR_NO_MATCH_TAG,
|
||||||
} PvCryptoErrors;
|
} PvCryptoErrors;
|
||||||
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_GROUP, EC_GROUP_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_KEY, EC_KEY_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EC_POINT, EC_POINT_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY, EVP_PKEY_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY, EVP_PKEY_free)
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY_CTX, EVP_PKEY_CTX_free)
|
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_PKEY_CTX, EVP_PKEY_CTX_free)
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Libcurl utils
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2022
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef LIBPV_CURL_H
|
|
||||||
#define LIBPV_CURL_H
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
|
|
||||||
#include "libpv/common.h"
|
|
||||||
|
|
||||||
#define CRL_DOWNLOAD_TIMEOUT_MS 3000
|
|
||||||
#define CRL_DOWNLOAD_MAX_SIZE 0x100000
|
|
||||||
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(CURL, curl_easy_cleanup)
|
|
||||||
|
|
||||||
/** curl_download:
|
|
||||||
* @url: URL to specify location of data
|
|
||||||
* @timeout_ms: time to wait until fail
|
|
||||||
* @max_size: Maximum size of the downloaded data
|
|
||||||
* @error: return location for a GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): Downloaded data as #GByteArray
|
|
||||||
*/
|
|
||||||
GByteArray *curl_download(const char *url, long timeout_ms, uint max_size, GError **err);
|
|
||||||
|
|
||||||
/** pv_curl_init:
|
|
||||||
*
|
|
||||||
* Should not be called by user.
|
|
||||||
* Use pv_init() instead which
|
|
||||||
* calls this function during creation.
|
|
||||||
*/
|
|
||||||
int pv_curl_init(void);
|
|
||||||
|
|
||||||
/** pv_curl_cleanup:
|
|
||||||
*
|
|
||||||
* Should not be called by user.
|
|
||||||
* Use pv_cleanup() instead which
|
|
||||||
* calls this function during creation.
|
|
||||||
*/
|
|
||||||
void pv_curl_cleanup(void);
|
|
||||||
|
|
||||||
#define PV_CURL_ERROR g_quark_from_static_string("pv-curl-error-quark")
|
|
||||||
typedef enum {
|
|
||||||
PV_CURL_ERROR_CURL_INIT_FAILED,
|
|
||||||
PV_CURL_ERROR_DOWNLOAD_FAILED,
|
|
||||||
} PvCurlErrors;
|
|
||||||
|
|
||||||
#endif /* LIBPV_CURL_H */
|
|
||||||
@@ -28,8 +28,6 @@
|
|||||||
#include <gmodule.h>
|
#include <gmodule.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "libpv/macros.h"
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) \
|
#define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) \
|
||||||
DO_PRAGMA(clang diagnostic push) \
|
DO_PRAGMA(clang diagnostic push) \
|
||||||
@@ -40,6 +38,8 @@
|
|||||||
#define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) G_DEFINE_AUTOPTR_CLEANUP_FUNC(__VA_ARGS__)
|
#define WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(...) G_DEFINE_AUTOPTR_CLEANUP_FUNC(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DO_PRAGMA(x) _Pragma(#x)
|
||||||
|
|
||||||
#define pv_wrapped_g_assert(__expr) g_assert(__expr)
|
#define pv_wrapped_g_assert(__expr) g_assert(__expr)
|
||||||
|
|
||||||
/** pv_sec_gbytes_new_take:
|
/** pv_sec_gbytes_new_take:
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Hashing definitions.
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2022
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef LIBPV_HASH_H
|
|
||||||
#define LIBPV_HASH_H
|
|
||||||
|
|
||||||
#include <openssl/hmac.h>
|
|
||||||
|
|
||||||
#include "libpv/common.h"
|
|
||||||
|
|
||||||
/** pv_digest_ctx_new:
|
|
||||||
* @md: mode of digest, e.g. #EVP_sha256()
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): a new #EVP_MD_CTX, or %NULL in case of an error
|
|
||||||
*/
|
|
||||||
EVP_MD_CTX *pv_digest_ctx_new(const EVP_MD *md, GError **error);
|
|
||||||
|
|
||||||
/** pv_digest_ctx_update:
|
|
||||||
* @ctx: EVP_MD_CTX to add data
|
|
||||||
* @data: #GBytes to add to the context
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Adds @data to the digest context. Can be called multiple times.
|
|
||||||
*
|
|
||||||
* Returns: 0 in case of success, -1 otherwise.
|
|
||||||
*/
|
|
||||||
int pv_digest_ctx_update(EVP_MD_CTX *ctx, GBytes *data, GError **error);
|
|
||||||
|
|
||||||
/** pv_digest_ctx_update_raw:
|
|
||||||
* @ctx: #EVP_MD_CTX to add data
|
|
||||||
* @buf: data to add to the context
|
|
||||||
* @size: size of @buf
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Adds @buf to the digest context. Can be called multiple times.
|
|
||||||
*
|
|
||||||
* Returns: 0 in case of success, -1 otherwise.
|
|
||||||
*/
|
|
||||||
int pv_digest_ctx_update_raw(EVP_MD_CTX *ctx, const uint8_t *buf, size_t size, GError **error);
|
|
||||||
|
|
||||||
/** pv_digest_ctx_finalize:
|
|
||||||
* @ctx: #EVP_MD_CTX with data to digest
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Calculates the digest of all previously added data. Do not use @ctx afterwards.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): Digest of all data added before as #GBytes, or NULL in case of error.
|
|
||||||
*/
|
|
||||||
GBytes *pv_digest_ctx_finalize(EVP_MD_CTX *ctx, GError **error);
|
|
||||||
|
|
||||||
/** pv_sha256_hash:
|
|
||||||
* @buf: data for which a sha256 hash sould be calculated
|
|
||||||
* @size: size of @buf
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Shorthand for initializing a sha256-digest ctx, updating, and finalizing.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): SHA256 of @buf as #GBytes, or NULL in case of error.
|
|
||||||
*/
|
|
||||||
GBytes *pv_sha256_hash(uint8_t *buf, size_t size, GError **error);
|
|
||||||
|
|
||||||
/** pv_hmac_ctx_new:
|
|
||||||
* @key: key used for the HMAC
|
|
||||||
* @md: mode of digest, e.g. #EVP_sha512()
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): New #HMAC_CTX or NULL in case of error
|
|
||||||
*/
|
|
||||||
HMAC_CTX *pv_hmac_ctx_new(GBytes *key, const EVP_MD *md, GError **error);
|
|
||||||
|
|
||||||
/** pv_hmac_ctx_update_raw:
|
|
||||||
* @ctx: #HMAC_CTX to add data
|
|
||||||
* @buf: data to add to the context
|
|
||||||
* @size: size of @buf
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Adds @buf to the HMAC context. Can be called multiple times.
|
|
||||||
*
|
|
||||||
* Returns: 0 in case of success, -1 otherwise.
|
|
||||||
*/
|
|
||||||
int pv_hmac_ctx_update_raw(HMAC_CTX *ctx, const void *data, size_t size, GError **error);
|
|
||||||
|
|
||||||
/** pv_hmac_ctx_update:
|
|
||||||
* @ctx: #HMAC_CTX to add data
|
|
||||||
* @data: #GBytes to add to the context
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Adds @data to the HMAC context. Can be called multiple times.
|
|
||||||
*
|
|
||||||
* Returns: 0 in case of success, -1 otherwise.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int pv_hmac_ctx_update(HMAC_CTX *ctx, GBytes *data, GError **error);
|
|
||||||
|
|
||||||
/** pv_hmac_ctx_finalize:
|
|
||||||
* @ctx: #HMAC_CTX with data to digest
|
|
||||||
* @error: return location for a #GError
|
|
||||||
*
|
|
||||||
* Calculates the HMAC of all previously added data. Do not use @ctx afterwards.
|
|
||||||
*
|
|
||||||
* Returns: (nullable) (transfer full): HMAC of all data added before as #GBytes, or NULL in case of error.
|
|
||||||
*/
|
|
||||||
GBytes *pv_hamc_ctx_finalize(HMAC_CTX *ctx, GError **error);
|
|
||||||
|
|
||||||
#define PV_HASH_ERROR g_quark_from_static_string("pv-crypro-error-quark")
|
|
||||||
typedef enum {
|
|
||||||
PV_HASH_ERROR_INTERNAL,
|
|
||||||
} PvHashErrors;
|
|
||||||
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(EVP_MD_CTX, EVP_MD_CTX_free)
|
|
||||||
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(HMAC_CTX, HMAC_CTX_free)
|
|
||||||
|
|
||||||
#endif /* LIBPV_HASH_H */
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Libpv common macro definitions.
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2022
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef LIBPV_MACROS_H
|
|
||||||
#define LIBPV_MACROS_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define PV_NONNULL(...)
|
|
||||||
#define DO_PRAGMA(x) _Pragma(#x)
|
|
||||||
|
|
||||||
/* Most significant bit */
|
|
||||||
#define PV_MSB(idx) ((uint64_t)1 << (63 - (idx)))
|
|
||||||
|
|
||||||
#endif /* LIBPV_MACROS_H */
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* OpenSSL compatibility utils
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2021
|
|
||||||
*
|
|
||||||
* 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 LIBPV_OPENSSL_COMPAT_H
|
|
||||||
#define LIBPV_OPENSSL_COMPAT_H
|
|
||||||
|
|
||||||
#include <openssl/opensslv.h>
|
|
||||||
#include <openssl/x509.h>
|
|
||||||
#include <openssl/x509_vfy.h>
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
||||||
#define pv_X509_STORE_CTX_get_current_cert(ctx) X509_STORE_CTX_get_current_cert(ctx)
|
|
||||||
#define pv_X509_STORE_CTX_get1_crls(ctx, nm) X509_STORE_CTX_get1_crls((ctx), (nm))
|
|
||||||
#define pv_X509_STORE_set_lookup_crls(st, cb) X509_STORE_set_lookup_crls(st, cb)
|
|
||||||
#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
||||||
#define pv_X509_STORE_CTX_get_current_cert(ctx) \
|
|
||||||
X509_STORE_CTX_get_current_cert((X509_STORE_CTX *)(ctx))
|
|
||||||
#define pv_X509_STORE_CTX_get1_crls(ctx, nm) \
|
|
||||||
X509_STORE_CTX_get1_crls((X509_STORE_CTX *)(ctx), (X509_NAME *)(nm))
|
|
||||||
#define pv_X509_STORE_set_lookup_crls(st, cb) \
|
|
||||||
X509_STORE_set_lookup_crls(st, (X509_STORE_CTX_lookup_crls_fn)(cb))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* LIBPV_OPENSSL_COMPAT_H */
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* PV/SE header definitions
|
|
||||||
*
|
|
||||||
* Copyright IBM Corp. 2020
|
|
||||||
*
|
|
||||||
* s390-tools is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the MIT license. See LICENSE for details.
|
|
||||||
*/
|
|
||||||
#ifndef LIBPV_SE_HDR_H
|
|
||||||
#define LIBPV_SE_HDR_H
|
|
||||||
|
|
||||||
#include "libpv/common.h"
|
|
||||||
|
|
||||||
#include <openssl/sha.h>
|
|
||||||
|
|
||||||
#include "boot/psw.h"
|
|
||||||
#include "libpv/crypto.h"
|
|
||||||
#include "libpv/macros.h"
|
|
||||||
|
|
||||||
/* Magic number which is used to identify the file containing the PV
|
|
||||||
* header
|
|
||||||
*/
|
|
||||||
#define PV_MAGIC_NUMBER 0x49424d5365634578ULL
|
|
||||||
#define PV_VERSION_1 0x00000100U
|
|
||||||
|
|
||||||
/* Plaintext control flags */
|
|
||||||
/* dumping of the configuration is allowed */
|
|
||||||
#define PV_PCF_ALLOW_DUMPING PV_MSB(34)
|
|
||||||
/* prevent Ultravisor decryption during unpack operation */
|
|
||||||
#define PV_PCF_NO_DECRYPTION PV_MSB(35)
|
|
||||||
/* PCKMO encrypt-DEA/TDEA-key functions allowed */
|
|
||||||
#define PV_PCF_PCKMO_DEA_TDEA PV_MSB(56)
|
|
||||||
/* PCKMO encrypt-AES-key functions allowed */
|
|
||||||
#define PV_PCF_PCKMO_AES PV_MSB(57)
|
|
||||||
/* PCKMO encrypt-ECC-key functions allowed */
|
|
||||||
#define PV_PCF_PCKM_ECC PV_MSB(58)
|
|
||||||
|
|
||||||
/* maxima for the PV version 1 */
|
|
||||||
#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE
|
|
||||||
#define PV_V1_PV_HDR_MIN_SIZE \
|
|
||||||
(sizeof(struct pv_hdr_head) + sizeof(struct pv_hdr_encrypted) + \
|
|
||||||
sizeof(((struct pv_hdr *)0)->tag) + 1 * sizeof(struct pv_hdr_key_slot))
|
|
||||||
#define PV_V1_PV_HDR_MAX_SIZE (2 * PAGE_SIZE)
|
|
||||||
|
|
||||||
#define PV_IMAGE_ENCR_KEY_SIZE 64
|
|
||||||
|
|
||||||
typedef struct pv_hdr_key_slot {
|
|
||||||
uint8_t digest_key[SHA256_DIGEST_LENGTH];
|
|
||||||
uint8_t wrapped_key[32];
|
|
||||||
uint8_t tag[16];
|
|
||||||
} __packed PvHdrKeySlot;
|
|
||||||
|
|
||||||
typedef struct pv_hdr_opt_item {
|
|
||||||
uint32_t otype;
|
|
||||||
uint8_t ibk[32];
|
|
||||||
uint8_t data[];
|
|
||||||
} __packed PvHdrOptItem;
|
|
||||||
|
|
||||||
/* integrity protected data (by GCM tag), but non-encrypted */
|
|
||||||
struct pv_hdr_head {
|
|
||||||
uint64_t magic;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t phs;
|
|
||||||
uint8_t iv[12];
|
|
||||||
uint32_t res1;
|
|
||||||
uint64_t nks;
|
|
||||||
uint64_t sea;
|
|
||||||
uint64_t nep;
|
|
||||||
uint64_t pcf;
|
|
||||||
PvEcdhPubKey cust_pub_key;
|
|
||||||
uint8_t pld[SHA512_DIGEST_LENGTH];
|
|
||||||
uint8_t ald[SHA512_DIGEST_LENGTH];
|
|
||||||
uint8_t tld[SHA512_DIGEST_LENGTH];
|
|
||||||
} __packed;
|
|
||||||
|
|
||||||
/* Must not have any padding */
|
|
||||||
struct pv_hdr_encrypted {
|
|
||||||
uint8_t cust_comm_key[32];
|
|
||||||
uint8_t img_enc_key_1[PV_IMAGE_ENCR_KEY_SIZE / 2];
|
|
||||||
uint8_t img_enc_key_2[PV_IMAGE_ENCR_KEY_SIZE / 2];
|
|
||||||
struct psw_t psw;
|
|
||||||
uint64_t scf;
|
|
||||||
uint32_t noi;
|
|
||||||
uint32_t res2;
|
|
||||||
};
|
|
||||||
G_STATIC_ASSERT(sizeof(struct pv_hdr_encrypted) == 32 + 32 + 32 + sizeof(struct psw_t) + 8 + 4 + 4);
|
|
||||||
|
|
||||||
typedef struct pv_hdr {
|
|
||||||
struct pv_hdr_head head;
|
|
||||||
struct pv_hdr_key_slot *slots;
|
|
||||||
struct pv_hdr_encrypted *encrypted;
|
|
||||||
struct pv_hdr_opt_item **optional_items;
|
|
||||||
uint8_t tag[16];
|
|
||||||
} PvHdr;
|
|
||||||
|
|
||||||
#endif /* LIBPV_SE_HDR_H */
|
|
||||||
@@ -15,8 +15,31 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lib/util_path.h"
|
||||||
|
#include "lib/util_panic.h"
|
||||||
#include "ipl_tools.h"
|
#include "ipl_tools.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look up for the device in /sys/devices/ hierarchy.
|
||||||
|
*
|
||||||
|
* path must be PATH_MAX large and the value will be replaced in place
|
||||||
|
*/
|
||||||
|
static int device_sysfs_path(const char *device, char *path, const size_t path_size)
|
||||||
|
{
|
||||||
|
util_assert(device != NULL, "Internal error: device is NULL");
|
||||||
|
util_assert(path != NULL, "Internal error: path is NULL");
|
||||||
|
util_assert(path_size == PATH_MAX, "Internal error: path_size is '%zu', but must be '%zu'",
|
||||||
|
path_size, PATH_MAX);
|
||||||
|
char *buf = util_path_sysfs("block/%s/device", device);
|
||||||
|
|
||||||
|
if (!realpath(buf, path)) {
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the specified device number is a valid device number
|
* Check if the specified device number is a valid device number
|
||||||
* which can be found in the /sys/bus/ccw/drivers/dasd-eckd/
|
* which can be found in the /sys/bus/ccw/drivers/dasd-eckd/
|
||||||
@@ -42,6 +65,26 @@ int ccw_is_device(const char *busid)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the specified device is a valid virtio subchannel device
|
||||||
|
*/
|
||||||
|
int ccw_is_virtio_device(const char *device)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX] = { '\0' };
|
||||||
|
unsigned virtio = 0;
|
||||||
|
|
||||||
|
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The output has the following format:
|
||||||
|
* /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)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return CCW Bus ID (old sysfs)
|
* Return CCW Bus ID (old sysfs)
|
||||||
*/
|
*/
|
||||||
@@ -77,11 +120,9 @@ out_fclose:
|
|||||||
*/
|
*/
|
||||||
static int ccw_busid_get_sysfs_new(const char *device, char *busid)
|
static int ccw_busid_get_sysfs_new(const char *device, char *busid)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], buf[4096];
|
char path[PATH_MAX] = { '\0' };
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
if (device_sysfs_path(device, path, sizeof(path)) != 0)
|
||||||
snprintf(path, sizeof(path), "/sys/block/%s/device", device);
|
|
||||||
if (realpath(path, buf) == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -89,7 +130,7 @@ static int ccw_busid_get_sysfs_new(const char *device, char *busid)
|
|||||||
* /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(buf, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
|
if (sscanf(path, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -391,7 +391,8 @@ static void dev_from_part_nvme(char *dev_name)
|
|||||||
static int set_reipl_type(const char *dev_name)
|
static int set_reipl_type(const char *dev_name)
|
||||||
{
|
{
|
||||||
if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 ||
|
if (strncmp(dev_name, "dasd", strlen("dasd")) == 0 ||
|
||||||
strncmp(dev_name, "vd", strlen("vd")) == 0)
|
strncmp(dev_name, "vd", strlen("vd")) == 0 ||
|
||||||
|
ccw_is_virtio_device(dev_name) == 0)
|
||||||
l.reipl_type = REIPL_CCW;
|
l.reipl_type = REIPL_CCW;
|
||||||
else if (strncmp(dev_name, "sd", strlen("sd")) == 0)
|
else if (strncmp(dev_name, "sd", strlen("sd")) == 0)
|
||||||
l.reipl_type = REIPL_FCP;
|
l.reipl_type = REIPL_FCP;
|
||||||
@@ -722,14 +723,14 @@ static void check_exists(const char *path, const char *attr)
|
|||||||
|
|
||||||
snprintf(fpath, sizeof(fpath), "/sys/firmware/%s", path);
|
snprintf(fpath, sizeof(fpath), "/sys/firmware/%s", path);
|
||||||
if (access(fpath, F_OK) != 0)
|
if (access(fpath, F_OK) != 0)
|
||||||
ERR_EXIT("System does not allow to set %s", attr);
|
ERR_EXIT("System does not allow one to set %s", attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
const char *attr)
|
const char *attr)
|
||||||
{
|
{
|
||||||
if (write_str_errno(string, file) && exit_on_fail)
|
if (write_str_errno(string, file) && exit_on_fail)
|
||||||
ERR_EXIT("System does not allow to set %s", attr);
|
ERR_EXIT("System does not allow one to set %s", attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ int nvme_is_device(char *fid_str, char *nsid_str);
|
|||||||
* CCW
|
* CCW
|
||||||
*/
|
*/
|
||||||
extern int ccw_is_device(const char *devno);
|
extern int ccw_is_device(const char *devno);
|
||||||
|
extern int ccw_is_virtio_device(const char *device);
|
||||||
extern void ccw_busid_get(const char *device, char *devno);
|
extern void ccw_busid_get(const char *device, char *devno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ RECURSIVE_TARGETS = all-recursive install-recursive clean-recursive \
|
|||||||
|
|
||||||
|
|
||||||
all: all-recursive
|
all: all-recursive
|
||||||
check: check-recursive
|
install: install-recursive
|
||||||
install: all install-recursive
|
|
||||||
clean: clean-recursive
|
clean: clean-recursive
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
prog_name=`basename $0`
|
prog_name=`basename $0`
|
||||||
guest_name=${USER:-`whoami 2>/dev/null`}
|
guest_name=${USER:-`whoami 2>/dev/null`}
|
||||||
terminal=lnxhvc0
|
terminal=lnxhvc0
|
||||||
iucvconn=`which iucvconn 2>/dev/null`
|
iucvconn=`command -v iucvconn 2>/dev/null`
|
||||||
|
|
||||||
__error() {
|
__error() {
|
||||||
printf "$prog_name: $@\n" >&2
|
printf "$prog_name: $@\n" >&2
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user