Compare commits

...

231 Commits

Author SHA1 Message Date
Jörn Siglen
940ce67900 New release s390-tools-2.39.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 10:32:38 +02:00
Peter Oberparleiter
c12faf0128 zdev/dracut: Prevent loading of unused kernel modules
zdev provides dracut logic for configuring devices early during boot via
kernel command line parameters rd.dasd and rd.zfcp. A copy of resulting
configuration directives is made available to the booted Linux using
chzdev's export function.

The use of command line option --all in this export step results in
chzdev loading all kernel modules required by supported types, even if
no device of that type exists on the booted system, or if no zdev kernel
parameter was specified.

Loading unused kernel modules during boot increases memory usage,
prolongs boot time, and expands the kernel's attack surface
unnecessarily.

Fix this by replacing command line option --all with --configured to
instruct chzdev to export only data for devices with a persistent
configuration, while not loading any kernel modules.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Shalini Chellathurai Saroja
a3d50487ed systemd: Suppress cpi service error message on SEL guests
On SEL guests, the default configuration does not permit the
Control-Program Identifiation (CPI) data to be sent by the cpi
service, resulting in a failure message in systemctl/log output
on start of the cpi service.

This is not a failure because it is expected behavior and the
cpi service is a one-shot service whose function is already
performed when the exit code is returned. Prevent the error log
by filtering the associated exit code in systemd.

Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Shalini Chellathurai Saroja
b1d8e40bfe scripts/cpictl: Modify name of the exit code 6
Modify the symbolic name of the exit code 6 to
EXIT_NOTCONFIGURED, which is according to the Linux Standard Base
(LSB) specification.

Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Suggested-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Steffen Eiden
8d3949f77b rust: Cargo.lock Update crate dependencies
cargo update -p openssl -p curl -p usafe-libyaml

By default users of the libs will use the version tagged in the
lockfile. Let make things easier for them and update the lock entries
with versins that have some CVEs fixed.

Note that this does not affect code shipped by distros as they ignore the
lockfile.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
2f49025d49 cpumf/man: Unify parameter case
Normalize parameter casing in man pages to improve consistency.

Reviewed-by:  Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
4c9ceeeb64 cpumf/lshwc: Add command line flag to specify individual counters
Add command-line option --counters "AAA,BBB,...,ZZZ" to specify a
comma-separated list of counter names to display. Counter names must
match exactly, ignoring case. All counters not listed are excluded
from output.

Reviewed-by:  Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
3a0c394fa2 libcpumf: Relocate ctr_in_list() for shared use
Move ctr_in_list() from cpumf/lspai.c to a shared location to enable
reuse in other binaries that require counter list filtering.

Reviewed-by:  Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Richie Buturla
20a4ebd83c zipl/boot: Fix undefined behaviour logic in menu
The code within 'menu_param()' previously assumed that a read from sclp
will never fail.

If 'sclp_param()' fails then 'endptr' is never initialised and
'loadparm' is compared with 'endptr' which is undefined behvaiour.

If a sclp read fails, an undefined 'endptr' is never accessed, and upon
a failed read, will return a new error code 'SCLP_ERROR' instead of
returning 'NUMBER_FOUND' which is incorrect logic wise.

Remove compare conditions and assignments of 0 in 'value', as 'value'
is initialised with 0 ('DEFAULT_MENU_ENTRY') and cannot be non zero,
only in the case where a number is found and we go to boot.

Logic:

Check if we got a number and boot from it.

If 'PRINT_PROMPT', break out to menu print logic.

If an 'SCLP_ERROR' occurs, print an error message and boot the default
since 'value' is initialised with 'DEFAULT_MENU_ENTRY'.

If 'NOTHING_FOUND', check if the menu is disabled. If disabled, go to
default boot. Otherwise break out to print logic.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Richie Buturla <richie@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Richie Buturla
4a9f66fc31 zipl/boot: Change error codes to enums
Change error codes returned from menu_param to enums.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Richie Buturla <richie@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
35d68b2101 dasdinfo: Fix memory leak by freeing readbuf
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
522c67a2c3 dasdinfo: Fix format-overflow warning
Use snprintf() instead of sprintf() to avoid buffer overflow.
Also change the integer type from signed to unsigned.

Error:
	dasdinfo.c: In function 'dinfo_create_devnode':
	dasdinfo.c:297:52: warning: '%04d' directive writing between 4 and 11
	bytes into a region of size 5 [-Wformat-overflow=]
	  297 |                         sprintf(filename, "dasdinfo%04d", retry);
	      |                                                    ^~~~

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
f4ee6c2c8d dasdinfo: Remove unused util_base.h include
The util_base.h header is no longer required in dasdinfo.c and can be
safely removed to reduce unnecessary dependencies.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
377f2a59f5 dasdinfo: Replace hardcoded /sys with util_path_sysfs()
The sysfs path is now constructed dynamically in an allocated buffer to
avoid potential buffer overflows. The default is '/sys', until the
SYSFS_ROOT environment variable is defined.

These modifications significantly improve testability by allowing sysfs
read and write operations to be redirected to an alternative file path,
which enables testing without affecting the active system state.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:57:06 +02:00
Jan Polensky
176f0405b8 .pre-commit-config.yaml: Add check-yaml, check-json and check-toml hooks
These hooks validate syntax of YAML, JSON and TOML files using
pre-commit-hooks.

Link: https://github.com/pre-commit/pre-commit-hooks
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:56:50 +02:00
Jan Polensky
839d34e758 .pre-commit-config.yaml: Bump pre-commit-hooks
Command:

	$ pre-commit autoupdate

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
a68d1e323b libccw/ccw.c: Include strings.h instead of string.h
Including string.h is incorrect as it doesn't provide the required
function prototype for strncasecmp() used in this file. Note that
the missing function prototype doesn't cause a compilation error
at the moment as the declaration is provided indirectly.

Use strings.h to provide the declaration for strncasecmp() directly,
avoiding unnecessary include dependencies and improving clarity.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
549c7ef9e7 zkey/kms.c: Use correct variable in warnx()
The variable filename was freed inside the loop and then incorrectly
used in the subsequent warnx() call. Replacing it with directory
reflects the indented context and avoids use after free.

Fixes: f25aaf32b8 ("zkey: Add support for key management system plugins")
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
103c9444c9 zkey/kms.c: Fix typos
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
fe7bef3f09 cpumf/pai.c: Fix memory use after free
Preventing a race condition by freeing the pmuname variable only after
its last usage.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
8a88ada9c5 dasdinfo/dasdinfo.c: Fix string termination
Use correct buffer and index to terminate string returned by readlink().

Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
538bc7b4e8 dasdinfo/dasdinfo.c: Replace buffer size magic number with anonymous enum
Use a local anonymous enum to define the buffer size constant, replacing
the hardcoded magic number and improving readability.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
b56451e5a4 cpumf/lspai.c: Use util_str_toupper() instead of str2uc()
Replace the custom str2uc() implementation with util_str_toupper() to
reduce code duplication and improve maintainability.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Thomas Richter
63f9a672d0 cpumf/lspai: Add command line flag to specify individual counters
Add command line option --counters XXX,YYY to specify a comma
separated list of counter names to be displayed. The counter names
have to match exactly beside case sensitivity.
All counters not listed in the list specified by the --counters option
are not shown.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Co-developed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Thomas Richter
2c5c5ef4b4 cpumf/lspai: Add command line flags for all cpus
Add a command line flag '-a' to include the counter set values
from each individual CPU. Up to now only the total sum from
all CPUs was printed.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Thomas Richter
5a3ffc2036 cpumf/lspai: Add command line flag for delta values
Add command line flag -d to display the counter value in form of
a delta value. This format shows the increase of that counter value
compared to the previous value.
The first line is the base for the delta calculation and always
shows 'Total'. The remaining lines show 'Delta' in the third
column.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Thomas Richter
e576443859 cpumf/lspai: Add command line flag for short counter names
Add command line flag -s to display the counter name in an
abbreviated form. The abbreviated form is a character for the
PAI counter set followed by a number.
PAI crypto counter set is abbreviated to 'C'.
PAI NNPA counter set is abbreviated to 'N'.
The number refers to the defined counter number ranging from
1 to X.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Thomas Richter
43067df78e cpumf/lspai: Add command line flags for hexadecimal output
Add command line flags -x and -X to print counter values in
hexadecimal format with leading 0x prefix (-X) and without (-x).

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
973059438f cpumf/lspai: Show counter values
Add command line flags -i (read interval) and -l (loops) to
show the counter values for the specified number of iterations.
The CPUs to read the counter values from can be specified
on the command line. If none are specified, all online CPUs
are used.

For example the command '# lspai -l 2 -i 10 -t nnpa'
displays all PAI NNPA counter values two times with 10 second
interval.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Co-developed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
9d3567d9ce libutil/util_libc.c: Move remove_whitespace() to util_str_rm_whitespace()
Relocate remove_whitespace() from zdsfs to libutil/util_str.c, renaming
it to util_str_rm_whitespace() to make the helper available
project-wide.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
7687b0fcda cpumf/lspai: Fix whitespace alignment
Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
6f70f34b79 cpumf/lspai: Rename show_format() -> format_painode()
Renamed the function show_format() to format_painode() to better reflect
its purpose.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:15 +02:00
Jan Polensky
37aed81745 cpumf/lspai: Rename show_painode() -> list_painode()
Renamed the function show_painode() to list_painode() to better reflect
its purpose.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:14 +02:00
Jan Polensky
5aa1824eef libcpumf: Move perf_event_open to reduce code duplication
Relocated the perf_event_open logic into a shared helper to eliminate
redundant implementations across multiple files. Enhances consistency,
reduces maintenance overhead, and lowers structural complexity.

Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:14 +02:00
Jan Polensky
82603e589a libcpumf: Fix typo
Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:14 +02:00
Jan Polensky
3ba897a1be cpumf/lscpumf.c: Fix typos
Acked-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:14 +02:00
Alexander Egorenkov
fa92a7f7c9 README.md: Update dependencies for zipl
Update Dependencies section for zipl with the information of
required tools/packages for stand-alone NVMe and list-directed DASD
dump.

Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Acked-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-10-14 09:39:14 +02:00
Thomas Huth
f569849e57 zipl/boot: Fix EBCDIC code page 500 conversion and decrease size by 200 bytes
The tables ebcdic_037 and ebcdic_500 are currently exactly the same, though
the 500 should differ at 7 entries (see the tables in the Linux kernel or
https://www.ibm.com/docs/en/db2-for-zos/12.0.0?topic=ebcdic-code-point-differences-between-ccsids
for example). Fix it by removing the ebcdic_500 table and by patching
the other table during start() if necessary. That way we can safe also
about 200 bytes in the stage3.bin binary.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/125
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/190
Suggested-by: Euan Bourke <euan@linux.ibm.com>
Tested-by: Euan Bourke <euan@linux.ibm.com>
Reviewed-by: Euan Bourke <euan@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:33 +02:00
Ingo Franzki
458c27a0e1 zkey-ekmfweb: Fix a potential compile error
Fix a potential compile error when symbol
EKMF_SUPPORTS_RSA_PSS_CERTIFICATES is defined. With this symbol support
for RSA-PSS can be enabled for the EKMFWeb plugin. Currently this symbol
is never defined.

Fixes: c570f51f5f ("zkey-ekmfweb: Generate certificate or CSR with identity key")
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:33 +02:00
Ingo Franzki
e4dcf084c5 libekmfweb: Fix generation of certificate or CSR with RSA-PSS instead of RSA
Currently a certificate or certificate signing request generated by the
zkey EKMFWeb library erroneously always uses RSA-PSS as signing algorithm,
although EKMFWeb does not support RSA-PSS certificates in all versions.

This bug was introduced with the rework to use libseckey for secure
key crypto operations.

Fixes: 26c34a49b1 ("libekmfweb: Make use of the new libseckey")
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:33 +02:00
Richie Buturla
bed1bc8676 zipl/boot/stage3.c: Fix [-Wnull-dereference] warning
Fix 'volatile' qualifier warning,
indirection of non-volatile null pointer will be deleted, not trap.

Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Richie Buturla <richie@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:33 +02:00
Richie Buturla
8e315c4401 zipl/src/scan.c: Fix [-Wparentheses] warning
Fix warning of redundant parentheses.

Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Richie Buturla <richie@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
ae8fa4371f pvimg: Update manpage
This update adds documentation for the new CLI option '--image-key',
updates the '--cck' description, and escapes dashes.

Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
29ff9408e0 rust/pvimg: Add support for '--image-key'
Add support for '--image-key'. This new option can be used to select the
components encryption key (e.g. kernel, initrd, and kernel command
line). Previously, this was only available as an experimental
option ('--x-comp-key').

Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
a24be25779 pvimg: Add CLI tests for '--x-comp-key'
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
58337d7f90 rust/pvimg: Refactor keys arguments into own struct
This makes it easier to add new user keys related CLI options.

Acked-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
fcaad5a8e2 pvimg: Improve phrasing of '--cck' option documentation
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Ingo Franzki
4d598ade86 zkey: Add support for generating and importing exportable secure keys
Normally, secure keys generated by zkey are intentionally export
restricted. Export restricted keys can not be wrapped with a key
encrypting key (KEK).

However, keys that are generated inside a Secure Execution for Linux
guest that shall also be used outside of the Secure Execution for Linux
guest can only be transported to outside the Secure Execution for Linux
guest by wrapping them with a KEK and unwrapping them outside of the
Secure Execution for Linux guest. For that such keys must be exportable.

Add an option to generate and import exportable secure keys, which then
can be wrapped, and thus transported to outside of a Secure Execution for
Linux guest.

This applies to keys of type 'CCA-AESCIPHER' and 'EP11-AES'. Keys of type
'CCA-AESDATA' are always exportable, and can not be export restricted.

For keys of type 'EP11-AES' additionally allow to set the
'wrap-with-trusted' attribute. This restricts the key so that it only can
be wrapped with a trusted key encrypting key.

For keys of type 'EP11-AES' to be exportable, the access control point
(ACP) XCP_CPB_ALLOW_COMBINED_EXTRACT must be 'ON' on all APQNs used. This
access control point is only supported on newer EP11 firmware levels. If
the access control point is 'OFF' or not supported by the EP11 firmware,
then the IOCTL to generate the key fails with a generic error
(Input/output error - EIO). The zkey tool prints an appropriate error
message in that case.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Ingo Franzki
b455ee9a31 zkey: Fix typo in error message
Fixes: bb6a47db55 ("Add KMS support for 'zkey generate' command")
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Vineeth Vijayan
82b9328e48 zdev: Fix double device configuration with rd.dasd
While parsing the rd.dasd kernel parameter, the dracut module
currently creates two separate udev rules for a single DASD — one
for ECKD type and one for FBA type. Because the kernel parameter
alone does not provide enough information to reliably determine the
DASD type, this dual configuration can lead to inconsistencies.

Update the logic to determine the DASD type dynamically by parsing
the modalias of available devices. If a device is not present during
boot, both udev rules will be generated.

Also add --no-module-load to the chzdev functions, because during this
time, we do not want chzdev to load the dasd module. The goal here is
to generate the right udev-rules only.

Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Vineeth Vijayan
f45a45c38c zdev: Fix double device configuration on DPM systems
During autoconfig, DPM systems currently configures DASD devices twice:
once for dasd-eckd and once for dasd-fba. Because the firmware
configuration file does not provide the DASD type, this can lead
to inconsistent and redundant configurations.

For example, lszdev may show two devices with the same ID:

    TYPE       ID        ON   PERS  NAMES
    dasd-eckd  0.0.f001  yes  auto  dasda
    dasd-fba   0.0.f001  no   auto

However, only dasd-eckd is actually present on the machine, and
the dasd-fba entry is incorrect.

Modify this configuration logic to determine the DASD type dynamically
by parsing the modalias for each device-ID, and configures only the
correct dasd-type. The resulting lszdev output accurately reflects
the actual DASD devices present.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Vineeth Vijayan
d1bf9e68c6 zdev: Introduce --no-module-load option for chzdev
When called with a device parameter, chzdev tries to load the kernel
module of the corresponding device type. This might not be desired in
certain situations like early initial RAM-disk processing.

To support this use cases, add a new command-line option
--no-module-load to prevent the loading of any kernel module by chzdev.

Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Vineeth Vijayan
0356d78bc2 zdev: Allow dynamic control of module load
module_load_suppress() currently ignores the state parameter. Modify
it to respect the state parameter, so that the module load suppress
can be both enabled or disabled.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
a4f48415a0 zipl/boot: Fix typo found by codespell
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
c9f0e3accf zipl/boot: menu: Reset the buffer before doing a retry
The 'temp_area' buffer was not zeroed out for a retry in case of an
invalid input to select a boot menu entry.

Before:

  zIPL v2.38.0-build-20250822 interactive boot menu

   0. default (1TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...

   1. 1TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
   2. 2TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
   3. 3TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
  Note: VM users please use '#cp vi vmsg <input>'

  Please choose (default will boot in 3 seconds):111
  Error: undefined configuration

  Please choose:1
  Error: undefined configuration

After:

  zIPL v2.38.0-build-20250822 interactive boot menu

   0. default (1TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...

   1. 1TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
   2. 2TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
   3. 3TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
  Note: VM users please use '#cp vi vmsg <input>'

  Please choose (default will boot in 3 seconds):111
  Error: undefined configuration

  Please choose:1
  Booting 1TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...

Acked-by: Eduard Shishkin <edward6@linux.ibm.com>
Acked-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Marc Hartmayer
9dd432ca94 zipl/boot: Remove useless cast
'temp_area' is already a 'char *' no reason to cast it to 'char *'.

Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Eduard Shishkin
179bc57cdf zipl/src: Use a matrix of component ranges instead of an array
Fix a design mistake leading to IPL programs corruption.
Use a matrix of component ranges to locate the added components in the
body of bootmap file instead of an array.
Earlier an array of NR_PROGRAM_COMPONENTS was used, which is incorrect
Now a matrix of (NR_PROGRAM_COMPONENTS X BOOT_MENU_ENTRIES) is used.

Don't duplicate environment block for each menu entry. Instead, reuse
the one that was added when processing the first menu entry.

Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reported-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:32 +02:00
Finn Callies
e1d1c6df9c rust-utils: remove unused renameat2 rust wrapper
Remove the unused rust wrapper function renameat2 which calls renameat2
from linux' libc implementation.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:47:29 +02:00
Finn Callies
e894fb61d8 rust-utils: use exists/rename instead of renameat2
Use exists and rename instead of renameat2 which is only available in the
linux implementation of libc. To enable compilation of pvsecret on macos
the rust wrapper function renameat2 which calls the libc renameat2 function
is replaced with rust native std::fs::exists ad std::fs::rename functions
because macos' implementation of libc does not have the renameat2 function.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:41:00 +02:00
Finn Callies
c3a84109b7 rust-utils: add PartialEq for AtomicFileOperation
Derive PartialEq for the AtomicFileOperation enum to allow comparison with
== operator.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:16 +02:00
Eduard Shishkin
1ca5f63dee zipl/src: Use generic infrastructure when adding environment block
Apply previously introduced generic infrastructure to add an
environment block as a "buffer component".


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:16 +02:00
Eduard Shishkin
60bc1e38d0 zipl/src: Reuse data of buffer components in bootmap
Don't duplicate data of components added via add_component_buffer()
and friends to bootmap file. Instead, reuse data that were previously
added when preparing a program table for the first mirror to create
metadata (block lists, program tables, etc) specific for other mirrors.


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:16 +02:00
Eduard Shishkin
431e4542ca zipl/src: Reuse data of file components in bootmap
If the option '--add-files' is specified, don't duplicate data of
components added via add_component_file() and friends to bootmap
file for each mirror. Instead, reuse the data that were added when
preparing a program table for the first mirror to create metadata
(block lists, program tables, etc) specific for other mirrors.


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:16 +02:00
Eduard Shishkin
731f00202c zipl/src: Enable heterogeneous mirrors support
Drop limitations on identical target parameters of base disks per
logical device;

Fix verbose zipl output to include geometry of each mirror and
component load addresses that would be used when booting from each
mirror.


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:16 +02:00
Eduard Shishkin
2945593991 zipl/src: Support (create/boot-with) different program tables per target
Replace struct install_set with a new type containing multiple
program tables and program components. Refactor the code accordingly.

When retrieving device INFO, for each mirror complete a respective
structure disk_info in the INFO.BASE array.

When building a bootmap, for each mirror create a separate program
table (or a pair of tables in case of DASD - for CCW-TYPE IPL and
for LD-IPL), using respective components in the arrays INFO.BASE and
BIS.MIRRORS

Make data of program components added via get_component_buffer() and
get_component_file() be duplicated per each mirror.

Make boot record on each mirror point out to a respective program
table in the bootmap (when booting from different mirrors, different
program tables in the bootmap are used).

This patch doesn't make functional changes. However, test cases
comparing boot meta-data dumps of different mirrors may fail (since
boot records on different mirrors now refer different copies of boot
data). This will be fixed by the next patches in the series which
allow boot data to be reused.


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Eduard Shishkin
f375327085 zipl/src: Support multiple disk_info structures per logical device
Replace struct disk_info with new 2 types.

Old type:

struct disk_info {
  A; /* logical device info */
  B; /* basedisk info */
};

New types:

struct disk_info {
  B; /* basedisk info */
};

and

struct device_info {
  A; /* logical device info */
  struct disk_info C [MAX_TARGETS]; /* array of base disks */
};

Here A (logical device info) is the following:

dev_t device;     /* logical device for bootmap creation */
char *name;       /* name of logical device as reetrieved from
                     "/proc/partitions" */
char *drv_name;   /* name of the driver managing the logical
                     device  as retrieved from "/proc/devices",
                     or evaluated */
int fs_block_size;

Refactor the code respectively, to use only the first element of
the array C, so that this patch represents an equivalent transform.


Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Peter Oberparleiter
338bea49c2 chpstat: Clarify scope of --scale option
Add a man page note to clarify that BPS value scaling only applies to
human-readable output format.

Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Peter Oberparleiter
d15e36cf24 chpstat: Add options to select IEC units for scaling
Add options to select power-of-two based IEC units such as KiB/s
(1024 B/s) for scaling throughput values in human readable reports.

Option            Scaling factor
================================
--scale ki        1024
--scale mi        1048576
--scale gi        1073741824
--scale auto-iec  IEC units

Reviewed-by: Jimmy Brisson <jbrisson@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Peter Oberparleiter
4b76530788 chpstat: Use SI units for default scaling
chpstat uses power-of-two based IEC units such as KiB/s (1024 B/s) when
scaling throughput values in human readable reports. A user interpreting
these numbers can easily be confused by chpstat's default column header
("B/s") to assume that numbers are scaled using power-of-ten based SI
units such as kB/s (1000 B/s).

In addition, users that have worked with similar z/OS tooling to display
channel path activity are used to SI-based scaling, which increases the
chance of chpstat reports being misinterpreted.

To reduce this confusion, use SI units for throughput scaling:

Option          Old factor      New factor
==========================================
--scale k       1024            1000
--scale m       1048576         1000000
--scale g       1073741824      1000000000
--scale auto    IEC units       SI units

Note that machine-readable format produced via option --format is not
affected by scaling.

Reviewed-by: Jimmy Brison <jbrisson@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Peter Oberparleiter
cb1c002bed chpstat: Ensure consistent table group spacing
In tabular output, chpstat adds an additional space between columns
of different groups (e.g. between READ and WRITE data). Currently this
is done by increasing the column width of the first column in a group.

Depending on the value displayed in this first column of a group, the
spacing may vanish, and under certain circumstances, the precision of
auto-scaled *_PART columns may be higher than the precision of the
related *_TOTAL columns, resulting in a confusing view.

Example:

DPU   READ(B/s)  WRITE(B/s)
 ID  PART TOTAL  PART TOTAL
  6 10.7M 10.7M 10.8M 10.8M
  6  0.00 11.3K  0.00  0.00
   ^^          ^^

Fix this by consistently adding padding between column groups without
increasing the column width of the first column of a group. Also ensure
the same width for *_PART and *_TOTAL columns.

Reviewed-by: Jimmy Brisson <jbrisson@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Eduard Shishkin
d6f7eff5b5 zipl_helper.device-mapper: Fix segmentation fault in an error path
Fix segmentation fault when trying to process not supported dm-targets
Release allocated memory in error paths

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-09-15 11:12:15 +02:00
Peter Oberparleiter
e1692b7079 chpstat: Fix scaling of DPU utilization calculation
chpstat incorrectly reports DPU utilization as fraction instead of
percent. Fix this by scaling utilization values to 100%.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-08-13 13:52:23 +02:00
Mikhail Zaslonko
54b3c9ef24 zipl/ngdump: Bail out if ngdump meta could not be saved
Bail out if the ngdump meta file could not be updated.
Save the boot log also for normal exit.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-08-13 13:52:23 +02:00
Marc Hartmayer
48743aa28b zpwr: Use 'LDLIBS' for specifying the math library
Use 'LDLIBS' to specify the libraries that the tool is linked against.
If it is specified as a dependency, the build system may attempt to
build it and fail.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-08-13 13:52:23 +02:00
Mete Durlu
7ce988ac59 zconf/chccwdev: Fix example descriptions
Match "chccwdev --online" example's description with its function
and improve "--safeoffline" example's wording.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-08-13 13:52:23 +02:00
Marc Hartmayer
f4fec5f120 rust/pvimg/boot: Use 'PVIMG_PKGDATADIR'
Use 'PVIMG_PKGDATADIR' as it is used by the 'pvimg_pkg_data' macro rule.
The problem only shows up if someone changes 'PVIMG_PKGDATADIR' to
something different than the default.

Fixes: f4cf4ae6eb ("rust: Add a new tool called 'pvimg'")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Steffen Eiden
2739b8a488 pv/examples: Add example for calculating host-key hashes
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Shalini Chellathurai Saroja
ce9c518b97 cpi: Disable CPI for SEL guests by default
The cpictl utility sends control-program identification data
from protected virtualization guests to hosts by default.
This behaviour leaks the below potentially sensitive
information to untrusted hosts.
- system_type
- system_level
- sysplex_name
- system_name

To prevent this behaviour, enhance the cpictl utility to stop
setting CPI information on protected virtualization guests by
default. If the user chooses to set the CPI information, it
could be set by one of the below options
- use the command line option --permit-cpi
- set the environment variable CPI_PERMIT_ON_PVGUEST to 1 to
control the CPI service behaviour during boot

Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Jörn Siglen
bd2a2cc6a1 dbginfo.sh: Enhance logging on timeout triggered
Rework command type selection and timeout trigger.
Add log entry when the timeout stopps a command or a non "zero" rc happens.

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Reviewed-by: Michael Storzer <MSTORZER@de.ibm.com>
Signed-off-by: Jörn Siglen <SIGLEN@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Mikhail Zaslonko
6547d1ae4c zdump/ngdump: Add error messages and debug trace logs
Add debug trace logs for ngdump_read_meta_from_device().

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Jörn Siglen
650265e296 AUTHORS.md: Remove duplication
Same name written in two versions

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-29 18:23:49 +02:00
Jan Höppner
b122acb422 iucvterm: Install symlink for lsiucvallow.8 man page
lsiucvallow is just a symlink to chiucvallow for 'chiucvallow --list'.
Only a man page for chiucvallow is provided though. A corresponding man
page for lsiucvallow could be expected by the user. Certain linter such
as linitan warn about the missing man page, too.

Install lsiucvallow.8 as a symlink to chiucvallow.8 to make the
documentation of these tools more accessible.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-09 16:59:09 +02:00
Dan Horák
9710f29770 man: Use CR for constant width font
With version 1.23 groff/troff disabled the non-portable font CW and
started to complain about a missing CW font when previewing some of the
man pages, with messages like

$ man --warnings cpumf/man/pai.8 > /dev/null
troff:<standard input>:244: warning: cannot select font 'CW'

Use CR to replace CW.

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/187
[hoeppner@linux.ibm.com: Adapt commit message]
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-08 10:23:08 +02:00
Nikita Dubrovskii
ed01bac8e2 zipl/src: Fix typos
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/186
Signed-off-by: Nikita Dubrovskii <nikita@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-08 10:23:08 +02:00
Nikita Dubrovskii
66d3aa849a zipl/src: remove global sync() call on exit
Remove the final sync(2), as zipl(8) already uses fsync(2), syncfs(2)
and ioctl(BLKFLSBUF) to flush all performed modifications.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/186
Signed-off-by: Nikita Dubrovskii <nikita@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-08 10:23:08 +02:00
Eduard Shishkin
95e4b3413a zipl/src: Prepare for global sync(2) removal
zipl tool calls sync(2) before exit, which may hang on attempts to
flush not relevant problematic mounts (e.g. nfs) [1].

Complete any modification performed by zipl(8) tool with calling
fsync(2), or syncfs(2). This allows to get rid of the mentioned
sync(2) call.

[1] https://github.com/openshift/os/issues/1720
Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/186
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-07-08 10:23:08 +02:00
Steffen Eiden
06e0d569f1 Prepare for next release
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-25 11:43:27 +02:00
Joern Siglen
660bab6e68 New release s390-tools-2.38.0
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-25 11:43:15 +02:00
Steffen Eiden
3dd91bb84e rust: Update rust crates version to 0.12.0
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-25 10:39:22 +02:00
Steffen Eiden
8fadcd9fe5 pvsecret: Fix some edge cases for plaintext keys
Fix two edge cases for generating and interpreting plaintext secrets:
1. The maximum payload size was two bytes to long. The space for the
   length header was forgotten to take into account.
2. One of the checks for if the plaintext secret has a size was too
   strict.

Fixes: fd024387d7 ("rust/pv: Retrievable secrets support")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Shalini Chellathurai Saroja
e8237e6ae0 cpictl: provide error for invalid options
cpictl tool supports options which start with - or -- alone. Getopt
command verifies options which start with - or -- alone. When an
option that does not start with - or -- is provided, the tool commits
the changes and does not report error as shown below.

$ ./cpictl abc
Inside cpi_commit function

Report error and do not commit for invalid options.

Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Jan Polensky
c746c5c267 cpumf/man/lshwc.8: Fix typo in example description
Corrected a grammatical error for proper subject-verb agreement.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Jan Polensky
b69b750ef5 cpumf/lshwc: Add support for structured output formats
Introduce a new command-line option --format FORMAT to control the output
format of lshwc. Supported formats include CSV, JSON, JSON-SEQ, and key-value
PAIRS. The output is now generated using the shared util_fmt infrastructure,
enabling consistent and machine-readable output.

This change also includes:
- Label generation for counters
- Integration of util_fmt for structured formatting
- Updated man page with documentation for the new option
- Updated man page with JSON output structure documentation
- Add option (-q) to force quoting all elements.

Reference: https://www.ietf.org/rfc/rfc4180.txt

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Thomas Richter
120ad30f1e cpumf/lscpumf: Add support for IBM z17 counter sets
Add support for IBM z17 machine types 9175 and 9176 CPU Measurement
facility basic, problem, crypto and extended counter sets.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Steffen Eiden
bfc9854eb5 check_hostkeydoc: Move check_hostkeydoc to scripts & deprecation warning
Move the check_hostkeydoc script to scripts. This eliminates the last file
in the genprotimg directory. Additionally, add a deprecation warning to
that script. Every pv tool can verify the chain itself using the pv
library.

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Steffen Eiden
619c466275 check_hostkeydoc: Fix indentation
Replace spaces with tabs using `unexpand check_hostkeydoc`.

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Marc Hartmayer
017377c093 check_hostkeydoc: Add workaround for old OpenSSL versions
Add a workaround for OpenSSL version that do not include the upstream
fix [1]. The missing fix results in an OpenSSL error when it tries to
download the CRL provided by DigiCert. The workaround is to identify
this situation and then fallback to download the CRL using 'curl'
instead.

[1] cdbe47bf3c

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Jan Polensky
7e38c7106b libutil: Avoid quoting CSV header cells unless FMT_QUOTEALL is set
This patch modifies the default behavior of CSV header generation:
header cells are no longer enclosed in double quotes unless the
FMT_QUOTEALL flag is explicitly set. According to RFC 4180, quoting is
only required when a cell contains control characters, commas, or double
quotes.

The goal of this change is to produce cleaner and more readable CSV
output by default, and to avoid unnecessary quoting in header rows. It
also simplifies algorithms that rely on FMT_UTIL and improves
compatibility with downstream tools expecting unquoted headers.

Tools that expect unquoted headers include:
 * SQL tools: Headers optional, usually unquoted
 * R (read.csv): Uses header=TRUE, no quotes needed
 * Pandas: Assumes headers, quoting not required
 * Excel: Detects headers; quotes only for special chars

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Mete Durlu
8dc06d14d7 udev: Introduce a rule to set newly hotplugged CPUs online
On s390 architecture a newly hotplugged CPU, should only stay offline if
it is on deconfigured state, otherwise it should automatically become
online. Introduce a new udev rule to enforce this behavior. This rule
should always be installed.

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Jörn Siglen
f07504d92e dbginfo.sh: Add Ubuntu snap tool
Adding snap as the new Ubuntu software repository tool.

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jörn Siglen <SIGLEN@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2025-06-24 15:07:48 +02:00
Peter Oberparleiter
02554fa6d8 chpstat: Add missing CMG 5 data fields
DPU-related data fields dpu_num_cores, dpu_channel_exec_time_cpc, and
dpu_exec_time_cpc are missing from machine-readable output for CMG 5
channel-paths.

Fix this by adding them to the corresponding output routines.

Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 13:00:55 +02:00
Peter Oberparleiter
3eb09e8842 chpstat: Fix DPU utilization calculation
chpstat reports incorrect DPU utilization values for CMG 4 and 5
channel-paths. Calculated values are too high due to counters being
interpreted as units of seconds while they are reported in units of
timer ticks. Also, a zero partition channel-path utilization value
(DPU PART) is incorrectly displayed as unavailable (-).

Fix this by using the correct timer unit in DPU utilization
calculations and making sure that zero DPU PART values are reported
correctly.

Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 13:00:55 +02:00
Steffen Eiden
3eb9711021 pvsecret: Fix man entry for aes-xts keys
Fixes: a8a3e7d49c ("rust/pvsecret: Update manuals and README")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 13:00:55 +02:00
Peter Jin
2349236bb4 zdev: Add support for virtio devices
Add support for managing virtual I/O ccw (virtio-ccw) devices in
lszdev/chzdev.

New zdev device type virtio. Each virtio device type (blk, net,
gpu, vsock, etc.) is represented by a unique subtype of the virtio
base type.

If the virtio device type is recognized, then it will show up as
virtio-blk or virtio-net, or whatever the virtio device type is.
Otherwise, it will just show up as virtio-ccw.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/29
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Peter Jin <pjin@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 13:00:55 +02:00
Gautam Gala
2d86117167 rust/pvimg: SE header tampering tool for use with tests
Adding a new tool (tamper_pvimg) for helping to test if the expected
RC and RRC values are received for several different reasons when
DIAG 308 subcode does not complete successfully. The reasons can include
issues related to host key hash, SE header, ALD/PDL/TLD mistmatch, etc.

This tool can read the SE image and manipulate one of the SE header
fields so that the SE image will fail to enter secure mode during the
stage3a booting process. The stage3a bootloader should receive UVC
command code id, RC and RRC values corresponding to the SE header
field that was manipulated. These values will be checked for
consistency in the tests for correctness of DIAG 308 subcode 10 RCs
and RRCs.

[hoeppner@linux.ibm.com: shortened commit subject]
Signed-off-by: Gautam Gala <ggala@linux.ibm.com>
Signed-off-by: Steffen Eiden <sediden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:58:03 +02:00
Gautam Gala
a0265d1069 rust/pvimg: Convert variables to public for use with SE header tampering tool
Converting several variables to public and exporting some structures
for use in SE header tampering tool.

Signed-off-by: Gautam Gala <ggala@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:38:45 +02:00
Gautam Gala
084792bdc6 pvimg/boot: Print error messages from stage3a bootloader
When DIAG 308 subcode 10 is specified, and the configuration fails to enter
the secure mode, then the stage3a bootloader reads the DIAG response code,
UV RC, RRC and command id from bit positions 48-63, 32-47, 16-31, and
0-15 of the general register R1 + 1.

The bootloader now prints the error codes to help pinpoint the error cause.
For some cases that are reported to occur often the bootloader also prints
the cause when possible or prints hints to help understand the cause.

QEMU patch "DIAG 308: extend subcode 10 to return UVC cmd id, RC and RRC
values upon failure to enter secure mode" (commit-id: )
is needed with this patch.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Gautam Gala <ggala@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:38:45 +02:00
Ingo Franzki
5ece6a3373 etc/modules-load.d/s390-pkey.conf: Add pkey sub-modules and paes_s390
Ensure that the pkey sub-modules are also loaded, as well as the paes
cipher.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:38:45 +02:00
Ingo Franzki
14c977768e zkey/dracut: Add a dracut config file for zkey
Provide a dracut config file that ensures that the required drivers and
executables, as well as the zkey repository is included into the initramfs.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:38:45 +02:00
Ingo Franzki
5bedcff65c zkey/initramfs: Update initramfs hook to correct drivers and include zkey plugins
The zkey tool might be configured to use plugins. Include the plugins also
into the initramfs, otherwise zkey might not be usable at early boot time,
when it is configure to use a plugin.

Update the list of driver to include, pkey_sysfs does not exist, its built
into the pkey base driver.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-06-11 12:38:45 +02:00
Jörn Siglen
479820528c dbginfo.sh: Reworking the container section
Adding podman commands to dbginfo.sh, which is a successor for docker.
We reduce standard details for docker (it can be collected on demand).
Inlcuding /etc/containers for registry and container engine configuration.

Suggested-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Jörn Siglen <SIGLEN@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Ingo Franzki
486882a4df libkmipclient: Fix findings from static code checker
The Coverity static code checker found a few bugs in the libkmipclient
code, fix those.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Marc Hartmayer
ce997c6d01 rust/Makefile: Create a symbolic link to the manpage 'pvimg-create' for genprotimg
Create a symbolic link to the 'pvimg-create' manpage of for 'genprotimg'
during the manpage installation. This helps the users to migrate to
'pvimg create'.

Suggested-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Marc Hartmayer
b9d1c86613 CHANGELOG.md: Describe the 'genprotimg' changes in v2.36.0
This helps the users and distro-partners to understand what has changed.

Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Marc Hartmayer
f9337f0576 genprotimg: manpage: Describe the 'genprotimg' changes in v2.36.0
Describe the breaking changes to genprotimg in the notes section. This
helps the users to adapt to the new behavior.

Fixes: f4cf4ae6eb (rust: Add a new tool called 'pvimg')
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Thomas Richter
a06302e7f0 cpumf/lspai: Add output format option
Add formatted output triggered with command line option --format XXX.
Sort included header files.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Maria Eisenhaendler <maria1@de.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Jan Höppner
7bc0fb809d zpcictl: Fix command line parsing for invalid options
Currently zpcictl silently accepts incorrect command line options while
it should be displaying an error message for invalid ones. There is a
check for the case when no arguments are supplied, but invalid arguments
or only specifying a device without an action does not display an error
nor give a failure exit code.

Fix this by changing parse_cmdline() to return a boolean indicating if
any arguments were supplied while exiting with an error and message when
invalid options are detected.

Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:31 +02:00
Thomas Richter
bc511f84fe cpumf/lshwc: Update man page for lshwc command line option time
Improve man page entry for lshwc command line option -t and --time.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Maria Eisenhaendler <maria1@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:30 +02:00
Ingo Franzki
3a3cea0061 zkey: Fix EP11 secure key reencipher function
Re-enciphering an EP11 secure key may fail with an error message like:
  "zkey-cryptsetup: Failed to re-encipher the secure volume key for device
  '<device>'"
or
  "zkey: Failed to re-encipher '<key>' from CURRENT to NEW master key"
or similar.

The verbose messages show the following debug message:
  "Command XCP_ADM_REENCRYPT failed. rc = 0x20"

This is due to uninitialized variables, which might cause the EP11 admin
request to contain garbage data, causing it to fail with CKR_DATA_INVALID
(0x20).

Fixes: 0be7efc956 ("zkey: Add support for re-enciphering EP11 secure keys")
Fixes: 4e2ebe0370 ("libseckey: Fix re-enciphering of EP11 secure key")
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Joerg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:18 +02:00
Marc Hartmayer
616d2f52f9 rust/Makefile: Install Bash and Zsh completions by default
The Bash and Zsh completion files are useful, therefore install them by
default.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-21 15:50:18 +02:00
Peter Oberparleiter
6dd671f24e zdev: Make initramfs root configuration more robust
zdev's initramfs hook does not add directives for enabling the root
device to the initrd if the root device is only configured in the
active configuration. As a result, a reboot using the new initrd fails
because the root device cannot be found.

This situation can occur for example when the zdev initramfs hook is
called from within an installer, where devices are only enabled in the
active configuration.

Address this situation by considering both the active and persistent
configuration of the root device during initramfs configuration. In case
the device is configured in both configurations, the persistent
configuration takes precedence.

Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-06 13:40:36 +02:00
Jakob Naucke
443652dcd2 rust/pv*: Add support for CCK update
The ultravisor supports a new secret type in `add-secret` to update
the customer communication key (CCK). Support this new secret
type (0x16).

[seiden@linux.ibm.com: Constify CCK Header struct usage]
Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Jakob Naucke
b11bb64732 rust/pvimg: Add secret flag to allow CCK update
The CCK will be able to be updated by an ultravisor call. For security
reasons, this feature must be enabled at Secure Execution header
creation time.

Because this makes it possible to dump without having set a CCK
earlier, the requirement to specify a CCK when creating an image with
guest dump support is extended to also allow for CCK update instead.

Change a CLI test for this that was a duplicate anyway.

[seiden@linux.ibm.com: Allow --cck & --enable-cck-update simultaneously]
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Steffen Eiden
2cd7c7a875 pv: Refactor Null secret
With the recent upgrade to zerocopy 0.8 it is now possible to create
those structs at compile time. This removes the use of a magic array
constant.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Steffen Eiden
8929d21948 rust: Upgrade zerocopy dependency to 0.8.X
This enables some const constructors, Dataful Enums,
Dynamically Sized Types and much more.

v0.8 introduces breaking changes including, but not limited to:
  - Rename AsBytes to IntoBytes
  - Fine-grain (derive) Traits that need to be implemented on top.
  - Rename FromZeroes to FromZeros
for which this patch takes care of as well.

Also a direct FromZeros derive is no longer necessary. As it is touched
anyways, remove it where appropriate.

See: https://github.com/google/zerocopy/discussions/1680

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Steffen Eiden
f7bba3a687 pvsecret: Deny adding secrets with preexisting IDs
Denies the addition of secrets with an ID that is already stored in the
secret store. This can be overruled by using the force option.

This is considered a breaking change as adding duplicated IDs was
possible without the '--force' option before.

Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Tested-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Mikhail Zaslonko
5d2c93bc7a zdump/dfi: Get online cpu count based on lowcore_ptr array
In case of missing dfi_cpu_info in the dump, obtain the number of online
cpus of the dumped system based on the number of present entries in the
lowcore_ptr array (if vmcoreinfo is available).

Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Mikhail Zaslonko
f1055a62e3 zdump: Remove unused structures and prototypes from dfi.h
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Eduard Shishkin
4c4ab4fd70 zipl_helper.device-mapper: Support mirrors over NVMe devices
\# lsblk
...
nvme0n1     259:0    0   7.3T  0 disk
\_nvme0n1p1 259:4    0     2G  0 part
  \_md0       9:0    0     2G  0 raid1 /mnt
nvme1n1     259:2    0 931.5G  0 disk
\_nvme1n1p1 259:1    0     2G  0 part
  \_md0       9:0    0     2G  0 raid1 /mnt

\# ./zipl_helper.md 9:0

Expected results:

targetbase=259:0
targettype=SCSI
targetblocksize=512
targetoffset=8192
targetbase=259:2
targettype=SCSI
targetblocksize=512
targetoffset=8192

Actual results:

targetbase=259:0
targettype=SCSI
targetblocksize=512
targetoffset=8192
targetbase=259:0   <--- Incorrect!
targettype=SCSI
targetblocksize=512
targetoffset=8192

Make zipl helpers be aware of NVMe devices;
Fix the procedure of partition resolution by including the NVMe case.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:37 +02:00
Eduard Shishkin
34a5e47508 zipl_helper.device-mapper: Fix imprecise is_device_mapper() predicate
Fix is_device_mapper() predicate to not base on checking a hardcoded
major number (253), which not always correct, since on some systems
dm-devices have different majors".

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:20:35 +02:00
Steffen Eiden
6d7cdb9e10 pvsecret: Improve documentation for duplicated secret IDs
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Tested-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Steffen Eiden
1fefdecbe7 pvsecret: Support retrieving a secret by index
Allow users to retrieve a secret by its index. This allows users to
extract a specific secret in case of multiple ids.

Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Tested-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Steffen Eiden
e62cdf9a6e pvsecret: Warn during retrieve if a secret-id is stored multiple times
Warn a user that there are multiple secrets in the secret store with the
same secret id, but retrieve one of them anyways.

This helps users to notice issues before they happen, as retrieve may
not retrieve the expected secret due to duplicated IDs.

Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Tested-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Steffen Eiden
fa00d1eac1 pvsecret: Warn during add if a secret-id is already in the store
Warn a user that the secret-id to be added is already in the secret
store, but add it anyways.

This helps users to notice issues before they happen, as retrieve may
not retrieve the expected secret due to duplicated IDs.

Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Tested-by: Finn Callies <fcallies@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Jan Höppner
0eac97542d libutil/util_file: Handle over-read in util_file_read_fd()
In certain situations util_file_read_fd_buf() might return a larger
buffer than printable characters were read (e.g. a file was padded with
zeros). This can lead to util_file_read_fd() returning NULL with a freed
buffer even though a certain amount of printable characters were read.

This behaviour causes a regression introduced with commit 9efd1df31d
("ipl_tools: Refactor read helper using util_file_read_text_file()") in
ipl_tools were the scp_data sysfs attribute is padded with 0 to fit an 8
byte alignment required by the architecture.

Fix this by comparing the size read with the actual string length and
use the smaller value for further processing.

Fixes: 9efd1df31d ("ipl_tools: Refactor read helper using util_file_read_text_file()")
Tested-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Thomas Richter
b3db52fd16 libutil: Add machine type definition for machines 9175 and 9176
Add machine type definition for machines 9175 and 9176.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Steffen Eiden
a9eb80b1a2 pvattest: Fix successful 'check' evaluation
Invert the polarization of the successful state. The checks are
considered to be successful if there are no issues. Therefore, test for
an empty issue list and not for a non-empty.

Fixes: 697dcc0f6b ("rust/pvattest: Add check command")
Reported-by: Reinhard Buendgen <buendgen@de.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-05-05 17:15:01 +02:00
Marc Hartmayer
e93668ae5b rust/Makefile: Fix file permissions for shell completion files
While at it, preserve the timestamps as well because it's recommended.

See https://docs.fedoraproject.org/en-US/packaging-guidelines/ShellCompletions/.

Fixes: b3055154db ("rust/Makefile: Add 'install-(bash|zsh)-completion' targets")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:36:56 +02:00
Eduard Shishkin
c68c3cb8b2 ipl_tools/chreipl: Use S390TOOLS_LIBDIR variable
Use S390TOOLS_LIBDIR environment variable to locate the helper
script.

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:36:50 +02:00
Eduard Shishkin
f63c548c2a ipl_tools/chreipl: Support md partitions
Fix the helper name construction procedure to support also the case
when the node is over a regular md-partition:

\# lsblk
dasda                             94:0    0 20.6G  0 disk
`-dasda1                          94:1    0 20.6G  0 part
  `-md0                            9:0    0 20.6G  0 raid1
    |-md0p1                      259:0    0    1M  0 md    /mnt
    `-md0p2                      259:1    0 20.6G  0 md
dasdb                             94:4    0 20.6G  0 disk
`-dasdb1                          94:5    0 20.6G  0 part
  `-md0                            9:0    0 20.6G  0 raid1
    |-md0p1                      259:0    0    1M  0 md    /mnt
    `-md0p2                      259:1    0 20.6G  0 md

\# chreipl /mnt

Actual result:

chreipl: Unsupported device node "/mnt" specified

Expected result:

Re-IPL type: ccw
Device:      0.0.6569
Loadparm:    ""
Bootparms:   ""
clear:       0

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:36:40 +02:00
Eduard Shishkin
1ab2fbb482 zipl_helper.device-mapper: Support dm- over md-devices
Add support for complex dm- over md-devices.
It includes an important particular use case in distro installation
process, when a linear dm-target is built on the top of software
RAID1:

dasda                      94:0    0  20.6G  0 disk
\_dasda1                   94:1    0    20G  0 part
  \_md127                   9:127  0    20G  0 raid1
    \_rhel_a46lp05-root00 253:5    0    20G  0 lvm   /
dasdb                      94:4    0  20.6G  0 disk
\_dasdb1                   94:5    0    20G  0 part
  \_md127                   9:127  0    20G  0 raid1
    \_rhel_a46lp05-root00 253:5    0    20G  0 lvm   /

\ # zipl_helper.device-mapper /

Expected result:

targetbase=94:0
targettype=CDL
targetgeometry=30051,15,12
targetblocksize=4096
targetoffset=4632
targetbase=94:4
targettype=CDL
targetgeometry=30051,15,12
targetblocksize=4096
targetoffset=4632

Actual result (incorrect):

targetbase=9:127
targettype=SCSI
targetblocksize=4096
targetoffset=256

Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:35:52 +02:00
Thomas Richter
fed79474e4 cpumf: Convert S390_CPUMF_XXX to util_path_sysfs()
Use util_path_sysfs() to form a fully qualified sysfs file name
for files S390_CPUMF_CF, S390_CPUMF_CFDIAG, S390_CPUMF_SF,
S390_SYSFS_PAI_CRYPTO and S390_SYSFS_PAI_EXT.
No functional change.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:45 +02:00
Thomas Richter
8c1ffd8989 cpumf: Convert S390_CPUMSF_BUFFERSZ to util_path_sysfs()
Use util_path_sysfs() to form a fully qualified sysfs file name
for file S390_CPUMSF_BUFFERSZ.
No functional change.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:45 +02:00
Ingo Franzki
33fc534a81 zkey: Adjust CCA host library version detection for newer CCA versions
Newer CCA versions might report the version string with CSUACFV or CSUACFQ
with keyword STATCCA using a different indicator character after the
version information. Ignore the indication character and the remaining
data entirely. Only the version information as such is of interest.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:45 +02:00
Thomas Richter
7e832ead9e libcpumf: Convert S390_CPUS_ONLINE to util_path_sysfs()
Use util_path_sysfs() to form a fully qualified sysfs file name
for file S390_CPUS_ONLINE.
No functional change.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:44 +02:00
Thomas Richter
7f0f765bb4 libcpumf: Remove define S390_CPUS_POSSIBLE
This define S390_CPUS_POSSIBLE is not referenced anymore.
Remove it.
No functional change.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:44 +02:00
Jan Polensky
69c7f45bb7 ipl_tools/cmd_lsreipl.c: Refactor to reduce code duplication
Eliminated redundant code to improve clarity and maintainability.
Replaced with existing utility functions from the library.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:44 +02:00
Jan Polensky
d843e08828 ipl_tools/ipl_tools.h: Remove redundant extern for functions
Function declarations in header files are implicitly extern, making
the explicit  use of extern unnecessary. Removing it simplifies the
code without changing semantics and behavior.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-16 12:12:44 +02:00
Joern Siglen
055c455571 dbginfo.sh: Update for network commands
New Distros are replacing iptables by nftables.
Collecting data of optical interfaces.

Suggested-by: Hendrik Brueckner<brueckner@linux.ibm.com>
Suggested-by: Niklas Schnelle <schnelle@linux.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Reviewed-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:19 +02:00
Jakob Naucke
ba387af804 rust/pvimg: Macroize flag parsing
Macroize flag parsing to save some repetition and lines.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jakob Naucke
8b9960abe9 rust/pvimg: Fix spelling of Enforcement
Fix spelling of CckExtensionSecretEnforcement and adhere to Rust
capitalisation conventions.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jakob Naucke
efdadfcdb9 rust/pv*: Unit test flag parsing
Add a unit test for flag parsing.

In order to ease this test, add derive Eq to ControlFlags and
Msb0Flags64. For the same test, add derive Default to
CreateBootImageArgs and the structs used in it. The latter can be
limited to only derive when testing to avoid confusion with any
user-level default.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jakob Naucke
ec10654c35 rust/pvimg: Make PCKMO plaintext control flags a constant
The PCKMO plaintext control flags are used in several places as is
and are also to be used in an upcoming unit test. Make them a constant.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jakob Naucke
76bddf9715 rust/pvapconfig: Add --unbind option
When the --unbind option is enabled, run with an empty config instead,
effectively unbinding all APQNs.

Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
b4cc30ac10 cpumf/lshwc: Add command line flag for run time
Add a command line flag to specify run time of lshwc command in
terms of days, hours, minutes and seconds. The command line flag
is named -t and has a number as argument followed by one of the
letters 's' for seconds (default), 'm' for minutes, 'h' for hours
and 'd' for days. Default is seconds when no trailing letter is
detected.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mikhail Zaslonko
9f9dddddd4 zdump: Drop build_arch for s390 DASD dumps
The build_arch field in s390 DASD dump header has originally been used to
indicate whether the dump tool has been built on s390 or s390x system.
Since no other architectures but s390x are supported for Linux on z, do
not process build_arch attribute. Bail out if any build architecture other
than ARCH_64 has been detected in s390_ext or s390mv_ext DASD dump header.
Remove build architecture line from 'zgetdump -i' output:
  Build arch.........: s390x (64 bit)
The man file for zgetdump is updated accordingly.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mikhail Zaslonko
f821a3c174 zdump: Drop support of 32-bit dump architecture
- Initialize dump and dump-tool architecture to DFI_ARCH_64 at the start
  of dfi_init() and dt_init() respectively.
- Bail out if any dump architecture other than ARCH_64 has been detected
  in s390_ext or s390mv_ext DASD dump header.
- Remove redundant dfi_arch_set() and dt_arch_set() functions.
- Get rid of l.arch local variables in dfi* and dt* source files and
  drop dfi_arch() function.
- Drop the usage of DFI_ARCH_32 and compeletely remove DFI_ARCH_UNKNOWN.
- Drop special register and lowcore processing functions used
  for DFI_ARCH_32.
- Drop df_s390_from_dfi_arch() and df_s390_to_dfi_arch() funcitons.
- Update the man file for zgetdump.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mikhail Zaslonko
ee4cb78dc2 zdump: Drop non-extended multi-volume DASD dump support
Since DASD standalone dumper does not support non-extended s390
multi-volume dumps for years, drop zgetdump support of non-extended s390_mv
DASD dumps and dump-tools:
- Merge dfi_s390mv_ext and dt_s390mv_ext with related dfi_s390mv and
  dt_s390mv counterparts.
- Update DFI and DT vectors of supported dump formats and dump-tools
  removing dfi_s390mv and dt_s390mv entries and keeping dt_s390mv_ext and
  dfi_s390mv_ext ones for s390_mv extended dump and dump-tool accordingly.
- Remove dfi_s390mv.c and dt_s390mv.c sources and update the Makefile.
- Make dfi_s390mv_ext_init() and dfi_s390mv_info() static.
- Remove magic number relevant to non-extended s390_mv DASD dumper.
- Completely drop DASD dumper version 5 case in df_s390_dumper_read().

Note: Since non-extended s390 multi-volume dumps can reside on DASD
partitions only and cannot be produced via DFO interface, we can drop this
dump format entirely.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mikhail Zaslonko
6f82c5792a zdump: Drop support of non-extended single volume DASD dumpers
Since DASD standalone dumper does not support non-extended s390 dump
format for years, drop zgetdump support of non-extended s390 single volume
DASD dump-tool:
- Merge dt_390sv_ext.c and dt_s390sv.c counterparts.
- Update DT vector of supported dump tools removing dt_s390sv entry and
  keeping dt_s390sv_ext entry for s390 single volume extended dump tool.
- Remove dt_s390sv.c source and update the Makefile accordingly.
- Remove magic constants relevant to non-extended s390 single volume DASD
  dumper.
- Drop s390 single volume DASD dumper version 5 in df_s390_dumper_read().

Note: We still need support of non-extended s390 dump format since such
output dump files can be produced by 'zgetdump -f s390' via dfo_s390. Thus,
both dfi_s390 and dfi_s390_ext DFI vector entries remain in order to
process s390 dumps files as well as s390_ext dumps on the DASD partition.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mikhail Zaslonko
2c5d4073a7 zdump: Drop support of obsolete dumps and dumpers
Drop support of obsolete dump and dump-tool versions (single-volume DASD,
FBA and Tape) in order to simplify zgetdump logic:
- CCW dumpers written in assembler instructions as well as stage2 dumpers
  of size less than 0x3000 (STAGE2_DUMPER_SIZE_V1 or STAGE2_DUMPER_SIZE_V2)
  haven't been used for years. Remove its traces completely as a cleanup.
  Keep the last version (version 5) of non-extended DASD dumper as well as
  newer extended DASD dumpers.
- Rename STAGE2_DUMPER_SIZE_V3 and STAGE2_DUMPER_SIZE_ZLIB constants.
- Drop support of non-extended s390 dumps of version < 5. Dump files
  of s390 format version 5 can be still produced by zgetdump (dfo_s390).
- Drop excessive dump version checking in df_s390_cpu_info_add() and
  df_s390_hdr_add() considering that obsolete s390 dumps of version lower
  than 5 no longer supported.
- Use cpu_cnt field in s390 dump header instead of the s390 dump version to
  indicate no cpu info available (DFI_CPU_CONTENT_NONE) for dfo_s390.
- Make df_s390_dumper_read() return error code upon unknown dumper
  version/magic detection.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jan Polensky
9efd1df31d ipl_tools: Refactor read helper using util_file_read_text_file()
Replace read_str() helper in ipl_tools/system.c with
util_file_read_text_file() to enhance maintainability and reduce
code duplication.

Additionally, allocate the buffer dynamically instead of using
fixed-size buffer to prevent potential overflows and data loss.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jan Polensky
6f53d7d3cd ipl_tools: Remove unused header
Optimize dependency management by reducing header inclusions. This
reduces hidden dependencies, improves modularity, and enhances
compilation performance.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jan Polensky
92486dfcaf ipl_tools/proc.{c,h}: Restrict header scope
Optimize dependency management by limiting header inclusions to
implementation files where possible. This reduces hidden dependencies,
improves modularity, and enhances compilation performance.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jan Polensky
29007541e8 ipl_tools/system.c: Cleanup unused function strlow()
It is no longer referenced in the code.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
2278f112ba cpumf/lshwc: Add support for delta counter value display
Add a flag to display the counter value in form of a delta
value. This format shows the increase of that counter value
in comparison to the previous readout.
The first line is the base for the delta calculation and always
shows 'Total'. The remaining lines show 'Delta' in the third
column.

 # ./lshwc -d -i 3 -l 5 -x -s :p
 Date,Time,CPU,P32,P33
 2024-11-27,15:45:55,Total,d7b,172
 2024-11-27,15:45:58,Delta,2be403,2d58bb
 2024-11-27,15:46:01,Delta,43e3b,22c41
 2024-11-27,15:46:04,Delta,58e3a,35319
 2024-11-27,15:46:07,Delta,5080e,2b81c
 #

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
c39722aff2 zipl/src: Implement '--dry-run' option for ngdumps
Use the directory specified by the shell environment variable TMPDIR
for temporary objects creation and ngdump job simulation. If TMPDIR is
not set, then use "/tmp" for the mentioned purposes;

While running ngdump job in 'dry-run' mode:
. Don't format/mount the target dump device. Instead, create the
  bootmap file and the meta-file at the temporary mount point without
  mounting anything to it. Thus, the mentioned files to be acrually
  created in the "proxy" file system owning the temporary mount point;
. Retrieve base disk info from the read-only dump device and
  complete that info with the block size of the proxy file system;

Separate the steps on retrieving/setting file system block size
into a dedicated procedure;

Use definitions instead of hardcoded file names;

Fix a bug in an error path (accessing freed memory);

Make misc_open_simulate() and misc_open_exclusive() static;

Update man pages with the requirements on the system environment
(resources) for ngdump job being executed in dry-run mode;

Provide hints for user (in stderr) in case when ngdump job in dry-run
mode failed due to inappropriate system environment.

Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
1e8edb6524 zipl/src: Implement --dry-run option for multi-volume DASD dumps
Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
bd5f03d1c4 zipl/src: implement --dry-run option for device-based DASD dumps
Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
f8ccd56bf1 zipl/src: implement --dry-run option for device-based SCSI dumps
Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
72218c5bc3 zipl/src: Introduce misc_open_simulate() and misc_open_device()
Introduce misc_open_simulate() to mark individual files as "opened
for write simulation".
Introduce misc_open_device() to open a file either in "usual", or
in "simulation" mode, depending on the passed argument

Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
b94566048b zipl/src: Introduce 'write simulation' mode for individual files
Introduce a write simulation operation, which doesn't write actual
data and just updates the current position in the file.
This allows to emulate block lists for files located on raw devices
(not formatted with a file system). This is used by the next patches
in the series to implement '--dry-run' zipl option for dumps of all
types (not only ngdumps).

Introduce a 'misc file descriptor', which allows to mark individual
files as "opened in a simulation mode".

Whenever bulding a bootmap file, use either real write, or write
simulation depending on the mode set in the 'misc file descriptor'.

Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Eduard Shishkin
85a232a711 zipl/src: Add missed removal of temporary ramdisk
Remove temporary ramdisk created by zipl_helper.prepare-ngdump in
dump job session

Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
931c61f141 libcpumf/libcpumf_cpuset: Use util_file_read_line()
Use function util_file_read_line() to read the file contents
of sysfs file named /sys/devices/system/cpu/online.
It has only one line.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Mete Durlu
253ca8a30e cpuplugd: Allow cpu hotplugging on systems without polarization
Cpuplugd checks for system polarization before adjusting cpu hotplug
states. Currently, if the sysfs attribute for polarization is not
present cpuplugd does not make any adjustments. Add a new polarization
type PLR_NONE to reflect systems with no polarization state and allow
cpuplugd to adjust cpu hotplugging.

Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
829fc3b294 cpumf/lshwc: Man page updates for new supported flags
Update and add description for new flags -x -X -s -H for command
lshwc.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Maria Eisenhaendler <maria1@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
3c5fb0f885 cpumf/lshwc: Free buffer allocated with malloc
Free all buffers allocated with malloc before program exit.
Handle memory leak in libcpumf_cpuset().

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
9df45d4256 cpumf/lshwc: Allocate memory for per-cpu counter
Allocate the memory required to save the per CPU CPUMF counter value
at the beginning of program execution when the involved number of
CPUs is known. This a bit faster then checking for memory allocation
each time a counter value is retrieved.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
283ae4dd2f cpumf/lshwc: Add flag to hide undefined counters of each counter set
Add command line option -H to hide counter value numbers from counters
which are not defined in a counter set. They are usually all zero and
are of no interest.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
718907d9ba cpumf/lswhc: Add short names to lshwc output
Add option -s or --short to display the header using a short
counter name. With this option the counter symbol names, which can be
very long as in IDCW_ON_DRAWER_DRAWER_HIT are replaced by a shorter
name. That name consists of an abbrevation for the counter set
this counter belongs to and the counter number in that set.

The abbrevations are:
B --> Basic counter set
P --> Problem state counter set
C --> Crypto counter set
E --> Extended counter set
M --> MT_Diagnostic counter set
U --> Undefined counter.

Display E165 for counter name IDCW_ON_DRAWER_DRAWER_HIT
which is counter number 165 from the extended counter set.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
26cf3ec769 cpumf: Move defines from source to header files
Move defines from a source file lscpumf.c to the header
file in the include directory to be reused in a follow on
patch. Also reshuffle the list of defines in proper
sequence of increasing numbers.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Thomas Richter
7150da3e4f cpumf/lshwc: Add flags to display counter values in hex
Add flags to display all counter values in hexadecimal
format with and without leading 0x indicator.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Joern Siglen
f946ce27f7 dbginfo.sh: Add missing config data and logs
Get a summary of chrony ntp info.
Add config directories for audit and selinux.
Get dmesg log from crash directories.

Reviewed-by: Michael Storzer <MSTORZER@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-04-07 17:42:18 +02:00
Jakob Naucke
4942504a9a rust/pv*: Split pvapconfig::ap to pv_core::apdevice
Move appropriate parts into new pv_core::ap module.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
e1245ed4e5 rust/pv*: Use pv_core::Error in pvapconfig
For the parts of pvapconfig::ap to be moved to pv_core, use
pv_core::Result<a>, i.e. Result<a, pv_core::Error>, instead of
Result<a, String>.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
272eb5ad8c rust/pvapconfig: Implement TryFrom for Apqn
Move assembling APQN struct out of gather_apqns and print non-fatal
warnings afterwards. Allows for moving Apqn to pv_core including this
TryFrom.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
543d41cb59 rust/pvapconfig: No stderr in ApqnInfo
ApqnInfo is to be moved to pv_core. Move warnings about missing
master/wrapping keys to gather_apqns to avoid stderr output in library
code.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
8619f14c0a rust/pvapconfig: Add doc-strings to ap
Add doc-strings and Debug derives.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
56aa3e2d26 rust/pv_core: Use file_error!
Macro already exists, but wasn't used in some places where it can
reduce lines.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
a9fbfcc7ae rust/pv_core: Fix error type of misc::read_file
Was Write, should be Read.

Fixes: 9b51b8b882 ("rust/pv: Refactor pv crate")
Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
a32adbf5d8 rust/pvapconfig: Remove sysfs_{read,write}_*
Remove sysfs_{read,write}_{i32,string} in favor of pv_core tools,
which support error contexts, making longer error handlings unnecessary.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
f9050799bb rust/pv_core: Add misc::read_file_string
Like read_file, this is a function that reads from a file with error
handling conveniences, but that reads to a trimmed string instead of a
byte vector.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:45 +01:00
Jakob Naucke
66a10d5e3e rust/pv*: Move u8_to_hexstring to pv_core
Move pvapconfig::helper::u8_to_hexstring to pv_core::utils::encode_hex.
Discard pvapconfig::helper::hexstring_to_u8 in favor of
pv_core::utils::decode_hex.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:44 +01:00
Jakob Naucke
152f446d76 rust: Fix cargo clippy findings
Fix the new `cargo clippy` findings for updated 1.84 toolchain.

Signed-off-by: Jakob Naucke <naucke@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-24 16:31:44 +01:00
Joern Siglen
646e080217 dbginfo.sh: Fix typos in console messages
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
3fd8c48245 pvsecret: Fix incorrect font escape sequences in man page
There are a couple place with incorrectly used font escape sequences.

$ man --warnings -E UTF-8 -l -Tutf8 -Z rust/pvsecret/man/pvsecret.1

troff:<standard input>:107: warning: cannot select font 'F'
troff:<standard input>:107: warning: cannot select font 'E'

$ man --warnings -E UTF-8 -l -Tutf8 -Z rust/pvsecret/man/pvsecret-verify.1
troff:<standard input>:119: warning: cannot select font 'F'
troff:<standard input>:119: warning: cannot select font 'F'
troff:<standard input>:119: warning: cannot select font 'F'
troff:<standard input>:119: warning: cannot select font 'F'
troff:<standard input>:119: warning: cannot select font 'F'
troff:<standard input>:131: warning: cannot select font 'F'

Use the correct escape sequences and regenerate the man pages.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
c93b74b527 pvattest: Fix various man page issues
The pvattest man pages are generated mostly from the rust doc entries
within the tool. Some escape sequences and whatis-entries are incorrect
as found by different linter:

$ man --warnings -E UTF-8 -l -Tutf8 -Z ./rust/pvattest/man/pvattest-create.1
troff:<standard input>:23: warning: macro 'create'' not defined

$ lexgrog -w -m rust/pvattest/man/pvattest-verify.1
rust/pvattest/man/pvattest-verify.1: parse failed

Fix this by regenerating the man pages with correct escape sequences and
whatis-entries.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
4fe6025b18 chreipl-fcp-mpath: Regenerate man page with new pandoc version
Older versions of pandoc (<3.1.7) can sometimes produce incorrect man
page macros [1][2]. The chreipl-fcp-mpath man page had a few of those:

$ man --warnings -E UTF-8 -l -Tutf8 -Z chreipl-fcp-mpath/chreipl-fcp-mpath.7
troff:<standard input>:5: warning: cannot select font 'CB'
troff:<standard input>:160: warning: cannot select font 'C'
troff:<standard input>:174: warning: cannot select font 'C'
troff:<standard input>:183: warning: cannot select font 'C'

Regenerate the man page using pandoc 3.1.11 to fix those issues.

[1] https://github.com/jgm/pandoc/issues/9020
[2] https://github.com/bin-cli/bin-cli/issues/44
Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
73b6a684ec vmur: Remove undefined macro SP from man page
The vmur man page uses the .SP macro a lot. This is not a valid macro
and it is not defined anywhere.

$ man --warnings -E UTF-8 -l -Tutf8 -Z vmur/vmur.8
troff:<standard input>:92: warning: macro 'SP' not defined

Remove it entirely as the initial intention is unclear and the rendered
man page doesn't change.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
40d9df5cc8 opticsmon: Add missing macro definition in man page
The .CL macro was copied from another man page but it is not defined in
the opticsmon man page:

$ man --warnings -E UTF-8 -l -Tutf8 -Z opticsmon/opticsmon.8
troff:<standard input>:70: warning: macro 'CL' not defined

Add the missing definition to fix this.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
9ebb8da624 zdev: Fix spelling error in man page italic macro
The SITE-ID parameter in the --site section is supposed to be formatted
as italic. Instead of .I .ID is used leading to misinterpretation and
the mentioning of the parameter missing in the rendered man page.

Found via:
$ man --warnings -E UTF-8 -l -Tutf8 -Z zdev/man/lszdev.8
troff:<standard input>:455: warning: macro 'ID' not defined

Use .I correctly to fix the issue.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
589ce29d41 lsqeth: Fix incorrectly used font change sequence in man page
The lsqeth man page uses the font change sequence \f without a
parameter, which is not allow:

$ man --warnings -E UTF-8 -l -Tutf8 -Z zconf/qeth/lsqeth.8
troff:<standard input>:13: error: a space character is not allowed in an escape sequence parameter
troff:<standard input>:13: error: a space character is not allowed in an escape sequence parameter
troff:<standard input>:13: error: a space character is not allowed in an escape sequence parameter
troff:<standard input>:13: error: a space character is not allowed in an escape sequence parameter
troff:<standard input>:13: error: a newline character is not allowed in an escape sequence parameter

Fix it by using proper espace sequence to format the specific parts of
the text correctly. This also brings the synopsis a bit more in line
with other qeth tools.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
b343672eb8 cpacfinfo: Fix missing escape sequence in man page
For the --available option the description contains a line starting with
". If", which is intended to be a punctuation and start of a new
sentence but is misinterpreted by groff as a macro. As a result, the
rendered paragraph is incorrectly displayed.

$ man --warnings -E UTF-8 -l -Tutf8 -Z rust/cpacfinfo/man/cpacfinfo.1
troff:<standard input>:128: warning: macro 'If' not defined

Even though it's not consistent with the rest of the man page, use the
font change escape sequence and surround the specific bold formatted
parts to fix this issue and correctly display the sentence.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:05 +01:00
Jan Höppner
df47036f01 zcryptstats: Remove beginning paragraph in man page
A single paragraph opening .TP macro at the end of the man page is
causing errors found with:
$ man --warnings -E UTF-8 -l -Tutf8 -Z zconf/zcrypt/zcryptstats.8
troff: error: automatically ending diversion 'an-div' on exit

It also causes the footer of the man page not rendering correctly.
Remove the macro. While at it, remove whitespace damage as well.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/issues/170
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
5febec5f44 zkey/kmip/zkey-kmip.1: Fix typos in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
84f44dd20f rust/pvapconfig/man/pvapconfig.1: Fix typos in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
d86dd0658f zpcictl/zpcictl.8: Fix typo in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
00c36baee0 zconf/lsluns.8: Fix typo in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
a40519fd16 scripts/dbginfo.sh.8: Fix typos in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
b836b4fb83 cpumf/man/lscpumf.8: Fix typo in man page
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Mete Durlu
1ab819cd81 zmemtopo: Add man page
Add man page with tool description and usage examples.

Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Mete Durlu
ee50f20c11 zmemtopo: Add parseable format
Allow users to fetch zmemtopo data in parse-able formats, such as
csv, json, json-seq and pairs.

Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Mete Durlu
0f17fe5183 s390-tools: Introduce new tool zmemtopo
s390 is able to provide memory topology information of the current CEC
via a new userspace-kernel interface. zmemtopo is a tool to convert the
raw data into human readable form.

Usage: zmemtopo [OPTIONS]

Display CEC memory topology of allocated memory increments.

OUTPUT FORMAT OPTIONS
 -l, --level NESTING_LEVEL  Set the topology display depth to NESTING_LEVEL
 -f, --full                 Display tree view with padded elements
 -r, --reverse              Reverse tree view hierarchy direction
 -t, --table                Use table view to display topology
 -s, --sort FIELD           Sort view by field
                            (nr, lpar, size)
 -i, --ascii                Use only ASCII characters

GENERAL OPTIONS
 -h, --help                 Print this help, then exit
 -v, --version              Print version information, then exit

Upon calling zmemtopo displays available topology level's structure
and memory increments defined on each topology location.

Ex:
$ zmemtopo
LPAR/LEVEL     SIZE
LPAR003          8G
└LEVEL4_0        8G
  ├LEVEL3_0      2G
  ├LEVEL3_1      2G
  ├LEVEL3_2      2G
  └LEVEL3_3      2G
LPAR005          8G
└LEVEL4_1        8G
  ├LEVEL3_0      2G
  ├LEVEL3_1      2G
  ├LEVEL3_2      2G
  └LEVEL3_3      2G
LPAR006          8G
└LEVEL4_3        8G
...

Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:35:04 +01:00
Jan Polensky
650e2da843 ipl_tools/cmd_lsreipl.c: Add secure boot state to output
The actual secure boot state ensures that a Linux instance has loaded
only trusted, signed software. During boot component signatures are
verified. If secure boot is enabled, unsigned or unverifiable components
prevent booting. Since Secure Boot on IBM Z is always triggered by the
hypervisor, its state is merely observable by the active system.

Secure boot: 1 - Linux booted secure (only trusted sources)
Secure boot: 0 - Booted from any source without verification

	$ dmesg -t | grep Secure-IPL
	setup: Linux is running with Secure-IPL enabled

	$ cat /sys/kernel/security/lockdown
	none [integrity] confidentiality

	$ lsreipl
	Re-IPL type: fcp
	WWPN:        0x500507630710572c
	LUN:         0x4022409600000000
	Device:      0.0.1908
	bootprog:    0
	br_lba:      0
	Loadparm:    ""
	Bootparms:   ""
	Secure boot: 1

References:
* https://www.ibm.com/docs/en/linux-on-systems?topic=using-verifying-secure-boot
* https://www.ibm.com/docs/en/linux-on-systems?topic=introduction-requirements
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
426311f440 ipl_tools/cmd_chreipl.c: Replace /sys mount point with util_path_sysfs
The default sysfs path is always set to '/sys' unless the SYSFS_ROOT
environment variable is defined.

To address security concerns, secure_getenv() is used within
util_path_sysfs() to protect against malicious values in SYSFS_ROOT.
Additionally, constructing the sysfs path dynamically in an allocated
buffer, rather than using a fixed-size buffer, helps prevent potential
buffer overflows.

These modifications also significantly improve testability by allowing
sysfs read and write operations to be redirected to an alternative file
path, which enables testing without affecting the active system state.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
5333085c55 ipl_tools/ccw.c: Cleanup obsolete ccw_busid_get_sysfs_old()
The function is no longer required since the removal of the PHYSDEVPATH
entry in /sys/block/%s/uevent with commit 39aba963d937 ("driver core:
remove CONFIG_SYSFS_DEPRECATED_V2 but keep it for block devices") in
2010.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
4c301d47dd ipl_tools/cmd_lsshut.c: Replace /sys mount point with util_path_sysfs
The default sysfs path is always set to '/sys' unless the SYSFS_ROOT
environment variable is defined.

To address security concerns, secure_getenv() is used within
util_path_sysfs() to protect against malicious values in SYSFS_ROOT.
Additionally, constructing the sysfs path dynamically in an allocated
buffer, rather than using a fixed-size buffer, helps prevent potential
buffer overflows.

These modifications also significantly improve testability by allowing
sysfs read operations to be redirected to an alternative file path,
which enables testing without affecting the active system state.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
aea2ba8728 ipl_tools/cmd_lsreipl.c: Construct sysfs paths with util_path_sysfs()
The default sysfs path is always set to '/sys' unless the SYSFS_ROOT
environment variable is defined.

To address security concerns, secure_getenv() is used within
util_path_sysfs() to protect against malicious values in SYSFS_ROOT.
Additionally, constructing the sysfs path dynamically in an allocated
buffer, rather than using a fixed-size buffer, helps prevent potential
buffer overflows.

These modifications also significantly improve testability by allowing
sysfs read operations to be redirected to an alternative file path,
which enables testing without affecting the active system state.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
594a554e56 ipl_tools/cmd_chreipl.c: Fix typo errrors->error
Fix typo in comment also helps to prevent pre-commit hook issues, w/o
functional changes or changes in behavior.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Jan Polensky
a0c3a74019 ipl_tools: Remove empty lines
Remove unnecessary empty lines to prevent pre-commit hook issues, w/o
functional changes or changes in behavior.

Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Ingo Franzki
efdd34a56c zkey-cryptsetup: Add new 'convert' command
The 'convert' command converts a LUKS2 volume that uses a clear volume key
and the 'aes' cipher to use a secure volume key and the 'paes' cipher.

Optionally, the volume can use the integrity option with LUKS2 using a
clear key integrity key.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Jorg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Ingo Franzki
c80a0c8af0 zkey-cryptsetup: Add '--volume-key-file' as alias for '--master-key-file'
Starting with cryptsetup version 2.5.0 the luksFormat command accepts
option '--volume-key-file' to specify the volume key file. Option
'--master-key-file' is still accepted as an alias to '--volume-key-file'.

Follow this pattern with the zkey-cryptsetup tool and also accept both
options '--volume-key-file' and '--master-key-file'. The short option
form stays '-m' for compatibility reasons (cryptsetup does not have a
short option for that).

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Jorg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Ingo Franzki
d98a10f67f zkey-cryptsetup: Fix logging of libcryptsetup debug messages
Messages from libcryptsetup for logging level CRYPT_LOG_DEBUG
may or may not include an EOL, dependent on the cryptsetup version:
Between libcryptsetup version 2.1 and 2.2 debug messages do not
include an EOL character, but since 2.2 they do.

Append an EOL only if the message does not already end with EOL.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Jorg Schmidbauer <jschmidb@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Steffen Eiden
fb6e7e70c6 rust/pvsecret: Update man page for retrieve secret
Clarify the Output format in the man files.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Ingo Franzki
e49569db60 rust/pvsecret: Update man page for clarifying the creation of HMAC secrets
The key supplied in the plain bytes file with 'pvsecret create retrievable'
with type 'hmac-sha' is they key 'K_0' as of FIPS-198-1, i.e. the key 'K'
after any necessary pre-processing. The pre-processing must be performed
by the user prior to creating the retrievable secret.

Describe in detail how that pre-processing must be performed.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Marc Hartmayer
b3055154db rust/Makefile: Add 'install-(bash|zsh)-completion' targets
Add installation targets for bash and zsh autocompletions for the PV
related tools. Do not use them by default.

Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Marc Hartmayer
6718c0edc9 common.mak: Introduce 'DATADIR'
This makes it easier to reuse. Stick to the conventions used by Meson [1].

[1] https://mesonbuild.com/Builtin-options.html#directories

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Joern Siglen
28d9405f73 dbginfo.sh: Updating info for disks and lvm
Adding some different views on disk and file system setup.
Getting more details on lvm setup.

Suggested-by: Mohamed AbouRehab <mohamed.abou.rehab@ibm.com>
Reviewed-by: Michael Storzer <MSTORZER@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-03-19 16:34:52 +01:00
Sumanth Korikkar
05f0aeb61e zpwr: Add man page for zpwr tool
Add man page for zpwr tool and its usage.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-02-14 14:38:58 +01:00
Sumanth Korikkar
6004a7029c s390-tools: Add zpwr tool
zpwr displays power readings of a partition and central processing
complex (CPC) from power information block (pib). pib is retrieved by
issuing diag324 ioctl to /dev/diag device.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-02-14 14:38:58 +01:00
Jan Höppner
16add4a4ae scsi_logging_level: Delete SCSI logging script
The script scsi_logging_level was made available in sg3_utils 2007 [1]
copied from s390-tools. The last functional change in s390-tools was
made 2006.

The sg3_utils version saw at least some improvements over the years.
Providing otherwise identical tools can lead to unnecessary conflicts.
Delete the script from s390-tools and let sg3_utils provide it.

[1] 7502647d46
Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/184
Acked-by: Nihar Panda <niharp@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2025-02-14 14:38:18 +01:00
Jan Höppner
ef752d1f45 Prepare for next release
Signed-off by: Jan Höppner <hoeppner@linux.ibm.com>
2025-02-07 15:47:07 +01:00
271 changed files with 10889 additions and 4903 deletions

2
.gitignore vendored
View File

@@ -137,4 +137,6 @@ zkey/kmip/libkmipclient.dep
zkey/kmip/zkey-kmip.so
zkey/zkey
zkey/zkey-cryptsetup
zmemtopo/zmemtopo
zpcictl/zpcictl
zpwr/zpwr

View File

@@ -2,7 +2,7 @@
exclude: \.(bin|crl|crt|key)$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
rev: v6.0.0
hooks:
- id: check-merge-conflict
- id: end-of-file-fixer
@@ -11,6 +11,9 @@ repos:
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
exclude_types: ['rust']
- id: check-yaml
- id: check-json
- id: check-toml
- repo: local
hooks:
- id: git-clang-format
@@ -24,7 +27,7 @@ repos:
minimum_pre_commit_version: "2.9.0"
types_or: [c++, c]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.1
rev: v2.4.1
hooks:
- id: codespell
exclude_types: ['rust']

View File

@@ -43,6 +43,7 @@ List of all individuals having contributed content to s390-tools
- Frank Munzert
- Frank Pavlic
- Fritz Elfert
- Gautam Gala
- Gerald Schaefer
- Gerhard Tonn
- Graham Inggs
@@ -63,6 +64,7 @@ List of all individuals having contributed content to s390-tools
- Jakub Čajka
- Jan Glauber
- Jan Höppner
- Jan Polensky
- Jan Willeke
- Jason J. Herne
- Javier Martinez Canillas
@@ -70,6 +72,7 @@ List of all individuals having contributed content to s390-tools
- Jens Remus
- Jochen Roehrig
- Joern Siglen
- Jörn Siglen
- Juergen Christ
- Julian Wiedmann
- Karsten Graul
@@ -97,6 +100,7 @@ List of all individuals having contributed content to s390-tools
- Nikita Dubrovskii
- Niklas Schnelle
- Nikolay Gueorguiev
- Peter Jin
- Peter Oberparleiter
- Peter Tiedemann
- Philipp Kern
@@ -106,12 +110,15 @@ List of all individuals having contributed content to s390-tools
- Raimund Schroeder
- Ralph Wuerthner
- Rene Trumpp
- Richie Buturla
- Rolf Schaefer
- Sa Liu
- Sascha Silbe
- Sebastian Ott
- Sertonix
- Seshagiri N. Ippili
- Shalini Chellathurai Saroja
- Siglen
- Simon Sturm
- Stefan Bader
- Stefan Haberland
@@ -121,6 +128,7 @@ List of all individuals having contributed content to s390-tools
- Steffen Eiden
- Steffen Maier
- Steffen Thoss
- Sumanth Korikkar
- Susanne Wintenberger
- Sven Schnelle
- Sven Schuetz

View File

@@ -1,6 +1,100 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.39.0 (2025-10-14)__
For Linux kernel version: 6.16 / 6.17
Changes of existing tools:
- chpstat: Add options to select IEC units for scaling (SI units are default)
- chzdev: Introduce --no-module-load option
- cpi: Disable CPI for SEL guests by default
- dbginfo.sh: Enhance logging on timeout triggered
- iucvterm: Install symlink for lsiucvallow.8 man page
- lshwc: Add command line flag to specify individual counters
- lspai: Add command line flag for delta values
- lspai: Add command line flag for short counter names
- lspai: Add command line flag to specify individual counters
- lspai: Add command line flags for all cpus
- lspai: Add command line flags for hexadecimal output
- man: Use CR for constant width font
- pvimg: Add '--image-key' option
- zdev: Allow dynamic control of module load
- zipl/boot: Fix EBCDIC code page 500 conversion and decrease size by 200 bytes
- zipl: Add support of heterogeneous mirrors (remove technical limitations
on mirrored targets, thus allowing mirrored devices consist of partitions
at different offsets on disks of different types and geometry).
- zkey: Add support for generating and importing exportable secure keys
Bug Fixes:
- chpstat: Fix scaling of DPU utilization calculation
- zdev/dracut: Prevent loading of unused kernel modules
- zdev: Fix double device configuration on DPM systems
- zdev: Fix double device configuration with rd.dasd
- zipl_helper.device-mapper: Fix segfault in an error path
* __v2.38.0 (2025-06-25)__
For Linux kernel version: 6.14 / 6.15
Add new tools:
- udev: New rule to set newly hotplugged CPUs online
- zmemtopo: Display memory topology information
- zpwr: Display power readings of a partition and CPC
Removed tools / features:
- check_hostkeydoc: Remove installation target
- scsi_logging_level: Delete SCSI logging script (available in sg3_utils)
- zdump: Drop build_arch for s390 DASD dumps
- zdump: Drop non-extended multi-volume DASD dump support
- zdump: Drop support of 32-bit dump architecture
- zdump: Drop support of non-extended single volume DASD dumpers
- zdump: Drop support of obsolete dumps and dumpers
Changes of existing tools / libraries:
- Various man-pages fixes
- check_hostkeydoc: Add deprecation warning
- check_hostkeydoc: Move to scripts directory
- cpuplugd: Allow cpu hotplugging on systems without polarization
- dbginfo.sh: Add Ubuntu snap tool
- dbginfo.sh: Add missing config data and logs
- dbginfo.sh: Reworking the container section
- dbginfo.sh: Update for network commands
- dbginfo.sh: Updating info for disks and lvm
- libutil: Add machine type definition for machines 9175 and 9176
- lscpumf: Add support for IBM z17 counter sets
- lshwc: Add command line flag for run time
- lshwc: Add flags to display counter values in hex
- lshwc: Add output '--format' option
- lshwc: Add support for delta counter value display
- lspai: Add output '--format' option
- lsreipl: Add secure boot state to output
- lswhc: Add short names to lshwc output
- pv_tools: Add Bash and Zsh completions
- pvapconfig: Add '--unbind' option
- pvimg/boot: Print error messages from stage3a bootloader
- pvimg: Add support for CCK update
- pvsecret: Add support for CCK update
- pvsecret: Allow retrieving secrets by index & warn for duplicated entries
- pvsecret: Deny adding secrets with duplicated secret IDs
- zdev: Add support for virtio devices
- zipl: Enhance mirror support
- zipl: Implement '--dry-run' option for all dump jobs
- zipl_helper.device-mapper: Support mirrors over NVMe devices
- zkey/dracut: Add a dracut config file for zkey
- zkey/initramfs: Update initramfs hook to correct drivers and include zkey plugins
- zkey: Add support for converting a clear-key LUKS2 volume to use a secure key
Bug Fixes:
- chpstat: Add missing CMG 5 data fields
- chpstat: Fix DPU utilization calculation
- libutil/util_file: Handle over-read in util_file_read_fd()
- pvattest: Fix successful 'check' evaluation
- pvsecret: Fix some edge cases for plaintext keys
- zipl_helper.device-mapper: Fix imprecise is_device_mapper() predicate
- zkey: Fix EP11 secure key reencipher function
- zpcictl: Fix command line parsing for invalid options
* __v2.37.0 (2025-02-07)__
For Linux kernel version: 6.13
@@ -49,6 +143,14 @@ Release history for s390-tools (MIT version)
- chpstat: Add support for full CMCB
- chpstat: Add support for new CMG types
- dbginfo.sh: add overview commands and crypto update
- genprotimg:
1. genprotimg is now a symbolic link to the new tool `pvimg create`
2. Breaking API changes in genprotimg:
1. An existing output file is no longer silently overwritten; to revert
to the old behavior use the `--overwrite` option.
2. The Linux kernel component is now checked to determine whether it is a
binary s390x kernel. To disable this behavior use the
`--no-component-check` option.
- hyptop: Support for structured output (json, json-seq, csv)
- lszfcp: Add missing fallback marker for non-good fc_host port_state
- lszfcp: Improve speed with many SCSI devices

View File

@@ -15,7 +15,8 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust opticsmon
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust opticsmon \
zpwr zmemtopo
else
BASELIB_DIRS =

View File

@@ -128,9 +128,6 @@ Package contents
* sclpdbf:
Display debug data for the sclp kernel component.
* scsi_logging_level:
Create, get or set the logging level for the SCSI logging facility.
* zconf:
Set of scripts to configure and list status information of Linux on s390
devices.
@@ -417,6 +414,18 @@ the different tools are provided:
dumping).
Removing the inflate modules and function prototypes are the only major
modifications made to the kernel version of zlib.
For stand-alone NVMe and list-directed DASD dump, the following tools/packages
are required to populate dumper's initramfs:
- cat
- cut
- findmnt
- logsave
- makedumpfile
- mount
- poweroff
- sha256sum
- sync
- umount
* zgetdump
For building zgetdump you need OpenSSL version 1.1.0 or newer

View File

@@ -1,182 +1,170 @@
.\" Automatically generated by Pandoc 2.16.1
.\" Automatically generated by Pandoc 3.1.11.1
.\"
.TH "CHREIPL-FCP-MPATH" "7" "2022-02-24" "s390-tools 2.20.0-build-20220224" "Administrator Manual"
.hy
.TH "CHREIPL\-FCP\-MPATH" "7" "2025\-03\-12" "s390-tools 2.37.0-build-20250312" "Administrator Manual"
.SH NAME
.PP
chreipl-fcp-mpath - use multipath information for re-IPL path failover
on a running Linux instance
chreipl\-fcp\-mpath \- use multipath information for re\-IPL path
failover on a running Linux instance
.SH DESCRIPTION
.PP
The IPL process of Linux on Z or LinuxONE from an FCP-attached SCSI
The IPL process of Linux on Z or LinuxONE from an FCP\-attached SCSI
volume uses exactly one path to the volume.
If this path is unavailable, the IPL fails.
.PP
The \f[B]chreipl-fcp-mpath\f[R] toolset monitors \f[B]udev\f[R] events
about paths to the re-IPL volume.
If the currently configured re-IPL path becomes unavailable, the toolset
checks for operational paths to the same volume.
If available, it reconfigures the re-IPL settings to use an operational
The \f[B]chreipl\-fcp\-mpath\f[R] toolset monitors \f[B]udev\f[R] events
about paths to the re\-IPL volume.
If the currently configured re\-IPL path becomes unavailable, the
toolset checks for operational paths to the same volume.
If available, it reconfigures the re\-IPL settings to use an operational
path.
.PP
Thus, re-IPL from an FCP-attached SCSI volume can be successful despite
path failures on a running Linux instance if at least one path to the
re-IPL volume remains operational.
Thus, re\-IPL from an FCP\-attached SCSI volume can be successful
despite path failures on a running Linux instance if at least one path
to the re\-IPL volume remains operational.
.PP
\f[B]Chreipl-fcp-mpath\f[R] requires \f[B]udev\f[R],
\f[B]multipathd\f[R] and \f[B]dm-multipath\f[R].
\f[B]Chreipl\-fcp\-mpath\f[R] requires \f[B]udev\f[R],
\f[B]multipathd\f[R] and \f[B]dm\-multipath\f[R].
Once installed, the toolset runs automatically and autonomously.
No user intervention is possible or required.
.PP
Other than installing the toolset, there is no user interface for
\f[B]chreipl-fcp-mpath\f[R].
\f[B]chreipl\-fcp\-mpath\f[R].
.SS Requirements
.PP
The \f[B]chreipl-fcp-mpath\f[R] tool has the following requirements on
The \f[B]chreipl\-fcp\-mpath\f[R] tool has the following requirements on
the Linux instance that is being monitored:
.IP \[bu] 2
The Linux instance must have started successfully, during IPL.
.IP \[bu] 2
The running Linux instance must use \f[B]dm-multipath\f[R] and
\f[B]multipathd\f[R] for the configured re-IPL volume - a volume that
contains a zipl boot record and has one of its paths used in the re-IPL
The running Linux instance must use \f[B]dm\-multipath\f[R] and
\f[B]multipathd\f[R] for the configured re\-IPL volume \- a volume that
contains a zipl boot record and has one of its paths used in the re\-IPL
configuration.
.IP \[bu] 2
\f[B]udev\f[R] must run.
.IP \[bu] 2
The toolset must observe at least one event about the configured re-IPL
The toolset must observe at least one event about the configured re\-IPL
path.
Examples for such events are: the SCSI disk comes online, or a path of
the corresponding multipath device goes down or comes back online.
.RS 2
.IP \[bu] 2
The WWID of the re-IPL volume must not change while the Linux instance
The WWID of the re\-IPL volume must not change while the Linux instance
is running.
.RE
.IP \[bu] 2
When the configured re-IPL path becomes unavailable while the Linux
instance is running, at least one operational path to the re-IPL volume
When the configured re\-IPL path becomes unavailable while the Linux
instance is running, at least one operational path to the re\-IPL volume
must be available, or must become available.
If no such path is available when the Linux instance is rebooted, the
re-IPL path is not changed.
re\-IPL path is not changed.
.IP \[bu] 2
The tool assumes that any manually reconfigured re-IPL device is valid
The tool assumes that any manually reconfigured re\-IPL device is valid
and operational.
.RS 2
.PP
The tool treats a newly configured re-IPL device like the initially
configured re-IPL device.
In particular, if the newly configured re-IPL device fulfills the
requirements of the tool, re-IPL path failover takes place if the
configured re-IPL path becomes unavailable.
The tool treats a newly configured re\-IPL device like the initially
configured re\-IPL device.
In particular, if the newly configured re\-IPL device fulfills the
requirements of the tool, re\-IPL path failover takes place if the
configured re\-IPL path becomes unavailable.
.RE
.SS Caution with Manual Changes to the Configured re-IPL Target
.PP
\f[B]chreipl-fcp-mpath\f[R] is designed to accept operator-inititated
changes of the re-IPL device.
.SS Caution with Manual Changes to the Configured re\-IPL Target
\f[B]chreipl\-fcp\-mpath\f[R] is designed to accept operator\-inititated
changes of the re\-IPL device.
However, concurrent changes by the operator and tool driven changes can
result in the operator change being overwritten.
.PP
To avoid this problem, change the re-IPL device only during steady-state
operations, when no path events happen.
To avoid this problem, change the re\-IPL device only during
steady\-state operations, when no path events happen.
Alternatively, make sure that no events are processed while you change
the device.
See EXAMPLES for one way to suspend event processing.
.SH MESSAGES
.PP
During monitoring and event processing, \f[B]chreipl-fcp-mpath\f[R]
During monitoring and event processing, \f[B]chreipl\-fcp\-mpath\f[R]
writes messages to the syslog.
.PP
When the configured re-IPL path is changed to a different path to the
When the configured re\-IPL path is changed to a different path to the
same volume (priority \f[I]daemon.notice\f[R]):
.RS
.PP
Changed re-IPL path to: <device-bus-id>:<wwpn>:<lun>.
Changed re\-IPL path to: <device\-bus\-id>:<wwpn>:<lun>.
.RE
.PP
When a path event indicates that the last available path has become
non-operational (priority \f[I]daemon.alert\f[R]):
non\-operational (priority \f[I]daemon.alert\f[R]):
.RS
.PP
The re-IPL device cannot be changed because no operational path to the
re-IPL volume remains.
The next re-IPL might fail unless you re-attach or enable at least one
valid path to the re-IPL volume.
The re\-IPL device cannot be changed because no operational path to the
re\-IPL volume remains.
The next re\-IPL might fail unless you re\-attach or enable at least one
valid path to the re\-IPL volume.
.RE
.PP
When changing the configured re-IPL device failed because of an error
When changing the configured re\-IPL device failed because of an error
with the used Linux kernel interface (priority \f[I]daemon.crit\f[R]):
.RS
.PP
Changing the re-IPL device failed.
The current re-IPL settings might be inconsistent.
Check and correct the settings (see the README.md of chreipl-fcp-mpath)
to make sure that the current re-IPL device is valid.
Changing the re\-IPL device failed.
The current re\-IPL settings might be inconsistent.
Check and correct the settings (see the README.md of
chreipl\-fcp\-mpath) to make sure that the current re\-IPL device is
valid.
.RE
.PP
A failure to change the re-IPL device can indicate an inconsistent
A failure to change the re\-IPL device can indicate an inconsistent
setting that cannot be corrected automatically by
\f[B]chreipl-fcp-mpath\f[R].
As a result, the next re-IPL might fail or might not use the intended
re-IPL device.
\f[B]chreipl\-fcp\-mpath\f[R].
As a result, the next re\-IPL might fail or might not use the intended
re\-IPL device.
.PP
You can use the following tools to check and correct the current
settings:
.IP \[bu] 2
\f[B]lsreipl\f[R] to confirm that the intended re-IPL device is
\f[B]lsreipl\f[R] to confirm that the intended re\-IPL device is
configured;
.IP \[bu] 2
\f[B]chreipl\f[R] to change the re-IPL device;
\f[B]chreipl\f[R] to change the re\-IPL device;
.IP \[bu] 2
\f[B]lszfcp\f[R] to inspect the state of available paths to the re-IPL
\f[B]lszfcp\f[R] to inspect the state of available paths to the re\-IPL
device.
.SH EXAMPLES
.SS Manual Changes to the Configured re-IPL Device
.PP
.SS Manual Changes to the Configured re\-IPL Device
As outlined in DESCRIPTION, be cautious when manually changing the
configured re-IPL device.
configured re\-IPL device.
Assure that your reconfiguration actions do not collide with concurrent
automatic event processing by \f[B]chreipl-fcp-mpath\f[R].
automatic event processing by \f[B]chreipl\-fcp\-mpath\f[R].
You can avoid such collisions, by stopping event processing, making your
changes, and then re-enabling event processing.
changes, and then re\-enabling event processing.
You need \f[I]root\f[R] privileges for running the commands in the
following example:
.IP
.nf
\f[C]
.EX
\[ti] # udevadm settle
\[ti] # udevadm control --stop-exec-queue
\[ti] # udevadm control \-\-stop\-exec\-queue
\[ti] # chreipl ...
\[ti] # udevadm control --start-exec-queue
\f[R]
.fi
\[ti] # udevadm control \-\-start\-exec\-queue
.EE
.SS Listing messages with journalctl
.PP
If your Linux instance includes \f[B]journalctl\f[R], use the following
command to list all messages that are issued by
\f[B]chreipl-fcp-mpath\f[R]:
\f[B]chreipl\-fcp\-mpath\f[R]:
.IP
.nf
\f[C]
\[ti] # journalctl -t chreipl-fcp-mpath
\f[R]
.fi
.EX
\[ti] # journalctl \-t chreipl\-fcp\-mpath
.EE
.PP
To list only messages that were issued since the last IPL, use this
command:
.IP
.nf
\f[C]
\[ti] # journalctl -t chreipl-fcp-mpath -b
\f[R]
.fi
.EX
\[ti] # journalctl \-t chreipl\-fcp\-mpath \-b
.EE
.SH REPORTING BUGS
.PP
Use the \f[B]Issues\f[R] functionality on GitHub to report any bugs in
\f[B]chreipl-fcp-mpath\f[R]: s390-tools
Issues (https://github.com/ibm-s390-linux/s390-tools/issues).
\f[B]chreipl\-fcp\-mpath\f[R]: \c
.UR https://github.com/ibm-s390-linux/s390-tools/issues
s390\-tools Issues
.UE \c
\&.
.SH SEE ALSO
.PP
\f[B]chreipl\f[R](8), \f[B]dracut\f[R](8), \f[B]journalctl\f[R](1),
\f[B]lsreipl(8)\f[R], \f[B]lszfcp\f[R](8), \f[B]multipath\f[R](8),
\f[B]multipathd\f[R](8), \f[B]udev\f[R](7), \f[B]udevadm\f[R](8),

View File

@@ -32,7 +32,7 @@ endif
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION := 2
RELEASE := 37
RELEASE := 39
PATCHLEVEL := 0
DISTRELEASE := build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -265,9 +265,12 @@ LIBDIR = $(INSTALLDIR)/lib
USRLIBDIR = $(INSTALLDIR)/usr/lib
USRLIB64DIR = $(INSTALLDIR)/usr/lib64
SYSCONFDIR = $(INSTALLDIR)/etc
MANDIR = $(INSTALLDIR)/usr/share/man
DATADIR = $(INSTALLDIR)/usr/share
MANDIR = $(DATADIR)/man
BASHCOMPLETIONDIR = $(DATADIR)/bash-completion/completions
ZSHCOMPLETIONDIR = $(DATADIR)/zsh/site-functions
VARDIR = $(INSTALLDIR)/var
TOOLS_DATADIR = $(INSTALLDIR)/usr/share/s390-tools
TOOLS_DATADIR = $(DATADIR)/s390-tools
TOOLS_LIBDIR = $(INSTALLDIR)/lib/s390-tools
ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
# Systemd support files are installed only if a directory is specified

View File

@@ -22,7 +22,7 @@ ALL_CPPFLAGS += -DVERSION=$(VERSION)
all: check_dep cpacfstats cpacfstatsd
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o cpacfstats_common.o \
$(rootdir)/libutil/libutil.a
$(rootdir)/libcpumf/libcpumf.a $(rootdir)/libutil/libutil.a
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
cpacfstats: cpacfstats.o stats_sock.o cpacfstats_common.o

View File

@@ -30,6 +30,7 @@
#include <libudev.h>
#include "cpacfstats.h"
#include "lib/libcpumf.h"
#include "../include/lib/zt_common.h"
/* correlation between counter and perf counter string */
@@ -123,16 +124,6 @@ static struct percpucounter *findcpu(unsigned int cpunum, int unlinkflag)
return NULL;
}
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
static int perf_supported(void)
{
return !access("/proc/sys/kernel/perf_event_paranoid", R_OK);

View File

@@ -16,11 +16,11 @@
#include <unistd.h>
#include <sys/stat.h>
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_base.h"
#include "lib/libcpumf.h"
#include "lib/util_base.h"
#include "lib/util_opt.h"
#include "lib/util_path.h"
#include "lib/util_prg.h"
static unsigned int verbose;
static unsigned long min_sdb, max_sdb;
@@ -88,21 +88,22 @@ static long parse_buffersize(char *string)
static int write_sfb(unsigned int min, unsigned int max)
{
int rc = EXIT_SUCCESS;
char text[64];
char text[64], *path;
size_t len;
FILE *fp;
fp = fopen(S390_CPUMSF_BUFFERSZ, "w");
path = util_path_sysfs(S390_CPUMSF_BUFFERSZ);
fp = fopen(path, "w");
if (!fp)
err(EXIT_FAILURE, S390_CPUMSF_BUFFERSZ);
err(EXIT_FAILURE, "%s", path);
snprintf(text, sizeof(text), "%u,%u", min, max);
len = strlen(text) + 1;
if (fwrite(text, 1, len, fp) != len) {
warn(S390_CPUMSF_BUFFERSZ);
warn("%s", path);
rc = EXIT_FAILURE;
}
if (fclose(fp)) {
warn(S390_CPUMSF_BUFFERSZ);
warn("%s", path);
rc = EXIT_FAILURE;
}
if (verbose && rc != EXIT_FAILURE)
@@ -110,6 +111,7 @@ static int write_sfb(unsigned int min, unsigned int max)
" Minimum:%7d sample-data-blocks\n"
" Maximum:%7d sample-data-blocks\n",
min, max);
free(path);
return rc;
}

View File

@@ -39,7 +39,7 @@
static bool actions[ACTION_SAMPLE + 1]; /* Specified command line options */
/* This defines the number of pages a Sample Data Buffer Table (SDBT) can hold
* as payload data. Each SDBT is one PAGE (4096 bytes) and continas 512 eight
* as payload data. Each SDBT is one PAGE (4096 bytes) and contains 512 eight
* byte data pointers to Sample Data Buffers (SDB). The last entry of a SDBT
* points to another SDBT and can not store payload.
*/
@@ -139,7 +139,7 @@ static struct samples { /* Sample definition for all machines */
* The CPU Measurement facility has a first and second version number.
*
* The first version number governs basic counter set and the
* problem state counter set. Currently used are first verion numbers 1 and 3.
* problem state counter set. Currently used are first version numbers 1 and 3.
* The counter numbers are identifical for version number 1 and 3, but
* have different purpose and description.
*
@@ -162,13 +162,6 @@ static struct samples { /* Sample definition for all machines */
* Second version number: >3 Range 448 to 495 inclusive (48 counters)
*/
#define CPUMF_CTRSET_NONE 0
#define CPUMF_CTRSET_BASIC 2
#define CPUMF_CTRSET_PROBLEM_STATE 4
#define CPUMF_CTRSET_CRYPTO 8
#define CPUMF_CTRSET_EXTENDED 1
#define CPUMF_CTRSET_MT_DIAG 32
struct counters {
int ctrnum;
int ctrset;
@@ -634,7 +627,7 @@ static struct counters cpumcf_z10_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1D_L3_LOCAL_WRITES",
.desc = "A directory write to the Level-1 D-Cache directory"
"\n\t\twhere the installtion cache line was source from"
"\n\t\twhere the installation cache line was source from"
"\n\t\tthe Level-3 cache that is on the same book as the"
"\n\t\tData cache (Local L2 cache)",
},
@@ -1923,7 +1916,7 @@ static struct counters cpumcf_z14_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
},
{
@@ -1931,7 +1924,7 @@ static struct counters cpumcf_z14_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom On-Chip memory",
},
{
@@ -1939,7 +1932,7 @@ static struct counters cpumcf_z14_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
},
{
@@ -2349,7 +2342,7 @@ static struct counters cpumcf_z15_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_L3_SOURCED_WRITES",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-3 cache without intervention",
},
{
@@ -2357,7 +2350,7 @@ static struct counters cpumcf_z15_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_MEMORY_SOURCED_WRITES",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom On-Chip memory",
},
{
@@ -2365,7 +2358,7 @@ static struct counters cpumcf_z15_counters[] = {
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1I_ONCHIP_L3_SOURCED_WRITES_IV",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache ine was sourced"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-3 cache with intervention",
},
{
@@ -3136,6 +3129,641 @@ static struct counters cpumcf_z16_counters[] = {
},
};
static struct counters cpumcf_z17_counters[] = {
{
.ctrnum = 128,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1D_RO_EXCL_WRITES",
.desc = "A directory write to the Level-1 Data cache where"
"\n\t\tthe line was originally in a Read-Only state in the"
"\n\t\tcache but has been updated to be in the Exclusive"
"\n\t\tstate that allows stores to the cache line.",
},
{
.ctrnum = 129,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DTLB2_WRITES",
.desc = "A translation has been written into The Translation"
"\n\t\tLookaside Buffer 2 (TLB2) and the request was made"
"\n\t\tby the Level-1 Data cache. This is a replacement"
"\n\t\tfor what was provided for the DTLB on z13 and prior"
"\n\t\tmachines.",
},
{
.ctrnum = 130,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DTLB2_MISSES",
.desc = "A TLB2 miss is in progress for a request made by"
"\n\t\tthe Level-1 Data cache. Incremented by one for"
"\n\t\tevery TLB2 miss in progress for the Level-1 Data"
"\n\t\tcache on this cycle. This is a replacement for what"
"\n\t\twas provided for the DTLB on z13 and prior"
"\n\t\tmachines.",
},
{
.ctrnum = 131,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "CRSTE_1MB_WRITES",
.desc = "A translation entry was written into the Combined"
"\n\t\tRegion and Segment Table Entry array in the Level-2"
"\n\t\tTLB for a one-megabyte page.",
},
{
.ctrnum = 132,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DTLB2_GPAGE_WRITES",
.desc = "A translation entry for a two-gigabyte page was"
"\n\t\twritten into the Level-2 TLB.",
},
{
.ctrnum = 134,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ITLB2_WRITES",
.desc = "A translation entry has been written into the"
"\n\t\tTranslation Lookaside Buffer 2 (TLB2) and the"
"\n\t\trequest was made by the Level-1 Instruction cache."
"\n\t\tThis is a replacement for what was provided for the"
"\n\t\tITLB on z13 and prior machines.",
},
{
.ctrnum = 135,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ITLB2_MISSES",
.desc = "A TLB2 miss is in progress for a request made by"
"\n\t\tthe Level-1 Instruction cache. Incremented by one"
"\n\t\tfor every TLB2 miss in progress for the Level-1"
"\n\t\tInstruction cache in a cycle. This is a replacement"
"\n\t\tfor what was provided for the ITLB on z13 and prior"
"\n\t\tmachines.",
},
{
.ctrnum = 137,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TLB2_PTE_WRITES",
.desc = "A translation entry was written into the Page Table"
"\n\t\tEntry array in the Level-2 TLB.",
},
{
.ctrnum = 138,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TLB2_CRSTE_WRITES",
.desc = "Translation entries were written into the Combined"
"\n\t\tRegion and Segment Table Entry array and the Page"
"\n\t\tTable Entry array in the Level-2 TLB.",
},
{
.ctrnum = 139,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TLB2_ENGINES_BUSY",
.desc = "The number of Level-2 TLB translation engines busy"
"\n\t\tin a cycle.",
},
{
.ctrnum = 140,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TX_C_TEND",
.desc = "A TEND instruction has completed in a constrained"
"\n\t\ttransactional-execution mode.",
},
{
.ctrnum = 141,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TX_NC_TEND",
.desc = "A TEND instruction has completed in a non-"
"\n\t\tconstrained transactional-execution mode.",
},
{
.ctrnum = 143,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "L1C_TLB2_MISSES",
.desc = "Increments by one for any cycle where a Level-1"
"\n\t\tcache or Level-2 TLB miss is in progress.",
},
{
.ctrnum = 145,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_REQ",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache.",
},
{
.ctrnum = 146,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_REQ_IV",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache with"
"\n\t\tintervention.",
},
{
.ctrnum = 147,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_REQ_CHIP_HIT",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache after using"
"\n\t\tchip level horizontal persistence, Chip-HP hit.",
},
{
.ctrnum = 148,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_REQ_DRAWER_HIT",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache after using"
"\n\t\tdrawer level horizontal persistence, Drawer-HP hit.",
},
{
.ctrnum = 149,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_CHIP",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache.",
},
{
.ctrnum = 150,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_CHIP_IV",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache with intervention.",
},
{
.ctrnum = 151,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_CHIP_CHIP_HIT",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache after using chip"
"\n\t\tlevel horizontal persistence, Chip-HP hit.",
},
{
.ctrnum = 152,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_CHIP_DRAWER_HIT",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache after using drawer"
"\n\t\tlevel horizontal persistence, Drawer-HP hit.",
},
{
.ctrnum = 153,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_MODULE",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Module Level-2 cache.",
},
{
.ctrnum = 154,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_DRAWER",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Drawer Level-2 cache.",
},
{
.ctrnum = 155,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_OFF_DRAWER",
.desc = "A directory write to the Level-1 Data cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an Off-Drawer Level-2 cache.",
},
{
.ctrnum = 156,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_CHIP_MEMORY",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from On-Chip memory.",
},
{
.ctrnum = 157,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_MODULE_MEMORY",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from On-Module memory.",
},
{
.ctrnum = 158,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_ON_DRAWER_MEMORY",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from On-Drawer memory.",
},
{
.ctrnum = 159,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DCW_OFF_DRAWER_MEMORY",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from Off-Drawer memory.",
},
{
.ctrnum = 160,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_MODULE_IV",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Module Level-2"
"\n\t\tcache with intervention.",
},
{
.ctrnum = 161,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_MODULE_CHIP_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Module Level-2"
"\n\t\tcache after using chip level horizontal"
"\n\t\tpersistence, Chip-HP hit.",
},
{
.ctrnum = 162,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_MODULE_DRAWER_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Module Level-2"
"\n\t\tcache after using drawer level horizontal"
"\n\t\tpersistence, Drawer-HP hit.",
},
{
.ctrnum = 163,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_DRAWER_IV",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Drawer Level-2"
"\n\t\tcache with intervention.",
},
{
.ctrnum = 164,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_DRAWER_CHIP_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tinstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Drawer Level-2"
"\n\t\tcache after using chip level horizontal"
"\n\t\tpersistence, Chip-HP hit.",
},
{
.ctrnum = 165,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_ON_DRAWER_DRAWER_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tinstruction cache directory where the returned"
"\n\t\tcache line was sourced from an On-Drawer Level-2"
"\n\t\tcache after using drawer level horizontal"
"\n\t\tpersistence, Drawer-HP hit.",
},
{
.ctrnum = 166,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_OFF_DRAWER_IV",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tinstruction cache directory where the returned"
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
"\n\t\tcache with intervention.",
},
{
.ctrnum = 167,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_OFF_DRAWER_CHIP_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tinstruction cache directory where the returned"
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
"\n\t\tcache after using chip level horizontal"
"\n\t\tpersistence, Chip-HP hit.",
},
{
.ctrnum = 168,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "IDCW_OFF_DRAWER_DRAWER_HIT",
.desc = "A directory write to the Level-1 Data or Level-1"
"\n\t\tInstruction cache directory where the returned"
"\n\t\tcache line was sourced from an Off-Drawer Level-2"
"\n\t\tcache after using drawer level horizontal"
"\n\t\tpersistence, Drawer-HP hit.",
},
{
.ctrnum = 169,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_REQ",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tthe requestors Level-2 cache.",
},
{
.ctrnum = 170,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_REQ_IV",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache with"
"\n\t\tintervention.",
},
{
.ctrnum = 171,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_REQ_CHIP_HIT",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache after using"
"\n\t\tchip level horizontal persistence, Chip-HP hit.",
},
{
.ctrnum = 172,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_REQ_DRAWER_HIT",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom the requestors Level-2 cache after using"
"\n\t\tdrawer level horizontal persistence, Drawer-HP hit.",
},
{
.ctrnum = 173,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_CHIP",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache.",
},
{
.ctrnum = 174,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_CHIP_IV",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache with intervention.",
},
{
.ctrnum = 175,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_CHIP_CHIP_HIT",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip Level-2 cache after using chip"
"\n\t\tlevel horizontal persistence, Chip-HP hit.",
},
{
.ctrnum = 176,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_CHIP_DRAWER_HIT",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Chip level 2 cache after using drawer"
"\n\t\tlevel horizontal persistence, Drawer-HP hit.",
},
{
.ctrnum = 177,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_MODULE",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Module Level-2 cache.",
},
{
.ctrnum = 178,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_ON_DRAWER",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an On-Drawer Level-2 cache.",
},
{
.ctrnum = 179,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "ICW_OFF_DRAWER",
.desc = "A directory write to the Level-1 Instruction cache"
"\n\t\tdirectory where the returned cache line was sourced"
"\n\t\tfrom an Off-Drawer Level-2 cache.",
},
{
.ctrnum = 202,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "CYCLES_SAMETHRD",
.desc = "The number of cycles the CPU is not in wait state"
"\n\t\tand the CPU is running by itself on the Core.",
},
{
.ctrnum = 203,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "CYCLES_DIFFTHRD",
.desc = "The number of cycles the CPU is not in wait state"
"\n\t\tand the CPU is running with another thread on the"
"\n\t\tCore.",
},
{
.ctrnum = 204,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "INST_SAMETHRD",
.desc = "The number of instructions executed on the CPU and"
"\n\t\tthe CPU is running by itself on the Core.",
},
{
.ctrnum = 205,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "INST_DIFFTHRD",
.desc = "The number of instructions executed on the CPU and"
"\n\t\tthe CPU is running with another thread on the Core.",
},
{
.ctrnum = 206,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "WRONG_BRANCH_PREDICTION",
.desc = "A count of the number of branches that were"
"\n\t\tpredicted incorrectly by the branch prediction"
"\n\t\tlogic in the Core. This includes incorrectly"
"\n\t\tpredicted branches that are executed in Firmware."
"\n\t\tExamples of instructions implemented in Firmware"
"\n\t\tare complicated instructions like MVCL (Move"
"\n\t\tCharacter Long) and PC (Program Call).",
},
{
.ctrnum = 225,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "VX_BCD_EXECUTION_SLOTS",
.desc = "Count of floating point execution slots used for"
"\n\t\tfinished vector arithmetic Binary Coded Decimal"
"\n\t\tinstructions. Instructions: VAP, VSP, VMP, VMSP,"
"\n\t\tVDP, VSDP, VRP, VLIP, VSRP, VPSOP, VCP, VTP, VPKZ,"
"\n\t\tVUPKZ, VCVB, VCVBG, VCVD, VCVDG, VSCHP, VSCSHP,"
"\n\t\tVCSPH, VCLZDP, VPKZR, VSRPR, VUPKZH, VUPKZL, VTZ,"
"\n\t\tVUPH, VUPL, VCVBX, VCVDX.",
},
{
.ctrnum = 226,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DECIMAL_INSTRUCTIONS",
.desc = "Decimal instruction dispatched. Instructions: CVB,"
"\n\t\tCVD, AP, CP, DP, ED, EDMK, MP, SRP, SP, ZAP, TP.",
},
{
.ctrnum = 232,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "LAST_HOST_TRANSLATIONS",
.desc = "Last Host Translation done.",
},
{
.ctrnum = 244,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TX_NC_TABORT",
.desc = "A transaction abort has occurred in a non-"
"\n\t\tconstrained transactional-execution mode.",
},
{
.ctrnum = 245,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TX_C_TABORT_NO_SPECIAL",
.desc = "A transaction abort has occurred in a constrained"
"\n\t\ttransactional-execution mode and the CPU is not"
"\n\t\tusing any special logic to allow the transaction to"
"\n\t\tcomplete.",
},
{
.ctrnum = 246,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "TX_C_TABORT_SPECIAL",
.desc = "A transaction abort has occurred in a constrained"
"\n\t\ttransactional-execution mode and the CPU is using"
"\n\t\tspecial logic to allow the transaction to complete.",
},
{
.ctrnum = 248,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DFLT_ACCESS",
.desc = "Cycles CPU spent obtaining access to Deflate unit.",
},
{
.ctrnum = 253,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DFLT_CYCLES",
.desc = "Cycles CPU is using Deflate unit.",
},
{
.ctrnum = 256,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "SORTL",
.desc = "Increments by one for every SORT LISTS (SORTL)"
"\n\t\tinstruction executed.",
},
{
.ctrnum = 265,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DFLT_CC",
.desc = "Increments by one for every DEFLATE CONVERSION CALL"
"\n\t\t(DFLTCC) instruction executed.",
},
{
.ctrnum = 266,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "DFLT_CCFINISH",
.desc = "Increments by one for every DEFLATE CONVERSION CALL"
"\n\t\t(DFLTCC) instruction executed that ended in"
"\n\t\tCondition Codes 0, 1 or 2.",
},
{
.ctrnum = 267,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_INVOCATIONS",
.desc = "Increments by one for every NEURAL NETWORK"
"\n\t\tPROCESSING ASSIST (NNPA) instruction executed.",
},
{
.ctrnum = 268,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_COMPLETIONS",
.desc = "Increments by one for every NEURAL NETWORK"
"\n\t\tPROCESSING ASSIST (NNPA) instruction executed that"
"\n\t\tended in Condition Code 0.",
},
{
.ctrnum = 269,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_WAIT_LOCK",
.desc = "Cycles CPU spent obtaining access to IBM Z"
"\n\t\tIntegrated Accelerator for AI.",
},
{
.ctrnum = 270,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_HOLD_LOCK",
.desc = "Cycles CPU is using IBM Z Integrated Accelerator"
"\n\t\tfor AI.",
},
{
.ctrnum = 272,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_INST_ONCHIP",
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
"\n\t\tinstruction has used the Local On-Chip IBM Z"
"\n\t\tIntegrated Accelerator for AI during its execution",
},
{
.ctrnum = 273,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_INST_OFFCHIP",
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
"\n\t\tinstruction has used an Off-Chip IBM Z Integrated"
"\n\t\tAccelerator for AI during its execution.",
},
{
.ctrnum = 274,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_INST_DIFF",
.desc = "A NEURAL NETWORK PROCESSING ASSIST (NNPA)"
"\n\t\tinstruction has used a different IBM Z Integrated"
"\n\t\tAccelerator for AI since it was last executed.",
},
{
.ctrnum = 276,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_4K_PREFETCH",
.desc = "Number of 4K prefetches done for a remote IBM Z"
"\n\t\tIntegated Accelerator for AI.",
},
{
.ctrnum = 277,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_COMPL_LOCK",
.desc = "A PERFORM LOCKED OPERATION (PLO) has completed.",
},
{
.ctrnum = 278,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_RETRY_LOCK",
.desc = "A PERFORM LOCKED OPERATION (PLO) has been retried and"
"\n\t\tthe CPU did not use any special logic to allow the"
"\n\t\tPLO to complete.",
},
{
.ctrnum = 279,
.ctrset = CPUMF_CTRSET_EXTENDED,
.name = "NNPA_RETRY_LOCK_WITH_PLO",
.desc = "A PERFORM LOCKED OPERATION (PLO) has been retried and"
"\n\t\tthe CPU is using special logic to allow PLO to"
"\n\t\tcomplete.",
},
{
.ctrnum = 448,
.ctrset = CPUMF_CTRSET_MT_DIAG,
.name = "MT_DIAG_CYCLES_ONE_THR_ACTIVE",
.desc = "Cycle count with one thread active",
},
{
.ctrnum = 449,
.ctrset = CPUMF_CTRSET_MT_DIAG,
.name = "MT_DIAG_CYCLES_TWO_THR_ACTIVE",
.desc = "Cycle count with two threads active",
},
};
/* Return the type number of the CPU Measurement facility from the sysfs file.
* If the type number is equal to PERF_TYPE_RAW, then the prefix is 'r' to
* specify the raw counter number by the perf tool.
@@ -3476,6 +4104,12 @@ static struct counters *get_counter(int ctrset, size_t *len)
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
cp = cpumcf_z16_counters;
*len = ARRAY_SIZE(cpumcf_z16_counters);
break;
case UTIL_ARCH_MACHINE_TYPE_Z17:
case UTIL_ARCH_MACHINE_TYPE_Z17_2:
cp = cpumcf_z17_counters;
*len = ARRAY_SIZE(cpumcf_z17_counters);
break;
}
break;
}

View File

@@ -1,4 +1,4 @@
/* Copyright IBM Corp. 2021
/* Copyright IBM Corp. 2021, 2024
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -37,8 +37,9 @@
#include "lib/util_base.h"
#include "lib/util_path.h"
#include "lib/util_scandir.h"
#include "lib/util_libc.h"
#include "lib/util_str.h"
#include "lib/util_file.h"
#include "lib/util_fmt.h"
#include "lib/libcpumf.h"
#include "lshwc.h"
@@ -51,18 +52,92 @@
static unsigned int read_interval = IOCTLSLEEP;
static int cfvn, csvn, authorization;
static unsigned long loop_count = 1;
static unsigned long loop_count = 1, timeout;
static unsigned char *ioctlbuffer;
static bool allcpu;
static char *ctrformat = "%ld";
static bool shortname;
static bool hideundef;
static bool delta, firstread;
static int output_format = FMT_CSV;
static bool quote_all;
static char *ctrlist; /* Comma separated list of counter to extract */
static unsigned int max_possible_cpus; /* No of possible CPUs */
static struct ctrname { /* List of defined counters */
char *name; /* Counter name */
char *label; /* Output name */
bool hitcnt; /* Counter number read from ioctl() */
unsigned long total; /* Total counter value */
unsigned long *ccv; /* Per CPU counter value */
unsigned long *ccvprv; /* Per CPU counter value (previous read) */
} ctrname[MAXCTRS];
struct time_formats {
char epoch[32];
char date_time[32];
char date[16];
char time[16];
};
static void mk_labels(void)
{
char label[64];
size_t i;
for (i = 0; i < ARRAY_SIZE(ctrname); ++i) {
if (shortname) {
if (ctrname[i].name)
snprintf(label, sizeof(label), "%s", ctrname[i].name);
else
snprintf(label, sizeof(label), "U%ld", i);
} else {
if (output_format == FMT_CSV)
snprintf(label, sizeof(label), "%s(%ld)",
ctrname[i].name ?: "Counter", i);
else if (ctrname[i].name)
snprintf(label, sizeof(label), "%s", ctrname[i].name);
else
label[0] = 0;
}
if (output_format != FMT_CSV)
util_str_tolower(label);
ctrname[i].label = util_strdup(label);
}
}
static char *mk_name(int ctr, char *name)
{
char ctrset[8];
if (!shortname)
return util_strdup(name);
switch (libcpumf_ctrset(ctr, cfvn, csvn)) {
case CPUMF_CTRSET_BASIC:
ctrset[0] = 'B';
break;
case CPUMF_CTRSET_PROBLEM_STATE:
ctrset[0] = 'P';
break;
case CPUMF_CTRSET_CRYPTO:
ctrset[0] = 'C';
break;
case CPUMF_CTRSET_EXTENDED:
ctrset[0] = 'E';
break;
case CPUMF_CTRSET_MT_DIAG:
ctrset[0] = 'M';
break;
default:
ctrset[0] = 'U';
break;
}
sprintf(ctrset, "%c%d", ctrset[0], ctr);
return util_strdup(ctrset);
}
static bool read_counternames(void)
{
struct dirent **namelist = NULL;
@@ -77,9 +152,11 @@ static bool read_counternames(void)
return false;
}
for (i = 0; i < count && ctr >= 0; i++) {
if (!ctr_in_list(namelist[i]->d_name, ctrlist))
continue;
util_asprintf(&ctrpath, "%s/%s", path, namelist[i]->d_name);
if (util_file_read_va(ctrpath, "event=%x", &ctr) == 1)
ctrname[ctr].name = util_strdup(namelist[i]->d_name);
ctrname[ctr].name = mk_name(ctr, namelist[i]->d_name);
else
warnx("Cannot parse %s", ctrpath);
free(ctrpath);
@@ -93,7 +170,9 @@ static void free_counternames(void)
{
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
free(ctrname[i].name);
free(ctrname[i].label);
free(ctrname[i].ccv);
free(ctrname[i].ccvprv);
}
}
@@ -298,77 +377,111 @@ static bool check_setpossible(void)
return true;
}
static void show_header(void)
static void safe_strtime(char *dest, size_t size, const char *fmt, const struct tm *tm)
{
static bool header;
bool comma = false;
if (header)
return; /* Printed already */
printf("Date,Time,CPU,"); /* Print counter name and number */
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
if (!ctrname[i].hitcnt)
continue;
if (comma)
putchar(',');
printf("%s(%ld)", ctrname[i].name ?: "Counter", i);
comma = true;
}
putchar('\n');
header = true;
if (!strftime(dest, size, fmt, tm))
dest[0] = 0;
}
static void line(char *header)
static void generate_timestamp(struct time_formats *date)
{
bool comma;
time_t now = time(NULL);
struct tm *now_tm = localtime(&now);
show_header();
if (allcpu) {
for (unsigned int h = 0; h < max_possible_cpus; ++h) {
char txt[16];
safe_strtime(date->date_time, sizeof(date->date_time), "%F %T%z", now_tm);
safe_strtime(date->date, sizeof(date->date), "%F", now_tm);
safe_strtime(date->time, sizeof(date->time), "%T", now_tm);
safe_strtime(date->epoch, sizeof(date->epoch), "%s", now_tm);
}
if (!check[h].cpu_hit)
continue;
comma = false;
snprintf(txt, sizeof(txt), "CPU%d,", h);
printf("%s%s", header, txt);
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
if (!ctrname[i].hitcnt)
continue;
if (comma)
putchar(',');
printf("%ld", ctrname[i].ccv[h]);
comma = true;
}
putchar('\n');
}
static void output_times(struct time_formats date)
{
if (output_format == FMT_CSV) {
util_fmt_pair(FMT_PERSIST, "Date", "%s", date.date);
util_fmt_pair(FMT_PERSIST, "Time", "%s", date.time);
} else {
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "date_time", "%s", date.date_time);
util_fmt_pair(FMT_PERSIST, "time_epoch", "%s", date.epoch);
}
}
/* Print total count of all CPUs */
printf("%sTotal,", header);
comma = false;
static void prepare_counter(size_t id, unsigned long value)
{
if (output_format == FMT_CSV) {
util_fmt_pair(FMT_PERSIST, ctrname[id].label, ctrformat, value);
} else {
util_fmt_obj_start(FMT_ROW, NULL);
if (strlen(ctrname[id].label))
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "name", ctrname[id].label);
util_fmt_pair(FMT_PERSIST, "id", ctrformat, id);
util_fmt_pair(FMT_PERSIST, "value", ctrformat, value);
util_fmt_obj_end();
}
}
static void output_per_cpu(struct time_formats date)
{
for (unsigned int h = 0; h < max_possible_cpus; ++h) {
if (!check[h].cpu_hit)
continue;
char txt[16];
snprintf(txt, sizeof(txt), "CPU%d", h);
util_fmt_obj_start(FMT_ROW, "cpu_%d", h);
output_times(date);
if (output_format == FMT_CSV) {
util_fmt_pair(FMT_PERSIST, "CPU", "CPU%d", h);
} else {
util_fmt_pair(FMT_PERSIST, "cpu", "%d", h);
util_fmt_obj_start(FMT_LIST, "counters");
}
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
if (!ctrname[i].hitcnt)
continue;
if (hideundef && !ctrname[i].name)
continue;
prepare_counter(i, ctrname[i].ccv[h]);
}
if (output_format != FMT_CSV)
util_fmt_obj_end();
util_fmt_obj_end();
}
}
static void output_total(struct time_formats date)
{
util_fmt_obj_start(FMT_ROW, "total");
output_times(date);
if (output_format == FMT_CSV) {
util_fmt_pair(FMT_PERSIST, "CPU", "%s", delta && !firstread ? "Delta" : "Total");
} else {
util_fmt_pair(FMT_PERSIST | FMT_QUOTE, "cpu", "%s",
delta && !firstread ? "delta" : "total");
util_fmt_obj_start(FMT_LIST, "counters");
}
for (size_t i = 0; i < ARRAY_SIZE(ctrname); ++i) {
if (!ctrname[i].hitcnt)
continue;
if (comma)
putchar(',');
printf("%ld", ctrname[i].total);
comma = true;
if (hideundef && !ctrname[i].name)
continue;
prepare_counter(i, ctrname[i].total);
ctrname[i].total = 0;
ctrname[i].hitcnt = false;
}
putchar('\n');
if (output_format != FMT_CSV)
util_fmt_obj_end();
util_fmt_obj_end();
}
static void show(void)
static void show_format(void)
{
time_t now = time(NULL);
struct tm *now_tm;
char now_text[32];
struct time_formats now;
now_tm = localtime(&now);
strftime(now_text, sizeof(now_text), "%F,%T,", now_tm);
line(now_text);
generate_timestamp(&now);
if (allcpu)
output_per_cpu(now);
output_total(now);
}
/* Return Counter set size numbers (in counters) */
@@ -442,11 +555,18 @@ static bool add_countervalue(size_t idx, unsigned int cpu, unsigned long value)
warnx("Invalid CPU number %d", cpu);
return false;
}
if (!ctrname[idx].ccv) /* Unknown counter */
ctrname[idx].ccv = calloc(max_possible_cpus,
sizeof(unsigned long));
if (ctrname[idx].ccv)
if (delta) {
if (firstread) {
ctrname[idx].ccvprv[cpu] = value;
ctrname[idx].ccv[cpu] = value;
} else {
ctrname[idx].ccv[cpu] = value - ctrname[idx].ccvprv[cpu];
ctrname[idx].ccvprv[cpu] = value;
value = ctrname[idx].ccv[cpu];
}
} else {
ctrname[idx].ccv[cpu] = value;
}
ctrname[idx].total += value;
ctrname[idx].hitcnt = true;
return true;
@@ -493,7 +613,8 @@ static int test_read(struct s390_hwctr_read *read)
}
}
}
show();
show_format();
firstread = false;
return 0;
}
@@ -556,6 +677,7 @@ static void do_sleep(void)
static int do_it(char *s)
{
struct s390_hwctr_start start;
unsigned int flags = FMT_WARN;
int ioctlfd;
int rc;
@@ -575,6 +697,24 @@ static int do_it(char *s)
return EXIT_FAILURE;
}
if (output_format == FMT_CSV)
flags |= FMT_NOMETA;
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ)
flags |= FMT_HANDLEINT;
if (quote_all)
flags |= FMT_QUOTEALL;
mk_labels();
util_fmt_init(stdout, output_format, flags, 1);
util_fmt_obj_start(FMT_DEFAULT, "lshwc");
if (output_format == FMT_JSON || output_format == FMT_JSONSEQ) {
util_fmt_obj_start(FMT_ROW, "cpumcf info");
util_fmt_pair(FMT_PERSIST, "counter first", "%d", cfvn);
util_fmt_pair(FMT_PERSIST, "counter second", "%d", csvn);
util_fmt_pair(FMT_PERSIST, "authorization", "%d", authorization);
util_fmt_obj_end();
}
util_fmt_obj_start(FMT_LIST, "measurements");
for (unsigned long i = 0; !rc && i < loop_count; ++i) {
rc = do_read(ioctlfd);
if (rc) {
@@ -584,6 +724,9 @@ static int do_it(char *s)
if (read_interval && i + 1 < loop_count)
do_sleep();
}
util_fmt_obj_end();
util_fmt_obj_end();
util_fmt_exit();
rc = do_stop(ioctlfd);
close(ioctlfd);
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
@@ -605,6 +748,46 @@ static struct util_opt opt_vec[] = {
.argument = "NUMBER",
.desc = "Specifies interval between read operations (seconds)"
},
{
.option = { "short", no_argument, NULL, 's' },
.desc = "Abbreviate counter name with counter set letter and number"
},
{
.option = { "hex0x", no_argument, NULL, 'X' },
.desc = "Counter values in hexadecimal format with leading 0x"
},
{
.option = { "hex", no_argument, NULL, 'x' },
.desc = "Counter values in hexadecimal format"
},
{
.option = { "hide", no_argument, NULL, 'H' },
.desc = "Do not display undefined counters of a counter set"
},
{
.option = { "delta", no_argument, NULL, 'd' },
.desc = "Display delta counter values"
},
{
.option = { "timeout", required_argument, NULL, 't' },
.argument = "NUMBER",
.desc = "run time in s (seconds) m (minutes) h (hours) and d (days)"
},
{
.option = { "quote-all", no_argument, NULL, 'q' },
.desc = "Apply quoting to all output elements"
},
{
.option = { "format", required_argument, NULL, 'f' },
.argument = "FORMAT",
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
},
{
.option = { "counters", required_argument, NULL, 'c' },
.argument = "LIST",
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "Specify comma separated list of counters to display"
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
@@ -634,6 +817,8 @@ static void have_support(void)
int main(int argc, char **argv)
{
enum util_fmt_t fmt;
unsigned long no;
char *slash;
int ch;
@@ -665,12 +850,71 @@ int main(int argc, char **argv)
if (errno || *slash)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
break;
case 'H':
hideundef = true;
break;
case 's':
shortname = true;
break;
case 'x':
ctrformat = "%lx";
break;
case 'X':
ctrformat = "%#lx";
break;
case 'a':
allcpu = true;
break;
case 'd':
delta = true;
firstread = true;
break;
case 't':
errno = 0;
no = strtoul(optarg, &slash, 0);
if (errno)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
switch (*slash) {
case 's':
case '\0':
timeout += no;
break;
case 'm':
timeout += no * 60;
break;
case 'h':
timeout += no * 60 * 60;
break;
case 'd':
timeout += no * 60 * 60 * 24;
break;
default:
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
break;
}
break;
case 'q':
quote_all = true;
break;
case 'f':
if (!util_fmt_name_to_type(optarg, &fmt))
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
output_format = fmt;
break;
case 'c':
hideundef = true;
ctrlist = util_strdup(optarg);
util_str_rm_whitespace(optarg, ctrlist);
util_str_toupper(ctrlist);
break;
}
}
if (timeout && timeout < read_interval)
read_interval = timeout;
/* If no timeout specified, simply add zero */
loop_count += timeout / read_interval;
have_support();
if (!libcpumf_cpumcf_info(&cfvn, &csvn, &authorization))
return EXIT_FAILURE;
@@ -681,6 +925,11 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
for (unsigned int i = 0; i < ARRAY_SIZE(ctrname); ++i) {
ctrname[i].ccv = util_zalloc(max_possible_cpus * sizeof(unsigned long));
ctrname[i].ccvprv = util_zalloc(max_possible_cpus * sizeof(unsigned long));
}
if (optind >= argc) {
ch = do_it(NULL);
} else {
@@ -692,5 +941,7 @@ int main(int argc, char **argv)
}
free_counternames();
free(check);
free(ioctlbuffer);
free(ctrlist);
return ch;
}

View File

@@ -6,7 +6,6 @@
/* List available Processor Assist Instrumentation (PAI) counters. */
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
@@ -17,29 +16,84 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <linux/perf_event.h>
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_base.h"
#include "lib/util_path.h"
#include "lib/util_scandir.h"
#include "lib/util_libc.h"
#include "lib/util_file.h"
#include "lib/util_fmt.h"
#include "lib/util_libc.h"
#include "lib/util_list.h"
#include "lib/util_opt.h"
#include "lib/util_path.h"
#include "lib/util_prg.h"
#include "lib/util_scandir.h"
#include "lib/util_str.h"
#include "lib/libcpumf.h"
#define STR_SUB(x) #x
#define STR(x) STR_SUB(x)
#define OPT_FORMAT 256 /* --format XXX option */
#define DEFAULT_LOOP_INTERVAL 60 /* loop interval in seconds */
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "all", no_argument, NULL, 'a' },
.desc = "Displays all CPUs in output"
},
{
.option = { "delta", no_argument, NULL, 'd' },
.desc = "Display delta counter values"
},
{
.option = { "counters", required_argument, NULL, 'c' },
.argument = "LIST",
.desc = "Specify comma separated list of counters to display"
},
{
.option = { "format", required_argument, NULL, OPT_FORMAT },
.argument = "FORMAT",
.flags = UTIL_OPT_FLAG_NOSHORT,
.desc = "List counters in specified FORMAT (" FMT_TYPE_NAMES ")"
},
{
.option = { "loops", required_argument, NULL, 'l' },
.argument = "COUNT",
.desc = "Number of read operations"
},
{
.option = { "interval", required_argument, NULL, 'i' },
.argument = "SECONDS",
.desc = "Time to wait between loop iterations (default "
STR(DEFAULT_LOOP_INTERVAL) "s)"
},
{
.option = { "numeric", no_argument, NULL, 'n' },
.desc = "Sort PAI counters by counter number"
},
{
.option = { "short", no_argument, NULL, 's' },
.desc = "Abbreviate counter name with counter set letter and number"
},
{
.option = { "type", required_argument, NULL, 't' },
.argument = "TYPE",
.desc = "Type of PAI counters to show: crypto, nnpa"
},
{
.option = { "hex0x", no_argument, NULL, 'X' },
.desc = "Counter values in hexadecimal format with leading 0x"
},
{
.option = { "hex", no_argument, NULL, 'x' },
.desc = "Counter values in hexadecimal format"
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
@@ -51,13 +105,24 @@ static const struct util_prg prg = {
{
.owner = "IBM Corp.",
.pub_first = 2023,
.pub_last = 2023,
.pub_last = 2025,
},
UTIL_PRG_COPYRIGHT_END
}
};
static bool allcpu; /* Show counter values per CPU */
static bool numsort; /* If true sort counter numerically */
static bool shortname; /* Use abbreviated counter names */
static bool delta, firstread; /* Display delta values */
static int output_format = -1; /* Generate style if >= 0 */
static unsigned int max_cpus; /* # of CPUs to read counter values from */
static unsigned int max_fds; /* # of file descriptor to read counter values */
static unsigned long loops; /* # loops */
static unsigned long read_interval = DEFAULT_LOOP_INTERVAL;
static cpu_set_t cpu_online_mask;
static char *ctrformat = "%ld"; /* Default counter output format */
static char *ctrlist; /* Comma separated list of counter to extract */
#define PAI_PATH "/bus/event_source/devices/%s"
@@ -69,9 +134,18 @@ enum pai_types { /* Bit mask for supported PAI counters */
static int pai_types_show;
struct pai_cpudata { /* Event data per CPU */
int fd; /* Event file descriptor */
int cpu; /* CPU number */
unsigned long value; /* Event value */
unsigned long prev_value; /* Previous value for deltas */
};
struct pai_ctrname { /* List of defined counters */
char *name; /* Counter name */
unsigned long nr; /* Counter number */
unsigned long total; /* Total count on all CPus */
struct pai_cpudata *data; /* Counter data per CPU */
};
struct pai_node { /* Head for PAI counter sets */
@@ -104,6 +178,20 @@ static unsigned long pai_type_base(enum pai_types t)
return 0;
}
/* Return character for this counter set. */
static char pai_type_char(enum pai_types t)
{
switch (t) {
case pai_type_crypto:
return 'C';
case pai_type_nnpa:
return 'N';
case pai_type_max:
break;
}
return 'U';
}
/* Test PAI counter name from command line option. */
static const char *pai_type_name(enum pai_types t)
{
@@ -145,16 +233,6 @@ static int pai_ctrcmp(const void *p1, const void *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.
*/
@@ -162,7 +240,7 @@ static void read_counternames(struct pai_node *node)
{
int i, more = 0, ctr = 0, count = 0;
struct dirent **namelist = NULL;
char *path, *ctrpath;
char *path, *ctrpath, sname[128];
/* Read counter names and assigned event number. */
path = util_path_sysfs(PAI_PATH "/events", node->sysfs_name);
@@ -175,9 +253,18 @@ static void read_counternames(struct pai_node *node)
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) {
snprintf(sname, sizeof(sname), "%c%ld",
pai_type_char(node->type), ctr - node->base);
if (!ctr_in_list(sname, ctrlist) &&
!ctr_in_list(namelist[i]->d_name, ctrlist)) {
/* Counter not listed in --counters option */
continue;
}
node->ctrlist[node->ctridx].data = NULL;
node->ctrlist[node->ctridx].name = util_strdup(namelist[i]->d_name);
node->ctrlist[node->ctridx++].nr = ctr;
more++;
max_fds++;
} else {
warnx("Cannot parse %s", ctrpath);
}
@@ -190,12 +277,47 @@ static void read_counternames(struct pai_node *node)
qsort(node->ctrlist, more, sizeof(*node->ctrlist), pai_ctrcmp);
}
static void show_painode(void)
static void format_painode(enum util_fmt_t fmt)
{
struct pai_node *node;
util_fmt_init(stdout, fmt, FMT_HANDLEINT, 1);
util_fmt_obj_start(FMT_DEFAULT, NULL);
util_list_iterate(&pai_list, node) {
util_fmt_obj_start(FMT_DEFAULT, "pmu");
util_fmt_pair(FMT_PERSIST, "base", "%d", node->base);
util_fmt_pair(FMT_PERSIST, "type", "%d", node->pmu);
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "pmu-name", "%s", node->sysfs_name);
util_fmt_obj_start(FMT_LIST, "counters");
for (int i = 0; i < node->ctridx; ++i) {
util_fmt_obj_start(FMT_ROW, "counter");
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
if (shortname)
util_fmt_pair(FMT_QUOTE, "name", "%c%d",
pai_type_char(node->type),
node->ctrlist[i].nr - node->base);
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
util_fmt_obj_end();
}
util_fmt_obj_end(); /* Counters */
util_fmt_obj_end(); /* PMU */
}
util_fmt_obj_end();
util_fmt_exit();
}
static void list_painode(void)
{
struct pai_node *node;
int indent = 0;
int offset = 0;
if (output_format != -1) {
format_painode(output_format);
return;
}
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i)
indent = MAX((size_t)indent, strlen(node->ctrlist[i].name));
@@ -223,8 +345,10 @@ static void free_painode(void)
util_list_iterate_safe(&pai_list, node, next) {
free(node->name_uc);
for (int i = 0; i < node->ctridx; ++i)
for (int i = 0; i < node->ctridx; ++i) {
free(node->ctrlist[i].name);
free(node->ctrlist[i].data);
}
free(node->ctrlist);
free(node);
}
@@ -238,12 +362,13 @@ static void make_painode(enum pai_types t)
node->type = t;
node->sysfs_name = pai_type_sysfs(t);
node->name = pai_type_name(t);
node->name_uc = str2uc(node->name);
node->name_uc = util_strdup(node->name);
util_str_toupper(node->name_uc);
node->filter_name = pai_type_filter(t);
node->base = pai_type_base(t);
/* Read PMU type number. */
path = util_path_sysfs(PAI_PATH, node->sysfs_name);
util_asprintf(&path, PAI_PATH, node->sysfs_name);
node->pmu = libcpumf_pmutype(path);
if (node->pmu < 0)
errx(EXIT_FAILURE, "Cannot open %s", path);
@@ -267,6 +392,267 @@ static void sort_painode(void)
util_list_sort(&pai_list, painode_cmp, NULL);
}
/* Read counter value. */
static unsigned long event_read(int fd)
{
unsigned long count;
int rc;
rc = read(fd, &count, sizeof(count));
if (rc != sizeof(count))
err(EXIT_FAILURE, "Failed to read counter value");
return count;
}
/* Write header. */
static void line_header(void)
{
struct pai_node *node;
static bool header;
bool comma = false;
if (header)
return; /* Printed already */
printf("Date,Time,CPU,"); /* Print counter name and number */
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
if (comma)
putchar(',');
if (shortname) {
printf("%c%ld", pai_type_char(node->type),
node->ctrlist[i].nr - node->base);
} else {
printf("%s(%ld)", node->ctrlist[i].name ?: node->name_uc,
node->ctrlist[i].nr - node->base);
}
comma = true;
}
}
putchar('\n');
header = true;
}
/* Print CPU specific counter values. */
static void line_cpu(char *header)
{
struct pai_cpudata *data;
struct pai_node *node;
bool comma;
char txt[16];
for (unsigned int h = 0; h < max_cpus; ++h) {
comma = false;
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
data = &node->ctrlist[i].data[h];
if (!comma) {
snprintf(txt, sizeof(txt), "CPU%d,", data->cpu);
printf("%s,%s", header, txt);
} else {
putchar(',');
}
printf(ctrformat, data->value);
comma = true;
}
}
putchar('\n');
}
}
/* Write an output line. */
static void line_out(char *header)
{
struct pai_node *node;
bool comma;
line_header();
if (allcpu)
line_cpu(header);
/* Print total count of all CPUs */
printf("%s,%s,", header, delta && !firstread ? "Delta" : "Total");
comma = false;
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
if (comma)
putchar(',');
printf(ctrformat, node->ctrlist[i].total);
comma = true;
}
}
putchar('\n');
}
/* Write a formatted line. */
static void format_line_out(time_t now, char *now_text)
{
static unsigned int called;
struct pai_node *node;
char cpuid[16];
if (!called) {
util_fmt_init(stdout, output_format, FMT_DEFAULT | FMT_HANDLEINT, 1);
util_fmt_obj_start(FMT_DEFAULT, NULL);
util_fmt_obj_start(FMT_LIST, "measurements");
}
util_list_iterate(&pai_list, node) {
if (!node->ctridx) /* Counter set not selected */
continue;
util_fmt_obj_start(FMT_DEFAULT, "entry");
util_fmt_pair(FMT_PERSIST, "iteration", "%d", called++);
util_fmt_pair(FMT_PERSIST, "time_epoch", "%d", now);
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "time", "%s", now_text);
util_fmt_pair(FMT_QUOTE | FMT_PERSIST, "valuetype",
(delta && !firstread) ? "delta" : "total");
util_fmt_obj_start(FMT_LIST, "counters");
for (int i = 0; i < node->ctridx; ++i) {
util_fmt_obj_start(FMT_ROW, "counter");
util_fmt_pair(FMT_QUOTE, "name", "%s", node->ctrlist[i].name);
if (shortname)
util_fmt_pair(FMT_QUOTE, "shortname", "%c%d",
pai_type_char(node->type),
node->ctrlist[i].nr - node->base);
util_fmt_pair(FMT_DEFAULT, "config", "%d", node->ctrlist[i].nr);
util_fmt_pair(FMT_DEFAULT, "id", "%d", node->ctrlist[i].nr - node->base);
util_fmt_pair(FMT_DEFAULT, "value", ctrformat, node->ctrlist[i].total);
if (allcpu) {
for (unsigned int j = 0; j < max_cpus; ++j) {
snprintf(cpuid, sizeof(cpuid), "cpu%d", j);
util_fmt_pair(FMT_DEFAULT, cpuid, ctrformat,
node->ctrlist[i].data[j].value);
}
}
util_fmt_obj_end();
}
util_fmt_obj_end(); /* Counters */
util_fmt_obj_end(); /* Entry */
}
}
/* Terminate formatted output. */
static void format_line_end(void)
{
util_fmt_obj_end(); /* Iteration */
util_fmt_obj_end(); /* Default */
util_fmt_exit();
}
/* Display counter values. */
static void show_values(void)
{
time_t now = time(NULL);
struct tm *now_tm;
char now_text[32];
now_tm = localtime(&now);
if (output_format != -1) {
strftime(now_text, sizeof(now_text), "%F %T%z", now_tm);
format_line_out(now, now_text);
} else {
strftime(now_text, sizeof(now_text), "%F,%T", now_tm);
line_out(now_text);
}
}
/* Read each counter value. */
static void read_painode(void)
{
struct pai_cpudata *data;
struct pai_node *node;
unsigned long value;
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
node->ctrlist[i].total = 0;
for (size_t j = 0; j < max_cpus; ++j) {
data = &node->ctrlist[i].data[j];
value = event_read(data->fd);
if (delta) {
data->value = value - data->prev_value;
data->prev_value = value;
} else {
data->value = value;
}
node->ctrlist[i].total += data->value;
}
}
}
}
static void wait_painode(void)
{
for (unsigned long i = 0; i < loops; ++i) {
read_painode();
show_values();
if (i + 1 < loops)
sleep(read_interval);
firstread = false;
}
format_line_end();
}
/* Install one event. */
static int event_add(int cpu, int idx, struct pai_node *node)
{
struct perf_event_attr attr;
int fd;
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
attr.config = node->ctrlist[idx].nr;
attr.type = node->pmu;
fd = perf_event_open(&attr, -1, cpu, -1, 0);
if (fd == -1)
err(EXIT_FAILURE, "Failed to open perf event: file descriptor not available");
return fd;
}
/* Increase number of file descriptors this process can open. */
static void event_fdlimit(void)
{
unsigned int needed = 3 + max_fds * max_cpus;
struct rlimit rlimit;
if (getrlimit(RLIMIT_NOFILE, &rlimit) == -1)
err(EXIT_FAILURE, "Failed to read RLIMIT_NOFILE");
if (needed > rlimit.rlim_cur)
rlimit.rlim_cur = needed;
if (setrlimit(RLIMIT_NOFILE, &rlimit) == -1)
err(EXIT_FAILURE, "Failed to set RLIMIT_NOFILE");
}
/* Install all events and iterate over requested read operations. */
static void event_painode(void)
{
size_t pai_cpudata_sz = sizeof(struct pai_cpudata) * max_cpus;
struct pai_cpudata *data;
struct pai_node *node;
event_fdlimit();
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
node->ctrlist[i].data = util_malloc(pai_cpudata_sz);
data = node->ctrlist[i].data;
for (unsigned int j = 0; j < CPU_SETSIZE; ++j) {
if (CPU_ISSET(j, &cpu_online_mask)) {
data->cpu = j;
data->fd = event_add(j, i, node);
data->value = 0;
data->prev_value = 0;
++data;
}
}
}
}
wait_painode();
util_list_iterate(&pai_list, node) {
for (int i = 0; i < node->ctridx; ++i) {
for (unsigned int j = 0; j < max_cpus; ++j)
close(node->ctrlist[i].data[j].fd);
}
}
}
/* Check for hardware support and return false if not available. */
static bool have_support(enum pai_types t)
{
@@ -303,8 +689,40 @@ static void check_type_name(const char *type)
errx(EXIT_FAILURE, "Invalid argument for -t %s", type);
}
/*
* Get list of specified CPUs from command line. Check if these CPUs
* exist and are online. Ignore those CPUs which are not available and
* issue one warning when CPUs have been specified but are not online.
*/
static void get_cpulist(char *parm)
{
bool warned = false;
cpu_set_t cpulist;
int i, rc;
CPU_ZERO(&cpulist);
rc = libcpumf_cpuset(parm, &cpulist);
if (rc)
err(EXIT_FAILURE, "Cannot parse cpulist %s", parm);
for (i = 0; i < CPU_SETSIZE; ++i) {
if (CPU_ISSET(i, &cpulist) && !CPU_ISSET(i, &cpu_online_mask)) {
if (!warned) {
warnx("some CPU(s) are offline, ignored");
warned = true;
}
}
if (!CPU_ISSET(i, &cpulist) && CPU_ISSET(i, &cpu_online_mask))
CPU_CLR(i, &cpu_online_mask);
}
}
int main(int argc, char **argv)
{
bool list_only = true;
enum util_fmt_t fmt;
bool i_flag = false;
bool l_flag = false;
char *endchar;
int ch;
util_list_init(&pai_list, struct pai_node, node);
@@ -316,6 +734,15 @@ int main(int argc, char **argv)
default:
util_opt_print_parse_error(ch, argv);
return EXIT_FAILURE;
case 'a':
allcpu = true;
list_only = false;
break;
case 'd':
delta = true;
firstread = true;
list_only = false;
break;
case 'h':
util_prg_print_help();
util_opt_print_help();
@@ -323,16 +750,80 @@ int main(int argc, char **argv)
case 'v':
util_prg_print_version();
return EXIT_SUCCESS;
case 'i':
i_flag = true;
list_only = false;
errno = 0;
read_interval = strtoul(optarg, &endchar, 0);
if (errno || *endchar)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
break;
case 'l':
l_flag = true;
list_only = false;
errno = 0;
loops = strtoul(optarg, &endchar, 0);
if (errno || *endchar)
errx(EXIT_FAILURE, "Invalid argument for -%c", ch);
break;
case 'n':
numsort = true;
break;
case 's':
list_only = false;
shortname = true;
break;
case 't':
check_type_name(optarg);
break;
case 'x':
list_only = false;
ctrformat = "%lx";
break;
case 'X':
list_only = false;
ctrformat = "%#lx";
break;
case OPT_FORMAT:
if (!util_fmt_name_to_type(optarg, &fmt))
errx(EXIT_FAILURE, "Supported formats:" FMT_TYPE_NAMES);
output_format = fmt;
break;
case 'c':
ctrlist = util_strdup(optarg);
util_str_rm_whitespace(optarg, ctrlist);
util_str_toupper(ctrlist);
break;
}
}
/* Nothing specified, show all PAI counters */
if (i_flag && !l_flag) {
util_prg_print_help();
util_opt_print_help();
return EXIT_FAILURE;
}
/*
* Read currently online CPUs and create a bit mask.
* This bitmap of online CPUs is used to check command line parameter
* for valid CPUs
* When any of the flags which set variable list_only to false have
* be specified, lets also show the counter value, not just list them.
*/
if (optind < argc) /* List of CPUs on command line */
list_only = false;
if (!list_only) { /* Show counter values */
ch = libcpumf_cpuset_fn(S390_CPUS_ONLINE, &cpu_online_mask);
if (ch)
err(EXIT_FAILURE, "Cannot read file /sys/" S390_CPUS_ONLINE);
while (optind < argc)
get_cpulist(argv[optind++]);
max_cpus = CPU_COUNT(&cpu_online_mask);
if (!loops)
loops = 1;
}
/* Nothing specified, use all PAI counters */
if (!pai_types_show)
pai_types_show = (1 << pai_type_crypto) | (1 << pai_type_nnpa);
@@ -346,7 +837,12 @@ int main(int argc, char **argv)
}
}
sort_painode();
show_painode();
ch = EXIT_SUCCESS;
if (!list_only)
event_painode();
else
list_painode();
free_painode();
free(ctrlist);
return ch;
}

View File

@@ -17,9 +17,9 @@ chcpumf \- manage the CPU-measurement facilities support
.SH SYNOPSIS
.B chcpumf
.RB [ \-m | \-\-min
.IR num_sdb ]
.IR NUM_SDB ]
.RB [ \-x | \-\-max
.IR num_sdb ]
.IR NUM_SDB ]
.RB [ \-V | \-\-verbose ]
.br
.B chcpumf
@@ -36,14 +36,14 @@ facilities for Linux on System z.
.
.SH OPTIONS
.TP
.BR \-m ", " \-\-min " \fInum_sdb\fP"
.BR \-m ", " \-\-min " \fINUM_SDB\fP"
Specifies the minimum sampling facility buffer size in sample-data-blocks
(SDB). A sample-data-block consumes about 4 kilobytes.
This is the initial buffer size when you start the sampling facility.
.
.TP
.BR \-x ", " \-\-max " \fInum_sdb\fP"
.BR \-x ", " \-\-max " \fINUM_SDB\fP"
Specifies the maximum sampling facility buffer size in sample-data-blocks
(SDB). A sample-data-block consumes about 4 kilobytes.

View File

@@ -50,7 +50,7 @@ counters for which the LPAR is not authorized. For counter measurements with
the perf program, the raw event identifier is displayed.
For Linux version 5.5 and later, the raw event identifier is
displayed as <type>:<number>, where type is an integer that the kernel
assignes to the CPU Measurement counter facility device driver.
assigns to the CPU Measurement counter facility device driver.
For earlier Linux versions the raw event identifier is displayed as r<number>.
.
.TP

View File

@@ -7,19 +7,25 @@
.\" ----------------------------------------------------------------------
.ds c \fBlshwc\fP
.
.TH \*c "8" "May 2022" "s390-tools" "CPU-MF management programs"
.TH \*c "8" "Mar 2025" "s390-tools" "CPU-MF management programs"
.
.SH NAME
lshwc \- extract CPU Measurement Facilities counter sets
.
.SH SYNOPSIS
\*c
.RB [ \-a ]
.RB [ \-a ][ \-d ][ \-H ][ \-s ][ \-x ][ \-X ][ \-q ]
.RB [ \-l
.IR count ]
.IR COUNT ]
.RB [ \-i
.IR interval ]
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
.IR INTERVAL ]
.RB [ \-t
.IR TIME ]
.RB [ \-f
.IR FORMAT ]
.RB [ \-c
.IR LIST ]
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
.br
\*c
.BR \-h | \-\-help
@@ -51,17 +57,130 @@ Displays counter values from each CPU.
The default is a total summary line of all counters from all CPUs.
.
.TP
.BR \-i ", " \-\-interval \fI\ seconds\fP
.BR \-d ", " \-\-delta
Displays counter values in form of deltas.
Each counter value shows the increment to the previous output line.
Without this flag the total value of each counter is displayed.
See Examples.
.
.TP
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
Specifies a time interval, in seconds,
that the command waits between read operations.
The default is 60 seconds.
.
.TP
.BR \-l ", " \-\-loop \fI\ count\fP
.BR \-l ", " \-\-loop \fI\ COUNT\fP
Performs the specified number of read operations.
.
.TP
\fR[\fIcpulist\fR][:\fIsets\fR]\fP
.BR \-H ", " \-\-hide
Do not display values of undefined counters.
.
.TP
.BR \-s ", " \-\-short
Displays counter names as short names in the heading.
A short name consists of
a letter for the counter set followed by a number.
For example,
this flag displays counter number 0 in the basic counter
set as
.B B0
instead of
.BR Cycles .
Valid counter set letters are:
.RS
.IP B
Basic counter set
.IP P
Problem state counter set
.IP C
Crypto counter set
.IP E
Extended counter set
.IP M
MT-Diagnostic counter set
.IP U
Undefined counter.
.RE
.
.TP
.BR \-t ", " \-\-time
Specifies the runtime as an integer in days,
hours, minutes or seconds.
This option can be specified multiple times:
the runtime sums up.
Specify time as an integer followed by one of the letters
.RS
.IP d
Specifies the runtime in days.
.IP h
Specifies the runtime in hours.
.IP m
Specifies the runtime in minutes.
.IP s
Specifies the runtime in seconds.
This is the default when no letter is given.
.RE
.
.TP
.BR \-x ", " \-\-hex
Displays counter values as hexadecimal values.
.
.TP
.BR \-X ", " \-\-hex0x
Displays counter values as hexadecimal values with a leading 0x prefix.
.
.TP
.BR \-q
Apply quoting to every output element, regardless of content or format.
.
.TP
.BR \-f ", " \-\-format \fI\ FORMAT\fP
Retrieve output in one of the following formats:
JSON, CSV, JSON-SEQ or PAIRS.
If no format is specified, the output defaults to CSV.
.
.SS JSON Output Structure
The JSON output contains two top-level objects:
.B "meta"
and
.B "lshwc"
.TP
.B meta
General metadata such as API version, host, and timestamp.
.TP
.B lshwc
Measurement data and configuration.
.RS
.IP \fBcpumcf info\fP
CPU Measurement Counter Facility information.
.IP \fBmeasurements\fP
An array of objects, each representing a CPU or "total". 
Each object includes:
.RS
.IP \fBcpu\fP
CPU identifier, such as 0, 1 or "delta" or "total".
.IP \fBdate_time\fP
Timestamp in ISO 8601 format.
.IP \fBtime_epoch\fP
The number of seconds since the epoch: 1970-01-01 00:00:00 UTC.
.IP \fBcounters\fP
An array of counter objects, each containing \fBname\fP (if available), \fBid\fP,
and \fBvalue\fP.
.RE
.RE
.
.TP
.BR \-c ", " \-\-counters \fI\ LIST\fP
Specify a comma-separated list of counter names to be printed.
If a counter name does not match any valid counter name, it is omitted. (Implies -H)
.
.TP
\fR[\fICPULIST\fR][:\fISETS\fR]\fP
A comma-separated list of CPUs.
Each CPU can optionally be followed by characters that specify the counter set.
See below for details.
@@ -94,7 +213,7 @@ Two read operations are performed and a summary line is printed for each
read operation.
.sp 1
.nf
.ft CW
.ft CR
# lshwc -l2 0-1:BP
Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES(3),L1D_DIR_WRITES(4),
L1D_PENALTY_CYCLES(5),PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
@@ -105,10 +224,10 @@ Date,Time,CPU,CPU_CYCLES(0),INSTRUCTIONS(1),L1I_DIR_WRITES(2),L1I_PENALTY_CYCLES
.ft
.fi
.sp 1
This example shows the counter values of the problem state counter set
per CPU. CPU 0 and CPU 1 is selected.
This example shows the counter values of the problem state counter set per CPU.
CPU 0 and CPU 1 are selected.
.nf
.ft CW
.ft CR
.sp 1
# lshwc -l3 -a 0-1:P
Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
@@ -123,6 +242,121 @@ Date,Time,CPU,PROBLEM_STATE_CPU_CYCLES(32),PROBLEM_STATE_INSTRUCTIONS(33)
2021-04-01,11:56:47,Total,6432163447,2978400903
.ft
.fi
.sp 1
This example shows the counter values of the basic counter set
using delta output format.
.nf
.ft CR
.sp 1
# lshwc -d -l 10 -i 5 -s :b
Date,Time,CPU,B0,B1,B2,B3,B4,B5
2025-03-26,10:34:19,Total,208075,117287,1950,50548,1082,49609
2025-03-26,10:34:24,Delta,85800055,70353492,590286,13228290,364034,12945804
2025-03-26,10:34:29,Delta,70654751,60656797,483047,10838672,305703,10570868
2025-03-26,10:34:34,Delta,81043162,69476160,587141,13228161,376662,12868298
2025-03-26,10:34:39,Delta,73434017,62675417,524857,11787256,333966,11543649
2025-03-26,10:34:44,Delta,68367967,58452919,506712,11370740,310785,10589883
2025-03-26,10:34:49,Delta,70351947,57607764,507675,11433377,312433,10676243
2025-03-26,10:34:54,Delta,77154817,65371168,562153,12671030,349750,12311061
2025-03-26,10:34:59,Delta,88871882,75441201,655310,14875963,392530,13773130
2025-03-26,10:35:04,Delta,83763472,71730813,609260,13643680,366992,12672405
.ft
.fi
.sp 1
This example shows the counter values of the problem state counter set with
CPU 3 selected.
.nf
.ft CR
.sp 1
# lshwc -l2 -a 3:P -H --format json
{
"meta": {
"api_level": 1,
"version": "2.37.0-build-20250616",
"host": "b46lp08.lnxne.boe",
"time_epoch": 1750094646,
"time": "2025-06-16 19:24:06+0200"
},
"lshwc": {
"cpumcf info": {
"counter first": 3,
"counter second": 8,
"authorization": 47
},
"measurements": [
{
"date_time": "2025-06-16 19:24:06+0200",
"time_epoch": 1750094646,
"cpu": 3,
"counters": [
{
"name": "problem_state_cpu_cycles",
"id": 32,
"value": 0
},
{
"name": "problem_state_instructions",
"id": 33,
"value": 0
}
]
},
{
"date_time": "2025-06-16 19:24:06+0200",
"time_epoch": 1750094646,
"cpu": "total",
"counters": [
{
"name": "problem_state_cpu_cycles",
"id": 32,
"value": 0
},
{
"name": "problem_state_instructions",
"id": 33,
"value": 0
}
]
},
{
"date_time": "2025-06-16 19:25:06+0200",
"time_epoch": 1750094706,
"cpu": 3,
"counters": [
{
"name": "problem_state_cpu_cycles",
"id": 32,
"value": 0
},
{
"name": "problem_state_instructions",
"id": 33,
"value": 0
}
]
},
{
"date_time": "2025-06-16 19:25:06+0200",
"time_epoch": 1750094706,
"cpu": "total",
"counters": [
{
"name": "problem_state_cpu_cycles",
"id": 32,
"value": 0
},
{
"name": "problem_state_instructions",
"id": 33,
"value": 0
}
]
}
]
}
}
.ft
.fi
.SH "SEE ALSO"
.BR lscpumf (8)
.BR chcpumf (8)

View File

@@ -10,13 +10,30 @@
.TH \*c "8" "August 2023" "s390-tools" "CPU-MF management programs"
.
.SH NAME
lspai \- list Processor Activity Instrumentation (PAI) counters
\*c \- list Processor Activity Instrumentation (PAI) counters and values
.
.SH SYNOPSIS
\*c
.RB [ \-\-format
.IR FORMAT ]
.RB [ \-n ]
.RB [ \-t
.IR TYPE ]
.br
\*c
.RB [ \-\-format
.IR FORMAT ]
.RB [ \-n ]
.RB [ \-t
.IR "\ TYPE" ]
.RB [ \-a ][ \-d ][ \-i
.IR SECONDS ]
.RB [ \-l
.IR COUNT ]
.RB [ \-s ][ \-x ][ \-x ]
.RB [ \-c
.IR LIST ]
.RI [ CPULIST ]
.br
\*c
.BR \-h | \-\-help
@@ -26,10 +43,34 @@ lspai \- list Processor Activity Instrumentation (PAI) counters
.
.
.SH DESCRIPTION
On the first line
\*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.
The output lists the available PAI counter names
and numbers in various formats.
If
.I CPULIST
is specified or any of the options
.BR \-a ,
.BR \-d ,
.BR \-s ,
.BR \-x ,
.BR \-X ,
.B \-l
or
.BR \-i,
are present on the command line,
\*c command extracts counter values from the
specified PAI counter sets.
Counter sets can be specified and extracted for individual CPUs.
By default the output is a comma-separated list of values.
Each line starts with a timestamp
followed by the extracted counter values.
A header line shows each counter name and the
counter number in parenthesis.
For other formats, use the
.B \-\-format
option.
.SH OPTIONS
.TP
.BR \-h ", " \-\-help
@@ -40,7 +81,44 @@ Displays help information, then exits.
Displays version information, then exits.
.
.TP
.BR \-t ", " \-\-type "\ TYPE"
.BR \-a ", " \-\-allcpu
Displays counter values from each CPU.
The default is a total summary line of all counters from all CPUs.
.
.TP
.BR \-d ", " \-\-delta
Displays counter values in form of deltas.
Each counter value shows the increment to the previous output line.
Without this flag the total value of each counter is displayed.
.
.TP
.BR \-c ", " \-\-counters \fI\ LIST\fP
Specify a comma separated list of counter names to
be printed.
If a counter name does not match any valid counter
name, it is omitted.
.
.TP
.BR \-s ", " \-\-short
Displays counter names as short names in the heading.
A short name consists of
a letter for the counter set followed by a number.
For example,
this flag displays counter number 0 in the PAI crypto counter
set as
.B C0
instead of
.BR CRYPTO_ALL .
Valid counter set letters are:
.RS
.IP C
PAI crypto counter set
.IP N
PAI NNPA counter set
.RE
.
.TP
.BR \-t ", " \-\-type "\ \fITYPE\fP"
Specifies the PAI counter set to list.
Valid counter set values are
.I crypto
@@ -55,6 +133,32 @@ Crypto refers to the Cryptografic Processing Assist facility counter set.
Shows the PAI counter sets sorted by counter number.
Default sort order is PAI counter name.
.
.TP
.BI \-\-format "\ FORMAT"
Retrieve output in one of the following formats:
JSON, csv, json-seq or pairs.
If no format is specified,
the output defaults to a human-readable format.
.
.TP
.BR \-i ", " \-\-interval \fI\ SECONDS\fP
Specifies a time interval, in seconds,
that the command waits between read operations.
The default is 60 seconds.
.
.TP
.BR \-l ", " \-\-loop \fI\ COUNT\fP
Performs the specified number of read operations.
The default is one.
.
.TP
.BR \-x ", " \-\-hex
Displays counter values as hexadecimal values.
.
.TP
.BR \-X ", " \-\-hex0x
Displays counter values as hexadecimal values with a leading 0x prefix.
.
.SH "EXAMPLE"
The \*c invocation lists all PAI Neural Network Processing Assist Facility
(NNPA) counters in numeric order:
@@ -75,6 +179,58 @@ suitable for
.IR perf "(8)"
event specification by name.
The third gives a short explanation, if available.
.sp 1
The \*c invocation displays all PAI Neural Network Processing Assist Facility
(NNPA) counters values.
Ten iterations with a two second delay in between
is printed on the screen.
.nf
# lspai -i 2 -l 10 -t nnpa -n
Date,Time,CPU,NNPA_ALL(0),NNPA_ADD(1),NNPA_SUB(2),NNPA_MUL(3),NNPA_DIV(4),
NNPA_MIN(5),NNPA_MAX(6),NNPA_LOG(7),NNPA_EXP(8),NNPA_IBM_RESERVED_9(9),
NNPA_RELU(10),NNPA_TANH(11),NNPA_SIGMOID(12),NNPA_SOFTMAX(13),NNPA_BATCHNORM(14),
NNPA_MAXPOOL2D(15),NNPA_AVGPOOL2D(16),NNPA_LSTMACT(17),NNPA_GRUACT(18),
NNPA_CONVOLUTION(19),NNPA_MATMUL_OP(20),NNPA_MATMUL_OP_BCAST23(21),
NNPA_SMALLBATCH(22),NNPA_LARGEDIM(23),NNPA_SMALLTENSOR(24),NNPA_1MFRAME(25),
NNPA_2GFRAME(26),NNPA_ACCESSEXCEPT(27)
2025-05-13,08:18:27,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:29,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:31,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:33,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:35,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:37,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:39,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:41,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:43,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2025-05-13,08:18:45,Total,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
#
.fi
.sp 1
This \*c example displays the value of PAI crypto counter number 7.
It is field number 116 in the output.
This counter is incremented after \*c is started and
the table shows the delta values for PAI crypto counter 7.
.nf
# lspai -d -s -i 5 -l3 -t crypto | \
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
Date,Time,CPU,C0,C7
2025-06-24,13:02:24,Total,0,0
2025-06-24,13:02:29,Delta,77122286,77122284
2025-06-24,13:02:34,Delta,92574403,92574403
#
.fi
.sp 1
The following table shows the total value for PAI crypto counter 7
after \*c is started.
.nf
# lspai -s -i 5 -l3 -t crypto | \
awk -F , '{ print $1 "," $2 "," $3 "," $4 "," $116; }'
Date,Time,CPU,C0,C7
2025-06-24,13:03:01,Total,0,0
2025-06-24,13:03:06,Total,72550754,72566121
2025-06-24,13:03:11,Total,164633982,164650377
#
.fi
.SH "SEE ALSO"
.BR pai (8)
.BR lscpumf (8)

View File

@@ -15,24 +15,24 @@ pai \- record and report Processor Activity Instrumentation (PAI) counters
.SH SYNOPSIS
\*c
.RB [ \-V ][ \-m | \-\-mapsize
.IR size ]
.IR SIZE ]
.RB [ \-i | \-\-interval
.IR ms ]
.IR MS ]
.RB [ \-R | \-\-realtime
.IR prio ]
.BR \-c | \-\-crypto [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
.IR PRIO ]
.BR \-c | \-\-crypto [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
.br
\*c
.RB [ \-V ][ \-m | \-\-mapsize
.IR size ]
.IR SIZE ]
.RB [ \-i | \-\-interval
.IR ms ]
.IR MS ]
.RB [ \-R | \-\-realtime
.IR prio ]
.BR \-n | \-\-nnpa [ \fIcpulist ][: \fIdata\fR "] [" \fIloops\fP ]
.IR PRIO ]
.BR \-n | \-\-nnpa [ \fICPULIST ][: \fIDATA\fR "] [" \fILOOPS\fP ]
.br
\*c
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIfiles\fP ]
.RB [ \-V ][ \-H | \-\-humantime ][ \-S | \-\-summary "] " \-r | \-\-report " [" \fIFILES\fP ]
.br
\*c
.BR \-h | \-\-help
@@ -73,7 +73,7 @@ Reporting evaluates files that are created by recording.
.SH OPTIONS
.TP
.BR \-c ", " \-\-crypto "\fR[\fIcpulist\fR][:\fIdata\fR]"
.BR \-c ", " \-\-crypto "\fR[\fICPULIST\fR][:\fIDATA\fR]"
Records data for all (default) or a specified list of CPUs.
The CPU list is a comma-separated list of CPU numbers and ranges.
In a range, a hyphen separates the first CPU number
@@ -106,7 +106,7 @@ execution.
.RE
.
.TP
.BR \-n ", " \-\-nnpa "\fR[\fIcpulist\fR][:\fIdata\fR]"
.BR \-n ", " \-\-nnpa "\fR[\fICPULIST\fR][:\fIDATA\fR]"
Records data for all (default) or a specified list of CPUs.
The CPU list is a comma-separated list of CPU numbers and ranges.
In a range, a hyphen separates the first CPU number
@@ -241,7 +241,7 @@ The program runs for 10 seconds
(10 intervals of 1000 milliseconds).
.sp 1
.nf
.ft CW
.ft CR
# \*c -c0 10
.ft R
.fi
@@ -256,7 +256,7 @@ and a comma-separated list of counter number, colon (:),
and the counter value n hexadecimal notation.
.sp 1
.nf
.ft CW
.ft CR
# \*c -r
0x62a668f2fa 0 event 4096 sample pid 4956/4956 9:0xa7,73:0x8,74:0x18
0x6319c75653 0 event 4096 sample pid 4972/4972 32:0x1

View File

@@ -59,14 +59,6 @@ static struct util_list list_pai_event;
static struct util_list list_pmu_event;
static bool summary;
/* System call to perf_event_open(2) */
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
return syscall(__NR_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
}
static void ev_dealloc(void)
{
struct pai_event *next, *p;
@@ -743,8 +735,8 @@ static int add_events(int type)
}
if (rc) {
free(pmuname);
warnx("failed building event list for %s", pmuname);
free(pmuname);
}
return rc;
}

View File

@@ -314,8 +314,7 @@ void check_config()
cpuplugd_debug("Daemon started with vertical polarization.\n");
cpuplugd_debug("Cpu adjustments won't be made until system ");
cpuplugd_debug("is in horizontal polarization\n");
} else if (saved_polarization == PLR_HORIZONTAL &&
cpu == 1) {
} else if (cpu == 1) {
apply_cpu_config();
}
if (memory == 1) {

View File

@@ -87,6 +87,8 @@ int get_polarization(void)
char *path;
path = util_path_sysfs("devices/system/cpu/dispatching");
if (!util_path_exists(path))
return PLR_NONE;
if (util_file_read_i(&polarization, NUM_BASE, path) < 0) {
polarization = -1;
cpuplugd_debug("failed to read system polarization\n");

View File

@@ -40,6 +40,7 @@
#define CPUSTATS 10
#define PLR_HORIZONTAL 0
#define PLR_VERTICAL 1
#define PLR_NONE 2
/*
* Precedence of C operators

View File

@@ -23,11 +23,11 @@
#include <unistd.h>
#include "lib/dasd_base.h"
#include "lib/util_base.h"
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_path.h"
#include "lib/zt_common.h"
#define RD_BUFFER_SIZE 80
@@ -283,7 +283,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
char filename[] = "dasdinfo0000";
mode_t mode;
unsigned int path;
int retry;
unsigned int retry;
int rc;
int fd;
@@ -294,7 +294,7 @@ static int dinfo_create_devnode(dev_t dev, char **devno)
if (pathname[path] == NULL)
continue;
for (retry = 0; retry < TEMP_DEV_MAX_RETRIES; retry++) {
sprintf(filename, "dasdinfo%04d", retry);
snprintf(filename, sizeof(filename), "dasdinfo%04d", retry);
result = dinfo_make_path(pathname[path], filename);
if (result == NULL)
return -1;
@@ -354,18 +354,26 @@ static int dinfo_extract_dev(dev_t *dev, char *str)
static int dinfo_get_dev_from_blockdev(char *blockdev, dev_t *dev)
{
char *readbuf = NULL;
char *path;
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
if (!readbuf) {
warnx("Error: Not enough memory to allocate readbuffer");
return -1;
}
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
"/sys/block/%s/dev", blockdev) < 0)
path = util_path_sysfs("block/%s/dev", blockdev);
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, path) < 0) {
free(path);
free(readbuf);
return -1;
if (dinfo_extract_dev(dev, readbuf) != 0)
}
free(path);
if (dinfo_extract_dev(dev, readbuf) != 0) {
free(readbuf);
return -1;
}
free(readbuf);
return 0;
}
@@ -373,8 +381,9 @@ static int
dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
int tflag, struct FTW *ftwbuf)
{
enum { LINK_DIR_SIZE = 128 };
char linkdir[LINK_DIR_SIZE];
char *tempdir;
char linkdir[128];
ssize_t i;
if (tflag != FTW_D || (strncmp((fpath + ftwbuf->base), searchbusid,
@@ -387,12 +396,12 @@ dinfo_is_busiddir(const char *fpath, const struct stat *UNUSED(sb),
*/
if (asprintf(&tempdir, "%s/driver", fpath) < 0)
return -1;
i = readlink(tempdir, linkdir, 128);
i = readlink(tempdir, linkdir, LINK_DIR_SIZE);
free(tempdir);
if ((i < 0) || (i >= 128))
if (i < 0 || i >= LINK_DIR_SIZE)
return -1;
/* append '\0' because readlink returns non zero terminated string */
tempdir[i + 1] = '\0';
linkdir[i] = '\0';
if (strstr(linkdir, "dasd") == NULL)
return FTW_CONTINUE;
free(busiddir);
@@ -439,7 +448,7 @@ dinfo_get_blockdev_from_busid(char *busid, char **blkdev)
char *tempdir = NULL;
char *result = NULL;
char *sysfsdir = "/sys/devices/";
char *sysfsdir = util_path_sysfs("devices/");
/* dinfo_is_devnode needs to know the busid */
searchbusid = busid;
@@ -475,6 +484,7 @@ out:
out2:
free(busiddir);
free(result);
free(sysfsdir);
return rc;
}
@@ -486,6 +496,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
DIR *directory = NULL;
struct dirent *dir_entry = NULL;
int rc = 0;
char *path;
if (stat(devnode, &stat_buffer) != 0) {
warnx("Error: could not stat %s", devnode);
@@ -495,32 +506,34 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
sprintf(stat_dev, "%d:%d", major(stat_buffer.st_rdev),
minor(stat_buffer.st_rdev));
directory = opendir("/sys/block/");
path = util_path_sysfs("block/");
directory = opendir(path);
if (directory == NULL) {
warnx("Error: could not open directory /sys/block");
warnx("Error: could not open directory %s", path);
free(path);
return -1;
}
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
if (!readbuf) {
warnx("Error: Not enough memory to allocate readbuffer");
free(path);
return -1;
}
while ((dir_entry = readdir(directory)) != NULL) {
if (util_file_read_line(readbuf, RD_BUFFER_SIZE,
"/sys/block/%s/dev",
if (util_file_read_line(readbuf, RD_BUFFER_SIZE, "%s%s/dev", path,
dir_entry->d_name) < 0)
continue;
if (strncmp(stat_dev, readbuf,
MAX(strlen(stat_dev), strlen(readbuf) - 1)) == 0) {
rc = snprintf(*uidfile, RD_BUFFER_SIZE,
"/sys/block/%s/device/uid",
rc = snprintf(*uidfile, RD_BUFFER_SIZE, "%s%s/device/uid", path,
dir_entry->d_name);
if (rc >= RD_BUFFER_SIZE) {
fprintf(stderr,
"Error: Device name was truncated\n");
free(path);
return -1;
}
@@ -529,6 +542,7 @@ static int dinfo_get_uid_from_devnode(char **uidfile, char *devnode)
}
closedir(directory);
free(path);
return 0;
}
@@ -626,16 +640,18 @@ int main(int argc, char *argv[])
}
readbuf = dinfo_malloc(RD_BUFFER_SIZE);
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
if (!(readbuf && uidfile))
if (!readbuf)
exit(1);
/* try to read the uid attribute */
if (busid) {
sprintf(uidfile, "/sys/bus/ccw/devices/%s/uid", busid);
uidfile = util_path_sysfs("bus/ccw/devices/%s/uid", busid);
} else if (blockdev) {
sprintf(uidfile, "/sys/block/%s/device/uid", blockdev);
uidfile = util_path_sysfs("block/%s/device/uid", blockdev);
} else if (devnode) {
uidfile = dinfo_malloc(RD_BUFFER_SIZE);
if (!uidfile)
exit(1);
if (dinfo_get_uid_from_devnode(&uidfile, devnode) != 0)
goto error;
}

View File

@@ -22,7 +22,7 @@
. ds pfont \\n[.f]
. nh
. na
. ft CW
. ft CR
\\$*
. ft \\*[pfont]
. ad

View File

@@ -1,2 +1,6 @@
# Load protected key support module on s390 early at boot
pkey
pkey_pckmo
pkey_ep11
pkey_cca
paes_s390

View File

@@ -18,3 +18,17 @@ CPI_SYSTEM_NAME=""
# CPI sysplex name
#
CPI_SYSPLEX_NAME=""
#
# CPI permit on protected virtualization guests
#
# Important: Set CPI_PERMIT_ON_PVGUEST=1 only if you trust the host system.
# Enabling these options allows the host to receive potentially sensitive
# Control-Program Identification (CPI) data from the protected virtualization
# guest, including:
# - system_type
# - system_level
# - sysplex_name
# - system_name
#
CPI_PERMIT_ON_PVGUEST=

View File

@@ -0,0 +1,4 @@
#
# Rules to set online a newly hotplugged cpu on s390x
#
SUBSYSTEM=="cpu", ACTION=="add", CONST{arch}=="s390*", ATTR{configure}=="1", TEST=="online", ATTR{online}!="1", ATTR{online}="1"

View File

@@ -31,11 +31,9 @@
#define ECKD2DUMP_STACK_SIZE _AC(0x2000, 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_SV _AC(0x3000, UL)
#define STAGE2_DUMPER_SIZE_MV _AC(0x4000, UL)
#define STAGE2_DUMPER_SIZE_ZLIB _AC(0x8000, UL)
#define STAGE2_DUMPER_SIZE_SV_ZLIB _AC(0x8000, UL)
#define STAGE3_ENTRY _AC(0xa000, UL)

View File

@@ -27,16 +27,9 @@
#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

View File

@@ -9,17 +9,38 @@
#include <sched.h>
#include <stdbool.h>
#include <asm/unistd.h>
#include <linux/perf_event.h>
#define S390_CPUMF_CF "/sys/devices/cpum_cf/"
#define S390_CPUMF_CFDIAG "/sys/devices/cpum_cf_diag/"
#define S390_CPUMF_SF "/sys/devices/cpum_sf/"
#define S390_CPUS_POSSIBLE "/sys/devices/system/cpu/possible"
#define S390_CPUS_ONLINE "/sys/devices/system/cpu/online"
#define S390_CPUMSF_BUFFERSZ "/sys/module/kernel/parameters/cpum_sfb_size"
#define S390_SYSFS_PAI_CRYPTO "/sys/devices/pai_crypto/"
#define S390_SYSFS_PAI_EXT "/sys/devices/pai_ext/"
#define S390_CPUMF_CF "devices/cpum_cf/"
#define S390_CPUMF_CFDIAG "devices/cpum_cf_diag/"
#define S390_CPUMF_SF "devices/cpum_sf/"
#define S390_CPUS_ONLINE "devices/system/cpu/online"
#define S390_CPUMSF_BUFFERSZ "module/kernel/parameters/cpum_sfb_size"
#define S390_SYSFS_PAI_CRYPTO "devices/pai_crypto/"
#define S390_SYSFS_PAI_EXT "devices/pai_ext/"
#define S390_SYSFS_PAI_NNPA S390_SYSFS_PAI_EXT "events/NNPA_ALL"
#define CPUMF_CTRSET_NONE 0
#define CPUMF_CTRSET_EXTENDED 1
#define CPUMF_CTRSET_BASIC 2
#define CPUMF_CTRSET_PROBLEM_STATE 4
#define CPUMF_CTRSET_CRYPTO 8
#define CPUMF_CTRSET_MT_DIAG 32
/**
* Return counter set a counter belongs to.
*
* Return the counter set a given counter belongs to, given the
* CPU Measurement facility counter version first and second number.
*
* @param[in] ctr Counter number
* @param[in] cfvn CPUM Counter facility first version number
* @param[in] csvn CPUM Counter facility second version number
* @retval >=0 Counter set number to counter belongs to
*/
int libcpumf_ctrset(int ctr, int cfvn, int csvn);
/**
* Read out the PMU type from a given file.
*
@@ -96,7 +117,7 @@ bool libcpumf_have_cpumcf(void);
*
* @param[out] min Minimum supported sampling interval
* @param[out] max Maximum supported sampling interval
* @param[out] speed Current CPU speed, number of CPU cylces per
* @param[out] speed Current CPU speed, number of CPU cycles per
* microsecond
* @param[out] basic_sz Basic sample size in bytes
* @param[out] diag_sz Diagnostic sample size in bytes
@@ -163,4 +184,37 @@ bool libcpumf_have_pai_ext(void);
* @retval false PAI_NNPA counter Facility is not available
*/
bool libcpumf_have_pai_nnpa(void);
/**
* Wrapper for the perf_event_open syscall used to configure performance events.
* This function simplifies usage of perf_event_open and provides a consistent
* interface for libcpumf internals.
*
* @param hw_event Pointer to perf_event_attr structure describing the event
* @param pid Target process ID (0 for current process)
* @param cpu Target CPU (-1 for all CPUs)
* @param group_fd File descriptor of event group leader, or -1 if none
* @param flags Additional flags (usually 0)
*
* @return File descriptor for the opened event on success
* @return -1 on failure, errno is set appropriately
*/
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd,
unsigned long flags);
/**
* Check if a counter name is present in a comma-separated list of counters.
*
* This function checks whether the given counter name appears in the
* provided list. If the list is NULL, the function assumes all counters
* are allowed and returns true.
*
* @param name Name of the counter to search for
* @param ctrlist Comma-separated list of counter names, or NULL
*
* @return true if the counter is in the list or list is NULL
* @return false otherwise
*/
bool ctr_in_list(char *name, char *ctrlist);
#endif

View File

@@ -28,6 +28,8 @@ enum util_arch_machine_type {
UTIL_ARCH_MACHINE_TYPE_Z15_T02 = 8562,
UTIL_ARCH_MACHINE_TYPE_Z16 = 3931,
UTIL_ARCH_MACHINE_TYPE_Z16_A02 = 3932,
UTIL_ARCH_MACHINE_TYPE_Z17 = 9175,
UTIL_ARCH_MACHINE_TYPE_Z17_2 = 9176,
};
int util_arch_machine_type(void);

View File

@@ -31,6 +31,7 @@ struct util_proc_dev_entry {
#define UTIL_PROC_DEV_ENTRY_SD "sd"
#define UTIL_PROC_DEV_ENTRY_BLKEXT "blkext"
#define UTIL_PROC_DEV_ENTRY_MD "md"
#define UTIL_PROC_DEV_ENTRY_DM "device-mapper"
int util_proc_part_get_entry(dev_t device, struct util_proc_part_entry *entry);
void util_proc_part_free_entry(struct util_proc_part_entry *entry);

17
include/lib/util_str.h Normal file
View File

@@ -0,0 +1,17 @@
/**
* @defgroup util_str_h util_str: String functions
* @{
* @brief Manipulate and work with strings
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIB_UTIL_STR_H
#define LIB_UTIL_STR_H
void util_str_rm_whitespace(const char *src, char *dest);
#endif /** LIB_UTIL_STR_H @} */

View File

@@ -9,7 +9,6 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -49,19 +48,19 @@ static int device_sysfs_path(const char *device, char *path, const size_t path_s
*/
int ccw_is_device(const char *busid)
{
char path[PATH_MAX];
static const char *const driver_paths[] = { "dasd-eckd", "virtio_ccw", "dasd-fba" };
char *path;
size_t i;
for (i = 0; i < ARRAY_SIZE(driver_paths); i++) {
path = util_path_sysfs("bus/ccw/drivers/%s/%s", driver_paths[i], busid);
if (access(path, R_OK) == 0) {
free(path);
return 1;
}
free(path);
}
snprintf(path, sizeof(path),
"/sys/bus/ccw/drivers/dasd-eckd/%s", busid);
if (access(path, R_OK) == 0)
return 1;
snprintf(path, sizeof(path),
"/sys/bus/ccw/drivers/virtio_ccw/%s", busid);
if (access(path, R_OK) == 0)
return 1;
snprintf(path, sizeof(path), "/sys/bus/ccw/drivers/dasd-fba/%s", busid);
if (access(path, R_OK) == 0)
return 1;
return 0;
}
@@ -72,6 +71,7 @@ int ccw_is_virtio_device(const char *device)
{
char path[PATH_MAX] = { '\0' };
unsigned virtio = 0;
char *path_pattern;
if (device_sysfs_path(device, path, sizeof(path)) != 0)
return -1;
@@ -80,76 +80,37 @@ int ccw_is_virtio_device(const char *device)
* 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)
path_pattern = util_path_sysfs("devices/css0/%%*[0-9a-f.]/%%*[0-9a-f.]/virtio%%u");
if (sscanf(path, path_pattern, &virtio) != 1) {
free(path_pattern);
return -1;
}
free(path_pattern);
return 0;
}
/*
* Return CCW Bus ID (old sysfs)
* Return CCW Bus ID
*/
static int ccw_busid_get_sysfs_old(const char *device, char *busid)
{
char path[PATH_MAX];
char buf[4096];
int rc = 0;
FILE *fh;
snprintf(path, sizeof(path), "/sys/block/%s/uevent", device);
fh = fopen(path, "r");
if (fh == NULL)
return -1;
/*
* The uevent file contains an entry like this:
* PHYSDEVPATH=/devices/css0/0.0.206a/0.0.7e78
*/
while (fscanf(fh, "%s", buf) >= 0) {
if (strstr(buf, "PHYSDEVPATH") != NULL) {
strcpy(busid, strrchr(buf, '/') + 1);
goto out_fclose;
}
}
rc = -1;
out_fclose:
fclose(fh);
return rc;
}
/*
* Return CCW Bus ID (new sysfs)
*/
static int ccw_busid_get_sysfs_new(const char *device, char *busid)
void ccw_busid_get(const char *device, char *busid)
{
char path[PATH_MAX] = { '\0' };
char *path_pattern;
if (device_sysfs_path(device, path, sizeof(path)) != 0)
return -1;
ERR_EXIT("Could not lookup device number for \"%s\"", device);
/*
* The output has the following format:
* /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda
* /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
*/
if (sscanf(path, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
return -1;
return 0;
}
path_pattern = util_path_sysfs("devices/css0/%%*[0-9a-f.]/%%[0-9a-f.]");
if (sscanf(path, path_pattern, busid) != 1) {
free(path_pattern);
ERR_EXIT("Could not lookup device number for \"%s\"", device);
}
free(path_pattern);
/*
* Return the device number for a device
* dasda can be found in /sys/block/dasda/uevent or in a
* symbolic link in the same directory. the first file only
* contains the relevant information if we run on a kernel with
* has the following kernel option enabled:
* CONFIG_SYSFS_DEPRECATED
*
* This does not work when booting from tape
*/
void ccw_busid_get(const char *device, char *busid)
{
if (ccw_busid_get_sysfs_old(device, busid) == 0)
return;
if (ccw_busid_get_sysfs_new(device, busid) == 0)
return;
ERR_EXIT("Could not lookup device number for \"%s\"", device);
return;
}

View File

@@ -12,12 +12,17 @@
#include <ctype.h>
#include <sys/sysmacros.h>
#include <sys/ioctl.h>
#include "lib/util_libc.h"
#include "lib/util_proc.h"
#include "lib/util_base.h"
#include "lib/zt_common.h"
#include "lib/util_path.h"
#include "ipl_tools.h"
#include "proc.h"
#include <linux/raid/md_u.h>
#define BOOTPARMS_NSS_MAX 56
#define BOOTPARMS_CCW_MAX 64
@@ -25,6 +30,8 @@
#define OPT_BRCHR 0x80
#define MD_MAJOR 9
enum target_type {
TT_CCW,
TT_FCP,
@@ -414,15 +421,38 @@ static int set_reipl_type(const char *dev_name)
return 0;
}
static int get_chreipl_helper_cmd(dev_t dev, char cmd[PATH_MAX])
static int is_md_device(const char *dev_name)
{
char abs_dev_name[PATH_MAX];
mdu_array_info_t array;
int is_md_device = 0;
int fd;
if (snprintf(abs_dev_name, PATH_MAX, "/dev/%s", dev_name) >= PATH_MAX)
return 0;
fd = open(abs_dev_name, O_RDONLY);
if (fd == -1)
return 0;
if (ioctl(fd, GET_ARRAY_INFO, &array) >= 0)
is_md_device = 1;
close(fd);
return is_md_device;
}
static int get_chreipl_helper_cmd(dev_t dev, char *dev_name, char cmd[PATH_MAX])
{
char *chreipl_helper;
struct proc_dev_entry pde;
char *chreipl_helper;
char *driver_name;
if (proc_dev_get_entry(dev, 1, &pde) != 0)
return -1;
driver_name = pde.name;
if (strcmp(driver_name, UTIL_PROC_DEV_ENTRY_BLKEXT) == 0 &&
is_md_device(dev_name))
driver_name = UTIL_PROC_DEV_ENTRY_MD;
util_asprintf(&chreipl_helper,
"%s/%s.%s", TOOLS_LIBDIR, "chreipl_helper", pde.name);
"%s.%s", util_libdir_path("chreipl_helper"), driver_name);
if (access(chreipl_helper, X_OK) != 0) {
proc_dev_free_entry(&pde);
free(chreipl_helper);
@@ -437,7 +467,7 @@ static int get_chreipl_helper_cmd(dev_t dev, char cmd[PATH_MAX])
/*
* Use chreipl_helper (E.g. for device mapper devices)
*/
static int set_reipl_type_helper(int maj, int min)
static int set_reipl_type_helper(int maj, int min, char *dev_name)
{
char helper_cmd[PATH_MAX], buf[4096];
struct proc_part_entry ppe;
@@ -445,7 +475,7 @@ static int set_reipl_type_helper(int maj, int min)
dev_t dev;
FILE *fh;
if (get_chreipl_helper_cmd(makedev(maj, min), helper_cmd) != 0)
if (get_chreipl_helper_cmd(makedev(maj, min), dev_name, helper_cmd) != 0)
return -1;
fh = popen(helper_cmd, "r");
if (fh == NULL)
@@ -499,7 +529,7 @@ static void parse_node_args(char *nargv[], int nargc)
ERR_EXIT("Invalid device node \"%s\" specified", path);
if (set_reipl_type(ppe.name) == 0)
goto out;
if (set_reipl_type_helper(major(dev), minor(dev)) == 0)
if (set_reipl_type_helper(major(dev), minor(dev), ppe.name) == 0)
goto out;
ERR_EXIT("Unsupported device node \"%s\" specified", path);
out:
@@ -719,11 +749,12 @@ static void parse_chreipl_options(int argc, char *argv[])
static void check_exists(const char *path, const char *attr)
{
char fpath[PATH_MAX];
char *fpath;
snprintf(fpath, sizeof(fpath), "/sys/firmware/%s", path);
fpath = util_path_sysfs("firmware/%s", path);
if (access(fpath, F_OK) != 0)
ERR_EXIT("System does not allow one to set %s", attr);
free(fpath);
}
static void write_str_optional(char *string, char *file, int exit_on_fail,
@@ -739,7 +770,7 @@ static void write_str_optional(char *string, char *file, int exit_on_fail,
* IMPLEMENTATION:
*
* "cio_ignore --is-ignored <busid>" returns 0 if the device is ignored,
* 1 for internal errrors, and 2 if the device is not ignored.
* 1 for internal errors, and 2 if the device is not ignored.
*
* We get the "cio_ignore" exit status by the return code of the system()
* function via WEXITSTATUS().
@@ -920,13 +951,14 @@ static void chreipl_nss(void)
static void chreipl_node(void)
{
char path[PATH_MAX];
char *path;
if (!l.dev_set)
ERR_EXIT("No device node specified");
snprintf(path, sizeof(path), "/sys/block/%s/device", l.dev);
path = util_path_sysfs("block/%s/device", l.dev);
if (chdir(path) != 0)
ERR_EXIT("Could not find device \"%s\"", l.dev);
free(path);
switch (l.reipl_type) {
case REIPL_CCW:

View File

@@ -9,6 +9,10 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "lib/util_path.h"
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "ipl_tools.h"
static struct {
@@ -42,24 +46,23 @@ static const char *get_ipl_banner(int show_ipl)
void print_nss(int show_ipl)
{
char *dir = show_ipl ? "ipl" : "reipl/nss";
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/parm" :
"/sys/firmware/reipl/nss/parm";
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
printf("%-12s nss\n", get_ipl_banner(show_ipl));
print_fw_str("Name: %s\n", dir, "name");
if (access(path_bootparms, R_OK) == 0)
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
free(path_bootparms);
}
void print_fcp(int show_ipl, int dump)
{
char *dir = show_ipl ? "ipl" : "reipl/fcp";
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
"/sys/firmware/reipl/fcp/scp_data";
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
"/sys/firmware/reipl/fcp/loadparm";
char loadparm[9], loadparm_path[PATH_MAX];
char *path_reipl_clear = "/sys/firmware/reipl/fcp/clear";
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
char *path_reipl_clear = util_path_sysfs("firmware/reipl/fcp/clear");
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
char *loadparm;
if (dump)
printf("%-12s fcp_dump\n", get_ipl_banner(show_ipl));
@@ -72,27 +75,31 @@ void print_fcp(int show_ipl, int dump)
print_fw_str("bootprog: %s\n", dir, "bootprog");
print_fw_str("br_lba: %s\n", dir, "br_lba");
if (access(path_loadparm, R_OK) == 0) {
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
if (strcmp(loadparm, " ") == 0)
loadparm[0] = 0;
loadparm = util_file_read_text_file(path_loadparm, 1);
util_strstrip(loadparm);
printf("Loadparm: \"%s\"\n", loadparm);
free(loadparm);
}
if (access(path_bootparms, R_OK) == 0)
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
print_fw_str("clear: %s\n", dir, "clear");
if (access(path_secure_boot, R_OK) == 0)
print_fw_str("Secure boot: %s\n", "ipl", "secure");
free(path_bootparms);
free(path_loadparm);
free(path_reipl_clear);
free(path_secure_boot);
}
void print_nvme(int show_ipl, int dump)
{
char *dir = show_ipl ? "ipl" : "reipl/nvme";
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/scp_data" :
"/sys/firmware/reipl/nvme/scp_data";
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
"/sys/firmware/reipl/nvme/loadparm";
char loadparm[9], loadparm_path[PATH_MAX];
char *path_reipl_clear = "/sys/firmware/reipl/nvme/clear";
char *path_bootparms = util_path_sysfs("firmware/%s/scp_data", dir);
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
char *path_reipl_clear = util_path_sysfs("firmware/reipl/nvme/clear");
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
char *loadparm;
if (dump)
printf("%-12s nvme_dump\n", get_ipl_banner(show_ipl));
@@ -104,49 +111,54 @@ void print_nvme(int show_ipl, int dump)
print_fw_str("bootprog: %s\n", dir, "bootprog");
print_fw_str("br_lba: %s\n", dir, "br_lba");
if (access(path_loadparm, R_OK) == 0) {
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
if (strcmp(loadparm, " ") == 0)
loadparm[0] = 0;
loadparm = util_file_read_text_file(path_loadparm, 1);
util_strstrip(loadparm);
printf("Loadparm: \"%s\"\n", loadparm);
free(loadparm);
}
if (access(path_bootparms, R_OK) == 0)
print_fw_str("Bootparms: \"%s\"\n", dir, "scp_data");
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
print_fw_str("clear: %s\n", dir, "clear");
if (access(path_secure_boot, R_OK) == 0)
print_fw_str("Secure boot: %s\n", "ipl", "secure");
free(path_bootparms);
free(path_loadparm);
free(path_reipl_clear);
free(path_secure_boot);
}
void print_ccw(int show_ipl)
{
char loadparm[9], loadparm_path[PATH_MAX];
char *dir = show_ipl ? "ipl" : "reipl/ccw";
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
"/sys/firmware/reipl/ccw/loadparm";
char *path_bootparms = show_ipl ? "/sys/firmware/ipl/parm" :
"/sys/firmware/reipl/ccw/parm";
char *path_reipl_clear = "/sys/firmware/reipl/ccw/clear";
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
char *path_bootparms = util_path_sysfs("firmware/%s/parm", dir);
char *path_reipl_clear = util_path_sysfs("firmware/reipl/ccw/clear");
char *loadparm;
printf("%-12s ccw\n", get_ipl_banner(show_ipl));
print_fw_str("Device: %s\n", dir, "device");
if (access(path_loadparm, R_OK) == 0) {
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
if (strcmp(loadparm, " ") == 0)
loadparm[0] = 0;
loadparm = util_file_read_text_file(path_loadparm, 1);
util_strstrip(loadparm);
printf("Loadparm: \"%s\"\n", loadparm);
free(loadparm);
}
if (access(path_bootparms, R_OK) == 0)
print_fw_str("Bootparms: \"%s\"\n", dir, "parm");
if (!show_ipl && access(path_reipl_clear, R_OK) == 0)
print_fw_str("clear: %s\n", dir, "clear");
free(path_loadparm);
free(path_bootparms);
free(path_reipl_clear);
}
void print_eckd(int show_ipl, const char *name)
{
char *path_loadparm = show_ipl ? "/sys/firmware/ipl/loadparm" :
"/sys/firmware/reipl/eckd/loadparm";
char *dir = show_ipl ? "ipl" : "reipl/eckd";
char loadparm[9], loadparm_path[PATH_MAX];
char *path_loadparm = util_path_sysfs("firmware/%s/loadparm", dir);
char *path_secure_boot = util_path_sysfs("firmware/ipl/secure");
char *loadparm;
printf("%-12s %s\n", get_ipl_banner(show_ipl), name);
@@ -155,14 +167,17 @@ void print_eckd(int show_ipl, const char *name)
print_fw_str("br_chr: %s\n", dir, "br_chr");
print_fw_str("Bootparm: \"%s\"\n", dir, "scp_data");
if (access(path_loadparm, R_OK) == 0) {
sprintf(loadparm_path, "%s/%s", dir, "loadparm");
read_fw_str(loadparm, loadparm_path, sizeof(loadparm));
if (strcmp(loadparm, " ") == 0)
loadparm[0] = 0;
loadparm = util_file_read_text_file(path_loadparm, 1);
util_strstrip(loadparm);
printf("Loadparm: \"%s\"\n", loadparm);
free(loadparm);
}
if (!show_ipl)
print_fw_str("clear: %s\n", dir, "clear");
if (access(path_secure_boot, R_OK) == 0)
print_fw_str("Secure boot: %s\n", "ipl", "secure");
free(path_loadparm);
free(path_secure_boot);
}
static void parse_lsreipl_options(int argc, char *argv[])
@@ -196,16 +211,14 @@ static void parse_lsreipl_options(int argc, char *argv[])
void cmd_lsreipl(int argc, char *argv[])
{
char reipl_type_str[1024];
char *reipl_type_str;
parse_lsreipl_options(argc, argv);
if (l.ipl_set)
read_fw_str(reipl_type_str, "ipl/ipl_type",
sizeof(reipl_type_str));
reipl_type_str = read_fw_str("ipl/ipl_type");
else
read_fw_str(reipl_type_str, "reipl/reipl_type",
sizeof(reipl_type_str));
reipl_type_str = read_fw_str("reipl/reipl_type");
if (strcmp(reipl_type_str, "fcp") == 0)
print_fcp(l.ipl_set, 0);
@@ -225,5 +238,6 @@ void cmd_lsreipl(int argc, char *argv[])
else
printf("%s: %s (unknown)\n", get_ipl_banner(l.ipl_set),
reipl_type_str);
free(reipl_type_str);
exit(0);
}

View File

@@ -9,6 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "lib/util_path.h"
#include "lib/util_file.h"
#include "ipl_tools.h"
static const char *const usage_lsshut =
@@ -60,12 +62,13 @@ static void parse_lsshut_options(int argc, char *argv[])
*/
static void read_vmcmd(char *str, const char *path)
{
char buf[128], tmp[512];
char *ptr_old, *ptr;
char tmp[512];
char *buf;
*str = 0;
buf = read_fw_str(path);
ptr_old = ptr = buf;
read_fw_str(buf, path, sizeof(buf));
while ((ptr = strchr(ptr_old, '\n'))) {
*ptr = 0;
sprintf(tmp, "\"%s\",", ptr_old);
@@ -74,23 +77,31 @@ static void read_vmcmd(char *str, const char *path)
}
sprintf(tmp, "\"%s\"", ptr_old);
strcat(str, tmp);
free(buf);
}
static void print_kdump(void)
{
struct stat sb;
char tmp[1024];
char *path;
char *tmp;
if (stat("/sys/kernel/kexec_crash_loaded", &sb) != 0)
path = util_path_sysfs("kernel/kexec_crash_loaded");
if (stat(path, &sb) != 0) {
free(path);
return;
read_str(tmp, "/sys/kernel/kexec_crash_loaded", sizeof(tmp));
}
tmp = util_file_read_text_file(path, 1);
if (strncmp(tmp, "1", 1) == 0)
printf("kdump,");
free(path);
free(tmp);
}
static void shutdown_trigger_print(struct shutdown_trigger *trigger)
{
char tmp[1024], cmd[1024], path[PATH_MAX];
char cmd[1024], path[PATH_MAX];
char *tmp;
sprintf(path, "shutdown_actions/%s", trigger->name_sysfs);
@@ -99,7 +110,7 @@ static void shutdown_trigger_print(struct shutdown_trigger *trigger)
if ((trigger == &shutdown_trigger_panic ||
trigger == &shutdown_trigger_restart))
print_kdump();
read_fw_str(tmp, path, sizeof(tmp));
tmp = read_fw_str(path);
if (strncmp(tmp, "vmcmd", strlen("vmcmd")) == 0) {
sprintf(path, "vmcmd/%s", trigger->name_sysfs);
read_vmcmd(cmd, path);
@@ -107,6 +118,7 @@ static void shutdown_trigger_print(struct shutdown_trigger *trigger)
} else {
printf("%s\n", tmp);
}
free(tmp);
}
void cmd_lsshut(int argc, char *argv[])

View File

@@ -10,6 +10,7 @@
*/
#include "lib/util_libc.h"
#include "lib/util_path.h"
#include "ipl_tools.h"
/*
@@ -18,11 +19,14 @@
*/
int fcp_is_device(const char *devno)
{
char path[PATH_MAX];
char *path;
snprintf(path, sizeof(path), "/sys/bus/ccw/drivers/zfcp/%s", devno);
if (chdir(path) != 0)
path = util_path_sysfs("bus/ccw/drivers/zfcp/%s", devno);
if (chdir(path) != 0) {
free(path);
return 0;
}
free(path);
return 1;
}
@@ -31,11 +35,12 @@ int fcp_is_device(const char *devno)
*/
void fcp_wwpn_get(const char *device, char *wwpn)
{
char path[PATH_MAX], buf[20];
char buf[20];
char *path;
FILE *fh;
int rc;
snprintf(path, sizeof(path), "/sys/block/%s/device/wwpn", device);
path = util_path_sysfs("block/%s/device/wwpn", device);
fh = fopen(path, "r");
if (fh == NULL)
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
@@ -44,19 +49,20 @@ void fcp_wwpn_get(const char *device, char *wwpn)
ERR_EXIT("Could not lookup WWPN \"%s\"", path);
util_strlcpy(wwpn, buf, 20);
fclose(fh);
free(path);
}
/*
* Return the lun of a device
*/
void fcp_lun_get(const char *device, char *lun)
{
char path[PATH_MAX], buf[20];
char buf[20];
char *path;
FILE *fh;
int rc;
snprintf(path, sizeof(path), "/sys/block/%s/device/fcp_lun", device);
path = util_path_sysfs("block/%s/device/fcp_lun", device);
fh = fopen(path, "r");
if (fh == NULL)
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
@@ -65,6 +71,7 @@ void fcp_lun_get(const char *device, char *lun)
ERR_EXIT("Could not lookup LUN \"%s\"", path);
util_strlcpy(lun, buf, 20);
fclose(fh);
free(path);
}
/*
@@ -72,11 +79,12 @@ void fcp_lun_get(const char *device, char *lun)
*/
void fcp_busid_get(const char *device, char *devno)
{
char buf[4096], path[PATH_MAX];
char buf[4096];
char *path;
FILE *fh;
int rc;
snprintf(path, sizeof(path), "/sys/block/%s/device/hba_id", device);
path = util_path_sysfs("block/%s/device/hba_id", device);
fh = fopen(path, "r");
if (fh == NULL)
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
@@ -85,4 +93,5 @@ void fcp_busid_get(const char *device, char *devno)
ERR_EXIT("Could not find device \"%s\"", path);
strcpy(devno, buf);
fclose(fh);
free(path);
}

View File

@@ -12,7 +12,6 @@
#ifndef IPL_TOOLS_H
#define IPL_TOOLS_H
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -36,41 +35,38 @@ extern struct globals {
/*
* Commands
*/
extern void cmd_lsshut(int argc, char *argv[]);
extern void cmd_chshut(int argc, char *argv[]);
extern void cmd_lsreipl(int argc, char *argv[]);
extern void cmd_chreipl(int argc, char *argv[]);
void cmd_lsshut(int argc, char *argv[]);
void cmd_chshut(int argc, char *argv[]);
void cmd_lsreipl(int argc, char *argv[]);
void cmd_chreipl(int argc, char *argv[]);
extern void print_ccw(int show_ipl);
extern void print_fcp(int show_ipl, int dump);
extern void print_nvme(int show_ipl, int dump);
extern void print_nss(int show_ipl);
extern void print_eckd(int show_ipl, const char *name);
void print_ccw(int show_ipl);
void print_fcp(int show_ipl, int dump);
void print_nvme(int show_ipl, int dump);
void print_nss(int show_ipl);
void print_eckd(int show_ipl, const char *name);
/*
* Helper
*/
extern int is_lpar(void);
extern int is_root(void);
int is_lpar(void);
int is_root(void);
extern void strlow(char *s);
void write_str(char *string, char *file);
int write_str_errno(char *string, char *file);
char *read_fw_str(const char *file);
void print_fw_str(const char *fmt, const char *dir, const char *file);
extern void write_str(char *string, char *file);
extern int write_str_errno(char *string, char *file);
extern void read_str(char *string, const char *file, size_t len);
extern void read_fw_str(char *string, const char *file, size_t len);
extern void print_fw_str(const char *fmt, const char *dir, const char *file);
extern void __noreturn print_version_exit(void);
extern void __noreturn print_help_hint_exit(void);
void __noreturn print_version_exit(void);
void __noreturn print_help_hint_exit(void);
/*
* FCP
*/
extern int fcp_is_device(const char *devno);
extern void fcp_lun_get(const char *device, char *lun);
extern void fcp_wwpn_get(const char *device, char *wwpn);
extern void fcp_busid_get(const char *device, char *devno);
int fcp_is_device(const char *devno);
void fcp_lun_get(const char *device, char *lun);
void fcp_wwpn_get(const char *device, char *wwpn);
void fcp_busid_get(const char *device, char *devno);
/*
* NVME
@@ -79,16 +75,16 @@ extern void fcp_busid_get(const char *device, char *devno);
#define NVME_DEV_MAX_LEN 15 /* "nvme" + u32 in decimal + null */
#define NVME_PATH_MAX (PATH_MAX + NAME_MAX + 1)
extern void nvme_fid_get(const char *device, char *fid);
extern void nvme_nsid_get(const char *device, char *nsid);
void nvme_fid_get(const char *device, char *fid);
void nvme_nsid_get(const char *device, char *nsid);
int nvme_is_device(char *fid_str, char *nsid_str);
/*
* CCW
*/
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);
int ccw_is_device(const char *devno);
int ccw_is_virtio_device(const char *device);
void ccw_busid_get(const char *device, char *devno);
/*
* Shutdown trigger

View File

@@ -16,6 +16,7 @@
#include "lib/util_libc.h"
#include "lib/util_file.h"
#include "lib/util_path.h"
#include "ipl_tools.h"
static void nvme_dev_from_bdev(char *dev_name)
@@ -31,8 +32,9 @@ static void nvme_dev_from_bdev(char *dev_name)
*/
void nvme_fid_get(const char *device, char *fid)
{
char path[PATH_MAX], buf[FID_MAX_LEN];
char nvme_dev[NVME_DEV_MAX_LEN];
char buf[FID_MAX_LEN];
char *path;
/*
* An NVMe may present multiple namespaces and thus block devices, even
@@ -42,24 +44,27 @@ void nvme_fid_get(const char *device, char *fid)
util_strlcpy(nvme_dev, device, sizeof(nvme_dev));
nvme_dev_from_bdev(nvme_dev);
snprintf(path, PATH_MAX, "/sys/class/nvme/%s/device/function_id", nvme_dev);
path = util_path_sysfs("class/nvme/%s/device/function_id", nvme_dev);
if (util_file_read_line(buf, FID_MAX_LEN, path))
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
util_strlcpy(fid, buf, FID_MAX_LEN);
free(path);
}
/*
* Return the nsid of a device
*/
void nvme_nsid_get(const char *device, char *nsid)
{
char path[PATH_MAX], buf[FID_MAX_LEN];
char buf[FID_MAX_LEN];
char *path;
snprintf(path, PATH_MAX, "/sys/block/%s/nsid", device);
path = util_path_sysfs("block/%s/nsid", device);
if (util_file_read_line(buf, FID_MAX_LEN, path))
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);
util_strlcpy(nsid, buf, FID_MAX_LEN);
free(path);
}
static int next_entry(DIR *dir, char *in_path, char *out_path,
@@ -93,13 +98,14 @@ static int next_entry(DIR *dir, char *in_path, char *out_path,
static int nvme_getdev_by_fid(char *fidstr, char *devpath)
{
char temp_path[PATH_MAX+19], real_path[PATH_MAX];
char *sys_path = "/sys/class/nvme";
char temp_path[PATH_MAX + 19], real_path[PATH_MAX];
u_int64_t target_fid, curfid;
char *sys_path;
DIR *dir;
char *end;
int rc = -1;
sys_path = util_path_sysfs("class/nvme");
target_fid = strtoul(fidstr, &end, 16);
if (*end)
ERR_EXIT("Invalid function_id given %s", fidstr);
@@ -126,6 +132,7 @@ static int nvme_getdev_by_fid(char *fidstr, char *devpath)
}
closedir(dir);
free(sys_path);
return rc;
}

View File

@@ -16,6 +16,7 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include <ctype.h>
#include "ipl_tools.h"
#include "proc.h"

View File

@@ -12,7 +12,6 @@
#ifndef PROC_H
#define PROC_H
#include <ctype.h>
#include <sys/types.h>
struct proc_part_entry {

View File

@@ -9,7 +9,8 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "lib/util_libc.h"
#include "lib/util_path.h"
#include "lib/util_file.h"
#include "ipl_tools.h"
/*
@@ -46,47 +47,18 @@ int is_root(void)
return 0;
}
/*
* Convert a string to lower case
*/
void strlow(char *s)
{
while (*s) {
*s = tolower(*s);
s++;
}
}
/*
* Read a string from a particular file
*/
void read_str(char *string, const char *path, size_t len)
{
size_t rc;
FILE *fh;
fh = fopen(path, "rb");
if (fh == NULL)
ERR_EXIT_ERRNO("Could not open \"%s\"", path);
rc = fread(string, 1, len - 1, fh);
if (rc == 0 && ferror(fh))
ERR_EXIT_ERRNO("Could not read \"%s\"", path);
fclose(fh);
string[rc] = 0;
if (string[strlen(string) - 1] == '\n')
string[strlen(string) - 1] = 0;
}
/*
* Read a string from a particular /sys/firmware file
*/
void read_fw_str(char *string, const char *file, size_t len)
char *read_fw_str(const char *file)
{
char *string;
char *path;
util_asprintf(&path, "/sys/firmware/%s", file);
read_str(string, path, len);
path = util_path_sysfs("firmware/%s", file);
string = util_file_read_text_file(path, 1);
free(path);
return string;
}
/*
@@ -94,11 +66,13 @@ void read_fw_str(char *string, const char *file, size_t len)
*/
void print_fw_str(const char *fmt, const char *dir, const char *file)
{
char path[PATH_MAX], str[4096];
char path[PATH_MAX];
char *str;
snprintf(path, sizeof(path), "%s/%s", dir, file);
read_fw_str(str, path, sizeof(str));
str = read_fw_str(path);
printf(fmt, str);
free(str);
}
/*
@@ -106,17 +80,19 @@ void print_fw_str(const char *fmt, const char *dir, const char *file)
*/
void write_str(char *string, char *file)
{
char path[PATH_MAX], value[4096];
char value[4096];
char *path;
int fh;
path = util_path_sysfs("firmware/%s", file);
snprintf(value, sizeof(value), "%s\n", string);
snprintf(path, sizeof(path), "/sys/firmware/%s", file);
fh = open(path, O_WRONLY);
if (fh < 0)
ERR_EXIT_ERRNO("Could not open \"%s\"", file);
if (write(fh, value, strlen(value)) < 0)
ERR_EXIT_ERRNO("Could not set \"%s\"", file);
close(fh);
free(path);
}
/*
@@ -124,17 +100,18 @@ void write_str(char *string, char *file)
*/
int write_str_errno(char *string, char *file)
{
char path[PATH_MAX], value[4096];
char value[4096];
char *path;
int fh;
path = util_path_sysfs("firmware/%s", file);
snprintf(value, sizeof(value), "%s\n", string);
snprintf(path, sizeof(path), "/sys/firmware/%s", file);
fh = open(path, O_WRONLY);
if (fh < 0)
return errno;
if (write(fh, value, strlen(value)) < 0)
return errno;
close(fh);
free(path);
return 0;
}

View File

@@ -15,6 +15,7 @@ install-man: $(MANS)
msection=`echo $$man |sed 's/.*\.\([1-9]\)$$/man\1/'` ; \
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 -D $$man $(DESTDIR)$(MANDIR)/$$msection/$$man ; \
done
ln -f -s chiucvallow.8 $(DESTDIR)$(MANDIR)/man8/lsiucvallow.8
clean:

View File

@@ -66,7 +66,7 @@ terminal application
To connect to the first z/VM IUCV HVC terminal device on the z/VM guest virtual
machine "LNX1234", run:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvconn LNX1234 lnxhvc0
@@ -215,7 +215,7 @@ For each HVC terminal device, a \fBgetty\fP program must be started.
To configure and start \fBgetty\fP on a HVC terminal, open
.BR /etc/inittab (5),
and add a new entry similar to this one:
.ft CW
.ft CR
.in +0.25in
.nf
@@ -261,7 +261,7 @@ IUCV HVC terminal:
.IP "1." 4
To display the current terminal name, issue the command:
.ft CW
.ft CR
.in +0.25in
.nf
user@host:~$ echo $TERM
@@ -275,7 +275,7 @@ To connect to a z/VM IUCV HVC terminal, run
.BR iucvconn (1)
and log in as usual:
.ft CW
.ft CR
.in +0.25in
.nf
user@host:~$ iucvconn MYLNX01 lnxhvc0
@@ -289,7 +289,7 @@ user@MYLNX01:~$
To assign the terminal name from step 1. to the terminal environment variable,
issue the following command:
.ft CW
.ft CR
.in +0.25in
.nf
user@MYLNX01:~$ export TERM=xterm
@@ -304,7 +304,7 @@ environment variable.
.PP
For getty programs, a sample terminal environment configuration might look like:
.ft CW
.ft CR
.in +0.25in
.nf
h0:2345:respawn:/sbin/agetty -L 9600 hvc0 linux

View File

@@ -123,7 +123,7 @@ the characters to the connected terminal.
To access the "lnxterm" terminal on the Linux instance in
z/VM guest virtual machine LNXSYS01:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvconn LNXSYS01 lnxterm
@@ -134,7 +134,7 @@ iucvconn LNXSYS01 lnxterm
To access the first z/VM IUCV HVC terminal on the Linux instance in
z/VM guest virtual machine LNXSYS02:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvconn LNXSYS02 lnxhvc0
@@ -145,7 +145,7 @@ iucvconn LNXSYS02 lnxhvc0
To create a transcript of the terminal session to the Linux instance in
z/VM guest virtual machine LNXSYS99:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvconn -s ~/transcripts/lnxsys99 LNXSYS99 lnxhvc0

View File

@@ -94,7 +94,7 @@ additional options.
.SH EXAMPLES
To allow remote logins using the terminal identifier "lnxterm":
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvtty lnxterm
@@ -104,7 +104,7 @@ iucvtty lnxterm
To only allow users from LNXSYS01 to connect to terminal "lnxterm":
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvtty -a LNXSYS01 lnxterm
@@ -115,7 +115,7 @@ iucvtty -a LNXSYS01 lnxterm
To only allow users from LNXSYS10 through LNXSYS19 to connect to terminal
"lnxterm":
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvtty -a "LNXSYS1[0-9]" lnxterm
@@ -125,7 +125,7 @@ iucvtty -a "LNXSYS1[0-9]" lnxterm
To use \fB/sbin/sulogin\fP instead of \fB/bin/login\fP for terminal "suterm":
.PP
.ft CW
.ft CR
.in +0.25in
.nf
iucvtty suterm -- /sbin/sulogin
@@ -136,7 +136,7 @@ iucvtty suterm -- /sbin/sulogin
An entry in \fB/etc/inittab\fP to facilitate user logins on terminal "lnxterm"
with \fB/bin/login\fP could be:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
t1:2345:respawn:/usr/bin/iucvtty lnxterm
@@ -147,7 +147,7 @@ t1:2345:respawn:/usr/bin/iucvtty lnxterm
An entry in \fB/etc/inittab\fP to facilitate user logins on terminal "suterm"
with \fB/sbin/sulogin\fP in single user mode could be:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
s1:S:respawn:/usr/bin/iucvtty suterm -- /sbin/sulogin

View File

@@ -79,7 +79,7 @@ users".
The output for "list" authorization is a list of z/VM guest virtual machines,
for example:
.ft CW
.ft CR
.in +0.25i
.nf
@@ -94,7 +94,7 @@ guest5
.ft
The output for "regex" authorization is a list of one or more
regular expressions, for example:
.ft CW
.ft CR
.in +0.25i
.nf
@@ -109,7 +109,7 @@ Regular expressions for your authorization:
If \fBts-shell\fP is configured to connect to particular z/VM guest virtual
machines only, the output for "regex" authorization is followed by a list of
the user IDs that match at least one of the regular expressions:
.ft CW
.ft CR
.in +0.25i
.nf
@@ -139,7 +139,7 @@ To change the default terminal identifier, use the \fBterminal\fP command.
In the following example, a user opens a terminal connection to the Linux
instance in z/VM guest virtual machine LNXSYS01:
.ft CW
.ft CR
.in +0.25i
.nf
@@ -164,7 +164,7 @@ If \fBterminal\fP is called with the \fIidentifier\fP being specified,
If \fIidentifier\fP is not specified, the current default terminal identifier
is displayed:
.ft CW
.ft CR
.in +0.25i
.nf
user@ts-shell> terminal
@@ -212,7 +212,7 @@ guest virtual machines.
A typical \fBIUCV\fP authorization statement in the z/VM directory entry of the
terminal server z/VM guest virtual machine might be:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
IUCV ANY
@@ -301,7 +301,7 @@ instance.
For example, to create a list of all z/VM guest virtual machines with names that
start with "LINUX" and are followed by digits, use:
.ft CW
.ft CR
.in +0.25in
.nf
@@ -373,7 +373,7 @@ group name and prefixed with "@".
Here is an example of a Linux user and group authorization:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
alice = list:guest01,guest02
@@ -395,7 +395,7 @@ name on a separate line.
.PP
The following example shows the usage of the \fIfile:\fP prefix:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
@testgrp = file:/etc/iucvterm/auth/test-systems.list
@@ -427,7 +427,7 @@ To authorize user bob for all z/VM guest virtual machines with names that
start with "lnx" and are followed with at least three but not more than five
alphanumeric characters, use:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
bob = regex:lnx\\w{3,5}
@@ -441,7 +441,7 @@ test or production environment: authorize all users in the "testgrp" group for
all systems in the test environment; and respectively, authorize all users in
the "prodgrp" group for all systems in the production environment:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
@testgrp = regex:test\\w+
@@ -461,7 +461,7 @@ of the other type are ignored.
Example:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
@users = list:guest01,guest03,guest05
@@ -484,7 +484,7 @@ To use the \fBts-shell\fP as the login shell for Linux users, follow these steps
Add the path of the \fBts-shell\fP program to the \fI/etc/shells\fP file that
contains the list of valid login shells:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
echo $(which ts-shell) >> /etc/shells
@@ -498,7 +498,7 @@ Change the login shell of a particular Linux user using the
.BR chsh (1)
program:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
chsh -s $(which ts-shell) alice

View File

@@ -116,7 +116,7 @@ specifies an exit status in this range.
.SS inittab
To start \fB/sbin/agetty\fP on terminal device "hvc1", specify:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
h1:2345:respawn:/sbin/\*s hvc1 /sbin/agetty -L 9600 %t linux
@@ -128,7 +128,7 @@ h1:2345:respawn:/sbin/\*s hvc1 /sbin/agetty -L 9600 %t linux
To start \fB/sbin/agetty\fP on terminal device "hvc1", add the following
settings to the job file:
.PP
.ft CW
.ft CR
.in +0.25in
.nf
respawn

View File

@@ -10,7 +10,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include "lib/ccw.h"

View File

@@ -7,7 +7,8 @@ examples = libcpumf_example
all: $(lib)
examples: $(lib) $(examples)
objects = libcpumf_pmutype.o libcpumf_cpuset.o libcpumf_support.o
objects = libcpumf_pmutype.o libcpumf_cpuset.o libcpumf_support.o \
libcpumf_ctrset.o
$(lib): $(objects)

View File

@@ -5,20 +5,23 @@
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lib/libcpumf.h"
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_path.h"
int libcpumf_cpuset(const char *parm, cpu_set_t *mask)
{
char *cp, *buffer = strdup(parm);
char *cp, *buffer = util_strdup(parm);
char *cp2 = buffer;
int to, from, rc;
if (!buffer) /* Errno set to ENOMEM */
return -1;
/* Check for invalid characters, such as 11.12 instead 11-12
* but allow blanks and newline. Newline is appended
* when the string is taken from sysfs files, for example
@@ -26,7 +29,8 @@ int libcpumf_cpuset(const char *parm, cpu_set_t *mask)
*/
if (strspn(buffer, "0123456789-,\n ") != strlen(buffer)) {
errno = EINVAL;
return -1;
rc = -1;
goto out;
}
CPU_ZERO(mask);
for (; (cp = strtok(buffer, ",")); buffer = NULL) {
@@ -51,25 +55,19 @@ int libcpumf_cpuset(const char *parm, cpu_set_t *mask)
}
rc = 0;
out:
free(buffer);
free(cp2);
return rc;
}
int libcpumf_cpuset_fn(const char *filename, cpu_set_t *mask)
{
char *txt = NULL;
ssize_t ret = -1;
size_t len = 0;
FILE *fp;
char *path = util_path_sysfs(filename);
char txt[PATH_MAX];
int ret = util_file_read_line(txt, sizeof(txt), "%s", path);
fp = fopen(filename, "r");
if (!fp)
return ret;
free(path);
/* Read out file, one line expected */
ret = getline(&txt, &len, fp);
fclose(fp);
if (ret > 0)
if (!ret)
ret = libcpumf_cpuset(txt, mask);
free(txt);
return ret;
}

View File

@@ -0,0 +1,53 @@
/* Copyright IBM Corp. 2022, 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.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "lib/libcpumf.h"
int libcpumf_ctrset(int ctr, int cfvn, int csvn)
{
/* Governs basic and problem state counters */
switch (cfvn) {
case 1:
if (ctr >= 0 && ctr < 32)
return CPUMF_CTRSET_BASIC;
if (ctr >= 32 && ctr < 38)
return CPUMF_CTRSET_PROBLEM_STATE;
break;
case 3:
if (ctr >= 0 && ctr < 32)
return CPUMF_CTRSET_BASIC;
if (ctr >= 32 && ctr < 34)
return CPUMF_CTRSET_PROBLEM_STATE;
break;
}
/* Governs crypto, extended and MT-Diagnositc counters */
switch (csvn) {
case 1 ... 5:
if (ctr >= 64 && ctr < 80)
return CPUMF_CTRSET_CRYPTO;
if ((csvn == 1 && ctr >= 128 && ctr < 160) ||
(csvn == 2 && ctr >= 128 && ctr < 176) ||
(ctr >= 128 && ctr < 256))
return CPUMF_CTRSET_EXTENDED;
break;
case 6 ... 8:
if (ctr >= 64 && ctr < 84)
return CPUMF_CTRSET_CRYPTO;
if (ctr >= 128 && ctr < 288)
return CPUMF_CTRSET_EXTENDED;
break;
}
if (csvn >= 3 && ctr >= 448 && ctr < 496)
return CPUMF_CTRSET_MT_DIAG;
return CPUMF_CTRSET_NONE;
}

View File

@@ -1,4 +1,4 @@
/* Copyright IBM Corp. 2022
/* Copyright IBM Corp. 2022, 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -18,16 +18,13 @@
int libcpumf_pmutype(const char *dirname)
{
int ret = -1;
FILE *file;
char *fn;
int ret;
ret = asprintf(&fn, "%s/type", dirname);
if (ret == -1) /* No memory, errno set */
return ret;
fn = util_path_sysfs("%s/type", dirname);
file = fopen(fn, "r");
free(fn);
ret = -1; /* Errno set on file open error */
if (file) {
/* Read out a single number from that file */
if (fscanf(file, "%u", &ret) != 1)

View File

@@ -13,6 +13,8 @@
#include <sys/stat.h>
#include "lib/libcpumf.h"
#include "lib/util_path.h"
#include "lib/util_libc.h"
#define SERVICELEVEL "/proc/service_levels"
@@ -129,34 +131,70 @@ bool libcpumf_have_sfb(void)
bool libcpumf_sfb_info(unsigned long *min, unsigned long *max)
{
int rc = false;
char *path;
FILE *fp;
fp = fopen(S390_CPUMSF_BUFFERSZ, "r");
path = util_path_sysfs(S390_CPUMSF_BUFFERSZ);
fp = fopen(path, "r");
if (!fp)
err(EXIT_FAILURE, "%s", S390_CPUMSF_BUFFERSZ);
err(EXIT_FAILURE, "%s", path);
if (fscanf(fp, "%lu,%lu", min, max) == 2)
rc = true;
fclose(fp);
free(path);
return rc;
}
static bool libcpumf_have_pai_sysfs(char *p)
{
char *path;
bool ret;
path = util_path_sysfs(p);
ret = util_path_exists(path);
free(path);
return ret;
}
bool libcpumf_have_pai_crypto(void)
{
struct stat statbuf;
return (stat(S390_SYSFS_PAI_CRYPTO, &statbuf) == -1) ? false : true;
return libcpumf_have_pai_sysfs(S390_SYSFS_PAI_CRYPTO);
}
bool libcpumf_have_pai_ext(void)
{
struct stat statbuf;
return (stat(S390_SYSFS_PAI_EXT, &statbuf) == -1) ? false : true;
return libcpumf_have_pai_sysfs(S390_SYSFS_PAI_EXT);
}
bool libcpumf_have_pai_nnpa(void)
{
struct stat statbuf;
return (stat(S390_SYSFS_PAI_NNPA, &statbuf) == -1) ? false : true;
return libcpumf_have_pai_sysfs(S390_SYSFS_PAI_NNPA);
}
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd,
unsigned long flags)
{
return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
}
bool ctr_in_list(char *name, char *ctrlist)
{
char *token;
char *list;
if (!ctrlist) /* No --counters means all counters */
return true;
list = util_strdup(ctrlist);
token = strtok(list, ",");
while (token) {
if (strcmp(token, name) == 0) {
free(list);
return true;
}
token = strtok(NULL, ",");
}
free(list);
return false;
}

View File

@@ -5099,14 +5099,15 @@ int ekmf_generate_csr(const struct ekmf_config *config,
}
}
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
if (rsa_pss_params != NULL)
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
rc = SK_OPENSSL_generate_csr(key_blob, key_blob_size,
subject_rdns, num_subject_rdns,
subject_utf8, cert,
extensions, num_extensions,
digest_nid, &pss_params, &req,
digest_nid, rsa_pss_params != NULL ?
&pss_params : NULL, &req,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "SK_OPENSSL_generate_csr failed "
@@ -5245,14 +5246,16 @@ int ekmf_generate_ss_cert(const struct ekmf_config *config,
}
}
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
if (rsa_pss_params != NULL)
_ekmf_copy_pss_params(rsa_pss_params, &pss_params);
rc = SK_OPENSSL_generate_ss_cert(key_blob, key_blob_size,
subject_rdns, num_subject_rdns,
subject_utf8, rcert,
extensions, num_extensions,
validity_days, digest_nid,
&pss_params, &cert,
rsa_pss_params != NULL ?
&pss_params : NULL, &cert,
&ext_lib_info.ext_lib, verbose);
if (rc != 0) {
pr_verbose(verbose, "SK_OPENSSL_generate_ss_cert failed "

View File

@@ -2432,7 +2432,7 @@ out:
kmip_node_free(iv);
kmip_node_free(tag);
kmip_node_free(ffl);
kmip_node_free(ffl);
kmip_node_free(ifl);
kmip_node_free(cnt);
kmip_node_free(icv);
kmip_node_free(salt);

View File

@@ -1471,7 +1471,7 @@ retry:
chain = SSL_get_peer_cert_chain(conn->plain_tls.ssl);
if (chain == NULL) {
kmip_debug(debug, "SSL_get_peer_cert_chain failed");
return -EIO;
rc = -EIO;
goto out;
}

View File

@@ -210,6 +210,8 @@ struct kmip_node *kmip_new_request_header(const struct kmip_version *version,
out:
kmip_node_free(ver);
kmip_node_free(max);
kmip_node_free(ccorr);
kmip_node_free(scorr);
kmip_node_free(async);
kmip_node_free(err);
kmip_node_free(ord);

View File

@@ -1369,7 +1369,7 @@ int kmip_get_get_response_payload(const struct kmip_node *node,
return 0;
error:
if (*unique_id != NULL) {
if (unique_id != NULL && *unique_id != NULL) {
kmip_node_free(*unique_id);
*unique_id = NULL;
}

View File

@@ -351,7 +351,6 @@ int kmip_connection_tls_init(struct kmip_connection *conn, bool debug)
if (tok == NULL) {
kmip_debug(debug, "malformed IPv6 address");
rc = -EINVAL;
free(hostname);
goto out;
}
tok++;

View File

@@ -1501,6 +1501,9 @@ int SK_EP11_reencipher_key(const struct sk_ext_ep11_lib *ep11_lib,
return -ENODEV;
}
memset(&rb, 0, sizeof(rb));
memset(&lrb, 0, sizeof(lrb));
rb.domain = domain;
lrb.domain = domain;

View File

@@ -97,6 +97,9 @@ const char *util_arch_machine_type_to_str(int type)
case UTIL_ARCH_MACHINE_TYPE_Z16:
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
return "IBM z16";
case UTIL_ARCH_MACHINE_TYPE_Z17:
case UTIL_ARCH_MACHINE_TYPE_Z17_2:
return "IBM z17";
default:
return "Unknown machine type";
}

View File

@@ -616,6 +616,10 @@ char *util_file_read_fd(FILE *fd, int chomp)
if (util_file_read_fd_buf(fd, (void **) &buffer, &done))
return NULL;
/* Prevent over-read if buffer is larger than amount of read characters */
if (buffer)
done = MIN(done, strnlen(buffer, done));
/* Check if this is a text file at all (required to filter out
* binary sysfs attributes).
*/

View File

@@ -307,9 +307,13 @@ static void add_key(const char *name, bool persist)
key.persist = persist;
util_add_array(&f.keys, &f.num_keys, key);
if (f.type == FMT_CSV) {
hdr = csv_quote(name);
util_rec_def(f.csv_rec, name, UTIL_REC_ALIGN_LEFT, 0, hdr);
free(hdr);
if (f.quote_all) {
hdr = csv_quote(name);
util_rec_def(f.csv_rec, name, UTIL_REC_ALIGN_LEFT, 0, hdr);
free(hdr);
} else {
util_rec_def(f.csv_rec, name, UTIL_REC_ALIGN_LEFT, 0, name);
}
util_rec_set(f.csv_rec, name, "\"\"");
f.csv_hdr = true;
}

33
libutil/util_str.c Normal file
View File

@@ -0,0 +1,33 @@
/*
* util - Utility function library
*
* Manipulate and work with strings
*
* Copyright IBM Corp. 2025
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <ctype.h>
#include "lib/util_str.h"
/**
* Copy characters from \a src to \a dest, omitting all blank characters
* (spaces and tabs). The resulting string in \a dest will be NUL terminated.
*
* @param[in] src Source string
* @param[out] dest Destination buffer
*/
void util_str_rm_whitespace(const char *src, char *dest)
{
while (*src != '\0') {
if (!isblank(*src)) {
*dest = *src;
dest++;
}
src++;
}
*dest = '\0';
}

View File

@@ -89,7 +89,7 @@ Socket communication with applications utilizing CMS AF_IUCV support
An AF_IUCV socket is represented by the following format:
.PP
.RS 8
.ft CW
.ft CR
.nf
#define AF_IUCV 32
@@ -290,7 +290,7 @@ It must not match any z/VM user ID in your environment.
To set an identifier, issue a command like this:
.PP
.RS 8
.ft CW
.ft CR
echo \fIidentifier\fP > /sys/devices/qeth/\fI<bus-ID>\fP/hsuid
.ft
.RE
@@ -303,7 +303,7 @@ For example, to use "MYHOST01" to bind AF_IUCV sockets to the
HiperSockets device with bus-ID 0.0.8000, run:
.PP
.RS 8
.ft CW
.ft CR
.nf
echo "MYHOST01" > /sys/devices/qeth/0.0.8000/hsuid
.fi
@@ -366,7 +366,7 @@ z/VM guest virtual machine with a maximum of 10\^000 outstanding messages for ea
incoming connection. Your z/VM guest virtual machine is permitted to connect to
all other z/VM guest virtual machines. The total number of connections for your
z/VM guest virtual machine cannot exceed 100.
.ft CW
.ft CR
.in +0.25i
.nf

View File

@@ -16,6 +16,19 @@
. if !'\\$1'' .IP "\fB\-\-\\$1\fP \\*[args]" 4
. PD
..
.\" Macro for inserting code line.
.\" .CL <text>
.de CL
. ds pfont \fP
. nh
. na
. ft CR
\\$*
. ft \\*[pfont]
. ad
. hy
. br
..
.
.TH opticsmon 8 "Oct 2024" s390-tools zpcictl
.
@@ -67,8 +80,7 @@ on".
.B Example: Extract module information for the first adapter
.CL
opticsmon --module-info | jq -r '.adapters[0].netdevs[0].optics.module_info' | base64 -d | hexdump -C
.CL opticsmon --module-info | jq -r '.adapters[0].netdevs[0].optics.module_info' | base64 -d | hexdump -C
.PP
.PP
.

182
rust/Cargo.lock generated
View File

@@ -47,7 +47,7 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -57,7 +57,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -190,7 +190,7 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "cpacfinfo"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"anyhow",
"cc",
@@ -205,9 +205,9 @@ dependencies = [
[[package]]
name = "curl"
version = "0.4.47"
version = "0.4.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265"
checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc"
dependencies = [
"curl-sys",
"libc",
@@ -215,14 +215,14 @@ dependencies = [
"openssl-sys",
"schannel",
"socket2",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
name = "curl-sys"
version = "0.4.78+curl-8.11.0"
version = "0.4.83+curl-8.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eec768341c5c7789611ae51cf6c459099f22e64a5d5d0ce4892434e33821eaf"
checksum = "5830daf304027db10c82632a464879d46a3f7c4ba17a31592657ad16c719b483"
dependencies = [
"cc",
"libc",
@@ -230,7 +230,7 @@ dependencies = [
"openssl-sys",
"pkg-config",
"vcpkg",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@@ -318,7 +318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -356,13 +356,25 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "getrandom"
version = "0.2.15"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
@@ -429,9 +441,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.169"
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libz-sys"
@@ -489,9 +501,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "openssl"
version = "0.10.70"
version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags",
"cfg-if",
@@ -521,9 +533,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.105"
version = "0.9.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc"
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
dependencies = [
"cc",
"libc",
@@ -539,9 +551,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
@@ -557,9 +569,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.93"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
@@ -575,8 +587,8 @@ dependencies = [
"bitflags",
"lazy_static",
"num-traits",
"rand",
"rand_chacha",
"rand 0.8.5",
"rand_chacha 0.3.1",
"rand_xorshift",
"regex-syntax",
"rusty-fork",
@@ -586,13 +598,13 @@ dependencies = [
[[package]]
name = "pvapconfig"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"clap",
"clap_complete",
"lazy_static",
"openssl",
"rand",
"rand 0.9.1",
"regex",
"s390_pv_core",
"serde",
@@ -602,7 +614,7 @@ dependencies = [
[[package]]
name = "pvattest"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"anyhow",
"base64",
@@ -622,7 +634,7 @@ dependencies = [
[[package]]
name = "pvimg"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"anyhow",
"clap",
@@ -642,7 +654,7 @@ dependencies = [
[[package]]
name = "pvsecret"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"anyhow",
"clap",
@@ -661,13 +673,19 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.38"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
[[package]]
name = "radium"
version = "0.7.0"
@@ -681,8 +699,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
]
[[package]]
@@ -692,7 +720,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@@ -701,7 +739,16 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
"getrandom 0.2.16",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.2",
]
[[package]]
@@ -710,7 +757,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
dependencies = [
"rand_core",
"rand_core 0.6.4",
]
[[package]]
@@ -752,7 +799,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -781,7 +828,7 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "s390_pv"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"byteorder",
"curl",
@@ -799,12 +846,13 @@ dependencies = [
[[package]]
name = "s390_pv_core"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"byteorder",
"lazy_static",
"libc",
"log",
"regex",
"serde",
"serde_test",
"thiserror",
@@ -817,7 +865,7 @@ version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
dependencies = [
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -881,12 +929,12 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "socket2"
version = "0.5.8"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
dependencies = [
"libc",
"windows-sys 0.52.0",
"windows-sys",
]
[[package]]
@@ -897,9 +945,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.96"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
@@ -920,10 +968,10 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
dependencies = [
"cfg-if",
"fastrand",
"getrandom",
"getrandom 0.2.16",
"once_cell",
"rustix",
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -933,7 +981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
dependencies = [
"rustix",
"windows-sys 0.59.0",
"windows-sys",
]
[[package]]
@@ -981,15 +1029,15 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unsafe-libyaml"
version = "0.2.8"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6"
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
[[package]]
name = "utf8parse"
@@ -999,7 +1047,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "utils"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"clap",
"libc",
@@ -1030,12 +1078,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows-sys"
version = "0.52.0"
name = "wasi"
version = "0.14.2+wasi-0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
dependencies = [
"windows-targets",
"wit-bindgen-rt",
]
[[package]]
@@ -1120,6 +1168,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags",
]
[[package]]
name = "wyz"
version = "0.5.1"
@@ -1131,19 +1188,18 @@ dependencies = [
[[package]]
name = "zerocopy"
version = "0.7.35"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
version = "0.8.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -14,7 +14,7 @@ ifneq (${HAVE_CARGO},0)
CARGO_TARGETS :=
BUILD_TARGETS = $(CARGO_TARGETS)
INSTALL_TARGETS := install-rust-tools install-man
INSTALL_TARGETS := install-rust-tools install-man install-shell-completions
CARGO_TEST_TARGETS = $(addsuffix .test, $(CARGO_TARGETS))
ifeq ($(HOST_ARCH),s390x)
@@ -86,7 +86,6 @@ install: $(INSTALL_TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(USRBINDIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 pvattest/tools/pvextract-hdr $(DESTDIR)$(USRBINDIR)
$(INSTALL) -d -m 755 $(DESTDIR)$(PVIMG_PKGDATADIR)
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 pvimg/tools/check_hostkeydoc $(DESTDIR)$(PVIMG_PKGDATADIR)
$(MAKE) -C pvimg/boot install
ln -sf pvimg $(DESTDIR)$(USRBINDIR)/genprotimg
@@ -115,8 +114,21 @@ install-man:
$(INSTALL) -m 644 $(target)/man/*.1 -t $(DESTDIR)$(MANDIR)/man1;)
$(foreach target,$(PV_TARGETS),\
$(INSTALL) -m 644 $(target)/man/*.1 -t $(DESTDIR)$(MANDIR)/man1;)
ln -sf pvimg-create.1 $(DESTDIR)$(MANDIR)/man1/genprotimg.1
.PHONY: all install clean skip-build install-rust-tools print-rust-targets install-man rust-test
install-shell-completions: install-bash-completion install-zsh-completion
install-bash-completion: $(PV_TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(BASHCOMPLETIONDIR)
$(foreach target,$(PV_TARGETS),\
$(INSTALL) -m 0644 --preserve-timestamps -- $(shell find $(shell ls --sort=time --reverse --directory target/release/build/$(target)-*/out/ |tail -n1) -name '*.bash') $(DESTDIR)$(BASHCOMPLETIONDIR);)
install-zsh-completion: $(PV_TARGETS)
$(INSTALL) -d -m 755 $(DESTDIR)$(ZSHCOMPLETIONDIR)
$(foreach target,$(PV_TARGETS),\
$(INSTALL) -m 0644 --preserve-timestamps -- $(shell find $(shell ls --sort=time --reverse --directory target/release/build/$(target)-*/out/ |tail -n1) -regex '.*/_[a-zA-Z0-9]+') $(DESTDIR)$(ZSHCOMPLETIONDIR);)
.PHONY: all install clean skip-build install-rust-tools print-rust-targets install-man rust-test install-bash-completion install-zsh-completion install-shell-completions
.check-cargo:
ifeq ($(shell command -v $(CARGO)),)

View File

@@ -1,6 +1,6 @@
[package]
name = "cpacfinfo"
version = "0.11.0"
version = "0.12.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
@@ -12,7 +12,7 @@ libc = "0.2"
serde = { version = "1.0.217", features = ["derive"] }
serde_json = "1.0"
utils = { path = "../utils" }
zerocopy = { version="0.7", features = ["derive"] }
zerocopy = { version="0.8", features = ["derive"] }
[build-dependencies]
cc = "1.2"

View File

@@ -124,8 +124,8 @@ Possible values for
Displays the CPACF subfunctions available on the system.
.B cpacfinfo \-f/\-\-functions
is the same as
.B cpacfinfo \-f/\-\-functions \-a/\-\-available
. If
\fBcpacfinfo \-f/\-\-functions \-a/\-\-available\fR.
If
.B -n/\-\-not-available
is specified no available functions are shown. To get available as well as functions not available use
.B cpacfinfo \-f/\-\-functions \-a/\-\-available \-n/\-\-not-available.

View File

@@ -9,7 +9,6 @@ use std::ops::Index;
use std::result::Result;
use zerocopy::FromBytes;
use zerocopy::FromZeroes;
use crate::msa::InstructionKind;
use crate::msa::QueryAuthInfo;
@@ -33,7 +32,7 @@ pub const QAI_PARAM_SIZE_IN_BYTES: usize = 256;
/// Query authentication information format identifier
const FORMAT_0: u8 = 0;
#[derive(FromBytes, FromZeroes)]
#[derive(FromBytes)]
#[repr(C)]
struct QaiFmt0 {
res00: [u8; 6],
@@ -175,7 +174,7 @@ pub fn check_sysfs() -> bool {
/// -----------------------------------------------------------------
fn parse_qai_format_0(qai: &mut QueryAuthInfo, param: &[u8]) {
// parse param to temporary struct to ease further conversion
let tmp = QaiFmt0::read_from_prefix(param).expect("programming error");
let (tmp, _) = QaiFmt0::read_from_prefix(param).expect("programming error");
// parse from temporary struct
qai.hash_len = tmp.hash_length;

View File

@@ -1,6 +1,6 @@
[package]
name = "s390_pv"
version = "0.11.0"
version = "0.12.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
@@ -23,9 +23,9 @@ openssl = "0.10.70"
openssl-sys = "0.9.105"
serde = { version = "1.0.217", features = ["derive"] }
thiserror = "2.0.11"
zerocopy = { version="0.7", features = ["derive"] }
zerocopy = { version="0.8", features = ["derive"] }
pv_core = { path = "../pv_core", package = "s390_pv_core", version = "0.11.0" }
pv_core = { path = "../pv_core", package = "s390_pv_core", version = "0.12.0" }
[dev-dependencies]
serde_test = "1.0.177"

View File

@@ -0,0 +1,28 @@
#![allow(missing_docs)]
use pv::request::EcPubKeyCoord;
use pv_core::misc::encode_hex;
use s390_pv as pv;
use std::env::args;
use pv::misc::{read_certs, read_file};
use pv::{Error, Result};
fn main() -> Result<()> {
let hkd = args().nth(1).expect("Expect one Host-key document");
let hkd_bin = read_file(&hkd, "Host-key document")?;
let certs = read_certs(hkd_bin).map_err(|source| Error::HkdNotPemOrDer { hkd, source })?;
let hkd_cert = certs
.first()
.expect("Expect at least one certificate in the HKD file");
let pc: EcPubKeyCoord = hkd_cert
.public_key()
.expect("Expected a public key in the Host-key document")
.try_into()
.unwrap();
println!("{}", encode_hex(pc.sha256().unwrap()));
Ok(())
}

View File

@@ -8,7 +8,7 @@ use std::{
};
use log::{debug, warn};
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32, U64};
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U32, U64};
// (SE) boot request control block aka SE header
use crate::{assert_size, request::MagicValue, static_assert, Error, Result, PAGESIZE};
@@ -21,7 +21,7 @@ use crate::{assert_size, request::MagicValue, static_assert, Error, Result, PAGE
/// Tweak List Digest (tld)
/// SE-Header Tag (tag)
#[repr(C)]
#[derive(Debug, Clone, Copy, AsBytes, PartialEq, Eq, FromBytes, FromZeroes)]
#[derive(Debug, Clone, Copy, IntoBytes, PartialEq, Eq, FromBytes, Immutable, KnownLayout)]
pub struct BootHdrTags {
pld: [u8; BootHdrHead::DIGEST_SIZE],
ald: [u8; BootHdrHead::DIGEST_SIZE],
@@ -40,8 +40,8 @@ impl TryFrom<Vec<u8>> for BootHdrTags {
type Error = Error;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
Self::ref_from(&value)
.ok_or_else(|| Error::InvBootHdrSize(value.len()))
Self::ref_from_bytes(&value)
.map_err(|_| Error::InvBootHdrSize(value.len()))
.copied()
}
}
@@ -49,7 +49,7 @@ impl TryFrom<Vec<u8>> for BootHdrTags {
/// Struct representing the Secure Execution boot image metadata
#[allow(unused)]
#[repr(packed)]
#[derive(Debug, Clone, FromBytes, FromZeroes, AsBytes, PartialEq, Eq)]
#[derive(Debug, Clone, FromBytes, IntoBytes, PartialEq, Eq, Immutable, KnownLayout)]
pub struct SeImgMetaData {
/// Magic value
magic: [u8; 8],
@@ -106,7 +106,7 @@ impl SeImgMetaData {
/// Gets the bytes of this value.
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
<Self as AsBytes>::as_bytes(self)
<Self as IntoBytes>::as_bytes(self)
}
/// Returns the version of this [`SeImgMetaData`].
@@ -154,7 +154,7 @@ where
// read in the header
img.read_exact(&mut img_metadata_bytes)?;
// Cannot fail because the buffer has the same size as SeImgMetaData.
let img_metadata = SeImgMetaData::ref_from(&img_metadata_bytes).unwrap();
let img_metadata = SeImgMetaData::ref_from_bytes(&img_metadata_bytes).unwrap();
let img_metadata_version = img_metadata.version();
if img_metadata_version != SeImgMetaData::V1 {
warn!("Unknown Secure Execution boot image version {img_metadata_version}");
@@ -226,8 +226,8 @@ impl BootHdrTags {
}
let hdr_head = match BootHdrHead::read_from_prefix(hdr.as_mut_slice()) {
Some(hdr) => hdr,
None => {
Ok((hdr, _)) => hdr,
Err(_) => {
debug!("Boot hdr is too small");
return Err(Error::InvBootHdr);
}
@@ -260,7 +260,7 @@ impl BootHdrTags {
}
#[repr(C)]
#[derive(Debug, Clone, FromBytes, FromZeroes)]
#[derive(Debug, Clone, FromBytes)]
struct BootHdrHead {
magic: U64<BigEndian>,
version: U32<BigEndian>,
@@ -388,7 +388,7 @@ mod tests {
0, 1, 96, 0,
];
assert_eq!(metadata.as_bytes(), &data);
assert_eq!(SeImgMetaData::ref_from(&data), Some(&metadata));
assert_eq!(SeImgMetaData::ref_from_bytes(&data), Ok(&metadata));
assert_eq!(metadata.version(), SeImgMetaData::V1);
}

View File

@@ -361,7 +361,7 @@ pub fn encrypt_aead(
aad: &[u8],
conf: &[u8],
) -> Result<AeadEncryptionResult> {
let tag_len = key.key_type().tag_len().ok_or_else(|| Error::NoAeadKey)?;
let tag_len = key.key_type().tag_len().ok_or(Error::NoAeadKey)?;
let nid = key.key_type().into();
let cipher = Cipher::from_nid(nid).ok_or(Error::UnsupportedCipher(nid))?;

View File

@@ -12,7 +12,7 @@ use openssl::{
pkey::{PKey, PKeyRef, Private, Public},
};
use pv_core::request::{RequestMagic, RequestVersion};
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32};
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U32};
use crate::{
assert_size,
@@ -358,7 +358,7 @@ ecdh_from!(Public);
/// Representation of the shared parts of the request header.
/// Used by [`ReqEncrCtx`]
#[repr(C)]
#[derive(Debug, Copy, Clone, AsBytes, FromBytes, FromZeroes)]
#[derive(Debug, Copy, Clone, IntoBytes, FromBytes, Immutable)]
struct RequestHdr {
magic: [u8; 8],
rqvn: U32<BigEndian>,
@@ -449,7 +449,7 @@ impl<'a> BinReqValues<'a> {
/// Does minimal sanity test, just tests to prevent panics.
/// `req` may be larger than the actual request.
pub(crate) fn get(req: &'a [u8]) -> Result<Self> {
let hdr = RequestHdr::read_from_prefix(req).ok_or(Error::BinRequestSmall)?;
let (hdr, _) = RequestHdr::read_from_prefix(req).map_err(|_| Error::BinRequestSmall)?;
let rql = hdr.rql.get() as usize;
let sea = hdr.sea.get() as usize;
@@ -506,9 +506,9 @@ impl<'a> BinReqValues<'a> {
/// [`FromBytes::ref_from_prefix`]
pub(crate) fn req_dep_aad<T>(&self) -> Option<&T>
where
T: FromBytes + Sized,
T: FromBytes + Sized + Immutable + KnownLayout,
{
T::ref_from_prefix(self.req_dep_aad)
T::ref_from_prefix(self.req_dep_aad).map(|s| s.0).ok()
}
/// Returns a reference to the tag of this [`BinReqValues`].
@@ -615,7 +615,7 @@ mod tests {
#[test]
fn req_hdr2() {
let mut hdr = RequestHdr::new(0x200, 0x1234, [0x11; 12], 15, 44, Some(TEST_MAGIC));
let hdr_bin = hdr.as_bytes_mut();
let hdr_bin = hdr.as_mut_bytes();
let hdr_bin_exp = [
0x12, 0x34, 0x56, 0x89, 0xab, 0xcd, 0xef, 0, // magic
0, 0, 2, 0, // vers

View File

@@ -4,7 +4,7 @@
use openssl::pkey::{PKey, Public};
use std::mem::size_of;
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32};
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U32};
use crate::{
assert_size,
@@ -276,7 +276,7 @@ impl From<AttestationVersion> for RequestVersion {
/// Authenticated additional Data of an [`AttestationRequest`]
#[repr(C)]
#[derive(Debug, AsBytes, FromZeroes, FromBytes, Clone, Copy)]
#[derive(Debug, IntoBytes, FromBytes, Clone, Copy, Immutable, KnownLayout)]
pub struct AttestationAuthenticated {
flags: AttestationFlags,
mai: U32<BigEndian>,
@@ -310,7 +310,7 @@ impl AttestationAuthenticated {
/// Attestation flags
#[repr(C)]
#[derive(Default, Debug, AsBytes, FromZeroes, FromBytes, Clone, Copy)]
#[derive(Default, Debug, IntoBytes, FromBytes, Clone, Copy, Immutable)]
pub struct AttestationFlags(UvFlags);
static_assert!(AttestationFlags::FLAG_TO_ADD_SIZE.len() < 64);
@@ -393,7 +393,7 @@ impl AttestationFlags {
}
#[repr(C)]
#[derive(Debug, AsBytes)]
#[derive(Debug, IntoBytes, Immutable)]
struct ReqConfData {
meas_key: [u8; 64],
nonce: AttNonce,

View File

@@ -12,7 +12,7 @@ use openssl::{
pkey::{PKeyRef, Private},
};
use std::mem::size_of;
use zerocopy::{AsBytes, BigEndian, U16, U32};
use zerocopy::{BigEndian, IntoBytes, U16, U32};
#[cfg(doc)]
use crate::attest::AttestationRequest;

View File

@@ -2,7 +2,7 @@
//
// Copyright IBM Corp. 2023
use super::user_data::UserData;
use super::{guest_secret::ListableSecretHdr, user_data::UserData};
use crate::{
assert_size,
crypto::{hkdf_rfc_5869, AeadEncryptionResult},
@@ -17,12 +17,12 @@ use openssl::{
md::Md,
pkey::{PKey, Private, Public},
};
use pv_core::{request::RequestVersion, secret::AddSecretMagic};
use zerocopy::AsBytes;
use pv_core::{request::RequestVersion, secret::AddSecretMagic, uv::SecretId};
use zerocopy::{Immutable, IntoBytes};
/// Authenticated data w/o user data
#[repr(C)]
#[derive(Debug, Clone, Copy, AsBytes)]
#[derive(Debug, Clone, Copy, IntoBytes, Immutable)]
struct ReqAuthData {
flags: UvFlags,
boot_tags: BootHdrTags,
@@ -283,6 +283,13 @@ impl AddSecretRequest {
.map(|res| res.into_buf())
}
/// Get a copy of the secret ID if any
pub fn bin_id(asrcb: &[u8]) -> Result<Option<SecretId>> {
AddSecretMagic::try_from_bytes(asrcb)?;
BinReqValues::get(asrcb)
.map(|req| req.req_dep_aad::<ListableSecretHdr>().map(|a| a.id.clone()))
}
/// Get a copy of the add secret request tag
pub fn bin_tag(asrcb: &[u8]) -> Result<Vec<u8>> {
AddSecretMagic::try_from_bytes(asrcb)?;

View File

@@ -17,7 +17,6 @@ use crate::{
},
Error, Result,
};
use byteorder::BigEndian;
use openssl::{
hash::MessageDigest,
nid::Nid,
@@ -26,9 +25,11 @@ use openssl::{
use pv_core::static_assert;
use serde::{Deserialize, Serialize};
use std::fmt::Display;
use zerocopy::{AsBytes, U16, U32};
use zerocopy::{BigEndian, KnownLayout};
use zerocopy::{FromBytes, Immutable, IntoBytes, U16, U32};
const ASSOC_SECRET_SIZE: usize = 32;
const CCK_SIZE: usize = 32;
/// Maximum size of a plain-text secret payload (8190)
pub(crate) const MAX_SIZE_PLAIN_PAYLOAD: usize = RetrieveCmd::MAX_SIZE - 2;
static_assert!(MAX_SIZE_PLAIN_PAYLOAD == 8190);
@@ -65,6 +66,14 @@ pub enum GuestSecret {
#[serde(skip)]
secret: Confidential<Vec<u8>>,
},
/// CCK update
///
/// Create CCK updates using [`GuestSecret::update_cck`]
UpdateCck {
/// Confidential actual CCK (32 bytes)
#[serde(skip)]
secret: Confidential<[u8; CCK_SIZE]>,
},
}
macro_rules! retr_constructor {
@@ -136,10 +145,19 @@ impl GuestSecret {
retr_constructor!(#[doc = r"This function will return an error if OpenSSL cannot create a hash or the curve is invalid"]
| #[doc = r"EC PRIVATE Key"] => PKey<Private>, ec);
/// Create a new [`GuestSecret::UpdateCck`].
///
/// * `secret` - New CCK.
pub fn update_cck(secret: [u8; CCK_SIZE]) -> Self {
Self::UpdateCck {
secret: secret.into(),
}
}
/// Use the name as ID, do not hash it
pub fn no_hash_name(&mut self) {
match self {
Self::Null => (),
Self::Null | Self::UpdateCck { .. } => (),
Self::Association {
name, ref mut id, ..
}
@@ -155,6 +173,7 @@ impl GuestSecret {
Self::Null => &[],
Self::Association { secret, .. } => secret.value().as_slice(),
Self::Retrievable { secret, .. } => secret.value(),
Self::UpdateCck { secret, .. } => secret.value(),
}
}
@@ -162,7 +181,8 @@ impl GuestSecret {
pub(crate) fn auth(&self) -> SecretAuth {
match &self {
Self::Null => SecretAuth::Null,
// Panic: every non null secret type is list-able -> no panic
Self::UpdateCck { .. } => SecretAuth::UpdateCck,
// Panic: other secret types are list-able -> no panic
listable => {
SecretAuth::Listable(ListableSecretHdr::from_guest_secret(listable).unwrap())
}
@@ -176,6 +196,7 @@ impl GuestSecret {
Self::Null => ListableSecretType::NULL,
Self::Association { .. } => ListableSecretType::ASSOCIATION,
Self::Retrievable { kind, .. } => kind.into(),
Self::UpdateCck { .. } => ListableSecretType::UPDATE_CCK,
}
}
@@ -185,13 +206,14 @@ impl GuestSecret {
Self::Null => 0,
Self::Association { secret, .. } => secret.value().len() as u32,
Self::Retrievable { secret, .. } => secret.value().len() as u32,
Self::UpdateCck { secret } => secret.value().len() as u32,
}
}
/// Returns the ID of the secret type (if any)
fn id(&self) -> Option<SecretId> {
match self {
Self::Null => None,
Self::Null | Self::UpdateCck { .. } => None,
Self::Association { id, .. } | Self::Retrievable { id, .. } => Some(id.to_owned()),
}
}
@@ -217,7 +239,7 @@ fn extend_to_multiple(mut key: Vec<u8>, multiple: usize) -> Confidential<Vec<u8>
/// ```
fn plaintext(inp: Confidential<Vec<u8>>) -> Result<RetrKeyInfo> {
let key_len = inp.value().len();
if key_len > RetrieveCmd::MAX_SIZE {
if key_len > MAX_SIZE_PLAIN_PAYLOAD {
return Err(Error::RetrInvKey {
what: "key size",
value: key_len.to_string(),
@@ -368,25 +390,51 @@ impl Display for GuestSecret {
pub(crate) enum SecretAuth {
Null,
Listable(ListableSecretHdr),
UpdateCck,
}
impl SecretAuth {
const NULL_HDR: NullSecretHdr = NullSecretHdr::new();
const UPDATE_CCK_HDR: UpdateCckHdr = UpdateCckHdr::new();
pub fn get(&self) -> &[u8] {
match self {
Self::Null => &[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
Self::Null => Self::NULL_HDR.as_bytes(),
Self::Listable(h) => h.as_bytes(),
Self::UpdateCck => Self::UPDATE_CCK_HDR.as_bytes(),
}
}
}
#[repr(C)]
#[derive(Debug, AsBytes)]
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
struct NullSecretHdr {
res0: u16,
kind: U16<BigEndian>,
secret_len: U32<BigEndian>,
res8: u64,
}
assert_size!(NullSecretHdr, 0x10);
impl NullSecretHdr {
const fn new() -> Self {
Self {
res0: 0,
kind: U16::new(ListableSecretType::NULL),
secret_len: U32::ZERO,
res8: 0,
}
}
}
#[repr(C)]
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
pub(crate) struct ListableSecretHdr {
res0: u16,
kind: U16<BigEndian>,
secret_len: U32<BigEndian>,
res8: u64,
id: SecretId,
pub(crate) id: SecretId,
}
assert_size!(ListableSecretHdr, 0x30);
@@ -402,6 +450,29 @@ impl ListableSecretHdr {
}
}
#[repr(C)]
#[derive(Debug, IntoBytes, Default, Immutable)]
struct UpdateCckHdr {
res0: u16,
kind: U16<BigEndian>,
secret_len: U32<BigEndian>,
res8: u64,
res10: [u8; 0x20],
}
assert_size!(UpdateCckHdr, 0x30);
impl UpdateCckHdr {
const fn new() -> Self {
Self {
res0: 0,
kind: U16::new(ListableSecretType::UPDATE_CCK),
secret_len: U32::new(CCK_SIZE as u32),
res8: 0,
res10: [0; 0x20],
}
}
}
#[cfg(test)]
mod test {
@@ -461,6 +532,16 @@ mod test {
retr_test!(retr_aes_hmac_256, hmac_sha, 64, HmacSha(HmacSizes::Sha256));
retr_test!(retr_aes_hmac_512, hmac_sha, 128, HmacSha(HmacSizes::Sha512));
#[test]
fn update_cck() {
let new_cck = [11; 32];
let req = GuestSecret::update_cck(new_cck);
let exp = GuestSecret::UpdateCck {
secret: new_cck.into(),
};
assert_eq!(req, exp);
}
#[test]
fn plaintext_no_pad() {
let key = vec![0, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7];
@@ -602,6 +683,24 @@ mod test {
);
}
#[test]
fn update_cck_parse() {
let cck = GuestSecret::UpdateCck {
secret: [0; 32].into(),
};
assert_tokens(
&cck,
&[
Token::StructVariant {
name: "GuestSecret",
variant: "UpdateCck",
len: 0,
},
Token::StructVariantEnd,
],
)
}
#[test]
fn guest_secret_bin_null() {
let gs = GuestSecret::Null;
@@ -643,4 +742,17 @@ mod test {
assert_eq!(exp, gs_bytes_auth);
assert_eq!(&[2; 32], gs.confidential());
}
#[test]
fn guest_secret_bin_cck() {
let gs = GuestSecret::UpdateCck {
secret: [2; 32].into(),
};
let gs_bytes_auth = gs.auth();
let mut exp = vec![0u8, 0, 0, 0x16, 0, 0, 0, 0x20];
exp.extend([0; 40]);
assert_eq!(exp, gs_bytes_auth.get());
assert_eq!(&[2; 32], gs.confidential());
}
}

View File

@@ -2,14 +2,14 @@
//
// Copyright IBM Corp. 2024
use crate::{pem::Pem, uvsecret::guest_secret::MAX_SIZE_PLAIN_PAYLOAD, Result};
use crate::{crypto::SymKeyType, pem::Pem, uvsecret::guest_secret::MAX_SIZE_PLAIN_PAYLOAD, Result};
use byteorder::BigEndian;
use log::warn;
use pv_core::{
request::Confidential,
uv::{ListableSecretType, RetrievableSecret, RetrieveCmd},
};
use zerocopy::BigEndian;
use zerocopy::{FromBytes, U16};
/// An IBM Protected Key
@@ -76,14 +76,16 @@ impl From<RetrieveCmd> for RetrievedSecret {
// minimum size
let len = U16::<BigEndian>::read_from_prefix(key.value())
.unwrap_or_default()
.0
.get() as usize;
// Test if the plain text secret has a size:
// 1. len <= 8190
// 2. first two bytes are max 15 less than buffer-size+2
// 2. first two bytes are max 15 less than buffer-size+2 i.e. smaller than the
// block length
// 3. bytes after len + 2 are zero
match len <= MAX_SIZE_PLAIN_PAYLOAD
&& key.value().len() - (len + 2) < 15
&& key.value().len() - (len + 2) < SymKeyType::AES_256_GCM_BLOCK_LEN
&& key.value()[len + 2..].iter().all(|c| *c == 0)
{
false => Self::Plaintext(key),

View File

@@ -15,7 +15,7 @@ use crate::{
};
use openssl::hash::MessageDigest;
use openssl::nid::Nid;
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U16};
use zerocopy::{BigEndian, FromBytes, IntoBytes, KnownLayout, U16};
/// User data.
///
@@ -59,7 +59,7 @@ pub(super) enum UserData {
}
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
#[derive(Debug, IntoBytes, FromBytes, KnownLayout)]
struct EcUserData {
data: [u8; 256],
signature: [u8; EC_SIGN_MAX_SIZE],
@@ -175,7 +175,7 @@ impl UserData {
// insert signature
if let UserDataType::SgnEcSECP521R1 = self.data_type() {
// Panic: will not panic buffer is 512+ bytes long
let buf_ec = EcUserData::mut_from_prefix(&mut buf[user_data_offset..]).unwrap();
let (buf_ec, _) = EcUserData::mut_from_prefix(&mut buf[user_data_offset..]).unwrap();
buf_ec.set_signature(&sgn);
} else {
// Panic: will not panic buffer is 512+ bytes long
@@ -328,12 +328,15 @@ impl VerifiedUserData {
let (ret, sgn) = match kind {
UserDataType::SgnEcSECP521R1 => {
let EcUserData {
data,
signature,
sgn_size,
..
} = EcUserData::mut_from_prefix(buf).unwrap();
let (
EcUserData {
data,
signature,
sgn_size,
..
},
_,
) = EcUserData::mut_from_prefix(buf).unwrap();
let data_len: usize = data.len();
let data = data.to_vec();
let mut signature = signature.to_vec();
@@ -480,7 +483,7 @@ mod test {
buf[..0x80].copy_from_slice(data);
user_data.sign(&mut buf, 0).unwrap();
let buf_ec = EcUserData::mut_from(&mut buf).unwrap();
let buf_ec = EcUserData::mut_from_bytes(&mut buf).unwrap();
let EcUserData {
data,
signature,

View File

@@ -1,6 +1,6 @@
[package]
name = "s390_pv_core"
version = "0.11.0"
version = "0.12.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
@@ -19,9 +19,10 @@ workspace = true
libc = "0.2.169"
log = { version = "0.4.25", features = ["std", "release_max_level_debug"] }
thiserror = "2.0.11"
zerocopy = {version = "0.7", features = ["derive"]}
zerocopy = {version = "0.8", features = ["derive"]}
serde = { version = "1.0.217", features = ["derive"]}
byteorder = "1.5"
regex = "1.10"
[dev-dependencies]
serde_test = "1.0.177"

View File

@@ -0,0 +1,468 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023
//
//! AP support functions
//
use crate::{
utils::{pv_guest_bit_set, read_file_string, write_file},
Error, Result,
};
use regex::Regex;
use std::fmt;
use std::thread;
use std::time;
const PATH_SYS_DEVICES_AP: &str = "/sys/devices/ap";
/// Regular expression for AP queue directories
pub const RE_QUEUE_DIR: &str = r"^([[:xdigit:]]{2})\.([[:xdigit:]]{4})$";
const RE_CARD_TYPE: &str = r"^CEX([3-8])([ACP])$";
const RE_EP11_MKVP: &str = r"WK\s+CUR:\s+(\S+)\s+(\S+)";
const RE_CCA_AES_MKVP: &str = r"AES\s+CUR:\s+(\S+)\s+(\S+)";
const RE_CCA_APKA_MKVP: &str = r"APKA\s+CUR:\s+(\S+)\s+(\S+)";
const SYS_BUS_AP_BIND_POLL_MS: u64 = 500;
const SYS_BUS_AP_BIND_TIMEOUT_MS: u64 = 10000;
const SYS_BUS_AP_ASSOC_POLL_MS: u64 = 500;
const SYS_BUS_AP_ASSOC_TIMEOUT_MS: u64 = 10000;
/// APQN mode
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApqnMode {
/// Accelerator mode
Accel,
/// EP11 (Enterprise PKCS #11) coprocessor mode
Ep11,
/// Common Cryptographic Architecture (CCA) coprocessor mode
Cca,
}
/// Info on an APQN configured for accelerator
#[derive(Debug, Clone)]
pub struct ApqnInfoAccel {
// empty
}
/// Info on an APQN configured for EP11 coprocessor
#[derive(Debug, Clone)]
pub struct ApqnInfoEp11 {
/// Serial number of the Crypto Express adapter as a case-sensitive ASCII string
pub serialnr: String,
/// Master key verification pattern as hex string
pub mkvp: String, // may be an empty string if no WK set
}
/// Info on an APQN configured for CCA coprocessor
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ApqnInfoCca {
/// Serial number of the Crypto Express adapter as a case-sensitive ASCII string
pub serialnr: String,
/// Master key verification pattern as hex string for AES
pub mkvp_aes: String, // may be an empty string if no MK set
/// Master key verification pattern as hex string for asymmetric public key algorithms
pub mkvp_apka: String, // may be an empty string if no MK set
}
/// Info for an APQN's mode
#[derive(Debug, Clone)]
pub enum ApqnInfo {
/// Info on an APQN configured for accelerator
Accel(ApqnInfoAccel),
/// Info on an APQN configured for EP11 coprocessor
Ep11(ApqnInfoEp11),
/// Info on an APQN configured for CCA coprocessor
#[allow(dead_code)]
Cca(ApqnInfoCca),
}
macro_rules! parse_error {
($subject:expr, $content:expr) => {
Error::ParseError {
subject: $subject,
content: $content,
}
};
}
impl ApqnInfo {
fn accel_info(_carddir: &str, _queuedir: &str) -> Result<Self> {
Ok(Self::Accel(ApqnInfoAccel {}))
}
fn cca_info(carddir: &str, queuedir: &str) -> Result<Self> {
let serialnr_str = read_file_string(format!("{carddir}/serialnr"), "serialnr")?;
let serialnr = serialnr_str.trim().to_string();
let mkvps = read_file_string(format!("{carddir}/{queuedir}/mkvps"), "mkvps")?;
let mut aes_mkvp = String::new();
let re_cca_aes_mkvp = Regex::new(RE_CCA_AES_MKVP).unwrap();
if !re_cca_aes_mkvp.is_match(&mkvps) {
return Err(parse_error!(format!("APQN {queuedir} MKVPs"), mkvps));
} else {
let caps = re_cca_aes_mkvp.captures(&mkvps).unwrap();
if caps.get(1).unwrap().as_str().to_lowercase() == "valid" {
aes_mkvp = caps.get(2).unwrap().as_str().to_lowercase();
if aes_mkvp.starts_with("0x") {
aes_mkvp = String::from(&aes_mkvp[2..]);
}
}
}
let mut apka_mkvp = String::new();
let re_cca_apka_mkvp = Regex::new(RE_CCA_APKA_MKVP).unwrap();
if !re_cca_apka_mkvp.is_match(&mkvps) {
return Err(parse_error!(format!("APQN {queuedir} MKVPs"), mkvps));
} else {
let caps = re_cca_apka_mkvp.captures(&mkvps).unwrap();
if caps.get(1).unwrap().as_str().to_lowercase() == "valid" {
apka_mkvp = caps.get(2).unwrap().as_str().to_lowercase();
if apka_mkvp.starts_with("0x") {
apka_mkvp = String::from(&apka_mkvp[2..]);
}
}
}
Ok(Self::Cca(ApqnInfoCca {
serialnr,
mkvp_aes: aes_mkvp,
mkvp_apka: apka_mkvp,
}))
}
fn ep11_info(carddir: &str, queuedir: &str) -> Result<Self> {
let serialnr_str = read_file_string(format!("{carddir}/serialnr"), "serialnr")?;
let serialnr = serialnr_str.trim().to_string();
let mkvps = read_file_string(format!("{carddir}/{queuedir}/mkvps"), "mkvps")?;
let mut mkvp = String::new();
let re_ep11_mkvp = Regex::new(RE_EP11_MKVP).unwrap();
if !re_ep11_mkvp.is_match(&mkvps) {
return Err(parse_error!(format!("APQN {queuedir} MKVPs"), mkvps));
} else {
let caps = re_ep11_mkvp.captures(&mkvps).unwrap();
if caps.get(1).unwrap().as_str().to_lowercase() == "valid" {
mkvp = caps.get(2).unwrap().as_str().to_lowercase();
if mkvp.starts_with("0x") {
mkvp = String::from(&mkvp[2..]);
}
if mkvp.len() > 32 {
mkvp = String::from(&mkvp[..32])
}
}
}
Ok(Self::Ep11(ApqnInfoEp11 { serialnr, mkvp }))
}
/// Get mode-specific info
pub fn info(mode: &ApqnMode, carddir: &str, queuedir: &str) -> Result<Self> {
match mode {
ApqnMode::Accel => Self::accel_info(carddir, queuedir),
ApqnMode::Cca => Self::cca_info(carddir, queuedir),
ApqnMode::Ep11 => Self::ep11_info(carddir, queuedir),
}
}
}
/// `Apqn` encodes an adjunct processor queue number.
#[derive(Debug, Clone)]
pub struct Apqn {
/// Name of the APQN
#[allow(dead_code)]
pub name: String,
/// Card number
pub card: u32,
/// Domain number
pub domain: u32,
/// CryptoExpress generation
pub gen: u32,
/// Mode that adapter is configured to use
pub mode: ApqnMode,
/// Mode-specific info
pub info: Option<ApqnInfo>,
}
impl TryFrom<&str> for Apqn {
type Error = Error;
/// Create an `Apqn` struct from a CARD.DOMAIN-formatted APQN
/// string, such as `28.0014`. Will not populate `info` upon
/// failure to read it. Other failures to read required information
/// are treated as an Error.
/// # Panics
/// Panics if the compilation of a static regular expression fails
/// or a regex capture that is already format-checked does not
/// parse, e.g. when the capture `([[:xdigit:]]{2})` does not
/// parse as hex string.
fn try_from(name: &str) -> Result<Self> {
let re_card_type = Regex::new(RE_CARD_TYPE).unwrap();
let re_queue_dir = Regex::new(RE_QUEUE_DIR).unwrap();
let caps = re_queue_dir
.captures(name)
.ok_or_else(|| parse_error!("queue".to_string(), name.to_string()))?;
let cardstr = caps.get(1).unwrap().as_str();
let card = u32::from_str_radix(cardstr, 16).unwrap();
let domstr = caps.get(2).unwrap().as_str();
let domain = u32::from_str_radix(domstr, 16).unwrap();
let path = format!("{PATH_SYS_DEVICES_AP}/card{cardstr}");
let card_type =
read_file_string(format!("{path}/type"), "card type").map(|s| s.trim().to_string())?;
let caps = re_card_type
.captures(&card_type)
.ok_or_else(|| parse_error!("card type".to_string(), card_type.to_string()))?;
let gen = caps.get(1).unwrap().as_str().parse::<u32>().unwrap();
let mode = match caps.get(2).unwrap().as_str().parse::<char>().unwrap() {
'A' => ApqnMode::Accel,
'C' => ApqnMode::Cca,
'P' => ApqnMode::Ep11,
_ => unreachable!("Code inconsistency between regex RE_CARD_TYPE and evaluation code."),
};
// the UV blocks requests to CCA cards within SE guest with AP
// pass-through support. However, filter out CCA cards as
// these cards cause hangs during information gathering.
if mode == ApqnMode::Cca && pv_guest_bit_set() {
return Err(Error::CcaSeIncompatible(card));
}
match read_file_string(format!("{path}/{name}/online"), "AP queue online status")
.map(|s| s.trim().parse::<i32>())
{
Ok(Ok(1)) => {}
_ => return Err(Error::ApOffline { card, domain }),
}
// For the MKVP and serialnr to fetch from the APQN within a SE
// guest the APQN needs to be bound to the guest. So if the APQN
// is not bound, temporarily bind it here until the info has
// been retrieved.
let mut tempbound = false;
if pv_guest_bit_set() {
let cbs = get_apqn_bind_state(card, domain)?;
if cbs == BindState::Unbound {
set_apqn_bind_state(card, domain, BindState::Bound)?;
tempbound = true;
}
}
let info = ApqnInfo::info(&mode, &path, name).ok();
if tempbound {
set_apqn_bind_state(card, domain, BindState::Unbound)?;
}
Ok(Apqn {
name: name.to_string(),
card,
domain,
gen,
mode,
info,
})
}
}
impl fmt::Display for Apqn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({},{})", self.card, self.domain)
}
}
impl Apqn {
/// Read bind state of the APQN.
pub fn bind_state(&self) -> Result<BindState> {
get_apqn_bind_state(self.card, self.domain)
}
/// Set bind state of the APQN.
pub fn set_bind_state(&self, state: BindState) -> Result<()> {
set_apqn_bind_state(self.card, self.domain, state)
}
/// Read associate state of the APQN.
pub fn associate_state(&self) -> Result<AssocState> {
get_apqn_associate_state(self.card, self.domain)
}
/// Set associate state of the APQN.
pub fn set_associate_state(&self, state: AssocState) -> Result<()> {
set_apqn_associate_state(self.card, self.domain, state)
}
}
/// Bind state of an APQN
#[derive(Debug, PartialEq, Eq)]
pub enum BindState {
/// APQN is bound
Bound,
/// APQN is unbound
Unbound,
/// APQN does not support bind
NotSupported,
}
/// Query bind state for this APQN.
///
/// Returns a BindState enum as defined above or on failure
/// an error string. Does NOT print any error messages.
pub fn get_apqn_bind_state(card: u32, dom: u32) -> Result<BindState> {
let path = format!(
"{}/card{:02x}/{:02x}.{:04x}/se_bind",
PATH_SYS_DEVICES_AP, card, card, dom
);
let state_str = read_file_string(path, "se_bind attribute")?;
let state = state_str.trim();
match state {
"bound" => Ok(BindState::Bound),
"unbound" => Ok(BindState::Unbound),
"-" => Ok(BindState::NotSupported),
_ => Err(Error::UnknownBindState(state.to_string())),
}
}
/// Bind or unbind an APQN.
///
/// The action is determined by the BindState given in.
/// But of course only Bound and Unbound is supported - otherwise
/// this function panics!
/// The function actively loops over the bind state until
/// the requested bind state is reached or a timeout has
/// occurred (SYS_BUS_AP_BIND_TIMEOUT_MS).
/// On success () is returned, on failure an error string
/// is returned. Does NOT print any error messages.
/// # Panics
/// Panics if a desired bind state other than Bound or Unbound is given.
pub fn set_apqn_bind_state(card: u32, dom: u32, state: BindState) -> Result<()> {
let ctx = "bind APQN";
let path = format!(
"{}/card{:02x}/{:02x}.{:04x}/se_bind",
PATH_SYS_DEVICES_AP, card, card, dom
);
match state {
BindState::Bound => write_file(path, 1.to_string(), ctx),
BindState::Unbound => write_file(path, 0.to_string(), ctx),
_ => panic!("set_apqn_bind_state called with invalid BindState."),
}?;
let mut ms: u64 = 0;
loop {
thread::sleep(time::Duration::from_millis(SYS_BUS_AP_BIND_POLL_MS));
ms += SYS_BUS_AP_BIND_POLL_MS;
if ms >= SYS_BUS_AP_BIND_TIMEOUT_MS {
break Err(Error::Timeout(format!(
"setting APQN({card},{dom}) bind state"
)));
}
let newstate = get_apqn_bind_state(card, dom)?;
if newstate == state {
return Ok(());
}
}
}
/// Association state of an APQN
#[derive(Debug, PartialEq, Eq)]
pub enum AssocState {
/// Associated with index
Associated(u16),
/// Association pending
AssociationPending,
/// Not associated
Unassociated,
/// APQN does not support association
NotSupported,
}
/// Query association state for this APQN.
///
/// Returns an AssocState enum as defined above or on failure
/// an error string. Does NOT print any error messages.
pub fn get_apqn_associate_state(card: u32, dom: u32) -> Result<AssocState> {
let path = format!(
"{}/card{:02x}/{:02x}.{:04x}/se_associate",
PATH_SYS_DEVICES_AP, card, card, dom
);
let state_str = read_file_string(path, "se_associate attribute")?;
let state = state_str.trim();
match state.strip_prefix("associated ") {
Some(prefix) => Ok(AssocState::Associated(prefix.parse()?)),
_ => match state {
"association pending" => Ok(AssocState::AssociationPending),
"unassociated" => Ok(AssocState::Unassociated),
"-" => Ok(AssocState::NotSupported),
_ => Err(Error::UnknownAssocState(state.to_string())),
},
}
}
fn set_apqn_associate_state_associate(card: u32, dom: u32, idx: u16) -> Result<()> {
let path = format!(
"{}/card{:02x}/{:02x}.{:04x}/se_associate",
PATH_SYS_DEVICES_AP, card, card, dom
);
write_file(path, idx.to_string(), "associate APQN")?;
let mut ms: u64 = 0;
loop {
thread::sleep(time::Duration::from_millis(SYS_BUS_AP_ASSOC_POLL_MS));
ms += SYS_BUS_AP_ASSOC_POLL_MS;
if ms >= SYS_BUS_AP_ASSOC_TIMEOUT_MS {
break Err(Error::Timeout(format!(
"setting APQN({card},{dom}) association index {idx} state",
)));
}
match get_apqn_associate_state(card, dom)? {
AssocState::Associated(i) if i == idx => return Ok(()),
AssocState::Associated(i) => {
return Err(Error::WrongAssocState {
card,
domain: dom,
desired: idx,
actual: i,
})
}
_ => {}
}
}
}
fn set_apqn_associate_state_unbind(card: u32, dom: u32) -> Result<()> {
let bindpath = format!(
"{}/card{:02x}/{:02x}.{:04x}/se_bind",
PATH_SYS_DEVICES_AP, card, card, dom
);
write_file(bindpath, 0.to_string(), "unbind APQN")?;
let mut ms: u64 = 0;
loop {
thread::sleep(time::Duration::from_millis(SYS_BUS_AP_ASSOC_POLL_MS));
ms += SYS_BUS_AP_ASSOC_POLL_MS;
if ms >= SYS_BUS_AP_ASSOC_TIMEOUT_MS {
break Err(Error::Timeout(format!(
"setting APQN({card},{dom}) association unbind state",
)));
}
let newstate = get_apqn_associate_state(card, dom)?;
if newstate == AssocState::Unassociated {
return Ok(());
}
}
}
/// Associate or Unassociate an APQN.
///
/// The action is determined by the AssocState given in.
/// But of course only Associated and Unassociated is supported
/// otherwise this function panics!
/// The function actively loops over the association state until
/// the requested state is reached or a timeout has
/// occurred (SYS_BUS_AP_ASSOC_TIMEOUT_MS).
/// The unassociate is in fact a unbind. So the code triggers
/// an unbind and then loops over the sysfs se_associate until
/// "unassociated" is reached.
/// On success () is returned, on failure an error string
/// is returned. Does NOT print any error messages.
/// # Panics
/// Panics if a desired bind state other than Associated or
/// Unassociated is given.
pub fn set_apqn_associate_state(card: u32, dom: u32, state: AssocState) -> Result<()> {
match state {
AssocState::Associated(idx) => set_apqn_associate_state_associate(card, dom, idx),
AssocState::Unassociated => set_apqn_associate_state_unbind(card, dom),
_ => panic!("set_apqn_associate_state called with invalid AssocState."),
}
}

View File

@@ -77,6 +77,36 @@ pub enum Error {
)]
InvalidRetrievableSecretType { id: SecretId, size: usize },
#[error("Unknown bind state '{0}'.")]
UnknownBindState(String),
#[error("Unknown association state '{0}'.")]
UnknownAssocState(String),
#[error(
"APQN({card:02x},{domain:04x}) is associated with {actual} but it should be {desired}."
)]
WrongAssocState {
card: u32,
domain: u32,
desired: u16,
actual: u16,
},
#[error("Timeout on {0}.")]
Timeout(String),
#[error(
"CCA card {0:02x} cannot be used with Secure Execution, as this combination is unsupported"
)]
CcaSeIncompatible(u32),
#[error("APQN({card:02x}{domain:04x}) is offline.")]
ApOffline { card: u32, domain: u32 },
#[error("Failure parsing {subject} '{content}'.")]
ParseError { subject: String, content: String },
// errors from other crates
#[error(transparent)]
Io(#[from] std::io::Error),

View File

@@ -2,6 +2,7 @@
//
// Copyright IBM Corp. 2023, 2024
#![doc = include_str!("../README.md")]
mod apdevice;
mod confidential;
mod error;
mod macros;
@@ -20,9 +21,11 @@ pub mod attest {
/// Miscellaneous functions and definitions
pub mod misc {
pub use crate::utils::pv_guest_bit_set;
pub use crate::utils::{create_file, open_file, read_exact_file, read_file, write_file};
pub use crate::utils::{decode_hex, parse_hex, to_u16, to_u32, try_parse_u128, try_parse_u64};
pub use crate::utils::{create_file, open_file};
pub use crate::utils::{decode_hex, encode_hex, parse_hex};
pub use crate::utils::{read, write};
pub use crate::utils::{read_exact_file, read_file, read_file_string, write_file};
pub use crate::utils::{to_u16, to_u32, try_parse_u128, try_parse_u64};
pub use crate::utils::{Flags, Lsb0Flags64, Msb0Flags64};
}
@@ -70,5 +73,29 @@ pub mod secret {
pub use crate::uvsecret::UserDataType;
}
/// Functionalities for the AP bus
pub mod ap {
pub use crate::apdevice::Apqn;
pub use crate::apdevice::RE_QUEUE_DIR;
pub use crate::apdevice::{get_apqn_bind_state, set_apqn_bind_state};
/// AP modes
pub mod apqn_mode {
pub use crate::apdevice::ApqnMode::{self, *};
}
/// AP info for each state
pub mod apqn_info {
pub use crate::apdevice::ApqnInfo::{self, *};
pub use crate::apdevice::{ApqnInfoAccel, ApqnInfoCca, ApqnInfoEp11};
}
/// AP bind states
pub mod bind_state {
pub use crate::apdevice::BindState::{self, *};
}
/// AP association states
pub mod assoc_state {
pub use crate::apdevice::AssocState::{self, *};
}
}
// Internal definitions/ imports
const PAGESIZE: usize = 0x1000;

View File

@@ -7,11 +7,11 @@ use std::{
path::Path,
};
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U64};
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, U64};
use crate::{
macros::{bail_spec, file_error},
Error, FileAccessErrorType, FileIoErrorType, Result,
Error, FileAccessErrorType, Result,
};
/// Trait that describes bitflags, represented by `T`.
@@ -34,7 +34,7 @@ pub trait Flags<T>: From<T> + for<'a> From<&'a T> {
///
/// Wraps an u64 to set/get individual bits
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
#[derive(Debug, Clone, Copy, Default, IntoBytes, FromBytes, Eq, PartialEq, Immutable)]
pub struct Msb0Flags64(U64<BigEndian>);
impl Flags<u64> for Msb0Flags64 {
#[track_caller]
@@ -82,7 +82,7 @@ impl From<Msb0Flags64> for u64 {
///
/// Wraps an u64 to set/get individual bits
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, AsBytes, FromZeroes, FromBytes)]
#[derive(Debug, Clone, Copy, Default, IntoBytes, FromBytes, Immutable)]
pub struct Lsb0Flags64(U64<BigEndian>);
impl Flags<u64> for Lsb0Flags64 {
#[track_caller]
@@ -262,6 +262,17 @@ pub fn read_exact_file<P: AsRef<Path>, const COUNT: usize>(
Ok(buf)
}
/// Read content from a file as string and add context in case of an error
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
/// # Errors
/// Passes through any kind of error `std::fs::read` produces
pub fn read_file_string<P: AsRef<Path>>(path: P, ctx: &str) -> Result<String> {
std::fs::read_to_string(&path).map_err(|e| file_error!(Read, ctx, path, e))
}
/// Read content from a file and add context in case of an error
///
/// * `path` - Path to file
@@ -284,12 +295,8 @@ pub fn read_file<P: AsRef<Path>>(path: P, ctx: &str) -> Result<Vec<u8>> {
/// Passes through any kind of error `std::fs::read` produces
pub fn read<R: Read, P: AsRef<Path>>(rd: &mut R, path: P, ctx: &str) -> Result<Vec<u8>> {
let mut buf = vec![];
rd.read_to_end(&mut buf).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.as_ref().to_path_buf(),
source: e,
})?;
rd.read_to_end(&mut buf)
.map_err(|e| file_error!(Read, ctx, path, e))?;
Ok(buf)
}
@@ -302,12 +309,7 @@ pub fn read<R: Read, P: AsRef<Path>>(rd: &mut R, path: P, ctx: &str) -> Result<V
/// # Errors
/// Passes through any kind of error `std::fs::write` produces
pub fn write_file<D: AsRef<[u8]>, P: AsRef<Path>>(path: P, data: D, ctx: &str) -> Result<()> {
std::fs::write(path.as_ref(), data.as_ref()).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.as_ref().to_path_buf(),
source: e,
})
std::fs::write(path.as_ref(), data.as_ref()).map_err(|e| file_error!(Write, ctx, path, e))
}
/// Write content to a [`std::io::Write`] and add context in case of an error
@@ -324,12 +326,8 @@ pub fn write<D: AsRef<[u8]>, P: AsRef<Path>, W: Write>(
path: P,
ctx: &str,
) -> Result<()> {
wr.write_all(data.as_ref()).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.as_ref().to_path_buf(),
source: e,
})
wr.write_all(data.as_ref())
.map_err(|e| file_error!(Write, ctx, path, e))
}
macro_rules! usize_to_ui {
@@ -355,6 +353,15 @@ usize_to_ui! {
#[doc = r"u16"]
=> u16, to_u16}
/// Converts the u8 slice into (lowercase) hexstring
pub fn encode_hex<S: AsRef<[u8]>>(s: S) -> String {
let slice = s.as_ref();
let string = String::with_capacity(2 * slice.len());
slice
.iter()
.fold(string, |acc, e| acc + &format!("{e:02x}"))
}
/// Converts the hexstring into a byte vector.
///
/// # Errors
@@ -504,6 +511,14 @@ mod tests {
fn lsb_flags_unset_panic() {
Lsb0Flags64::default().unset_bit(64)
}
#[test]
fn encode_hex() {
let arr = [0x12, 0x34, 0x56, 0xac, 0xbe, 0xf0];
let exp = "123456acbef0";
assert_eq!(super::encode_hex(arr), exp);
}
#[test]
fn parse_hex() {
let s = "123456acbef0";

View File

@@ -3,8 +3,8 @@
// Copyright IBM Corp. 2024
use crate::{request::MagicValue, Error};
use byteorder::{BigEndian, ByteOrder};
use zerocopy::U32;
use zerocopy::{BigEndian, ByteOrder};
/// The magic value used to identify an attestation request
///

View File

@@ -4,7 +4,7 @@
use super::{ffi, AttestationUserData, ConfigUid, UvCmd};
use crate::{Error, Result};
use std::ptr;
use zerocopy::{AsBytes, FromZeroes};
use zerocopy::{FromZeros, IntoBytes};
/// _Retrieve Attestation Measurement_ UVC
///
@@ -222,7 +222,7 @@ impl UvCmd for AttestationCmd {
}
fn data(&mut self) -> Option<&mut [u8]> {
Some(self.uvio_attest.as_bytes_mut())
Some(self.uvio_attest.as_mut_bytes())
}
}

View File

@@ -12,7 +12,7 @@
use std::mem::size_of;
use crate::{assert_size, static_assert};
use zerocopy::{AsBytes, FromBytes, FromZeroes};
use zerocopy::{FromBytes, IntoBytes};
pub const UVIO_ATT_ARCB_MAX_LEN: usize = 0x100000;
pub const UVIO_ATT_MEASUREMENT_MAX_LEN: usize = 0x8000;
@@ -65,7 +65,7 @@ assert_size!(uvio_ioctl_cb, 0x40);
/// Note that bit 0 (`UVIO_IOCTL_UVDEV_INFO_NR`) is always zero for `supp_uv_cmds`
/// as there is no corresponding UV-call.
#[repr(C)]
#[derive(Debug, Copy, Clone, AsBytes, FromZeroes, FromBytes)]
#[derive(Debug, Copy, Clone, IntoBytes, FromBytes)]
pub struct uvio_uvdev_info {
pub supp_uvio_cmds: u64,
pub supp_uv_cmds: u64,
@@ -95,7 +95,7 @@ pub const UVIO_ATT_UID_LEN: usize = 0x10;
///
/// All numbers are in big-endian!
#[repr(C)]
#[derive(Debug, AsBytes, FromZeroes, FromBytes)]
#[derive(Debug, IntoBytes, FromBytes)]
pub struct uvio_attest {
pub arcb_addr: u64, // in
pub meas_addr: u64, // out

View File

@@ -9,7 +9,7 @@ use crate::{
Result,
};
use std::fmt::Display;
use zerocopy::{AsBytes, FromZeroes};
use zerocopy::{FromZeros, IntoBytes};
/// Information of supported functions by the uvdevice
///
@@ -74,7 +74,7 @@ impl UvCmd for uvio_uvdev_info {
const UV_IOCTL_NR: u8 = ffi::UVIO_IOCTL_UVDEV_INFO_NR;
fn data(&mut self) -> Option<&mut [u8]> {
Some(self.as_bytes_mut())
Some(self.as_mut_bytes())
}
fn rc_fmt(&self, _: u16, _: u16) -> Option<&'static str> {

View File

@@ -266,7 +266,7 @@ impl<'de> Deserialize<'de> for RetrievableSecret {
D: serde::Deserializer<'de>,
{
struct RetrSecretVisitor;
impl<'de> serde::de::Visitor<'de> for RetrSecretVisitor {
impl serde::de::Visitor<'_> for RetrSecretVisitor {
type Value = RetrievableSecret;
fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {

View File

@@ -11,7 +11,7 @@ use crate::{
};
use log::debug;
use std::{io::Read, mem::size_of_val};
use zerocopy::AsBytes;
use zerocopy::IntoBytes;
/// _List Secrets_ Ultravisor command.
///

View File

@@ -8,7 +8,6 @@ use crate::{
uvdevice::UvCmd,
Error, Result,
};
use byteorder::{BigEndian, ByteOrder};
use serde::{Deserialize, Serialize, Serializer};
use std::{
cmp::min,
@@ -19,13 +18,14 @@ use std::{
slice::Iter,
vec::IntoIter,
};
use zerocopy::{AsBytes, FromBytes, FromZeroes, U16, U32};
use zerocopy::{BigEndian, ByteOrder};
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, U16, U32};
/// The 32 byte long ID of an UV secret
///
/// (de)serializes itself in/from a hex-string
#[repr(C)]
#[derive(PartialEq, Eq, AsBytes, FromZeroes, FromBytes, Debug, Clone, Default)]
#[derive(PartialEq, Eq, IntoBytes, FromBytes, Debug, Clone, Default, Immutable, KnownLayout)]
pub struct SecretId([u8; Self::ID_SIZE]);
assert_size!(SecretId, SecretId::ID_SIZE);
@@ -132,7 +132,7 @@ impl AsRef<[u8]> for SecretId {
/// A secret in a [`SecretList`]
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq, AsBytes, FromZeroes, FromBytes, Serialize)]
#[derive(Debug, Clone, PartialEq, Eq, IntoBytes, FromBytes, Serialize, Immutable)]
pub struct SecretEntry {
#[serde(serialize_with = "ser_u16")]
index: U16<BigEndian>,
@@ -183,7 +183,7 @@ impl SecretEntry {
/// The slice is guaranteed to be 32 bytes long.
/// ```rust
/// # use s390_pv_core::uv::SecretEntry;
/// # use zerocopy::FromZeroes;
/// # use zerocopy::FromZeros;
/// # let secr = SecretEntry::new_zeroed();
/// # assert_eq!(secr.id().len(), 32);
/// ```
@@ -211,7 +211,9 @@ impl Display for SecretEntry {
}
#[repr(C)]
#[derive(Debug, FromBytes, AsBytes, FromZeroes, Clone, PartialEq, Eq, Default, Serialize)]
#[derive(
Debug, FromBytes, IntoBytes, Clone, PartialEq, Eq, Default, Serialize, Immutable, KnownLayout,
)]
struct SecretListHdr {
#[serde(skip)]
num_secrets_stored: U16<BigEndian>,
@@ -325,7 +327,8 @@ impl SecretList {
/// Encodes the list in the same binary format the UV would do
pub fn encode<T: Write>(&self, w: &mut T) -> Result<()> {
w.write_all(self.hdr.as_bytes())?;
let hdr = self.hdr.as_bytes();
w.write_all(hdr)?;
for secret in &self.secrets {
w.write_all(secret.as_bytes())?;
}
@@ -336,14 +339,14 @@ impl SecretList {
pub fn decode<R: Read + Seek>(r: &mut R) -> std::io::Result<Self> {
let mut buf = [0u8; size_of::<SecretListHdr>()];
r.read_exact(&mut buf)?;
let hdr = SecretListHdr::ref_from(&buf).unwrap();
let hdr = SecretListHdr::ref_from_bytes(&buf).unwrap();
let mut buf = [0u8; SecretEntry::STRUCT_SIZE];
let mut v = Vec::with_capacity(hdr.num_secrets_stored.get() as usize);
for _ in 0..hdr.num_secrets_stored.get() {
r.read_exact(&mut buf)?;
// cannot fail. buffer has the same size as the secret entry
let secr = SecretEntry::read_from(buf.as_slice()).unwrap();
let secr = SecretEntry::read_from_bytes(buf.as_slice()).unwrap();
v.push(secr);
}
Ok(Self {
@@ -395,6 +398,7 @@ pub enum ListableSecretType {
///
/// 0 is reserved
/// 1 is Null secret, with no id and not list-able
/// 21 is Update CCK secret, with no id and not list-able
Invalid(u16),
/// Unknown secret type
Unknown(u16),
@@ -433,6 +437,8 @@ impl ListableSecretType {
pub const ECDSA_ED25519_KEY: u16 = 0x0014;
/// UV secret-type id for an ed448-private-key secret
pub const ECDSA_ED448_KEY: u16 = 0x0015;
/// UV secret-type id for a new customer communication key
pub const UPDATE_CCK: u16 = 0x0016;
}
impl Display for ListableSecretType {
@@ -479,6 +485,7 @@ impl From<u16> for ListableSecretType {
Self::ECDSA_P521_KEY => Self::Retrievable(RetrievableSecret::Ec(EcCurves::Secp521R1)),
Self::ECDSA_ED25519_KEY => Self::Retrievable(RetrievableSecret::Ec(EcCurves::Ed25519)),
Self::ECDSA_ED448_KEY => Self::Retrievable(RetrievableSecret::Ec(EcCurves::Ed448)),
Self::UPDATE_CCK => Self::Invalid(Self::UPDATE_CCK),
n => Self::Unknown(n),
}
}
@@ -538,10 +545,13 @@ where
#[cfg(test)]
mod test {
use std::io::{BufReader, BufWriter, Cursor};
use serde_test::{assert_ser_tokens, assert_tokens, Token};
use zerocopy::FromZeros;
use super::*;
use std::io::{BufReader, BufWriter, Cursor};
#[test]
fn dump_secret_entry() {
const EXP: &[u8] = &[

View File

@@ -7,9 +7,9 @@ use crate::{
request::{MagicValue, RequestMagic},
Error, Result,
};
use byteorder::{BigEndian, ByteOrder};
use byteorder::ByteOrder;
use std::{fmt::Display, mem::size_of};
use zerocopy::{AsBytes, U16};
use zerocopy::{BigEndian, Immutable, IntoBytes, U16};
/// The magic value used to identify an `AddSecretRequest`.
///
@@ -25,7 +25,7 @@ use zerocopy::{AsBytes, U16};
/// # }
/// ```
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, AsBytes)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoBytes, Immutable)]
pub struct AddSecretMagic {
magic: [u8; 6], // [0x61, 0x73, 0x72, 0x63, 0x62, 0x4D]
kind: U16<BigEndian>,
@@ -56,7 +56,7 @@ impl AddSecretMagic {
}
// Panic: Will not panic, bytes is at least 8 elements long
let kind = BigEndian::read_u16(&bytes[6..8]);
let kind = byteorder::BigEndian::read_u16(&bytes[6..8]);
let kind = UserDataType::try_from(kind)?;
Ok(Self::from(kind))
}

View File

@@ -2,7 +2,7 @@
name = "pvapconfig"
description = "A tool to configure the AP resources inside a SE guest based on UV secrets and an AP config file."
authors = ["Harald Freudenberger <freude@linux.ibm.com>"]
version = "0.11.0"
version = "0.12.0"
edition.workspace = true
license.workspace = true
rust-version.workspace = true
@@ -12,7 +12,7 @@ clap = { version ="4.5", features = ["derive", "wrap_help"]}
lazy_static = "1.5"
openssl = { version = "0.10.70" }
pv_core = { path = "../pv_core", package = "s390_pv_core"}
rand = "0.8"
rand = "0.9"
regex = "1.11"
serde = { version = "1.0.217", features = ["derive"] }
serde_yaml = "0.9"

View File

@@ -91,6 +91,9 @@ All AP config entries need to be satisfied to have pvapconfig
terminate with success. Without this option one applied AP config
entry is enough to meet the expectations.
.TP 8
.B \-\-unbind
Unbind all available APQNs.
.TP 8
.B \-v, \-\-verbose
Print out informational messages about what pvapconfig is actually
doing.
@@ -104,7 +107,7 @@ entries. Each entry may hold this information:
- mode: AP queue mode information, required, either "EP11" or "Accel".
.TP 2
- mkvp: AP queue Master Key Verification Pattern (MKVP), required for
EP11, hex string optional prepented with 0x. The MKVP hex string value
EP11, hex string optional prepended with 0x. The MKVP hex string value
may hold either 16 bytes (32 hex characters) or 32 bytes (64 hex
characters) but only the leftmost 16 bytes hold MKVP information and
thus the rest is ignored.
@@ -117,7 +120,7 @@ lowercase character(s) count different.
"CEX7" or "CEX8" for Accelerator, string "CEC8" for EP11, optional. If
given specifies the minimal accepted Crypto card generation.
.TP 2
- secretid: Secret id, hex string with optional 0x prepented, required
- secretid: Secret id, hex string with optional 0x prepended, required
for EP11, ignored for Accel. Details see the following text.
.TP 2
- name: ASCII string, optional, but see details below.

Some files were not shown because too many files have changed in this diff Show More