Compare commits

..

158 Commits

Author SHA1 Message Date
Jan Höppner
f75c923627 New release s390-tools-2.25.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-12-08 13:40:15 +01:00
Fedor Loshakov
bca8fa3f9c ziomon: fix Makefile install step chown warnings
Since coreutils v9.1 commit 8f31074cb ("chown: warn about USER.GROUP")
chown utility now warns about using of wrong separator for USER and
GROUP options. This leads to warnings during intall step in ziomon:

$ make install
  INSTALL ziomon
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’
  SED     ziomon/install
chown: warning: '.' should be ':': ‘root.root’

To fix those warnings use ':' as separator instead of '.'. With this
patch applied those warnings are no longer present.

Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Joern Siglen
d713ea6389 dbginfo.sh: log the work dir state in dbginfo.log
As on space problems the packing may fail, incomplete tgz are send.
Today no evidence for this is in dbginfo.log, packed upfront into the tgz.
This update helps to identify space related corruption of tgz files.

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Niklas Schnelle
f9fbe79e4f ipl_tools: Fix chreipl node for NVMes with CONFIG_NVME_MULTIPATH
When the kernel is build with CONFIG_NVME_MULTIPATH enabled and an NVMe
where the driver exposes its controller separately is used, chreipl node
on a mount point of the NVMe fails. The failure occurs because chreipl
tries to get the function_id from the NVMe's nvmeXnY block device via
the path '/sys/block/nvmeXnY/device/device/function_id' which does not
exist.

The underlying problem is that with NVMe multipath support the PCI
function is not associated directly with a particular NVMe namespace but
instead with the entire NVMe device which may host multiple NVMe
namespaces. The correct way to get from the block device to the
underlying PCI device and its function ID is then to extract the device
name i.e. the 'nvmeX' part from 'nvmeXnY' and use that to get the
function ID via '/sys/class/nvme/nvme<X>/device/function_id'.

Fixes: 0472b5ea5c ("ipl-tools: Add nvme device support to lsreipl/chreipl")
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:54:09 +01:00
Steffen Eiden
3cc0b4cdea pvattest/tools: remove xxd dependency from scripts
xxd has vim-common as a dependency. We can avoid that by using od
instead which is from coreutils.

While at it, add the require_command function from the
pvattest-info script to the pvextract-hdr script and use it.

Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:53:37 +01:00
Steffen Eiden
eef9f622c0 pvattest/man: fix wording
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:16 +01:00
Daniel S. Haischt
889293e557 zdev: implement --shell command line switch
Fix issue in the lszdev command where column names if using the --pairs
command line switch can contain characters that are not allowed to be
used as variable names in a shell environment.

Replace bad characters in column names by an underscore if the --shell
command line switch is specified along with the --pairs switch.

The additional --shell switch mimics what is already available in the
lsblk command and thus it shall be used along with the --pairs switch.

Signed-off-by: Daniel S. Haischt <modean@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:16 +01:00
Jan Höppner
0c5b9f5d11 mon_tools: Silence address-of-packed-member compile warning
The proc_sum_t struct is defined with the packed attribute and
produces the following compile warning:

mon_procd.c: In function ‘read_cpu’:
mon_procd.c:351:27: warning: taking address of packed member of ‘struct proc_sum_t’ may result in an unaligned pointer value [-Waddress-of-packed-member]
  351 |         cal_cpu(&cpudata, &proc_sum.cpu);
      |                           ^~~~~~~~~~~~~

Silence the warning with -Wno-address-of-packed-member compile flag
since the struct is required to be as is.

Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:50:09 +01:00
Jan Höppner
02af069d48 boot_defs.h: Fix compile warning in zfcpdump
The struct scsi_dump_sb is defined with the __packed attribute and
produces the following compile warning in zfcpdump:

zfcpdump_part.c: In function ‘csum_update’:
zfcpdump_part.c:125:41: warning: taking address of packed member of ‘struct scsi_dump_sb’ may result in an unaligned pointer value [-Waddress-of-packed-member]
  125 |                      dump_sb.csum_size, &dump_sb.csum)) {
      |                                         ^~~~~~~~~~~~~

However, all members are of the same size and the __packed attribute is
unnecessary. Remove the attribute to get rid of the warning.
Add assertion to ensure correct size of the struct during compile time.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2022-12-07 16:49:04 +01:00
Steffen Eiden
5e0056db8d util_lockfile: fix includes
The 'unistd.h' header was missing. Under some circumstances the
-D_GNU_SOURCE gcc flag does not trigger including that file.
Therefore, explicitly include this file here.

Fixes: e1aec24e84 ("libutil: introduce util_lockfile")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-30 15:51:15 +01:00
Matthew Rosato
4b5937f142 ap_tools/ap-check: use new mdevctl install location
mdevctl has been updated to use /usr/lib/mdevctl/scripts.d/callouts/
instead of /etc/mdevctl.d/scripts.d/callouts/.  The /etc location
is considered deprecated, meaning mdevctl will also look at that
location for now but might eventually stop looking in /etc for
callout scripts.
Based on that, update the installation location for the ap-check
callout.  However, because older versions of mdevctl will still
only look in /etc, let's also put a wrapper script in /etc for now
to provide backward compatibility, and plan to remove it at a
later time.

Link: df6bb57429
Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/139
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-30 15:50:33 +01:00
Marc Hartmayer
8d8d5e9746 zdump: Fix Makefile dependencies
The Makefile target `check_dep_fuse` was declared as .PHONY and
therefore it was always rebuilt. This caused zgetdump to always be
relinked. While at it, remove the non-existent Makefile target
`check_dep_zlib` and add the cache files to `.gitignore`.

Closes: https://github.com/ibm-s390-linux/s390-tools/issues/144
Fixes: e537ab902e ("zdump: Makefile: add basic libpv support")
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Jan Höppner
5bdabe3e06 common.mak: Fix pretty print for linking
Commit ae7217806b ("common.mak: remove `LINK` and `LINKXX`") changed
the LINK and LINKXX definition to ensure that the same compiler is used
for compilation and linking when specified with CC= (or CXX=
respectively) on the commandline.

However, the commit also removed the pretty print for both commands. Add
the pretty print back in and use the already defined $(CC) and $(CXX)
variables to preserve the original change.

Fixes: ae7217806b ("common.mak: remove `LINK` and `LINKXX`")
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Marc Hartmayer
8a1db94d37 zdump: add missing newlines for log messages
Signed-off-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>
2022-11-29 17:03:57 +01:00
Marc Hartmayer
1911cba130 zdump: check provided sizes for reasonableness
Check the dump provided sizes for reasonableness. This avoids that a
corrupted dump leads to allocation of large buffers on the heap.

Signed-off-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>
2022-11-29 17:03:57 +01:00
Marc Hartmayer
f4ed0b0ec6 zdump: check size before mmap'ing
Verify that the size is large enough before doing the mmap. Otherwise
this can result in a SIGBUS signal if there is an attempt to access a
page that lies beyond the end of the mapped file (see `man 2 mmap`).

Fixes: 8fa1b5a00b ("zdump: dfi: add support to read Protected Virtualization dumps")
Signed-off-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>
2022-11-29 17:03:57 +01:00
Marc Hartmayer
6e42c527d7 zdump: pv_process_pglist: convert assertions into errors
Corrupted dumps might have invalid page states. Therefore, let's convert
the assertions into errors.

Fixes: 8fa1b5a00b ("zdump: dfi: add support to read Protected Virtualization dumps")
Signed-off-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>
2022-11-29 17:03:57 +01:00
Eduard Shishkin
f7d2339c6a zipl: List-Directed IPL from ECKD DASD
Make zipl tool prepare ECKD DASD for booting by different IPL
programs (with the same boot record installed).

Besides standard CCW-type IPL, user gets an ability to trigger
(with the same boot record installed!) List-Directed IPL. This
allows to use the feature of secure boot from ECKD DASD (which
is not available for CCW-type IPL).

When using the old boot interfaces, the usual CCW-type IPL is
triggered for DASD. Also for compatibility reasons zipl(8) tool
is modified to create and install one, or two "similar" program
tables per boot partition, depending on job and disk type. The
"similar" program tables differ only in block pointers format.
The old IPL programs (CCW-type IPL) use program table based on the
old format.

All program tables are packed to the same bootmap file. Their
order and logical offsets in the file are not significant (not
used by anyone).

The picture below shows which program table is used for IPL of
specified type from disk of specified type. Here "0" and "1" are
identifiers of program tables based on the old and new block
pointers format respectively. E.g. program table "0" is used for
CCW-type IPL from ECKD DASD. LD-IPL from DASD FBA is unsupported
(respectively, only one program table "0" is used), etc.

                            CCW-IPL   LD-IPL

 SCSI                          X        0
 DASD FBA                      0        X
 ECKD DASD LDL                 0        X
 ECKD DASD CDL                 0        1

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>
2022-11-29 17:03:57 +01:00
Eduard Shishkin
cf5f373142 zipl: Rename component_type enum
Rename component_type enum from COMPONENT_* to COMPONENT_TYPE_*

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Eduard Shishkin
e09c675b70 libvtoc: Introduce is_vol1() check
Introduce is_vol1() in vtoc.h and update the user in libzds.c

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Eduard Shishkin
6bd93f475c Clean up of libdasd
Remove standalone IOCTLs definitions and use sys/mount.h instead

Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-29 17:03:57 +01:00
Stefan Haberland
3f12bdf4c7 tunedasd: add copy_pair swap capability
Add an option to tunedasd to trigger a copy pair swap using the appropriate
ioctl for DASD devices.

      -s, --copy-pair-swap COPY_PAIR

This command requires a comma separated pair of primary,secondary to be
specified. In case of success the old secondary will become the new primary
device and the old primary will become a secondary device.

Example:

tunedasd /dev/dasda -s 0.0.9700,0.0.9740

This will set the old secondary device 0.0.9740 as the new primary.
The old primary device 0.0.9700 will automatically become a secondary
device.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
3aa7f6e298 libdasd: fix ioctl macro to return also positive return codes
In case of an error the ioctl macro only returns errno to the calling
function.
This misses positive returncodes from ioctls.
Change the macro to also return positive return codes.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
4e28047eb4 tunedasd: move tunedasd ioctls to libdasd
Move all DASD IOCTLs to libdasd and adapt all affected
users accordingly.

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
f654b971d0 zdev: add copy_pair attribute for DASD devices
The DASD device driver has a new attribute copy_pair to make storage
server copy pairs known to the driver.
Add this attribute to zdev.

Usage example:

Add two copy pairs 1000,2000 and 1000,3000 to a DASD device 1000
$ chzdev dasd 1000 copy_pairs=1000,2000 copy_pairs=1000,3000

or

$ chzdev dasd 1000 copy_pairs="1000,2000 1000,3000"

To add a third copy pair later on:
$ chzdev dasd 1000 copy_pairs=1000,4000

To remove all copy pairs from the device 1000:
$ chzdev dasd 1000 -r copy_pairs

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
e742d1c9ae zdev: correctly handle multiple values for CCW devices
Correctly create multiple lines in the udev rule for CCW device attributes
with multi bit set that contain multiple values.

Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
803b87e324 zconf/lsdasd: add Copy Pair output option
Add an option -P|--copy-pairs to show all DASD devices with copy
relations set up in the system and their roles.

The output looks like:

    # ./s390-tools/zconf/lsdasd -h
    [...]
            -P|--copy-pairs
	             Print information about copy pairs.

     # ./s390-tools/zconf/lsdasd -P
     Bus-ID    Role       Name      Paired devices
     ================================================================================
     0.0.9700  primary    dasdd     0.0.9740,0.0.9743,0.0.9744,0.0.9745
     0.0.9740  secondary            0.0.9700
     0.0.9701  primary    dasdf     0.0.9741
     0.0.9741  secondary            0.0.9701
     0.0.9702  primary    dasdh     0.0.9742
     0.0.9742  secondary            0.0.9702

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Stefan Haberland
5107a7be16 zconf/lsdasd: fix Copy Pair related output
Fix the default output for copy pair secondary devices to not show
a faulty blockdevice entry and major:minor combination.

The new output looks like:

    # lsdasd
    Bus-ID    Status    Name      Device  Type         BlkSz  Size      Blocks
    ================================================================================
    0.0.9740  secondary                   ECKD
    0.0.9741  secondary                   ECKD
    0.0.9742  secondary                   ECKD
    0.0.e964  active    dasda     94:0    ECKD         4096   21129MB   5409180
    0.0.e967  active    dasdb     94:4    ECKD         4096   21129MB   5409180
    0.0.9330  active    dasdc     94:8    ECKD         4096   782MB     200340
    0.0.9700  active    dasdd     94:12   ECKD         4096   782MB     200340
    0.0.9701  active    dasdf     94:20   ECKD         4096   782MB     200340
    0.0.9702  active    dasdh     94:28   ECKD         4096   782MB     200340

Also add copy_pairs to extended output:

     # lsdasd -l 9700
     0.0.9700/dasdd/94:12
       status:                               active
       type:                                 ECKD
       blksz:                                4096
       size:                                 782MB
       blocks:                               200340
       extent_size:                          1113
       logical_capacity:                     1113
       space_allocated:                      1113
       use_diag:                             0
       readonly:                             0
       eer_enabled:                          0
       erplog:                               0
       hpf:                                  1
       uid:                                  IBM.750000000ABT31.9700.00
       fc_security:                          Unsupported
       paths_installed:                      38 39 3a 3b
       paths_in_use:                         38 39 3a 3b
       paths_non_preferred:
       paths_invalid_cabling:
       paths_cuir_quiesced:
       paths_invalid_hpf_characteristics:
       paths_error_threshold_exceeded:
       copy_pairs:                           0.0.9700,0.0.9740 0.0.9700,0.0.9743 0.0.9700,0.0.9744 0.0.9700,0.0.9745

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-15 10:24:42 +01:00
Jan Höppner
1178291686 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 17:11:48 +01:00
Jan Höppner
c8d1aa55b4 New release s390-tools-2.24.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 17:11:48 +01:00
Matthew Rosato
25a70ac5a8 libap: use util_lockfile and remove liblockfile dependency
Now that we have a utility library for file locking, remove all
calls to liblockfile functions from libap and remove all links to
the library from the current users of the libap liblockfile
implementation (ap_tools/ap-check and zdev).

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/142
Suggested-by: Luca BRUNO <luca.bruno@coreos.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 16:09:19 +01:00
Matthew Rosato
6235a51d7c libutil: add example for util_lockfile
Adds util_lockfile_example.c, which can be used to sample
util_lockfile support.

To acquire a lock using a parent PID (e.g. your shell instance):
util_lockfile_exmample -f <path> -l <retries>

To release the lock using the parent PID:
util_lockfile_example -f <path> -r

To acquire the lock, sleep briefly, and then release the lock
using the PID of the util_lockfile_example process:
util_lockfile_example -f <path> -L <retries>

In each example, the <path> is the location of the desired lockfile
and <retries> is the number of times to retry acquiring the lock
if it fails.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/issues/142
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 16:09:19 +01:00
Matthew Rosato
e1aec24e84 libutil: introduce util_lockfile
Implement simple file-locking routines that use process PIDs for stale
lock detection.  The implementation is meant to be a simplified subset of
what liblockfile was previously being used for by libap, allowing the
external dependency to be removed.

This initial implementation provides a series of functions that allow for
creating/release file locks using either the current process PID or the
PID of the current process parent.  When creating a file lock, first a
temporary file is created and the appropriate PID (either this process
PID or the parent process PID) is placed in the file to specify the owner
of the lock.  Then an attempt is made to link that file to the desired
file location; if this succeeds, the lock is now held on behalf of the
specified PID.  If it fails, this implies the file already exists
(meaning the lock is already held).  In this case, stale lock detection
is performed by reading the PID from the file and ensuring that the
associated process still exists -- if it does not, then the lock is
presumed stale and destroyed.  If the process still exists, then either
the lock request fails or the caller will sleep and retry, depending on
an optional retry setting.

A lock remains valid until either 1) it is released via the corresponding
util_lockfile function, which will delete the corresponding file 2) the
associated PID no longer exists, which leaves the file in-place but will
cause it to be destroyed the next time a different process attempts to
lock that file or 3) the file is directly removed (e.g. rm).

A typical usecase for such support would be to provide a means for
multiple invocations of the same (or different) tools to ensure that they
do not access the same shared resource simultaneously.  For example,
ap-check, chzdev and lszdev all have a need to view and/or modify the AP
and vfio-ap configuration files; util_lockfile can be used to ensure that
only one instance of any of these utilities do that at a time by ensuring
they all use the same lockfile.
Additionally, providing the ability to specify the parent PID rather than
the current PID allows for a general purpose tool (like mdevctl) to
invoke a sub-program (ap-check) to acquire and release a lockfile as
necssary while allowing stale lock detection to be controlled by that
parent PID, allowing the lock to remain held over multiple sub-program
invocations.

Note that this implementation is sufficient for our current usage (e.g.
lockfiles placed in tmpfs) but does not take into consideration things
like NFS, which a more complete lockfile solution like liblockfile does.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/issues/142
Suggested-by: Luca BRUNO <luca.bruno@coreos.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 16:09:19 +01:00
Eduard Shishkin
d9a6fb3ccf zipl/src: fix secure boot status check
Set up the secure_boot_supported global variable at the
function bootmap_create() instead of bootmap_create_device()
to make sure that the secure boot status is checked for all
relevant jobs.

Fixes: 7b369318dd ("zipl: check for secure boot once")
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-09 16:09:19 +01:00
Steffen Eiden
a47dd4570a README: update zgetdump information
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
8fa1b5a00b zdump: dfi: add support to read Protected Virtualization dumps
Sometimes dumping a virtual machine from the outside is the only way to
get the data that is needed. This can be the case if a dumping mechanism
like kdump hasn't been configured or data needs to be fetched at a
specific point. Dumping a protected guest from the outside without help
from FW/HW doesn't yield sufficient data to be useful. Hence we have
introduced Protected Virtualization (PV) dump support - also named
confidential dump support.

The confidential dump support works by integrating the firmware into the
dump process. New Ultravisor calls (UVC) are used to initiate the dump
process, dump CPU data, dump memory state and lastly complete the dump
process. The guest's data is fully encrypted and can only be decrypted
by the entity that owns the customer communication key (CCK) for the
dumped guest. The output format is very similar the normal s390 vmcore
ELF format, it's only enriched by new sections where the returned data
from the UVC "Complete Configuration Dump" and the UVC "Dump
Configuration Storage State" is stored. The encrypted CPU data is stored
in a new note type `NT_S390_PV_CPU_DATA`. The old note types do still
exists but without any confidential data stored. The memory data is
stored in the LOAD segment as usual but for PV dumps it's fully AES-XTS
encrypted.

This commit adds support for reading/decrypting PV guest dumps to
zgetdump by introducing a new DFI input module (`dfi_pv_elf.c`). For
specifying the customer communication key a new command line option
`--key` is added.

Signed-off-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>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
e537ab902e zdump: Makefile: add basic libpv support
The functionalities of libpv are used in the next patch. Libpv itself
requires glib2 and libcrypto.

Signed-off-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>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
f0fb4a180a zdump: refactor usage print
The function will be reused in a later patch.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
f957d895cd zdump: consolidate error reporting
Consolidate error reporting to make sure that error messages are used
consistently. In addition, don't call `zg_exit()` directly, but instead
return the value 1 in `main()`.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
73c3a9e684 libpv: fix memory leak in pv_get_openssl_error
While at it, improve documentation and adapt libpv code.

Signed-off-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>
2022-11-03 17:45:38 +01:00
Marc Hartmayer
2ee1387f34 libpv/genprotimg/pvattest: use glib/gi18n.h
Replace `<glib/gi18n-lib.h>` with `<glib/gi18n.h>` since `<glib/gi18n-lib.h>` should only be used
for libraries (see https://docs.gtk.org/glib/i18n.html).

Signed-off-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>
2022-11-03 17:45:38 +01:00
Eduard Shishkin
10cefb3337 zipl/src/zipl_helper.device-mapper: Fix bug in error path
Prevent double free/close that happens in get_multipath_status()
when the output of "dmsetup status XXX" is empty

Fixes: 599b141 ("zipl: Rewrite helper script in C")
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:45:09 +01:00
Dan Horák
7b369318dd zipl: check for secure boot once
Check for secure boot status only once when starting to create the
bootmap.

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/133
Signed-off-by: Dan Horák <dan@danny.cz>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Dan Horák
cf2fb296f0 zipl: be verbose about secure boot support
Report the details about the state of secure boot on the system when running
zipl in verbose mode.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/133
Signed-off-by: Dan Horák <dan@danny.cz>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
6cbd81f997 zdump: zg.h: consolidate PAGE_SIZE macros
Reuse `PAGE_SIZE` defined in `boot/s390.h`.

Signed-off-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>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
2025cf751f zdump: man: fix long form of abbreviation
ELF stands for "Executable and Linkable Format" (see
https://refspecs.linuxfoundation.org/elf/TIS1.1.pdf).

Signed-off-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>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
5a052103ae zdump: fix signatures of the wrappers zg_alloc, zg_realloc and zg_ioctl
Adapt the wrappers `zg_alloc`, `zg_realloc` and `zg_ioctl` to match the
signatures used by `calloc`, `realloc` and `ioctl`.

Signed-off-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>
2022-11-03 17:38:53 +01:00
Thomas Richter
2ced5853b4 cpumf/lshwc: fix incremented counter output
lshwc displays counter values extracted from the /dev/hwctr device.
The counter values are retrieved using a loop and incremented instead
of just displayed on output.
This leads to the situation where a counter is incremented in large
numbers while the counter triggering program is active. When this
program terminates, the counter should not increase but remain steady.

This is not the case as this example shows:

 # lshwc -i 2 -l90 -a :a | fgrep Total  | \
	awk -F ',' '{print $2 "," $152 "," $157}'
 Report time and values of DFLT_ACCESS and DFLT_CC counters
 sleep 10
 # DFLTCC=1 python3 -c "import zlib; zlib.compress(b'A'*6000000000);
 Increment counter DFLT_ACCESS and DFLT_CC, runs about 45 seconds

Output before:
15:24:20,0,0
15:24:22,0,0
15:24:24,0,0
15:24:26,0,0
15:24:28,0,0
15:24:30,0,0
15:24:32,2067027,592996481      <--- python3 program start
15:24:34,6953101,2039012580
15:24:36,14494585,4264340060
15:24:38,24759568,7346128396
....
15:24:56,232929262,70526362509
15:24:58,269037963,81464038124
15:25:00,307757248,93171809261
15:25:02,348900718,105620730492
15:25:04,392646075,118841031269  <--- python3 program stop
15:25:06,438956016,132853968029  <-- Value column two increased by 49148217
15:25:08,488104233,147709011658  <-- Similar high increase

The reason is that lshwc takes the last read counter value and keeps
adding it to the total count, even if there zero delta to the previous
read value. Fix this by clearing the total count value between ioctl()
read operations.

Output after:
15:39:26,0,0
15:39:28,0,0
15:39:30,0,0
15:39:32,0,0
15:39:34,0,0
15:39:36,1367250,380721127      <--- python3 program start
15:39:38,4104791,1108181711
15:39:40,6740994,1858843730
15:39:42,9277545,2646351211
15:39:44,11895180,3444375804
....
15:40:16,54060774,16315924126
15:40:18,57830349,17513712210
15:40:20,61628170,18690791102
15:40:22,65410470,19864086006
15:40:24,69070765,21028646754   <--- python3 program stop
15:40:26,70429758,21472772340   <-- No increase of value in column two
15:40:28,70429758,21472772340
15:40:30,70429758,21472772340
15:40:32,70429758,21472772340
15:40:34,70429758,21472772340
15:40:36,70429758,21472772340
15:40:38,70429758,21472772340

Fixes: 27a562da0a ("cpumf/lshwc: Program to extract complete counter sets")
Reported-by: Axel Busch <Axel.Busch@ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Thomas Richter
13edbb7d5e cpumf/pai: fix core dump when summary flag set
pai dumps core when invoked with summary flag -S and
certain painnpa.XXXXX data files:

   # ~/s390-tools/cpumf/pai -r -S
   Segmentation fault (core dumped)
   #

Fix this and check the existence of event raw data before
reading it. This avoid accessing NULL pointer trying to read raw
data when no counter values have been appended as raw data by the
kernel.

Fixes: dc73c77d73 ("cpumf/pai: Omit detailed event information when summary flag selected")
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
1643af4578 zdev: dracut: modifiy the module-setup.sh
Export and import the configurations with zdev:early on the
site-specific configurations as well. Filter the site-specific
configurations by attribute "zdev:early" and import the output
to the corresponding sites.

Note that --site parameter does not work with the device type.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
c7ac1e63bd zdev: add export/import support for site
Add export and import support for site-specific settings. For each
site-specific configuration, a new site-block will be generated as
below. The same format can be interpreted by the import function and use
the values on the device's site-specific configuration.

Typical example of a site-block in the export file:

[site3 dasd-fba 0.0.f001]
online=1
cmb_enable=0

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
fa3dd0ec20 zdev: add --deconfigure-all function for chzdev
Introduce --deconfigure-all feature, which will remove all available
settings from the mentioned device. A typical device can have 10
different site-specific settings, active settings, persistent
settings and sometimes auto-configured settings configured in it.
--deconfigure-all can be used to remove all of them with a single
command.

usage: 	chzdev -D <device-id>
	chzdev --deconfigure-all <device-id>

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
34146c3f92 zdev: modify man-pages to update the site information
Add the new site parameter help information in the man-pages of both
chzdev and lszdev.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
298ede17f5 zdev: provide site-specific information in lszdev
lszdev must be modified to share the site-specific configuration
information from the persistent settings. The persistent configuration
array will be read and tabularized based on the site-id input from the
user.

This patch also accommodates the site specific information in the
lszdev --info command. New information about the site-ids are integrated
with the command. For example,

DEVICE dasd-eckd 0.0.f001
  Names              : -
  Modules            : dasd_eckd_mod dasd_mod
  Online             : no
  Exists             : yes
  Persistent         : yes
  Sites              : 1,2

  ATTRIBUTE                     ACTIVE    PERSISTENT  SITE1  SITE2
  cmb_enable                    "0"       "0"         "1"    -
  eer_enabled                   "0"       -           -      -
  erplog                        "0"       -           -      -
  failfast                      "0"       -           -      -
  last_known_reservation_state  "none"    -           -      -
  online                        "0"       "1"         "1"    "1"
  raw_track_access              "0"       -           -      -
  readonly                      "0"       -           -      -
  reservation_policy            "ignore"  -           -      -
  use_diag                      "0"       -           -      -

Each available site specific configuration will be shown as column. The
"Sites" parameter in the above output indicates the available site
configurations and the SITE1 and SITE2 colums indicates the detailed
configuration for the respective sites.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
d66ace8121 zdev: add functionality to read site-specific settings
Modify the dev_get_setting_list function to get the site-specific
attributes of the device. The new site_id parameter for this function
must be less than SITE_FALLBACK to read the site-specific attributes.
As SITE_FALLBACK setting is same as persistent setting, we do not need
a separate read function for it.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
2e89722ef0 zdev: make site specific udev-rule for ccw
The udev-rules must be modified to make it site-specific. The site
specific part of the rule should be executed only on the sites where the
devices belong. Change the generic udev rule to support the site-specific
udev-rule.

During boot, the current site-id is read from the LOADPARM which is
located at /sys/firmware/ipl. The zdev_id command reads this LOADPARM
and prints the SITE_ID based on the value. This SITE_ID is the
current site where the udev-rule is executing. Based on this assumption,
the rule is divided in to multiple blocks where each site block is executed
only for the corresponding sites.

The rule executes based on the value read from the LOADPARM.
1. When the LOADPARM specifies a site-id and if the current device has
   an associated configuration settings, it will be used.
2. When the LOADPARM specifies a site, and the current device does not
   have any associated configuration set, the udev rule uses the
   fallback configuration settings.
3. If the device does not have a fallback-configuration settings or any
   site-specific settings, no configurations will be used.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
c8ad5f57d0 zdev: modify zdev_id to read the site_id from loadparm
The currently active site can be found from the loadparm attribute which
is located at /sys/firmware/ipl/loadparm. Read the value of loadparm and
extract the site_id.

The loadparm is an 8 byte alphanumerical IPL parameter. The content of
loadparm can be of different forms to indicate different boot menu
options, which are used by Linux for selecting the respective boot menu
entries. To indicate the site-id, loadparm adds a 'S' character. Where,
the following character after 'S' indicates either the site-id or
indivcation to derive the site-id from SSID.
For example,
If the loadparm value is Sn,'n' is the integer which could be one of the
valid site_ids from 0 to 9; i.e when booted on site-1, loadparm value will
be S1.
If loadparm value is "SS", zdev_id extracts the site_id from the SSID of
the current ipl device. For ccw and zfcp devices, the current ipl device-id
can be found at /sys/firmware/ipl/device.

In any case, if the loadparm contains invalid value, or empty, the
site_id will be default to the common-site.

After the first invocation of the zdev_id from udev-rule, the site-id
information is stored in /run/zdev_id.env file. This will reduce the
number of further invocation of zdev_id from within udev-rules.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
d2317943c0 zdev: add site specific states for devices
Currently zdev supports the configuration and maintenance of one single
persistent device state. With the introduction of sites, zdev should be
able to store, configure and maintaine NUM_SITES number of states in
the persistent configuration. This patch modifies the struct device and
adds a new site_specific device_state array, which stores the
persistent configuration for all the available sites.

Total number of available sites are configured with NUM_SITES. Where,
10 site-specific configurations and 1 common configuration.

1. during read, all site data is always read and update the
   site_specific[] array.
2. dev->persistent is a copy of dev->site_specific[global_site_id]
3. modifications are only done on dev->persistent, and during write
   dev->persistent overlays dev->site_specific[global_site_id]

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Vineeth Vijayan
198c9fc052 zdev: onboard --site option on zdev commands
In some high-availability setups, root and boot disks of a Linux
installation are copied to remote sites that can take over execution
of a Linux workload in case of an outage of the original site.
A site in this context is an execution environment such as an LPAR
or z/VM guest.

Each site may provide a different set of devices, or require different
parameters to be applied per device. chzdev supports site-specific
device configuration for up to 10 sites. Each site is identified by
a number in the range 0 to 9. You can provide a separate set of persistent
device configuration for each site. The IPL Load parameter value specified
during boot determines the currently active site. Only the device
configuration of the active site is applied during boot and when new
devices become available. A common configuration can be provided that is
applied when no site-specific configuration is available for a device in
the active site.

User can use the --site parameter to configure devices for a specific
site only. Configuration actions without a site parameter apply to the
common configuration.

During the boot, the active site configuration is chosed based on the
IPL LOADPARM variable. If the LOADPARM contains no valid site-id (0 to 9),
the fallback-site id will be used. The fallback-site-id can also be
configured with the zdev tools by not specifying the --site parameter.

Some of the new chzdev/lszdev commands with site-parameter can be as
follows

1. chzdev -ep f001 --site 3

This command is used to configure the device f001 for the site 3. During
boot, if the LOADPARM value is S3, this device configuration will be
used.

2. lszdev --site 3

This command lists all the devices which are configured for site 3.

3. chzdev -ep f001

Above command does not have a --site parameter. This device settings
will be used for the following conditions

1. When the loadparm specifies a site, (e.g S3), and the device does not
   have an associated config-set, zdev uses fallback config set.
2. When the loadparm does not specify any site information, then the
   fallback config set will be used.

When the loadparm specifies a site, and the device does not have an
associated config set, nor a fallback site, nothing is configured for this
device.

Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
b3551f50a8 Provide codespell configuration
While at it, add a list with words to ignore. This suppresses the following codespell finding:

$ codespell libcpumf/libcpumf_cpuset.c
libcpumf/libcpumf_cpuset.c:15: parm ==> param, pram, parma
libcpumf/libcpumf_cpuset.c:17: parm ==> param, pram, parma

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
4ff360e621 Provide CheckPatch configuration
Provie a CheckPatch configuration file and mention it in the coding style
guidelines (this feature was introduced with CheckPatch version 0.32 ~11 years
ago).

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
87e8fa18cf CODINGSTYLE.md: mention EditorConfig configuration
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Marc Hartmayer
4bd135c3c7 Add project-wide .clang-format
Add a .clang-format configuration and mention it in the coding guidelines.

Usage example:

 $ clang-format -i **/*.[ch]

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-11-03 17:38:53 +01:00
Matthew Rosato
f69350e8bd ap_tools/ap-check: reject start for control domains without usage
When configuring a vfio-ap device, specifying only control domains
without any usage domains results in a useless configuration in that
both adapters and usage domains are required to make cryptographic
resources available to the guest.  Without that, the control domains
are useless.  While the kernel allows this, let's reject this
combination with a message.

Suggested-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:22 +02:00
Peter Oberparleiter
5768d55a08 zipl/boot: add secure boot trailer
This patch enhances the zipl stage3 loader image adding a trailer as
required for secure boot by future firmware versions.

Note: with the change in this patch the padding via objcopy command line
options is replaced by padding via linker script directives with the
same effect.

Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Holger Dengler
538264a8cd lszcrypt: fix parameter handling for device list
lszcrypt allows the explicit definition of a list of devices. Continue
the parameter processing if multiple devices are specified.

Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
7f09f0e4ad zdump: refactor pt_load_add
In an upcoming patch the refactored function `pt_load_add` is reused. While at
it, add a wrap-around check to `pt_load_add`, replace `g.opts.device` access
with `fh->path` (this makes this function easier testable) and improve the
documentation.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
e36084d7f2 libpv/pvattest: consolidate __PV_BIT and BIT macros
Consolidate `__PV_BIT` and `BIT` macros.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
bd18166a21 zdump: opts: declare print_usage_exit in header file
Remove `static` attribute from `print_usage_exit` and declare it in the header
file `opts.h`. The function will be reused in a later patch.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
a6f2c38891 zdump: constify dfi_vmcoreinfo_get
Caller of `dfi_vmcoreinfo_get` must not modify the returned value, therefore
return a `const char *` value for `dfi_vmcoreinfo_get`.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
029a3f8f52 zdump: add guarded storage support for ELF input and output format
Add guarded storage registers support for the ELF input and the ELF output
format. See `man 2 s390_guarded_storage` for details about guarded storage.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
dc87aef335 zdump: dfo_elf: replace HDR_PER_CPU_SIZE with get_max_note_size_per_cpu
The maximum size of all supported ELF note entries for a CPU can be 0x4a4 bytes
and not 0x4a0. Use a function for the calculation so it's easier to maintain.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
d712806b39 lib/zt_common.h: add macro for determining field size
The macro `sizeof_field` is used in the next patch.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
2734724432 zdump: df_elf: add multiple ELF section helper
Preparation for upcoming patches.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
6176509076 zdump: df_elf: refactor check_elf_hdr
The function will be reused by upcoming patches.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
1780efae07 zdump: df_elf: ehdr_is_elf_object: add ELF version check
Currently, only the ELF version `1` is defined by the ELF specification. See
`man 5 elf` for details. Therefore of course, we do only support this version.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
922e8cbb2f zdump: since we create ELF version 1 files use this value explicitly
The value of `EV_CURRENT` might change. The ELF specification says: "The value
of EV_CURRENT, though given as 1 above, will change as necessary to reflect the
current version number." [1]

[1] https://refspecs.linuxfoundation.org/elf/elf.pdf

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
eef0dd4fa4 zdump: df_elf: add missing endianness check
A s390x ELF file must use big-endian encoding.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
f93f437f8b zdump: df_elf: read_elf_hdr: return Elf64_Ehdr struct
This makes the API of `read_elf_hdr` consistent with `read_elf_phdrs`.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
4e6d43e2ac zdump: dfi_elf: refactor nt_* functions
The functions are refactored so the `struct zg_fh` value is now passed as
argument to the `nt_*` functions instead of accessing the global variable `g.fh`
from within of the functions. This makes the functions reusable and easier to
test. While at it, improve the documentation of `nt_read`.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
922d29ee49 zdump: dfi_elf_init: introduce temporary variable
Introduce variable `phdrs` and shrink the scope of `phdr`. This removes
duplicated code `&phdr[i]` and makes the code easier to read. While at it,
constify the parameter of `pt_notes_add`.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
25475bdf42 zdump: read_elf_phdrs: fix -Wconversion issue
`ehdr->e_phoff` has the type `Elf64_Off` and this maps to `uint64_t`, but `off_t` is signed. Let's
add a check for this.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
09c413b1be zdump: read_elf_phdrs: handle no program header case
Handle the case where no program headers are defined (see `man 5 elf`).

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
8944c2f60d zdump: dfi_elf: refactor read_elf_(ehdr|phdrs)
Make the function unit testable and easier to reuse - no functional change.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
ff3fe4bf43 zdump: constify struct zg_fh *fh parameter in the zg file APIs
Constify the `struct zg_fh *fh` parameter in the file APIS, e.g. `zg_path()`.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Joern Siglen
5fe2e19277 dbginfo.sh: fix man page
add missing option in man page

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Joern Siglen
b8cf861aea dbginfo.sh: add kuberentes (OCP) data collection
generalize the collection step name from "docker" to "container host"

initial version of adding data collection for OCP.

all log file content might be too much for most installations

Reviewed-by: Alexander Klein <alkl@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Reviewed-by: Mike Storzer <mstorzer@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Joern Siglen
6ca3576dbf dbginfo.sh: fix typo
typo in KVM section

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
7ea425db5e pvattest/exchange_format.c: use proper endianess conversion macro for hdr->version
GUINT32_TO_BE and GUINT32_FROM_BE do exactly the same in case of glib2, just the
naming differs. However, at this point the conversion is from be to system
endianness therefore `GUINT32_FROM_BE` is the proper macro.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
330ddb7adb libpv: add copied parameter to pv_gbytes_memcpy and adapt pvattest
It's often useful to know how much data was actually copied, therefore let's
introduce an nullable parameter `@copied` to `pv_gbytes_memcpy`.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
d69b9fab4a pvattest: build_attestation_v1_ioctl: make the code more robust
...by adding a compile time assertion about the buffer size. While at it, report
the actual user data size in case of an error.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
4e02dc8751 pvattest: uvio.c: remove endianness handling
The endianness handling was only partially implemented for uvio.c. Let's remove
it since doesn't make much sense here, because the IOCTL must be build on the
same system where they're actually executed.

Signed-off-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>
2022-10-22 20:27:16 +02:00
Joern Siglen
0c8be405ce dbginfo.sh: fix vmcp buffer resizing
the buffer sizing did not work any longer
add explaining comments and rework the variable names for claritiy

refering commit f7cc14753cc9d930af804e2ac3ce108a12145db6

Reported-by: Mike Storzer <MSTORZER@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Steffen Eiden
24677dc561 libpv: remove wrong parameter attribute
`error` is actually used therefore let's remove the `G_GNUC_UNUSED` attribute.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Steffen Eiden
7e7c38755d libpv: improve error reporting
Use `PV_CERT_ERROR` error domain whenever useful. Currently, it's only used
internally in libpv and therefore there is no problem in changing it.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
229cd6d194 zdump: don't modify passed program header in pt_load_add()
There should be no problem with this change since the changed value was never
used. Therefore, let's remove the assignment and declare the parameter as const
to prevent such a behavior in the future.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
776e5d41d7 zdump: dfi_elf: factor out some ELF functionalities
This makes them reuseable and testable.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
8d7e8a87b5 zdump: df_elf: move function documentation to function declarations
It's more common to have the function documentation next to the function
declarations.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
e24d8c936c zdump: move NOTE_NAME_* definitions to df_elf.h
This allows the reuse in other source files.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
39b6c4a273 zdump: introduce ELF_NOTE_ROUNDUP macro
Introduce and use `ELF_NOTE_ROUNDUP` macro.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Marc Hartmayer
da9b96fb12 lib/zt_common.h: consolidate ROUNDUP macro
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:27:16 +02:00
Alexander Egorenkov
7d855acd07 util_arch: Fix max HSA size for Z16 machine
The machine types are not strictly increasing anymore since Z16, therefore,
we cannot use numerical comparison to find out the correct HSA size
of a machine.

Fixes: 2515832469 ("util_arch: Add IBM z16 as known machine")
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Marc Hartmayer
f961a2bf90 common.mak: fix compiler command line for afl-clang
`afl-clang` requires a white space between a option name and the option value.
Therefore let's fix this for `-xc` by adding a white space.

How to reproduce:

$ make -C zdump CC=afl-clang-fast LINK=afl-clang-fast

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Joern Siglen
9f93af614f dbginfo.sh: ensure compatibility with /bin/dash
some versions of /bin/dash do interpreted our commands different, which
causes a variable failure and termination of the script.

e.g. a new line char "\n" will split the cmd_type to a multiple line variable
not working with the followup commands. adding the head command does avoid
multiline variables now.

Problem found in Ubuntu 20.4 and some older Ubuntu versions

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Joern Siglen
d529ba07d3 dbginfo.sh: update message on not beeing root
add a hint that dbginfo.sh -c can check some basic stuff even as non-root

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Joern Siglen
0fffb05d01 dbginfo.sh: add tool check for testing
move tool checking to the top of the script and add the output to
the check function (-c) for easy verifivation and testing

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Joern Siglen
92b8409207 dbginfo.sh: ensure type commands compatible with dash
All debian distors use the dash shell as default, where type is not supprting "-t" parameter

Remove of "-t" where not important and change type check not using -t

Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:34 +02:00
Steffen Maier
bc3134ba5a dbginfo.sh: collect config and logs of Dandified YUM (DNF)
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:31 +02:00
Steffen Maier
c7f55a182f dbginfo.sh: collect YaST log files of successful installation
Cf. /usr/sbin/save_y2logs of yast2-logs.rpm.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:28 +02:00
Steffen Maier
5078be45b8 dbginfo.sh: collect generated unattended installation kickstart files
anaconda-7.2.91-1
c4249bbe06 (diff-86b9da41b3aa75b36055aa04a2effff06c0decadc7b80f6efd8a513fe265746eR49)
("merge dispatch to HEAD")

anaconda-24.7-1
1c4af3b432
("Include original kickstart in /root/original-ks.cfg (#1227939)")
https://github.com/rhinstaller/anaconda/pull/447
https://bugzilla.redhat.com/show_bug.cgi?id=1227939

Cf. https://anaconda-installer.readthedocs.io/en/latest/boot-options.html#inst-nosave
from anaconda-25.2-1
b7d699a547
("Make it possible to skip saving of kickstarts and logs (#1285519)")

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:24 +02:00
Steffen Maier
2418ea93fc dbginfo.sh: collect anaconda log files of successful installation
Since anaconda-15.2-1
7e2754473e (diff-3b740ff14364c6d399b86ef7a6ca044e17b334ab351988600058d9af0e7fa0bc)

See also /usr/libexec/anaconda/log-capture of anaconda-core.rpm.

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:26:21 +02:00
Steffen Maier
13cac5de44 dbginfo.sh: also collect "local" multipath-tools config
Easier to read for a first glimpse than the (still required) full config.

$ man multipathd
       list|show config local
              Show the currently used configuration like show config, but lim‐
              iting  the  devices  section  to those devices that are actually
              present in the system.

Works as of multipath-tools 0.7.8 commit
c23924dc74ee ("multipathd: implement "show config local"")

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:17:31 +02:00
Joern Siglen
b6687925cc dbginfo.sh: cleanup outdated comment and formating
remove spaces and outdated comment line

Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:17:31 +02:00
Marc Hartmayer
7ee51182bf zdump: fix memory leak of path
==660622== 385 bytes in 7 blocks are definitely lost in loss record 30 of 37
==660622==    at 0x484417C: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-s390x-linux.so)
==660622==    by 0x4E93BD7: strdup (strdup.c:42)
==660622==    by 0x11249F: zg_strdup (zg.c:115)
==660622==    by 0x11249F: zg_open (zg.c:164)
==660622==    by 0x114FBF: dfi_dump_open (dfi.c:750)
==660622==    by 0x114FBF: dfi_init (dfi.c:772)
==660622==    by 0x111465: do_copy (zgetdump.c:192)
==660622==    by 0x111465: main (zgetdump.c:216)

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:17:31 +02:00
Siglen
ec3e5b4a75 dbginfo.sh: save dbginfo.sh version to dbginfo.log
we do miss a simple way to see the dbginfo.sh version used by the
customer for the debug generation. saving the version now to dbginfo.log

Reported-by: Mike Storzer <MSTORZER@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-10-22 20:17:31 +02:00
Jan Höppner
0b5aac3d79 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-18 15:33:16 +02:00
Jan Höppner
bea3180836 New release s390-tools-2.23.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-18 15:33:16 +02:00
Steffen Eiden
1ffd767977 pvattest/tools: Add script to display config UID and additional data
Although the previous patch enables pvattest to display the
config UID this script enables the user to extract the config UID of
the SE-guest and the additional data if specified. This allows users of
pvattest v2.22.0 to view the config UID without examining binary blobs.

$ ./pvattest-info attresult.bin
Config UID:
1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a
Additional Data:
1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b
1b1b

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
a4e396fdd7 pvattest: Add more information to verbose logging
In verbose mode (-v) `pvattest verify´ now also prints
"Attestation measurement verified", if the verification was successful and the
Config UID of the SE-guest and any additional data if available.

$ pvattest -V verify  [...]
Attestation measurement verified
Config UID:
1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a

Additional Data:
1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b
1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b1b

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
972d4fe0a5 pvattest: Improve logging
Change the name of `hexdump´ to `pvattest_log_bytes´. Additionally, allow
that function to dump the bytes as a single hexadecimal number.

Change the name of `printf_hexdump´ to `pvattest_hexdump´.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
148460c235 pvattest: Improve error reporting
Map the Ultravisor return code 0x2 to "Invalid UV command" string. This
results in better error messages.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
8c2f6790fe genprotimg: sync man and help with pvattest
Syncronizes the description of shared options of genprotimg and pvattest

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
044272ea25 pvattest: Improve man pages and help
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Matthew Rosato
7d67dc8f1c zdev: add some --type ap examples to manpages
The ap type has some unique input parameters, provide some examples
on how to modify and set the apmask and aqmask via chzdev.  Also
include an example of using lszdev to view the apmask and aqmask.

Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/140
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Benjamin Block
71461d80bf Makefile: use common Make definition for DRACUTDIR
The dracut installation directory is referenced from `chreipl-fcp-mpath`,
`zdev`, and `zipl`; in each with its own individual definition and
variable name. This makes it unnecessarily hard to change it when
installing from the top level directory of s390-tools and passing
variable overwrites via the command line.

Fix this by defining a common `DRACUTDIR` variable in the shared
`common.mak` file, and referencing this in each tool as base directory.
With this a user can simply pass `DRACUTDIR=/foo/bar/baz` on the
commandline and change the installation for all three tools.

Further, also derive common `DRACUTCONFDIR` and `DRACUTMODDIR` variables
from `DRACUTDIR` in `common.mak`, so that `zdev` and `zipl` don't use
different variable names for the same directory anymore, and all these
are defined together in a common place.

Semantically nothing changes for a default build/installation.

Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Benjamin Block
9eac2788d7 Makefile: use common Make definition for UDEVDIR and UDEVRULESDIR
UDEVDIR is used in both `chreipl-fcp-mpath` and `zdev`, but with a
different meaning. In the former it points to the base udev directory,
not the rules directory; in the later it points to the rules directory.
If someone was to call `make` from the top level directory, and set
UDEVDIR for the whole build/installation, it would either break `zdev`
or `chreipl-fcp-mpath` (depending on what it was set to).

Fix this by pulling the definition of it in the shared `common.mak`
file, and giving it a common meaning. Point UDEVDIR to the base udev
directory, and UDEVRULESDIR to the rules directory below it.

Semantically nothing changes for a default build/installation.

Signed-off-by: Benjamin Block <bblock@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
6ff8202fa9 zipl: Add missing check for a nullpointer.
Fixes a bug that leads to a segmentation fault when no parmline is
provided.

Fixes: 11b401b5 ("zipl: move and make check for maximum command line length dynamic")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
acf30de415 pvattest: remove unnecessary variable
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
a766411306 pvattest: fix dependency checking
Fixes a bug that make still tried to build pvattest even when the
compilation of pvattest was turned off.
This lead to a build bug when one of the dependencies was not met.

Also fixes the check of the OpenSSL version at build time.

Fixes: 3ab06d77 ("pvattest: Create, perform, and verify attestation measurements")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Steffen Eiden
cbcab61c65 libpv: fix dependency checking
Fixes a bug that make still tried to build libpv even when the
compilation of libpv was turned off.
This lead to a build bug when one of the dependencies was not met.

Also fixes the check of the OpenSSL version at build time.i

Fixes: 38639269 ("libpv: New library for PV tools")
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-08-16 18:28:21 +02:00
Marc Hartmayer
c3d179f06e libpv: Fix condition in pv_BIO_reset()
pv_BIO_reset() wrongfully handled the BIO_reset() rc for non-file-backed BIOs.
This is currently not an issue as the only non-file BIO used cannot fail
at BIO_reset()

Fixes: 3ab06d77fb ("pvattest: Create, perform, and verify attestation measurements")
Signed-off-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>
2022-08-16 18:27:36 +02:00
Marc Hartmayer
f42250ca9b genprotimg: Fix BIO_reset() returncode handling
The returncode handling for BIO_reset() was wrong when handling with
file based BIOs.

This resulted in a bug that DER formated certificates cannot be read
by genprotimg which is now fixed.

Fixes: d90344a2 (genprotimg: check return value of BIO_reset)
Signed-off-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>
2022-08-16 18:23:13 +02:00
Dan Horák
7217903ce4 libvmdump: add default assignment operators
lkcd_dump.cpp: In constructor ‘LKCDDump32::LKCDDump32(Dump*, const RegisterContent32&)’:
lkcd_dump.cpp:191:27: warning: implicitly-declared ‘constexpr RegisterContent32& RegisterContent32::operator=(const RegisterContent32&)’ is deprecated [-Wdeprecated-copy]
  191 |         registerContent = r;
      |                           ^
In file included from lkcd_dump.h:18,
                 from lkcd_dump.cpp:17:
register_content.h:63:9: note: because ‘RegisterContent32’ has user-provided ‘RegisterContent32::RegisterContent32(const RegisterContent32&)’
   63 |         RegisterContent32(const RegisterContent32&);
      |         ^~~~~~~~~~~~~~~~~
lkcd_dump.cpp: In constructor ‘LKCDDump64::LKCDDump64(Dump*, const RegisterContent64&)’:
lkcd_dump.cpp:232:27: warning: implicitly-declared ‘constexpr RegisterContent64& RegisterContent64::operator=(const RegisterContent64&)’ is deprecated [-Wdeprecated-copy]
  232 |         registerContent = r;
      |                           ^
register_content.h:49:9: note: because ‘RegisterContent64’ has user-provided ‘RegisterContent64::RegisterContent64(const RegisterContent64&)’
   49 |         RegisterContent64(const RegisterContent64&);
      |         ^~~~~~~~~~~~~~~~~

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
708abbf380 dasdfmt: fix buffer overread warning
dasdfmt.c: In function ‘dasdfmt_write_labels’:
dasdfmt.c:1110:22: warning: ‘write’ reading 88 bytes from a region of size 4 [-Wstringop-overread]
 1110 |                 rc = write(fd, &vlabel->vollbl, (sizeof(*vlabel)
      |                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1111 |                                                  - sizeof(vlabel->volkey)));
      |                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from dasdfmt.c:23:
../include/lib/vtoc.h:84:14: note: source object ‘vollbl’ of size 4
   84 |         char vollbl[4];         /* volume label                              */
      |              ^~~~~~
In file included from ../include/lib/util_opt.h:16,
                 from dasdfmt.c:20:
/usr/include/unistd.h:378:16: note: in a call to function ‘write’ declared with attribute ‘access (read_only, 2, 3)’
  378 | extern ssize_t write (int __fd, const void *__buf, size_t __n) __wur
      |                ^~~~~

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
28dbec093b iucvterm: fix function declaration
GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
daf02f75b1 dasdview: fix string truncation warning
Replace strncpy() with util_strlcpy() which provides the required
semantic.

In function ‘dasdview_print_format1’,
    inlined from ‘dasdview_view_standard’ at dasdview.c:1952:4,
    inlined from ‘dasdview_view’ at dasdview.c:2165:3,
    inlined from ‘main’ at dasdview.c:2364:3:
dasdview.c:1791:25: warning: ‘strncpy’ output may be truncated copying 16 bytes from a string of length 1023 [-Wstringop-truncation]
 1791 |                         strncpy(asc, (char *)dumpstr + i, 16);
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dasdview.c:1792:25: warning: ‘strncpy’ output may be truncated copying 16 bytes from a string of length 1023 [-Wstringop-truncation]
 1792 |                         strncpy(ebc, (char *)dumpstr + i, 16);
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In function ‘dasdview_print_format2’,
    inlined from ‘dasdview_view_standard’ at dasdview.c:1935:4,
    inlined from ‘dasdview_view’ at dasdview.c:2165:3,
    inlined from ‘main’ at dasdview.c:2364:3:
dasdview.c:1825:25: warning: ‘strncpy’ output may be truncated copying 8 bytes from a string of length 1023 [-Wstringop-truncation]
 1825 |                         strncpy(asc, (char *)dumpstr + i, 8);
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dasdview.c:1826:25: warning: ‘strncpy’ output may be truncated copying 8 bytes from a string of length 1023 [-Wstringop-truncation]
 1826 |                         strncpy(ebc, (char *)dumpstr + i, 8);
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
[hoeppner@linux.ibm.com: sort include]
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
71b0460d11 mon_tools: drop an always-true condition
The d_name member of struct dirent is a statically allocated string,
thus it's always non-NULL.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Acked-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
ff62f4d425 mon_tools: fix user counting condition
The ut_user (aka ut_name) member of struct utmp is a statically
allocated string, thus always non-NULL.

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Acked-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
53c523ab19 ziomon: silence unaligned pointer value warnings
The build produces a number of warnings like the ones below. The
unaligned pointers are expected, thus silence the warnings by disabling
the compiler diagnostics.

ziomon_dacc.c: In function ‘read_message’:
ziomon_dacc.c:189:44: warning: taking address of packed member of ‘struct message’ may result in an unaligned pointer value [-Waddress-of-packed-member]
  189 |         if ( (rc = read_message_header(fp, &msg->length, &msg->type)) )
      |                                            ^~~~~~~~~~~~

or

In file included from ziomon_mgr.c:36:
blkiomon.h: In function ‘blkiomon_stat_init’:
blkiomon.h:70:21: warning: taking address of packed member of ‘struct blkiomon_stat’ may result in an unaligned pointer value [-Waddress-of-packed-member]
   70 |         minmax_init(&bstat->size_r);
      |                     ^~~~~~~~~~~~~~

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Dan Horák
2285b9527b lib: avoid redefinition of _AC() macro
The kernel already provides the same macro as does the zt_common.h file,
thus check for its availability first.

  CC      zconf/qeth/lsqeth.o
In file included from ../../include/lib/util_base.h:17,
                 from lsqeth.c:30:
../../include/lib/zt_common.h:27: warning: "_AC" redefined
   27 | #define _AC(X, TYPE)    X##TYPE
      |
In file included from /usr/include/linux/ethtool.h:17,
                 from lsqeth.c:12:
/usr/include/linux/const.h:21: note: this is the location of the previous definition
   21 | #define _AC(X,Y)        __AC(X,Y)
      |

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/137
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Balint Reczey
b4648ec4bd dumpconf: Don't run the service in containers
It just fails to start in unprivileged containers

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/85
Signed-off-by: Balint Reczey <balint.reczey@canonical.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
[hoeppner@linux.ibm.com: expanded from !lxc to !container]
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Juergen Christ
c6207db8fc cpacfstats: Typos and Explanation
Correct wrong counter name.
Clarify counting of KMA.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Sven Schnelle
1bd73c68f9 zipl/boot: don't use lt to test value in tape0.S
This instruction is not present on older machines, therefore
use ltr.

Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Fixes: 1627c6a39f ("zipl: Support command lines longer than 896 bytes in bootloader")
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Joern Siglen
47016441f0 dbginfo.sh: get more details on lspci command
The new version of lspci does support an extended verbose mode "-vvv"

Using the the tripple v parameter does also work for the old version
having the same result as the double v called before.

Reported-by: Eberhard Pasch <epasch@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Steffen Maier
eeed384a51 dbginfo.sh: fix accidental ftrace buffer shrinkage/free
https://www.kernel.org/doc/html/latest/trace/ftrace.html?highlight=free_buffer

  free_buffer:

        If a process is performing tracing, and the ring buffer should be
        shrunk "freed" when the process is finished, even if it were to be
        killed by a signal, this file can be used for that purpose. On close
        of this file, the ring buffer will be resized to its minimum size.
        Having a process that is tracing also open this file, when the process
        exits its file descriptor for this file will be closed, and in doing so,
        the ring buffer will be "freed".

        It may also stop tracing if disable_on_free option is set.

$ cat /sys/kernel/debug/tracing/buffer_size_kb
7 (expanded: 1408)
$ cat /sys/kernel/debug/tracing/free_buffer
cat: /sys/kernel/debug/tracing/free_buffer: Invalid argument
$ cat /sys/kernel/debug/tracing/buffer_size_kb
0

Reported-by: Thomas Lambart <Thomas.Lambart2@ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Steffen Eiden
cd5d6a5004 libpv/cert.c: Improve error reporting
The current implementation drops the reason why a download of a CRL
failed. This is changed to the reporting of the error triggered by the
last CRL download attempt.

This mainly helps to check for the download error during CI testing
and prevent connectivity issues to be the reason of a test failure.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:57:17 +02:00
Thomas Richter
e4733002da cpumf/pai: Extract type number from PMU named pai_ext
Use PMU named pai_ext to extract the PMU type number required
for the installation of PAI NNPA counters using perf_event_open()
system call.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:56:44 +02:00
Thomas Richter
15158ee0ca libcpumf: Detect PMU named pai_ext
Add a check to detect Processor Activity Instrumentation (PAI)
Extension 1 facility unit.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:56:44 +02:00
Thomas Richter
dc73c77d73 cpumf/pai: Omit detailed event information when summary flag selected
When the summary flag is selected do not print detailed information
on every single event. Just print the summary information on each
non-zero counter value.

Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:56:44 +02:00
Thomas Richter
56529261db cpumf/pai: Omit file write progress information
During recording, progress information is displayed on the screen
on how many event have been processed and at which offset these
events have been extracted from the ring buffer.

This information is usually of no interest to the user. Omit this
data and only print them when requested via verbose flag.

Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-07-21 15:56:44 +02:00
Juergen Christ
fcb1f7efd1 cpacfstats: Add PAI and hotplug support
Add virtual counters pai_user and pai_kernel to detail all Processor Activity
 Instrumentation (PAI) counters in user resp. kernel space.  Once activated,
they will show all counters for the corresponding set.  Add option -n to limit
the display to only non-zero counter values.

Add support for cpu hotplug events based on libudev.  CPU hotplug events are
used to either detach from a vanishing CPU or (re-)attach to a (re-)appearing
CPU.  In that case, a "hotplug detected" virtual counter is set to a non-zero
value to indicate possible loss of counters which happens when CPACF is used
on the CPU before cpacfstatsd could attach to it.  The hotplug indication is
cleared once all counters are deactivated.

Add support for JSON output.  The JSON document is an array of JSON objects
representing the counters and their values.  Every object has a name (property
"counter") and a value (property "value").  For PAI counters, the counters
also have a space (property "space") determining the counter set pai_user or
pai_kernel, and a numeric id (property "counterid") that can be used to filter
the JSON document.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-29 14:07:34 +02:00
Juergen Christ
72b5e8b313 cpacfstats: Handle CPU hotplug
cpacfstatsd now correctly handles offline cpus and dynamically attaches to
cpus once they get online.  If events are enabled when a hotplug event
occurs, cpacfstatsd uses a pseudo-counter to notify user applications about
the occurence of this event and a potential data inaccuracy.

cpacfstats shows if a hotplug event has been detected since at least one
counter was activated.  As soon as all counters are deactivated, the
hotplug detection state is reset.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-29 14:07:31 +02:00
Juergen Christ
225964875c cpacfstats: Use timed operations in daemon.
The cpacfstats daemon is susceptible to dos attacks from malicious clients
that connect but either do not send a query or receive an answer fast
enough.  The latter currently is impossible but might occur once we
introduce further counters.

Solve both problems by exploiting a timed read/write operation in the
daemon and close the connection on timeout.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-29 14:06:35 +02:00
Marc Hartmayer
e580190074 common.mak: remove -rdynamic since it's a linker flag
Remove `-rdynamic` since it's a linker flag. This should not cause any problems
because we differentiate between compilation and linking by default. While at
it, adapt the `print_backtrace` documentation accordingly.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Acked-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-29 14:06:35 +02:00
Thomas Richter
8ef593904d cpumf/pai: Use util_file_read_va function
Use util_file_read_va() function to read out the event number
given the event file. Also use util_strdup() function to save
the event name. This function terminates on Out Of Memory condition.

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>
2022-06-29 14:06:35 +02:00
Frank Heimes
51b9504720 zkey: use default benchmarked Argon2i with LUKS2.
cryptsetup 2.1.0 requires excessive amount of RAM (1GB) to luksOpen encrypted
drives (LP: #1820049).
LUKS2 introduced support for Argon2i and Argon2id as a Password-Based Key
Derivation Function (PBKDF).
Argon2 is the winner of Password Hashing Competition and is now officially
recommended by RFC 9106.
PBKDF2 is currently used in zkey to mitigate out-of-memory errors when
multiple LUKS2 volumes are opened automatically via /etc/crypttab.

This patch is to use Argon2i (the deflaut algorithm) as key derivation function
for LUKS2 volumes, but with options for low memory and time requirements.
Using the default Argon2i options might still cause out-of-memory errors.

Link: https://bugs.launchpad.net/ubuntu/+source/cryptsetup/+bug/1820049
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/138
Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
Acked-by: Ingo Franzki ifranzki@linux.ibm.com
[hoeppner@linux.ibm.com: fix whitespace, line break, and commit message]
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-29 14:06:34 +02:00
Thomas Richter
e9d0e267c5 cpumf/lscpumf: Replace /sys mount point by util_path_sysfs
Replace hard coded /sys directory by call to util_path_sysfs()
function.

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>
2022-06-29 14:06:34 +02:00
Jan Höppner
b028d4c254 Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2022-06-20 14:08:53 +02:00
165 changed files with 8971 additions and 2039 deletions

12
.checkpatch.conf Normal file
View File

@@ -0,0 +1,12 @@
--max-line-length=100
--strict
# Not Linux therefore don't expect a Linux tree
--no-tree
# Ignore the following
--ignore PREFER_KERNEL_TYPES
--ignore EXECUTE_PERMISSIONS
--ignore FILE_PATH_CHANGES
--ignore NEW_TYPEDEFS
--ignore SPDX_LICENSE_TAG

134
.clang-format Normal file
View File

@@ -0,0 +1,134 @@
# Must be compatible with clang-format 14
---
AccessModifierOffset: "-4"
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments: false
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveMacros: AcrossComments
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BitFieldColonSpacing: Both
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeComma
BreakConstructorInitializersBeforeComma: false
BreakStringLiterals: false
ColumnLimit: "100"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: "8"
ContinuationIndentWidth: "8"
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
# git grep -h '^#define [^[:space:]]*\(for_each\|iterate\)[^[:space:]]*(' \
# | sed "s,^#define \([^[:space:]]*\(for_each\|iterate\)[^[:space:]]*\)(.*$, - '\1'," \
# | LC_ALL=C sort -u
ForEachMacros:
- "dfi_cpu_iterate"
- "dfi_mem_chunk_iterate"
- "dfo_chunk_iterate"
- "for_each_rb_entry"
- "ns_range_for_each"
- "sd_cpu_item_enable_iterate"
- "sd_cpu_item_iterate"
- "sd_cpu_iterate"
- "sd_cpu_type_iterate"
- "sd_sys_item_enable_iterate"
- "sd_sys_item_iterate"
- "sd_sys_iterate"
- "table_col_iterate"
- "table_iterate_mark_keys"
- "util_list_iterate"
- "util_list_iterate_safe"
- "util_opt_iterate"
- "util_rec_iterate"
IncludeBlocks: Preserve
# Leave imports as is
IncludeCategories:
- Regex: .*
Priority: 1
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: "8"
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: "1"
NamespaceIndentation: Inner
PackConstructorInitializers: CurrentLine
PenaltyBreakAssignment: "10"
PenaltyBreakBeforeFirstCallParameter: "30"
PenaltyBreakComment: "10"
PenaltyBreakFirstLessLess: "0"
PenaltyBreakString: "10"
PenaltyExcessCharacter: "100"
PenaltyReturnTypeOnItsOwnLine: "60"
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatementsExceptForEachMacros
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: "1"
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementMacros:
- "STATIC_ASSERT"
TabWidth: "8"
TypenameMacros:
- "STACK_OF"
UseTab: Always
WhitespaceSensitiveMacros:
- "STRINGIFY"

5
.codespellrc Normal file
View File

@@ -0,0 +1,5 @@
[codespell]
ignore-words-list = parm,parms
skip = ''
count = ''
quiet-level = 3

3
.gitignore vendored
View File

@@ -95,6 +95,9 @@ zdev/src/chzdev_usage.c
zdev/src/lszdev
zdev/src/lszdev_usage.c
zdsfs/zdsfs
zdump/.check_dep_fuse
zdump/.check_dep_zgetdump
zdump/.detect_openssl.dep.c
zdump/zgetdump
zfcpdump/10-zfcpdump.install
zfcpdump/cpioinit

View File

@@ -9,6 +9,7 @@ List of all individuals having contributed content to s390-tools
- Antoinette Kaschner
- Arnd Bergmann
- Axel Wirbser
- Balint Reczey
- Benjamin Block
- Brian C. Lane
- Carsten Otte
@@ -20,6 +21,7 @@ List of all individuals having contributed content to s390-tools
- Colin Walters
- Dan Horak
- Dan Horák
- Daniel S. Haischt
- Despina Papadopoulou
- Dimitri John Ledkov
- Eberhard Pasch

View File

@@ -1,5 +1,66 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.25.0 (2022-12-08)__
For Linux kernel version: 6.1
Changes of existing tools:
- ap_tools: Use new mdevctl installation location
- lsdasd/tunedasd/zdev: Add support to handle copy pair relations presented by the DASD driver
- zdev: Add --shell command line switch to generate output suitable for shell environments
- zipl: Add List-Directed IPL from ECKD DASD to support secure boot
Bug Fixes:
- ipl_tools: Fix chreipl node for NVMes with CONFIG_NVME_MULTIPATH
- libdasd: Fix bug that prevented positive ioctl return codes
* __v2.24.0 (2022-11-09)__
For Linux kernel version: 6.0
Add new tools / libraries:
- Provide config files for checkpatch, codespell, and clang-format
Changes of existing tools:
- dbginfo.sh: Collect log from various distro tools (YaST, DNF, Anaconda)
- dbginfo.sh: add Kubernetes data collection
- libutil: Introduce util_lockfile
- zdev: Add site-aware device configuration
- zdump: Add support to read Protected Virtualization dumps
- zipl/boot: Add secure boot trailer
Bug Fixes:
- ap_tools/ap-check: Reject start for control domains without usage
- cpumf/lshwc: Fix incremented counter output
- cpumf/pai: Fix core dump when summary flag set
- dbginfo.sh: Ensure compatibility with /bin/dash shell
- dbginfo.sh: Save dbginfo.sh version to dbginfo.log
- zipl/src/zipl_helper.device-mapper: Fix bug in error path
* __v2.23.0 (2022-08-18)__
For Linux kernel version: 5.19
Changes of existing tools:
- Makefile: use common Make definition for DRACUTDIR
- Makefile: use common Make definition for UDEVDIR and UDEVRULESDIR
- cpacfstats: Add PAI and hotplug support
- cpumf/pai: Omit file write progress information
- dbginfo.sh: Get more details on lspci command
- dumpconf: Prevent running the service in containers
- libcpumf: Detect PMU named pai_ext
- pvattest: Improve error reporting and logging
- zdev: Add some --type ap examples to manpages
- zkey: Use default benchmarked Argon2i with LUKS2
Bug Fixes:
- dbginfo.sh: Fix accidental ftrace buffer shrinkage/free
- genprotimg: Fix BIO_reset() returncode handling
- libpv: Fix dependency checking
- pvattest: Fix dependency checking
- zipl: Fix segmentation fault when no parmline is provided
* __v2.22.0 (2022-06-20)__
For Linux kernel version: 5.18

View File

@@ -4,8 +4,10 @@ Coding guidelines for s390-tools
For s390-tools the preferred language is C. We provide libraries, e.g.
[`libutil`](libutil) that should be used by all tools if possible.
The coding style is based on the Linux [kernel guidelines]. Therefore, use
the [checkpatch] tool for verification before you submit a patch.
The coding style is based on the Linux [kernel guidelines]. Therefore, use the
[checkpatch] tool for verification before you submit a patch. s390-tools
provides a CheckPatch configuration for this - see
[`.checkpatch.conf`](.checkpatch.conf).
[kernel guidelines]: https://www.kernel.org/doc/html/latest/process/coding-style.html
[checkpatch]: https://github.com/torvalds/linux/blob/master/scripts/checkpatch.pl
@@ -17,6 +19,39 @@ This package started in 2001 and has a long "tradition" - therefore, older tools
might not follow all recommendations. Note that when changing existing code,
consistency could have priority over applying rules.
Automatic Code Formatting
-------------------------
> **NOTE:** clang-format is a helpful tool but please don't use it blindly!
s390-tools provides a ClangFormat (https://clang.llvm.org/docs/ClangFormat.html)
configuration file - see [`.clang-format`](.clang-format). It can be used to
format your C/C++ code automatically.
Clang-format can format a single file or multiple files at once. For example, to
format `main.c` in place, run the following command in a terminal:
```bash
clang-format -i main.c
```
In order to format only your current staged changes use the clang-format git
plugin:
```bash
git clang-format --staged
```
See also `git clang-format -h`.
Automatic Editor Configuration
------------------------------
s390-tools provides a EditorConfig (https://editorconfig.org/) configuration
file - see [`.editorconfig`](.editorconfig). EditorConfig defines coding style
rules (such as indentation size, use of tabs, etc.) and is supported by most
common editors natively or via plugins.
Standard abbreviations
----------------------

View File

@@ -60,6 +60,7 @@ Package contents
* zgetdump:
Retrieve system dumps from either tapes, DASDs, SCSIs or NVMes.
Decrypt Protected Virtualization (PV) dumps from IBM Secure Execution guests.
* qetharp:
Read and flush the ARP cache on OSA Express network cards.
@@ -306,20 +307,19 @@ build options:
| | | hsavmcore |
| zlib | `HAVE_ZLIB` | zgetdump, dump2tar |
| ncurses | `HAVE_NCURSES` | hyptop |
| pfm | `HAVE_PFM` | cpacfstats |
| net-snmp | `HAVE_SNMP` | osasnmpd |
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb, |
| | | libkmipclient, pvattest |
| | | libkmipclient, pvattest, zgetdump |
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, |
| | | libkmipclient |
| glib2 | `HAVE_GLIB2` | genprotimg, pvattest |
| glib2 | `HAVE_GLIB2` | genprotimg, pvattest, zgetdump |
| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb, libkmipclient,|
| | | pvattest |
| libxml2 | `HAVE_LIBXML2` | libkmipclient |
| systemd | `HAVE_SYSTEMD` | hsavmcore |
| liblockfile | `HAVE_LOCKFILE` | ap-check |
| libudev | `HAVE_LIBUDEV` | cpacfstatsd |
This table lists additional build or install options:
@@ -376,6 +376,13 @@ the different tools are provided:
- Packages: blktrace, multipath-tools, sg3-utils
- Tools: rsync, tar, lsscsi
* zgetdump
For building zgetdump you need OpenSSL version 1.1.0 or newer
installed (openssl-devel.rpm). Also required is glib2
(glib2-devel.rpm) and zlib (zlib-devel.rpm).
Tip: you may skip the zgetdump build by adding
`HAVE_OPENSSL=0`, `HAVE_GLIB2=0`, or `HAVE_ZLIB=0`.
* cmsfs-fuse/zdsfs/hmcdrvfs/zgetdump:
The tools cmsfs-fuse, zdsfs, hmcdrvfs, and zgetdump depend on FUSE.
FUSE is provided by installing the fuse3 and libfuse3 packages and by a
@@ -403,14 +410,13 @@ the different tools are provided:
As of s390-tools-1.13.0, the minimum required kernel level is 2.6.38.
* cpacfstats:
For building the cpacfstats tools you need libpfm version 4 or
newer installed (libpfm-devel.rpm). Tip: you may skip the cpacfstats
build by adding `HAVE_PFN=0` to the make invocation. To run the
cpacfstats daemon the kernel needs to have performance
events enabled (check for `CONFIG_PERF_EVENTS=y`) and you need libpfm
version 4 or newer installed. A new group 'cpacfstats' needs to be
created and all users intending to use the tool should be added to
this group.
For building the cpacfstats tools you need libudev installed
(systemd-devel.rpm). Tip: you may skip the cpacfstats build by
adding `HAVE_LIBUDEV=0` to the make invocation. To run the
cpacfstats daemon the kernel needs to have performance events
enabled (check for `CONFIG_PERF_EVENTS=y`). A new group 'cpacfstats'
needs to be created and all users intending to use the tool should
be added to this group.
* zdev:
Depending on the boot loader and initial RAM-disk mechanism used by a
@@ -506,8 +512,7 @@ the different tools are provided:
GNU awk for the build process.
* ap-check:
For building the ap-check mdevctl callout utility you need liblockfile
version 1.14 or newer installed (liblockfile-devel.rpm). Also required is
json-c version 0.13 or newer (json-c-devel.rpm).
Tip: you may skip ap-check build by adding `HAVE_LOCKFILE=0` or `HAVE_JSONC=0`
to the make invocation.
For building the ap-check mdevctl callout utility you need json-c version
0.13 or newer (json-c-devel.rpm).
Tip: you may skip ap-check build by adding `HAVE_JSONC=0` to the make
invocation.

View File

@@ -1,27 +1,23 @@
include ../common.mak
MDEVCTL_DIR = /etc/mdevctl.d/
MDEVCTL_SCRIPTS = /etc/mdevctl.d/scripts.d/
MDEVCTL_CALLOUTS = /etc/mdevctl.d/scripts.d/callouts/
MDEVCTL_DIR = /usr/lib/mdevctl/
MDEVCTL_SCRIPTS = /usr/lib/mdevctl/scripts.d/
MDEVCTL_CALLOUTS = /usr/lib/mdevctl/scripts.d/callouts/
MDEVCTL_DEP_DIR = /etc/mdevctl.d/
MDEVCTL_DEP_SCRIPTS = /etc/mdevctl.d/scripts.d/
MDEVCTL_DEP_CALLOUTS = /etc/mdevctl.d/scripts.d/callouts/
libs = $(rootdir)/libap/libap.a \
$(rootdir)/libutil/libutil.a
ifeq (${HAVE_LOCKFILE},0)
all:
$(SKIP) HAVE_LOCKFILE=0
install:
$(SKIP) HAVE_LOCKFILE=0
else ifeq (${HAVE_JSONC},0)
ifeq (${HAVE_JSONC},0)
all:
$(SKIP) HAVE_JSONC=0
install:
$(SKIP) HAVE_JSONC=0
else
LDLIBS += -llockfile -ljson-c
LDLIBS += -ljson-c
all: ap-check
@@ -39,6 +35,17 @@ install: all
fi; \
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ap-check \
$(DESTDIR)$(MDEVCTL_CALLOUTS)
@if [ ! -d $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS) ]; then \
mkdir -p $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_DIR); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_SCRIPTS); \
chown $(OWNER).$(GROUP) $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_DIR); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_SCRIPTS); \
chmod 755 $(DESTDIR)$(MDEVCTL_DEP_CALLOUTS); \
fi; \
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 ap-check.sh \
$(DESTDIR)$(MDEVCTL_DEP_CALLOUTS)
endif
clean:

View File

@@ -133,7 +133,7 @@ static void ap_check_cleanup(struct ap_check_anchor *anc)
if (anc->dev)
vfio_ap_device_free(anc->dev);
if (anc->cleanup_lock)
ap_release_lock();
ap_release_lock_callout();
}
/*
@@ -685,6 +685,14 @@ static int ap_check_handle_start(struct ap_check_anchor *anc)
goto out;
}
/* Ensure device with control domains also has usage domains */
if (util_list_is_empty(anc->dev->domains) &&
!util_list_is_empty(anc->dev->controls)) {
fprintf(stderr, "At least one usage domain must be specified\n");
rc = -1;
goto out;
}
/* Check against all other active vfio-ap devices */
rc = check_other_mdevs_sysfs(anc);
/* Check against the system sysfs values for apmask/aqmask */
@@ -767,7 +775,7 @@ out:
*/
static int ap_check_handle_post(void)
{
return ap_release_lock();
return ap_release_lock_callout();
}
/* For the specified device, print the attributes to stdout in JSON format */

15
ap_tools/ap-check.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
#
# ap-check.sh - Wrapper script for 'ap-check' binary
#
# mdevctl has deprecated the /etc/mdevctl.d/scripts.d/callouts/ location in
# newer releases. This wrapper ensures that mdevctl 1.2.0 and older can
# still access 'ap-check' for now, and will be removed at a later time.
#
# Copyright 2022 IBM Corp.
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
#
[ -e /usr/lib/mdevctl/scripts.d/callouts/ap-check ] && /usr/lib/mdevctl/scripts.d/callouts/ap-check "$@"

View File

@@ -27,11 +27,7 @@ ENABLE_DOC = 0
# https://www.gnu.org/software/make/manual/make.html#Directory-Variables
CHREIPLZFCPMPDIR = $(USRLIBDIR)/chreipl-fcp-mpath
UDEVDIR = $(USRLIBDIR)/udev
UDEVRULESDIR = $(UDEVDIR)/rules.d
UDEVRUNDIR = /run/udev
DRACUTDIR = $(USRLIBDIR)/dracut
DRACUTCONFDIR = $(DRACUTDIR)/dracut.conf.d
DEBUGOUTDIR = $(UDEVRUNDIR)
INSTALL_EXEC = $(INSTALL) -g $(GROUP) -o $(OWNER) --preserve-timestamps

View File

@@ -5,7 +5,7 @@ COMMON_INCLUDED = true
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2
RELEASE = 22
RELEASE = 25
PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -60,8 +60,10 @@ endef
$(eval $(call cmd_define, AS," AS ",$(CROSS_COMPILE)as))
$(eval $(call cmd_define, CC," CC ",$(CROSS_COMPILE)gcc))
$(eval $(call cmd_define, LINK," LINK ",$(CC)))
$(eval $(call cmd_define, HOSTCC," HOSTCC ",gcc))
$(eval $(call cmd_define, CXX," CXX ",$(CROSS_COMPILE)g++))
$(eval $(call cmd_define, LINKXX," LINKXX ",$(CXX)))
$(eval $(call cmd_define, CPP," CPP ",$(CROSS_COMPILE)gcc -E))
$(eval $(call cmd_define, AR," AR ",$(CROSS_COMPILE)ar))
$(eval $(call cmd_define, NM," NM ",$(CROSS_COMPILE)nm))
@@ -81,8 +83,6 @@ CHECKTOOL = $(call echocmd," CHECK ",/$@)$(CHECK_SILENT)
SKIP = echo " SKIP $(call reldir) due to"
INSTALL = install
LINK = $(CC)
LINKXX = $(CXX)
CP = cp
ifneq ("${V}","1")
MAKEFLAGS += --quiet
@@ -91,7 +91,7 @@ ifneq ("${V}","1")
else
echocmd=
endif
DEFAULT_CFLAGS = -g -rdynamic -fstack-protector-all -W -Wall -Wformat-security
DEFAULT_CFLAGS = -g -fstack-protector-all -W -Wall -Wformat-security
ifeq ("${W}","1")
DEFAULT_CFLAGS += -Wextra -Wshadow -Wundef -Wuninitialized -Wdouble-promotion -Wconversion
endif
@@ -120,7 +120,7 @@ endif
define check_header_prereq
$(shell printf "#include <%s>\n int main(void) {return 0;}\n" $1 | \
( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) \
$2 -o /dev/null -xc - ) >/dev/null 2>&1 && echo -n yes)
$2 -o /dev/null -x c - ) >/dev/null 2>&1 && echo -n yes)
endef
#
@@ -133,7 +133,7 @@ endef
# $5: Additional compiler & linker options (optional)
#
check_dep=\
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) $5 -o /dev/null -xc - ) > /dev/null 2>&1; \
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
if [ $$? != 0 ]; \
then \
printf " REQCHK %s (%s)\n" $1 $2; \
@@ -193,6 +193,11 @@ ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
SYSTEMDSYSTEMUNITDIR =
USRINCLUDEDIR = $(INSTALLDIR)/usr/include
ZKEYKMSPLUGINDIR = $(USRLIB64DIR)/zkey
UDEVDIR = $(USRLIBDIR)/udev
UDEVRULESDIR = $(UDEVDIR)/rules.d
DRACUTDIR = $(USRLIBDIR)/dracut
DRACUTCONFDIR = $(DRACUTDIR)/dracut.conf.d
DRACUTMODDIR = $(DRACUTDIR)/modules.d
ifeq ($(LIBDIR),$(INSTALLDIR)/lib)
SOINSTALLDIR = $(USRLIB64DIR)

View File

@@ -1,11 +1,28 @@
include ../common.mak
ifeq (${HAVE_LIBUDEV},0)
all:
$(SKIP) HAVE_LIBUDEV=0
install:
$(SKIP) HAVE_LIBUDEV=0
else
check_dep:
$(call check_dep, \
"cpacfstatsd", \
"libudev.h", \
"systemd-devel", \
"HAVE_LIBUDEV=0")
ALL_CPPFLAGS += -DVERSION=$(VERSION)
all: cpacfstats cpacfstatsd
all: check_dep cpacfstats cpacfstatsd
cpacfstatsd: cpacfstatsd.o stats_sock.o perf_crypto.o
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -ludev -lpthread -o $@
cpacfstats: cpacfstats.o stats_sock.o
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
@@ -16,6 +33,8 @@ install: all
$(INSTALL) -m 644 cpacfstatsd.8 $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 cpacfstats.1 $(DESTDIR)$(MANDIR)/man1
endif
clean:
rm -f *.o *~ cpacfstatsd cpacfstats

View File

@@ -1,6 +1,6 @@
.\" cpacfstats.1
.\"
.\" Copyright IBM Corp. 2015, 2020
.\" Copyright IBM Corp. 2015, 2022
.\" s390-tools is free software; you can redistribute it and/or modify
.\" it under the terms of the MIT license. See LICENSE for details.
.\"
@@ -32,7 +32,9 @@ cpacfstats \- enable, disable and display CPACF statistical data
.RB ]
.RB [ \-p | \-\-print
.I counter
.RB [ \-n | \-\-nonzero]
.RB ]
.RB [ \-j | \-\-json ]
.
.SH DESCRIPTION
The cpacfstats client application interacts with the cpacfstatsd daemon and
@@ -44,12 +46,347 @@ All counters are initially disabled and must be switched on to measure
CPACF activities of the system. There is a slight performance penalty with
CPACF counters enabled.
Note: All cryptographic counters are bound to physical CPUs. If you use
dedicated CPUs for your LPAR, you obtain only your CPACF activities. If
your CPUs are shared with other LPARs, their cryptographic activities might
distort the results. CPACF performance counters are available on LPARs
only. For security reasons only members of the group \fIcpacfstats\fR are
allowed to run the cpacfstats client application.
CPACF activity counters come in two flavors: CPU-MF and PAI. CPU-MF
counters are only available on LPARs and have to be authorized. If
they are available, the counters
.B des,
.B aes,
.B sha,
.B rng,
and
.B ecc
are made available. These counters can individually be activated,
reset, printed, or deactivated. PAI counters are a lot more detailed.
The user interface only offers the counters
.B pai_user
and
.B pai_kernel
to count CPACF usage in user-space or kernel-space. When printing
these counters, detailed counters are shown. The detailed names are:
.RS
.IP \(bu
KM DES,
.IP \(bu
KM 2key TDES,
.IP \(bu
KM TDES,
.IP \(bu
KM DES protected key,
.IP \(bu
KM 2key TDES protected key,
.IP \(bu
KM TDES protected key,
.IP \(bu
KM AES 128bit,
.IP \(bu
KM AES 192bit,
.IP \(bu
KM AES 256bit,
.IP \(bu
KM AES 128bit protected key,
.IP \(bu
KM AES 192bit protected key,
.IP \(bu
KM AES 256bit protected key,
.IP \(bu
KM AES-XTS 128bit,
.IP \(bu
KM AES-XTS 256bit,
.IP \(bu
KM AES-XTS 128bit protected key,
.IP \(bu
KM AES-XTS 256bit protected key,
.IP \(bu
KMC DES,
.IP \(bu
KMC 2key TDES,
.IP \(bu
KMC TDES,
.IP \(bu
KMC DES protected key,
.IP \(bu
KMC 2key TDES protected key,
.IP \(bu
KMC TDES protected key,
.IP \(bu
KMC AES 128bit,
.IP \(bu
KMC AES 192bit,
.IP \(bu
KMC AES 256bit,
.IP \(bu
KMC AES 128bit protected key,
.IP \(bu
KMC AES 192bit protected key,
.IP \(bu
KMC AES 256bit protected key,
.IP \(bu
KMC PRNG,
.IP \(bu
KMA AES 128bit,
.IP \(bu
KMA AES 192bit,
.IP \(bu
KMA AES 256bit,
.IP \(bu
KMA AES 128bit protected key,
.IP \(bu
KMA AES 192bit protected key,
.IP \(bu
KMA AES 256bit protected key,
.IP \(bu
KMF DES,
.IP \(bu
KMF 2key TDES,
.IP \(bu
KMF TDES,
.IP \(bu
KMF DES protected key,
.IP \(bu
KMF 2key TDES protected key,
.IP \(bu
KMF TDES protected key,
.IP \(bu
KMF AES 128bit,
.IP \(bu
KMF AES 192bit,
.IP \(bu
KMF AES 256bit,
.IP \(bu
KMF AES 128bit protected key,
.IP \(bu
KMF AES 192bit protected key,
.IP \(bu
KMF AES 256bit protected key,
.IP \(bu
KMCTR DES,
.IP \(bu
KMCTR 2key TDES,
.IP \(bu
KMCTR TDES,
.IP \(bu
KMCTR DES protected key,
.IP \(bu
KMCTR 2key TDES protected key,
.IP \(bu
KMCTR TDES protected key,
.IP \(bu
KMCTR AES 128bit,
.IP \(bu
KMCTR AES 192bit,
.IP \(bu
KMCTR AES 256bit,
.IP \(bu
KMCTR AES 128bit protected key,
.IP \(bu
KMCTR AES 192bit protected key,
.IP \(bu
KMCTR AES 256bit protected key,
.IP \(bu
KMO DES,
.IP \(bu
KMO 2key TDES,
.IP \(bu
KMO TDES,
.IP \(bu
KMO DES protected key,
.IP \(bu
KMO 2key TDES protected key,
.IP \(bu
KMO TDES protected key,
.IP \(bu
KMO AES 128bit,
.IP \(bu
KMO AES 192bit,
.IP \(bu
KMO AES 256bit,
.IP \(bu
KMO AES 128bit protected key,
.IP \(bu
KMO AES 192bit protected key,
.IP \(bu
KMO AES 256bit protected key,
.IP \(bu
KIMD SHA1,
.IP \(bu
KIMD SHA256,
.IP \(bu
KIMD SHA512,
.IP \(bu
KIMD SHA3-224,
.IP \(bu
KIMD SHA3-256,
.IP \(bu
KIMD SHA3-384,
.IP \(bu
KIMD SHA3-512,
.IP \(bu
KIMD SHAKE 128,
.IP \(bu
KIMD SHAKE 256,
.IP \(bu
KIMD GHASH,
.IP \(bu
KLMD SHA1,
.IP \(bu
KLMD SHA256,
.IP \(bu
KLMD SHA512,
.IP \(bu
KLMD SHA3-224,
.IP \(bu
KLMD SHA3-256,
.IP \(bu
KLMD SHA3-384,
.IP \(bu
KLMD SHA3-512,
.IP \(bu
KLMD SHAKE 128,
.IP \(bu
KLMD SHAKE 256,
.IP \(bu
KMAC DES,
.IP \(bu
KMAC 2key TDES,
.IP \(bu
KMAC TDES,
.IP \(bu
KMAC DES protected key,
.IP \(bu
KMAC 2key TDES protected key,
.IP \(bu
KMAC TDES protected key,
.IP \(bu
KMAC AES 128bit,
.IP \(bu
KMAC AES 192bit,
.IP \(bu
KMAC AES 256bit,
.IP \(bu
KMAC AES 128bit protected key,
.IP \(bu
KMAC AES 192bit protected key,
.IP \(bu
KMAC AES 256bit protected key,
.IP \(bu
PCC Last Block CMAC DES,
.IP \(bu
PCC Last Block CMAC 2key TDES,
.IP \(bu
PCC Last Block CMAC TDES,
.IP \(bu
PCC Last Block CMAC DES protected key,
.IP \(bu
PCC Last Block CMAC 2key TDES protected key,
.IP \(bu
PCC Last Block CMAC TDES protected key,
.IP \(bu
PCC Last Block CMAC AES 128bit,
.IP \(bu
PCC Last Block CMAC AES 192bit,
.IP \(bu
PCC Last Block CMAC AES 256bit,
.IP \(bu
PCC Last Block CMAC AES 128bit protected key,
.IP \(bu
PCC Last Block CMAC AES 192bit protected key,
.IP \(bu
PCC Last Block CMAC AES 256bit protected key,
.IP \(bu
PCC XTS Parameter AES 128bit,
.IP \(bu
PCC XTS Parameter AES 256bit,
.IP \(bu
PCC XTS Parameter AES 128bit protected key,
.IP \(bu
PCC XTS Parameter AES 256bit protected key,
.IP \(bu
PCC Scalar Mult P256,
.IP \(bu
PCC Scalar Mult P384,
.IP \(bu
PCC Scalar Mult P521,
.IP \(bu
PCC Scalar Mult Ed25519,
.IP \(bu
PCC Scalar Mult Ed448,
.IP \(bu
PCC Scalar Mult X25519,
.IP \(bu
PCC Scalar Mult X448,
.IP \(bu
PRNO SHA512 DRNG,
.IP \(bu
PRNO TRNG Query Ratio,
.IP \(bu
PRNO TRNG,
.IP \(bu
KDSA ECDSA Verify P256,
.IP \(bu
KDSA ECDSA Verify P384,
.IP \(bu
KDSA ECDSA Verify P521,
.IP \(bu
KDSA ECDSA Sign P256,
.IP \(bu
KDSA ECDSA Sign P384,
.IP \(bu
KDSA ECDSA Sign P521,
.IP \(bu
KDSA ECDSA Sign P256 protected key,
.IP \(bu
KDSA ECDSA Sign P384 protected key,
.IP \(bu
KDSA ECDSA Sign P521 protected key,
.IP \(bu
KDSA EdDSA Verify Ed25519,
.IP \(bu
KDSA EdDSA Verify Ed448,
.IP \(bu
KDSA EdDSA Sign Ed25519,
.IP \(bu
KDSA EdDSA Sign Ed448,
.IP \(bu
KDSA EdDSA Sign Ed25519 protected key,
.IP \(bu
KDSA EdDSA Sign Ed448 protected key,
.IP \(bu
PCKMO DES,
.IP \(bu
PCKMO 2key TDES,
.IP \(bu
PCMKO TDES,
.IP \(bu
PCKMO AES 128bit,
.IP \(bu
PCKMO AES 192bit,
.IP \(bu
PCMKO AES 256bit,
.IP \(bu
PCKMO ECC P256,
.IP \(bu
PCKMO ECC P384,
.IP \(bu
PCKMO ECC P521,
.IP \(bu
PCKMO ECC Ed25519,
.IP \(bu
PCKMO ECC Ed448,
.IP \(bu
Reserved 1, and
.IP \(bu
Reserved 2.
.RE
Note that the counters starting with PCKMO and Reserved are only
available in the pai_kernel set. Also note that the counters are
designed to count successful operations. In the case of KMA this
means only complete GCM operations including final hashing are
counted.
Note: CPU-MF based CPACF performance counters are available on LPARs
only. PAI counters are available on all hypervisors. For security
reasons only members of the group \fIcpacfstats\fR are allowed to run
the cpacfstats client application.
Example usage scenario:
.P
@@ -101,12 +438,34 @@ argument can be one of: \fBdes\fR, \fBaes\fR, \fBsha\fR, \fBprng\fR,
\fBecc\fR, or \fBall\fR. If the counter argument is omitted, all
performance counters are reset to 0.
.TP
\fB\-p\fR or \fB\-\-print\fR [counter]
\fB\-p\fR or \fB\-\-print\fR [\fB\-n\fR or \fB\-\-nonzero\fR] [counter]
Display the value of one or all CPACF performance counters. The
optional counter argument can be one of: \fBdes\fR, \fBaes\fR,
\fBsha\fR, \fBprng\fR, \fBecc\fR, or \fBall\fR. If the counter
argument is omitted or if there is no argument, all performance
counters are displayed.
\fBsha\fR, \fBprng\fR, \fBecc\fR, \fBpai_user\fR, \fBpai_kernel\fR, or
\fBall\fR. If the counter argument is omitted or if there is no
argument, all performance counters are displayed. If the optional
\fB\-n\fR or \fB\-\-nonzero\fR argument is given, then only PAI
counters that have a non-zero value are printed.
.TP
\fB\-j\fR or \fB\-\-json\fR
Display all activated counters in JSON format. The JSON contains an
array of counter objects. Each object contains the property
.B counter
specifying either a CPU-MF counter of one of the detailed PAI counter.
Additional properties include
.B error
an error number if the counter could not be read,
.B value
the counter value if the counter could be read,
.B space
for PAI counters to specify
.B user
or
.B kernel
space counter set, and
.B counterid
for PAI counters to specify the PAI counter number as specified in the
Principles of Operation.
.TP
The default command is --print all.
.

View File

@@ -3,7 +3,7 @@
*
* cpacfstats client implementation
*
* Copyright IBM Corp. 2015, 2020
* Copyright IBM Corp. 2015, 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -39,17 +39,187 @@ static const char *const usage =
"\t-d, --disable [counter] Disable one or all counters\n"
"\t-r, --reset [counter] Reset one or all counter values\n"
"\t-p, --print [counter] Print one or all counter values\n"
"\tcounter can be: 'aes' 'des' 'rng' 'sha' 'ecc' or 'all'\n";
"\t-n, --nonzero Print all PAI counters\n"
"\t-j, --json Print all counter values in JSON format\n"
"\tcounter can be: 'aes' 'des' 'rng' 'sha' 'ecc'\n"
"\t 'pai_user' 'pai_kernel' or 'all'\n";
static const char *const counter_str[] = {
[DES_FUNCTIONS] = "des",
[AES_FUNCTIONS] = "aes",
[SHA_FUNCTIONS] = "sha",
[PRNG_FUNCTIONS] = "rng",
[ECC_FUNCTIONS] = "ecc",
[ALL_COUNTER] = "all"
[ECC_FUNCTIONS] = "ecc",
[ALL_COUNTER] = "all",
[PAI_USER] = "pai_user",
[PAI_KERNEL] = "pai_kernel"
};
/* Strings for the pai counter details. Note that this is 0-based
* while PoP is 1-based.
*/
static const char *const pai_str[] = {
[ 0] = "KM DES",
[ 1] = "KM 2key TDES",
[ 2] = "KM TDES",
[ 3] = "KM DES protected key",
[ 4] = "KM 2key TDES protected key",
[ 5] = "KM TDES protected key",
[ 6] = "KM AES 128bit",
[ 7] = "KM AES 192bit",
[ 8] = "KM AES 256bit",
[ 9] = "KM AES 128bit protected key",
[ 10] = "KM AES 192bit protected key",
[ 11] = "KM AES 256bit protected key",
[ 12] = "KM AES-XTS 128bit",
[ 13] = "KM AES-XTS 256bit",
[ 14] = "KM AES-XTS 128bit protected key",
[ 15] = "KM AES-XTS 256bit protected key",
[ 16] = "KMC DES",
[ 17] = "KMC 2key TDES",
[ 18] = "KMC TDES",
[ 19] = "KMC DES protected key",
[ 20] = "KMC 2key TDES protected key",
[ 21] = "KMC TDES protected key",
[ 22] = "KMC AES 128bit",
[ 23] = "KMC AES 192bit",
[ 24] = "KMC AES 256bit",
[ 25] = "KMC AES 128bit protected key",
[ 26] = "KMC AES 192bit protected key",
[ 27] = "KMC AES 256bit protected key",
[ 28] = "KMC PRNG",
[ 29] = "KMA AES 128bit",
[ 30] = "KMA AES 192bit",
[ 31] = "KMA AES 256bit",
[ 32] = "KMA AES 128bit protected key",
[ 33] = "KMA AES 192bit protected key",
[ 34] = "KMA AES 256bit protected key",
[ 35] = "KMF DES",
[ 36] = "KMF 2key TDES",
[ 37] = "KMF TDES",
[ 38] = "KMF DES protected key",
[ 39] = "KMF 2key TDES protected key",
[ 40] = "KMF TDES protected key",
[ 41] = "KMF AES 128bit",
[ 42] = "KMF AES 192bit",
[ 43] = "KMF AES 256bit",
[ 44] = "KMF AES 128bit protected key",
[ 45] = "KMF AES 192bit protected key",
[ 46] = "KMF AES 256bit protected key",
[ 47] = "KMCTR DES",
[ 48] = "KMCTR 2key TDES",
[ 49] = "KMCTR TDES",
[ 50] = "KMCTR DES protected key",
[ 51] = "KMCTR 2key TDES protected key",
[ 52] = "KMCTR TDES protected key",
[ 53] = "KMCTR AES 128bit",
[ 54] = "KMCTR AES 192bit",
[ 55] = "KMCTR AES 256bit",
[ 56] = "KMCTR AES 128bit protected key",
[ 57] = "KMCTR AES 192bit protected key",
[ 58] = "KMCTR AES 256bit protected key",
[ 59] = "KMO DES",
[ 60] = "KMO 2key TDES",
[ 61] = "KMO TDES",
[ 62] = "KMO DES protected key",
[ 63] = "KMO 2key TDES protected key",
[ 64] = "KMO TDES protected key",
[ 65] = "KMO AES 128bit",
[ 66] = "KMO AES 192bit",
[ 67] = "KMO AES 256bit",
[ 68] = "KMO AES 128bit protected key",
[ 69] = "KMO AES 192bit protected key",
[ 70] = "KMO AES 256bit protected key",
[ 71] = "KIMD SHA1",
[ 72] = "KIMD SHA256",
[ 73] = "KIMD SHA512",
[ 74] = "KIMD SHA3-224",
[ 75] = "KIMD SHA3-256",
[ 76] = "KIMD SHA3-384",
[ 77] = "KIMD SHA3-512",
[ 78] = "KIMD SHAKE 128",
[ 79] = "KIMD SHAKE 256",
[ 80] = "KIMD GHASH",
[ 81] = "KLMD SHA1",
[ 82] = "KLMD SHA256",
[ 83] = "KLMD SHA512",
[ 84] = "KLMD SHA3-224",
[ 85] = "KLMD SHA3-256",
[ 86] = "KLMD SHA3-384",
[ 87] = "KLMD SHA3-512",
[ 88] = "KLMD SHAKE 128",
[ 89] = "KLMD SHAKE 256",
[ 90] = "KMAC DES",
[ 91] = "KMAC 2key TDES",
[ 92] = "KMAC TDES",
[ 93] = "KMAC DES protected key",
[ 94] = "KMAC 2key TDES protected key",
[ 95] = "KMAC TDES protected key",
[ 96] = "KMAC AES 128bit",
[ 97] = "KMAC AES 192bit",
[ 98] = "KMAC AES 256bit",
[ 99] = "KMAC AES 128bit protected key",
[100] = "KMAC AES 192bit protected key",
[101] = "KMAC AES 256bit protected key",
[102] = "PCC Last Block CMAC DES",
[103] = "PCC Last Block CMAC 2key TDES",
[104] = "PCC Last Block CMAC TDES",
[105] = "PCC Last Block CMAC DES protected key",
[106] = "PCC Last Block CMAC 2key TDES protected key",
[107] = "PCC Last Block CMAC TDES protected key",
[108] = "PCC Last Block CMAC AES 128bit",
[109] = "PCC Last Block CMAC AES 192bit",
[110] = "PCC Last Block CMAC AES 256bit",
[111] = "PCC Last Block CMAC AES 128bit protected key",
[112] = "PCC Last Block CMAC AES 192bit protected key",
[113] = "PCC Last Block CMAC AES 256bit protected key",
[114] = "PCC XTS Parameter AES 128bit",
[115] = "PCC XTS Parameter AES 256bit",
[116] = "PCC XTS Parameter AES 128bit protected key",
[117] = "PCC XTS Parameter AES 256bit protected key",
[118] = "PCC Scalar Mult P256",
[119] = "PCC Scalar Mult P384",
[120] = "PCC Scalar Mult P521",
[121] = "PCC Scalar Mult Ed25519",
[122] = "PCC Scalar Mult Ed448",
[123] = "PCC Scalar Mult X25519",
[124] = "PCC Scalar Mult X448",
[125] = "PRNO SHA512 DRNG",
[126] = "PRNO TRNG Query Ratio",
[127] = "PRNO TRNG",
[128] = "KDSA ECDSA Verify P256",
[129] = "KDSA ECDSA Verify P384",
[130] = "KDSA ECDSA Verify P521",
[131] = "KDSA ECDSA Sign P256",
[132] = "KDSA ECDSA Sign P384",
[133] = "KDSA ECDSA Sign P521",
[134] = "KDSA ECDSA Sign P256 protected key",
[135] = "KDSA ECDSA Sign P384 protected key",
[136] = "KDSA ECDSA Sign P521 protected key",
[137] = "KDSA EdDSA Verify Ed25519",
[138] = "KDSA EdDSA Verify Ed448",
[139] = "KDSA EdDSA Sign Ed25519",
[140] = "KDSA EdDSA Sign Ed448",
[141] = "KDSA EdDSA Sign Ed25519 protected key",
[142] = "KDSA EdDSA Sign Ed448 protected key",
[143] = "PCKMO DES",
[144] = "PCKMO 2key TDES",
[145] = "PCMKO TDES",
[146] = "PCKMO AES 128bit",
[147] = "PCKMO AES 192bit",
[148] = "PCMKO AES 256bit",
[149] = "PCKMO ECC P256",
[150] = "PCKMO ECC P384",
[151] = "PCKMO ECC P521",
[152] = "PCKMO ECC Ed25519",
[153] = "PCKMO ECC Ed448",
[154] = "Reserved 1",
[155] = "Reserved 2"
};
static int paiprintnonzero;
static int send_query(int s, enum cmd_e cmd, enum ctr_e ctr)
{
@@ -62,7 +232,7 @@ static int send_query(int s, enum cmd_e cmd, enum ctr_e ctr)
m.query.m_ctr = ctr;
m.query.m_cmd = cmd;
return send_msg(s, &m);
return send_msg(s, &m, 0);
}
@@ -71,7 +241,7 @@ static int recv_answer(int s, int *ctr, int *state, uint64_t *value)
struct msg m;
int rc;
rc = recv_msg(s, &m);
rc = recv_msg(s, &m, 0);
if (rc == 0) {
if (m.head.m_ver != VERSION) {
eprint("Received msg with wrong version %d != %d\n",
@@ -92,9 +262,139 @@ static int recv_answer(int s, int *ctr, int *state, uint64_t *value)
}
static void print_answer(int ctr, int state, uint64_t value)
static void printjsonsep(void)
{
if (state < 0)
static const char *jsonsep = "";
fputs(jsonsep, stdout);
jsonsep = ",";
}
static void json_print_virtual_counter_answer(int s, int ctr,
int state, uint64_t value)
{
int paictr = 0, paistate = 0, ec;
uint64_t i, paivalue = 0, maxnum;
const char *space;
switch (ctr) {
case HOTPLUG_DETECTED:
printjsonsep();
printf("{\"counter\":\"hotplug detected\",");
if (state < 0)
printf("\"error\":%d}", state);
else
printf("\"value\":%d}", !!value);
return;
case PAI_USER:
maxnum = NUM_PAI_USER;
space = "user";
break;
case PAI_KERNEL:
maxnum = NUM_PAI_KERNEL;
space = "kernel";
break;
default:
return;
}
/* Here, we have validated the PAI counter retrieved, but not
* yet printed. */
if (state != ENABLED)
return;
if (value > maxnum) {
eprint("Incompatible versions detected!\n");
eprint("Expected %"PRIu64" counter space for %s, but got %"PRIu64"\n",
maxnum, space, value);
exit(EXIT_FAILURE);
}
for (i = 0; i < value; ++i) {
ec = recv_answer(s, &paictr, &paistate, &paivalue);
if (ec < 0 || paistate < 0) {
eprint("Error on receiving answer message from daemon\n");
/* No more data for this virtual event after error. */
return;
}
if (paictr > NUM_PAI_KERNEL) {
eprint("Pai counter number too big: %d\n", paictr);
} else {
printjsonsep();
printf("{\"counter\":\"%s\",\"space\":\"%s\",\"counterid\":%d,",
pai_str[paictr], space, paictr + 1);
if (paistate < 0) {
printf("\"error\":%d}", paistate);
/* Protocol does not send furter counters. */
return;
}
printf("\"value\":%"PRIu64"}", paivalue);
}
}
}
static void print_virtual_counter_answer(int s,
int ctr, int state, uint64_t value)
{
static const char *const states[] = {
[DISABLED] = "disabled",
[ENABLED] = "enabled",
[UNSUPPORTED] = "unsupported"
};
int paictr = 0, paistate = 0, ec;
uint64_t i, paivalue = 0, maxnum;
const char *ctrstr;
switch (ctr) {
case HOTPLUG_DETECTED:
if (state >= 0 && value > 0)
printf(" hotplug detected\n");
return;
case PAI_USER:
maxnum = NUM_PAI_USER;
ctrstr = "pai_user";
break;
case PAI_KERNEL:
maxnum = NUM_PAI_KERNEL;
ctrstr = "pai_kernel";
break;
default:
return;
}
/* Here, we have validated the PAI counter retrieved, but not
* yet printed. */
if (state < 0 || state > UNSUPPORTED) {
printf(" %11s: error state %d\n", ctrstr, state);
/* No details follow if counter in error state. */
return;
}
printf(" %-11s: %s\n", ctrstr, states[state]);
if (state != ENABLED)
return;
if (value > maxnum) {
eprint("Incompatible versions detected!\n");
eprint("Expected %"PRIu64" counters for %s, but got %"PRIu64"\n",
maxnum, ctrstr, value);
exit(EXIT_FAILURE);
}
for (i = 0; i < value; ++i) {
ec = recv_answer(s, &paictr, &paistate, &paivalue);
if (ec < 0 || paistate < 0) {
eprint("Error on receiving answer message from daemon\n");
/* No more data for this virtual event after error. */
return;
}
if (paictr > NUM_PAI_KERNEL)
eprint("Pai counter number too big: %d\n", paictr);
else if (!paiprintnonzero || paivalue > 0)
printf(" %-45s: %"PRIu64"\n", pai_str[paictr], paivalue);
}
}
static void print_answer(int s, int ctr, int state, uint64_t value)
{
if (ctr > ALL_COUNTER)
print_virtual_counter_answer(s, ctr, state, value);
else if (state < 0)
printf(" %s counter: error state %d\n",
counter_str[ctr], state);
else if (state == DISABLED)
@@ -106,6 +406,22 @@ static void print_answer(int ctr, int state, uint64_t value)
}
static void json_print_answer(int s, int ctr, int state, uint64_t value)
{
if (ctr > ALL_COUNTER) {
json_print_virtual_counter_answer(s, ctr, state, value);
} else if (state < 0) {
printjsonsep();
printf("{\"counter\":\"%s\",", counter_str[ctr]);
printf("\"error\":%d}\n", state);
} else if (state == ENABLED) {
printjsonsep();
printf("{\"counter\":\"%s\",", counter_str[ctr]);
printf("\"value\":%"PRIu64"}", value);
}
}
int eprint(const char *format, ...)
{
char buf[1024];
@@ -128,7 +444,7 @@ int main(int argc, char *argv[])
{
enum ctr_e ctr = ALL_COUNTER;
enum cmd_e cmd = PRINT;
int i, j, s, state;
int i, j, s, state, num, json = 0;
uint64_t value;
if (argc > 1) {
@@ -140,98 +456,108 @@ int main(int argc, char *argv[])
{ "disable", 0, NULL, 'd' },
{ "reset", 0, NULL, 'r' },
{ "print", 0, NULL, 'p' },
{ "nonzero", 0, NULL, 'n' },
{ "json", 0, NULL, 'j' },
{ NULL, 0, NULL, 0 } };
while (1) {
opt = getopt_long(argc, argv,
"hvedrp", long_opts, &idx);
"hvedrpnj", long_opts, &idx);
if (opt == -1)
break; /* no more arguments */
switch (opt) {
case 'h':
printf(usage, name);
exit(0);
break;
return 0;
case 'v':
printf("%s: Linux on System z CPACF Crypto Activity Counters Client\n"
"Version %s\n%s\n",
name, RELEASE_STRING, COPYRIGHT);
exit(0);
break;
return 0;
case 'e':
cmd = ENABLE;
json = 0;
break;
case 'd':
cmd = DISABLE;
json = 0;
break;
case 'r':
cmd = RESET;
break;
case 'p':
cmd = PRINT;
json = 0;
break;
case 'n':
paiprintnonzero = 1;
break;
case 'j':
cmd = PRINT;
json = 1;
break;
default:
eprint("Invalid argument, try -h or --help for more information\n");
exit(1);
break;
return EXIT_FAILURE;
}
}
/* there may be an optional counter argument */
if (optind > 0 && optind < argc) {
for (i = 0; i <= ALL_COUNTER; i++)
for (i = 0; i < NUM_COUNTER; i++)
if (strcmp(argv[optind], counter_str[i]) == 0)
break;
if (i > ALL_COUNTER) {
if (i >= NUM_COUNTER) {
eprint("Unknown counter '%s'\n", argv[optind]);
exit(1);
return EXIT_FAILURE;
}
ctr = (enum ctr_e) i;
}
}
if (json)
ctr = ALL_COUNTER;
/* try to open and connect socket to the cpacfstatsd daemon */
s = open_socket(CLIENT);
if (s < 0) {
eprint("Can't connect to daemon\n");
exit(1);
return EXIT_FAILURE;
}
/* send query */
if (send_query(s, cmd, ctr) != 0) {
eprint("Error on sending query message to daemon\n");
close(s);
exit(1);
return EXIT_FAILURE;
}
if (ctr == ALL_COUNTER) {
for (i = 0; i < ALL_COUNTER; i++) {
/* receive answer */
if (recv_answer(s, &j, &state, &value) != 0) {
eprint("Error on receiving answer message from daemon\n");
exit(1);
}
if (state < 0) {
eprint("Received bad status code %d from daemon\n",
state);
close(s);
exit(1);
}
print_answer(j, state, value);
}
/* The -1 is for ALL_COUNTER which is not sent, +1 for
* hotplug state. */
num = NUM_COUNTER - 1 + 1;
} else {
/* +1 for hotplug state */
num = 1 + 1;
}
if (json)
putchar('[');
for (i = 0; i < num; i++) {
/* receive answer */
if (recv_answer(s, &j, &state, &value) != 0) {
eprint("Error on receiving answer message from daemon\n");
close(s);
exit(1);
return EXIT_FAILURE;
}
if (state < 0) {
eprint("Received bad status code %d from daemon\n",
state);
state);
close(s);
exit(1);
return EXIT_FAILURE;
}
print_answer(j, state, value);
if (json)
json_print_answer(s, j, state, value);
else
print_answer(s, j, state, value);
}
if (json)
putchar(']');
/* close connection */
close(s);

View File

@@ -3,7 +3,7 @@
*
* common function prototypes and definitions
*
* Copyright IBM Corp. 2015, 2020
* Copyright IBM Corp. 2015, 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -14,13 +14,27 @@
#include "lib/zt_common.h"
#define COPYRIGHT "Copyright IBM Corp. 2015, 2020"
#define COPYRIGHT "Copyright IBM Corp. 2015, 2022"
#define DEFAULT_SEND_TIMEOUT (30 * 1000)
#define DEFAULT_RECV_TIMEOUT (30 * 1000)
/*
* Number of PAI counters for user space. This excludes PCKMO since
* this instruction is privileged.
*/
#define NUM_PAI_USER 143
/* Number of PAI counters for kernel space. Contains all counters. */
#define NUM_PAI_KERNEL 156
int eprint(const char *format, ...);
/*
* Counter names
* ALL_COUNTER must always be the last member of the enum
* ALL_COUNTER specifies the number of physical counters. Virtual
* counters might be added afterwards. NUM_COUNTER is the last
* managed counter (i.e., a counter that can be activated, reset,
* deactivated).
*/
enum ctr_e {
DES_FUNCTIONS = 0,
@@ -28,7 +42,11 @@ enum ctr_e {
SHA_FUNCTIONS,
PRNG_FUNCTIONS,
ECC_FUNCTIONS,
ALL_COUNTER
ALL_COUNTER,
PAI_USER,
PAI_KERNEL,
NUM_COUNTER,
HOTPLUG_DETECTED = 0xffff
};
enum type_e {
@@ -50,7 +68,7 @@ enum state_e {
};
/*
* query send from clent to daemon
* query send from client to daemon
* Consist of:
* enum counter
* enum command
@@ -63,7 +81,7 @@ struct msg_query {
/*
* answer send from daemon to client
* Consist of:
* enum counter
* enum counter or PAI counter number if following PAI_USER or PAI_KERNEL
* status code: < 0 error, 0 disabled, > 0 enabled
* counter value
*/
@@ -99,17 +117,20 @@ struct msg {
} __packed;
int open_socket(int mode);
int send_msg(int sfd, struct msg *m);
int recv_msg(int sfd, struct msg *m);
int send_msg(int sfd, struct msg *m, int timeout);
int recv_msg(int sfd, struct msg *m, int timeout);
/* perf_crypto.c */
int perf_init(void);
void perf_stop(void);
void perf_close(void);
int perf_enable_ctr(enum ctr_e ctr);
int perf_disable_ctr(enum ctr_e ctr);
int perf_reset_ctr(enum ctr_e ctr);
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value);
int perf_read_ctr(enum ctr_e ctr, uint64_t *value);
int perf_ecc_supported(void);
int perf_ctr_state(enum ctr_e ctr);
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value);
#endif

View File

@@ -3,7 +3,7 @@
*
* cpacfstatsd daemon implementation
*
* Copyright IBM Corp. 2015, 2017
* Copyright IBM Corp. 2015, 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -28,6 +28,7 @@
#include "lib/zt_common.h"
#include "cpacfstats.h"
static volatile int stopsig;
static const char *const name = "cpacfstatsd";
@@ -43,15 +44,12 @@ static const char *const usage =
static int daemonized;
static int ctr_state[ALL_COUNTER];
static int recv_query(int s, enum ctr_e *ctr, enum cmd_e *cmd)
{
struct msg m;
int rc;
rc = recv_msg(s, &m);
rc = recv_msg(s, &m, DEFAULT_RECV_TIMEOUT);
if (rc == 0) {
if (m.head.m_ver != VERSION) {
eprint("Received msg with wrong version %d != %d\n",
@@ -83,38 +81,82 @@ static int send_answer(int s, int ctr, int state, uint64_t value)
m.answer.m_state = state;
m.answer.m_value = value;
return send_msg(s, &m);
return send_msg(s, &m, DEFAULT_SEND_TIMEOUT);
}
/*
* Print according to protocol for PAI:
* - first the state and the number of PAI counters that follow
* - if state is ENABLED:
* - for each PAI counter the value with state ENABLED
* Note that the PAI counters are 0-based, not 1 based as in PoP!
* Sending ends with the first error.
*/
static int do_send_pai(int s, int user)
{
int ctr, state, i, maxctr, rc = 0;
uint64_t value;
if (user) {
ctr = PAI_USER;
maxctr = NUM_PAI_USER;
} else {
ctr = PAI_KERNEL;
maxctr = NUM_PAI_KERNEL;
}
state = perf_ctr_state(ctr);
if (state != ENABLED)
return rc;
for (i = 0; i < maxctr; ++i) {
rc = perf_read_pai_ctr(i, user, &value);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
send_answer(s, i, state, value);
}
return rc;
}
static int do_enable(int s, enum ctr_e ctr)
{
uint64_t value;
uint64_t value = 0;
int i, rc = 0;
int state;
for (i = 0; i < ALL_COUNTER; i++) {
for (i = 0; i < NUM_COUNTER; i++) {
if (i == ALL_COUNTER)
continue;
if (i == (int) ctr || ctr == ALL_COUNTER) {
if (ctr_state[i] == DISABLED) {
state = perf_ctr_state(i);
if (state == DISABLED) {
rc = perf_enable_ctr(i);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
ctr_state[i] = ENABLED;
state = ENABLED;
}
if (ctr_state[i] == UNSUPPORTED) {
send_answer(s, i, UNSUPPORTED, 0);
} else {
if (state != UNSUPPORTED) {
rc = perf_read_ctr(i, &value);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
send_answer(s, i, ENABLED, value);
}
send_answer(s, i, state, value);
if (i == PAI_USER)
rc = do_send_pai(s, 1);
if (i == PAI_KERNEL)
rc = do_send_pai(s, 0);
}
}
if (rc == 0) {
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
send_answer(s, HOTPLUG_DETECTED, rc, value);
}
return rc;
}
@@ -122,67 +164,90 @@ static int do_enable(int s, enum ctr_e ctr)
static int do_disable(int s, enum ctr_e ctr)
{
int i, rc = 0;
uint64_t value;
for (i = 0; i < ALL_COUNTER; i++) {
for (i = 0; i < NUM_COUNTER; i++) {
if (i == ALL_COUNTER)
continue;
if (i == (int) ctr || ctr == ALL_COUNTER) {
if (ctr_state[i] == ENABLED) {
if (perf_ctr_state(i) == ENABLED) {
rc = perf_disable_ctr(i);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
ctr_state[i] = 0;
}
send_answer(s, i, ctr_state[i], 0);
send_answer(s, i, perf_ctr_state(i), 0);
}
}
if (rc == 0) {
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
send_answer(s, HOTPLUG_DETECTED, rc, value);
}
return rc;
}
static int do_reset(int s, enum ctr_e ctr)
{
int i, rc = 0;
int i, rc = 0, state;
uint64_t value;
for (i = 0; i < ALL_COUNTER; i++) {
for (i = 0; i < NUM_COUNTER; i++) {
if (i == ALL_COUNTER)
continue;
if (i == (int) ctr || ctr == ALL_COUNTER) {
if (ctr_state[i] == ENABLED) {
rc = perf_reset_ctr(i);
state = perf_ctr_state(i);
if (state == ENABLED) {
rc = perf_reset_ctr(i, &value);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
send_answer(s, i, ENABLED, 0);
} else {
send_answer(s, i, ctr_state[i], 0);
}
send_answer(s, i, state, value);
if (i == PAI_USER)
rc = do_send_pai(s, 1);
if (i == PAI_KERNEL)
rc = do_send_pai(s, 0);
}
}
if (rc == 0) {
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
send_answer(s, HOTPLUG_DETECTED, rc, value);
}
return rc;
}
static int do_print(int s, enum ctr_e ctr)
{
int i, rc = 0;
uint64_t value;
int i, rc = 0, state;
uint64_t value = 0;
for (i = 0; i < ALL_COUNTER; i++) {
for (i = 0; i < NUM_COUNTER; i++) {
if (i == ALL_COUNTER)
continue;
if (i == (int) ctr || ctr == ALL_COUNTER) {
if (ctr_state[i] == ENABLED) {
state = perf_ctr_state(i);
if (state == ENABLED) {
rc = perf_read_ctr(i, &value);
if (rc != 0) {
send_answer(s, i, rc, 0);
break;
}
send_answer(s, i, ENABLED, value);
} else {
send_answer(s, i, ctr_state[i], 0);
}
send_answer(s, i, state, value);
if (i == PAI_USER)
rc = do_send_pai(s, 1);
if (i == PAI_KERNEL)
rc = do_send_pai(s, 0);
}
}
if (rc == 0) {
rc = perf_read_ctr(HOTPLUG_DETECTED, &value);
send_answer(s, HOTPLUG_DETECTED, rc, value);
}
return rc;
}
@@ -324,18 +389,8 @@ static void remove_pidfile(void)
void signalhandler(int sig)
{
if (sig == SIGTERM)
eprint("Caught signal SIGTERM, terminating...\n");
else if (sig == SIGINT)
eprint("Caught signal SIGINT, terminating...\n");
else
eprint("Caught signal %d, terminating...\n", sig);
remove_sock();
perf_close();
remove_pidfile();
exit(0);
perf_stop();
stopsig = sig;
}
@@ -381,7 +436,7 @@ int main(int argc, char *argv[])
switch (opt) {
case 'h':
printf(usage, name);
exit(0);
return 0;
case 'f':
foreground = 1;
break;
@@ -389,40 +444,37 @@ int main(int argc, char *argv[])
printf("%s: Linux on System z CPACF Crypto Activity Counters Daemon\n"
"Version %s\n%s\n",
name, RELEASE_STRING, COPYRIGHT);
exit(0);
return 0;
default:
printf("%s: Invalid argument, try -h or --help for more information\n",
name);
exit(1);
return EXIT_FAILURE;
}
}
}
if (check_pidfile() != 0) {
eprint("Stalled pid file or daemon allready running, terminating\n");
exit(1);
return EXIT_FAILURE;
}
if (!foreground) {
if (become_daemon() != 0) {
eprint("Couldn't daemonize\n");
exit(1);
return EXIT_FAILURE;
}
}
if (perf_init() != 0) {
eprint("Couldn't initialize perf lib\n");
exit(1);
return EXIT_FAILURE;
}
atexit(perf_close);
if (!perf_ecc_supported())
ctr_state[ECC_FUNCTIONS] = UNSUPPORTED;
sfd = open_socket(SERVER);
if (sfd < 0) {
eprint("Couldn't initialize server socket\n");
exit(1);
return EXIT_FAILURE;
}
atexit(remove_sock);
@@ -432,17 +484,19 @@ int main(int argc, char *argv[])
if (sigaction(SIGINT, &act, 0) != 0) {
eprint("Couldn't establish signal handler for SIGINT, errno=%d [%s]\n",
errno, strerror(errno));
exit(1);
return EXIT_FAILURE;
}
if (sigaction(SIGTERM, &act, 0) != 0) {
eprint("Couldn't establish signal handler for SIGTERM, errno=%d [%s]\n",
errno, strerror(errno));
exit(1);
return EXIT_FAILURE;
}
/* Ignore SIGPIPE such that we see EPIPE as return from write. */
signal(SIGPIPE, SIG_IGN);
eprint("Running\n");
while (1) {
while (!stopsig) {
enum ctr_e ctr;
enum cmd_e cmd;
int s;
@@ -453,7 +507,7 @@ int main(int argc, char *argv[])
continue;
eprint("Accept() failure, errno=%d [%s]\n",
errno, strerror(errno));
exit(1);
return EXIT_FAILURE;
}
rc = recv_query(s, &ctr, &cmd);
@@ -480,5 +534,13 @@ cleanup:
close(s);
}
if (stopsig == SIGTERM)
eprint("Caught signal SIGTERM, terminating...\n");
else if (stopsig == SIGINT)
eprint("Caught signal SIGINT, terminating...\n");
else
eprint("Caught signal %d, terminating...\n", stopsig);
remove_pidfile();
return 0;
}

View File

@@ -3,7 +3,7 @@
*
* low level perf functions
*
* Copyright IBM Corp. 2015, 2020
* Copyright IBM Corp. 2015, 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -16,14 +16,21 @@
#include <inttypes.h>
#include <limits.h>
#include <linux/perf_event.h>
#include <pthread.h>
#include <poll.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <unistd.h>
#include <libudev.h>
#include "cpacfstats.h"
#include "../include/lib/zt_common.h"
/* correlation between counter and perf counter string */
static const struct {
@@ -38,25 +45,83 @@ static const struct {
{"cpum_cf", "ECC_FUNCTION_COUNT", ECC_FUNCTIONS}
};
/*
* We need one filedescriptor per CPU per counter.
* So perf_init builds this:
*
* ctr_fds - is an array of pointers to file descriptor arrays.
* Each file descriptor array has space for number of logical CPUs + 1
* filedescriptors (int values). The last element of each file descriptor
* array is always 0, assuming there will never appear a filedescriptor
* with value 0:
*
* ctr_fds:
* ctr_fds[0] -> [file descriptor 0] [fd1] ... [fd cpus-1][0]
* ctr_fds[1] -> [file descriptor 0] [fd1] ... [fd cpus-1][0]
* ...
* ctr_fds[ALL_COUNTER-1] -> [file descriptor 0] [fd1] ... [fd cpus-1][0]
*/
static int *ctr_fds[ALL_COUNTER];
static struct pmf_data {
int pmutype;
int eventid;
} pmf_counter_data[ALL_COUNTER];
static int ecc_supported;
struct percpucounter {
int ctr_fds[ALL_COUNTER];
int pai_user[NUM_PAI_USER];
int pai_kernel[NUM_PAI_KERNEL];
unsigned int cpunum;
struct percpucounter *next;
};
static struct percpucounter *root;
pthread_mutex_t rootmux = PTHREAD_MUTEX_INITIALIZER;
static volatile int hotplugdetected;
static unsigned int enabledcounter;
pthread_t hotplugthread;
#define foreachcpu(PCPU) if (pthread_mutex_lock(&rootmux)) return -1; \
for ((PCPU) = root; (PCPU) != NULL; (PCPU) = (PCPU)->next)
#define endforeachcpu() pthread_mutex_unlock(&rootmux)
static int ctr_state[NUM_COUNTER];
static volatile int stoprequested;
static int paipmutype, paipmueventstart;
static struct percpucounter *allocpercpucounter(unsigned int cpunum)
{
struct percpucounter *ppc;
ppc = malloc(sizeof(struct percpucounter));
if (ppc) {
int i;
for (i = 0; i < ALL_COUNTER; ++i)
ppc->ctr_fds[i] = -1;
for (i = 0; i < NUM_PAI_USER; ++i)
ppc->pai_user[i] = -1;
for (i = 0; i < NUM_PAI_KERNEL; ++i)
ppc->pai_kernel[i] = -1;
ppc->cpunum = cpunum;
ppc->next = NULL;
}
return ppc;
}
static void freepercpucounter(struct percpucounter *pcpu)
{
int i;
for (i = 0; i < ALL_COUNTER; ++i)
(void)close(pcpu->ctr_fds[i]);
for (i = 0; i < NUM_PAI_USER; ++i)
(void)close(pcpu->pai_user[i]);
for (i = 0; i < NUM_PAI_KERNEL; ++i)
(void)close(pcpu->pai_kernel[i]);
free(pcpu);
}
static struct percpucounter *findcpu(unsigned int cpunum, int unlinkflag)
{
struct percpucounter **prev = &root, *walk = root;
while (walk) {
if (walk->cpunum == cpunum) {
if (unlinkflag)
*prev = walk->next;
return walk;
}
prev = &(walk->next);
walk = walk->next;
}
return NULL;
}
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
@@ -85,12 +150,43 @@ static int perf_counter_supported(const char *pmu, const char *counter)
return !access(buf, R_OK);
}
static int perf_event_encode(struct perf_event_attr *attr,
static int cpumf_authorized(void)
{
unsigned vermin, vermax, auth;
int res = 0, found = 0;
size_t linesize = 0;
char *line = NULL;
FILE *f;
f = fopen("/proc/service_levels", "r");
if (f == NULL) {
eprint("Failed to open /proc/service_levels (%d:%s)\n",
errno, strerror(errno));
return 0;
}
while (getline(&line, &linesize, f) >= 0) {
if (sscanf(line,
"CPU-MF: Counter facility: version=%d.%d authorization=%x",
&vermin, &vermax, &auth) == 3) {
if (auth & 0x8)
res = 1;
else
eprint("CPU-MF counters not authorized.\n");
found = 1;
break;
}
}
if (!found)
eprint("CPU-MF counters not available.\n");
free(line);
fclose(f);
return res;
}
static int perf_event_encode(int *pmutype, int *eventid,
const char *pmu, const char *event)
{
FILE *f;
int eventid;
int pmutype;
char buf[PATH_MAX];
if (snprintf(buf, PATH_MAX, "/sys/bus/event_source/devices/%s/events/%s",
@@ -104,7 +200,7 @@ static int perf_event_encode(struct perf_event_attr *attr,
errno, strerror(errno));
return -1;
}
if (fscanf(f, "event=0x%x\n", &eventid) != 1) {
if (fscanf(f, "event=0x%x\n", eventid) != 1) {
fclose(f);
eprint("Event file %s has invalid format\n", buf);
return -1;
@@ -121,21 +217,257 @@ static int perf_event_encode(struct perf_event_attr *attr,
errno, strerror(errno));
return -1;
}
if (fscanf(f, "%d\n", &pmutype) != 1) {
if (fscanf(f, "%d\n", pmutype) != 1) {
fclose(f);
eprint("Type file %s has invalid format\n", buf);
return -1;
}
attr->type = pmutype;
attr->config = eventid;
return 0;
}
static int activatecpu(unsigned int cpu)
{
struct perf_event_attr pfm_event;
struct percpucounter *ppc;
int fd, i, rc = 0;
ppc = allocpercpucounter(cpu);
if (ppc == NULL) {
eprint("Failed to allocate per cpu counter data");
return -1;
}
if (pthread_mutex_lock(&rootmux)) {
freepercpucounter(ppc);
return -1;
}
/* activate CPU-MF */
for (i = 0; i < ALL_COUNTER; ++i) {
if (ctr_state[i] == UNSUPPORTED)
continue;
memset(&pfm_event, 0, sizeof(pfm_event));
pfm_event.size = sizeof(pfm_event);
pfm_event.type = pmf_counter_data[i].pmutype;
pfm_event.config = pmf_counter_data[i].eventid;
/* fetch file descriptor for this perf event
* the counter event should start disabled
*/
pfm_event.disabled = ctr_state[i] == DISABLED;
fd = perf_event_open(
&pfm_event,
-1, /* pid -1 means all processes */
cpu,
-1, /* group filedescriptor */
0); /* flags */
if (fd < 0) {
eprint("Perf_event_open() failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
ctr_state[i] = UNSUPPORTED;
} else {
ppc->ctr_fds[i] = fd;
}
}
/* activate pai_user and pai_kernel */
/* invariant:
(ctr_state[PAI_USER] == UNSUPPORTED) ==
(ctr_state[PAI_KERNEL] == UNSUPPORTED) */
if (ctr_state[PAI_USER] != UNSUPPORTED) {
for (i = 1; i <= NUM_PAI_USER; ++i) {
memset(&pfm_event, 0, sizeof(pfm_event));
pfm_event.size = sizeof(pfm_event);
pfm_event.type = paipmutype;
pfm_event.config = paipmueventstart + i;
pfm_event.exclude_kernel = 1;
pfm_event.exclude_user = 0;
pfm_event.disabled = ctr_state[PAI_USER] == DISABLED;
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
if (fd < 0) {
eprint("Perf_event_open() failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
ctr_state[PAI_USER] = UNSUPPORTED;
ctr_state[PAI_KERNEL] = UNSUPPORTED;
goto outevents;
} else {
ppc->pai_user[i - 1] = fd;
}
pfm_event.exclude_kernel = 0;
pfm_event.exclude_user = 1;
pfm_event.disabled = ctr_state[PAI_KERNEL] == DISABLED;
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
if (fd < 0) {
eprint("Perf_event_open() failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
ctr_state[PAI_USER] = UNSUPPORTED;
ctr_state[PAI_KERNEL] = UNSUPPORTED;
goto outevents;
} else {
ppc->pai_kernel[i - 1] = fd;
}
}
for (; i <= NUM_PAI_KERNEL; ++i) {
memset(&pfm_event, 0, sizeof(pfm_event));
pfm_event.size = sizeof(pfm_event);
pfm_event.type = paipmutype;
pfm_event.config = paipmueventstart + i;
pfm_event.exclude_kernel = 0;
pfm_event.exclude_user = 1;
pfm_event.disabled = ctr_state[PAI_KERNEL] == DISABLED;
fd = perf_event_open(&pfm_event, -1, cpu, -1, 0);
if (fd < 0) {
eprint("Perf_event_open() failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
ctr_state[PAI_USER] = UNSUPPORTED;
ctr_state[PAI_KERNEL] = UNSUPPORTED;
goto outevents;
} else {
ppc->pai_kernel[i - 1] = fd;
}
}
}
outevents:
ppc->next = root;
root = ppc;
if (enabledcounter)
hotplugdetected = 1;
pthread_mutex_unlock(&rootmux);
return rc;
}
static void deactivatecpu(unsigned int cpunum)
{
struct percpucounter *pcpu;
int i;
if (pthread_mutex_lock(&rootmux))
return;
pcpu = findcpu(cpunum, 1);
if (pcpu != NULL) {
for (i = 0; i < ALL_COUNTER; ++i)
(void)close(pcpu->ctr_fds[i]);
for (i = 0; i < NUM_PAI_USER; ++i)
(void)close(pcpu->pai_user[i]);
for (i = 0; i < NUM_PAI_KERNEL; ++i)
(void)close(pcpu->pai_kernel[i]);
free(pcpu);
if (enabledcounter)
hotplugdetected = 1;
}
pthread_mutex_unlock(&rootmux);
}
static int addallcpus(void)
{
unsigned int start, end;
int scanned, rc = 0;
FILE *fp;
/* comma separated list of intervals */
if ((fp = fopen("/sys/devices/system/cpu/online", "r")) == NULL) {
eprint("Failed to get online cpus (%d:%s)\n",
errno, strerror(errno));
return -1;
}
while (!feof(fp)) {
/* scan all intervals of online cpus */
scanned = fscanf(fp, "%u-%u", &start, &end);
/* take care of singleton intervals */
if (scanned == 1)
end = start;
for (; start <= end; ++start) {
if (activatecpu(start)) {
rc = -1;
goto out;
}
}
/* Skip comma separator */
(void)fgetc(fp);
}
out:
fclose(fp);
return rc;
}
static int perf_load_counter_data(void)
{
int i, res = 0;
for (i = 0; i < ALL_COUNTER; ++i) {
if (ctr_state[i] != UNSUPPORTED)
res |= perf_event_encode(&pmf_counter_data[i].pmutype,
&pmf_counter_data[i].eventid,
pmf_counter_name[i].pmu,
pmf_counter_name[i].pfm_name);
}
if (ctr_state[PAI_USER] != UNSUPPORTED)
res |= perf_event_encode(&paipmutype, &paipmueventstart,
"pai_crypto", "CRYPTO_ALL");
return res;
}
static void *hotplughandler(void *UNUSED(unused))
{
struct udev *hotplug;
struct udev_monitor *monitor;
struct pollfd item;
hotplug = udev_new();
if (!hotplug) {
eprint("Failed to create hotplug device\n");
return NULL;
}
monitor = udev_monitor_new_from_netlink(hotplug, "udev");
udev_monitor_filter_add_match_subsystem_devtype(monitor, "cpu", NULL);
udev_monitor_enable_receiving(monitor);
item.fd = udev_monitor_get_fd(monitor);
item.events = POLLIN;
item.revents = 0;
while (!stoprequested) {
struct udev_device *dev;
const char *path, *action;
unsigned int cpunum;
int rc, on, off;
errno = 0;
rc = poll(&item, 1, -1);
if (rc == -1) {
if (errno == EINTR)
continue;
break;
}
dev = udev_monitor_receive_device(monitor);
if (dev == NULL)
continue;
action = udev_device_get_action(dev);
if (action == NULL)
continue;
off = strcmp(action, "offline") == 0;
on = strcmp(action, "online") == 0;
if (!on && !off)
continue;
path = udev_device_get_devpath(dev);
if (sscanf(path, "/devices/system/cpu/cpu%u", &cpunum) != 1)
continue;
if (on && activatecpu(cpunum))
eprint("Failed to attach to hotplugged CPU %u\n", cpunum);
if (off)
deactivatecpu(cpunum);
}
udev_monitor_unref(monitor);
udev_unref(hotplug);
return NULL;
}
int perf_init(void)
{
int i, cpus, ctr, cpu, *fds;
memset(ctr_fds, 0, sizeof(ctr_fds));
int ecc_supported, i, num;
unsigned long maxfd;
struct rlimit rlim;
FILE *f;
/* initialize performance monitoring library */
if (!perf_supported()) {
@@ -143,99 +475,105 @@ int perf_init(void)
return -1;
}
/* We currently support all cpumf counters plus two virtual
* counters for PAI. */
num = ALL_COUNTER + 2;
/* Check if ECC is supported on current hardware */
ecc_supported = perf_counter_supported("cpum_cf", "ECC_FUNCTION_COUNT");
/* get number of logical processors */
cpus = sysconf(_SC_NPROCESSORS_ONLN);
/* for each counter */
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
/* Skip ECC counters completely if unsupported */
if (ctr == ECC_FUNCTIONS && !ecc_supported)
continue;
/*
* allocate an array of ints to store for each CPU
* one filedescriptor + a terminating 0
*/
fds = (int *) calloc(sizeof(int), cpus+1);
if (!fds) {
eprint("Malloc() of %d byte failed, errno=%d [%s]\n",
(int)(sizeof(int) * (cpus+1)),
errno, strerror(errno));
return -1;
}
ctr_fds[ctr] = fds;
/* search for the counter's corresponding pfm name */
for (i = ALL_COUNTER-1; i >= 0; i--)
if ((int) pmf_counter_name[i].ctr == ctr)
break;
if (i < 0) {
eprint("Pfm ctr name not found for counter %d, please adjust pmf_counter_name[] in %s\n",
ctr, __FILE__);
return -1;
}
for (cpu = 0; cpu < cpus; cpu++) {
struct perf_event_attr pfm_event;
int fd;
memset(&pfm_event, 0, sizeof(pfm_event));
pfm_event.size = sizeof(pfm_event);
if (perf_event_encode(&pfm_event,
pmf_counter_name[i].pmu,
pmf_counter_name[i].pfm_name)) {
eprint("Failed to initialize counter %s for pmu %s\n",
pmf_counter_name[i].pfm_name,
pmf_counter_name[i].pmu);
return -1;
}
/* fetch file descriptor for this perf event
* the counter event should start disabled
*/
pfm_event.disabled = 1;
fd = perf_event_open(
&pfm_event,
-1, /* pid -1 means all processes */
cpu,
-1, /* group filedescriptor */
0); /* flags */
if (fd < 0) {
eprint("Perf_event_open() failed with errno=%d [%s]\n",
errno, strerror(errno));
return -1;
}
fds[cpu] = fd;
}
if (!cpumf_authorized()) {
for (i = 0; i < ALL_COUNTER; ++i)
ctr_state[i] = UNSUPPORTED;
num -= ALL_COUNTER;
} else if (!ecc_supported) {
ctr_state[ECC_FUNCTIONS] = UNSUPPORTED;
--num;
}
return 0;
if (!perf_counter_supported("pai_crypto", "CRYPTO_ALL")) {
ctr_state[PAI_USER] = UNSUPPORTED;
ctr_state[PAI_KERNEL] = UNSUPPORTED;
num -= 2;
}
if (num == 0) {
eprint("No crypto counters supported!\n");
return -1;
}
if (perf_load_counter_data())
return -1;
/* We have to adjust the number of FDs possible since we might
* need more than 1024 (the typical soft limit) */
f = fopen("/proc/sys/fs/nr_open", "r");
if (f == NULL) {
eprint("fopen failed for /proc/sys/fs/nr_open with errno=%d [%s]\n",
errno, strerror(errno));
return -1;
}
if (fscanf(f, "%lu", &maxfd) != 1) {
fclose(f);
eprint("Failed to parse /proc/sys/fs/nr_open\n");
return -1;
}
fclose(f);
rlim.rlim_cur = maxfd;
rlim.rlim_max = maxfd;
if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
eprint("setrlimit failed with errno=%d [%s]\n",
errno, strerror(errno));
return -1;
}
if (pthread_create(&hotplugthread, NULL, hotplughandler, NULL)) {
eprint("Failed to start hotplug handler thread\n");
return -1;
}
return addallcpus();
}
void perf_stop(void)
{
stoprequested = 1;
}
void perf_close(void)
{
int ctr, *fds;
struct percpucounter *walk, *next;
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
for (fds = ctr_fds[ctr]; fds && *fds; fds++) {
close(*fds);
*fds = 0;
}
free(ctr_fds[ctr]);
ctr_fds[ctr] = NULL;
pthread_kill(hotplugthread, SIGINT);
pthread_join(hotplugthread, NULL);
walk = root;
while (walk) {
next = walk->next;
freepercpucounter(walk);
walk = next;
}
}
static int enable_array(int *arr, int size)
{
int i, ec, rc = 0;
for (i = 0; i < size; ++i) {
ec = ioctl(arr[i], PERF_EVENT_IOC_ENABLE, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
return rc;
}
int perf_enable_ctr(enum ctr_e ctr)
{
int *fds, ec, rc = 0;
struct percpucounter *pcpu;
int ec, rc = 0;
if (ctr == ALL_COUNTER) {
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
@@ -243,24 +581,64 @@ int perf_enable_ctr(enum ctr_e ctr)
if (rc != 0)
return rc;
}
} else {
for (fds = ctr_fds[ctr]; fds && *fds; fds++) {
ec = ioctl(*fds, PERF_EVENT_IOC_ENABLE, 0);
} else if (ctr < ALL_COUNTER) {
foreachcpu(pcpu) {
ec = ioctl(pcpu->ctr_fds[ctr], PERF_EVENT_IOC_ENABLE, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_ENABLE) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
ctr_state[ctr] = ENABLED;
++enabledcounter;
endforeachcpu();
} else if (ctr == PAI_USER) {
foreachcpu(pcpu) {
ec = enable_array(pcpu->pai_user, NUM_PAI_USER);
if (ec < 0)
rc = -1;
}
ctr_state[ctr] = ENABLED;
++enabledcounter;
endforeachcpu();
} else if (ctr == PAI_KERNEL) {
foreachcpu(pcpu) {
ec = enable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
if (ec < 0)
rc = -1;
}
ctr_state[ctr] = ENABLED;
++enabledcounter;
endforeachcpu();
} else {
rc = -1;
}
return rc;
}
static int disable_array(int *arr, int size)
{
int i, ec, rc = 0;
for (i = 0; i < size; ++i) {
ec = ioctl(arr[i], PERF_EVENT_IOC_DISABLE, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
return rc;
}
int perf_disable_ctr(enum ctr_e ctr)
{
int *fds, ec, rc = 0;
struct percpucounter *pcpu;
int ec, rc = 0;
if (ctr == ALL_COUNTER) {
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
@@ -268,70 +646,183 @@ int perf_disable_ctr(enum ctr_e ctr)
if (rc != 0)
return rc;
}
} else {
for (fds = ctr_fds[ctr]; fds && *fds; fds++) {
ec = ioctl(*fds, PERF_EVENT_IOC_DISABLE, 0);
} else if (ctr < ALL_COUNTER) {
foreachcpu(pcpu) {
ec = ioctl(pcpu->ctr_fds[ctr], PERF_EVENT_IOC_DISABLE, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_DISABLE) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
ctr_state[ctr] = DISABLED;
--enabledcounter;
if (enabledcounter == 0)
hotplugdetected = 0;
endforeachcpu();
} else if (ctr == PAI_USER) {
foreachcpu(pcpu) {
ec = disable_array(pcpu->pai_user, NUM_PAI_USER);
if (ec < 0)
rc = -1;
}
ctr_state[ctr] = DISABLED;
--enabledcounter;
if (enabledcounter == 0)
hotplugdetected = 0;
endforeachcpu();
} else if (ctr == PAI_KERNEL) {
foreachcpu(pcpu) {
ec = disable_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
if (ec < 0)
rc = -1;
}
ctr_state[ctr] = DISABLED;
--enabledcounter;
if (enabledcounter == 0)
hotplugdetected = 0;
endforeachcpu();
} else {
rc = -1;
}
return rc;
}
int perf_reset_ctr(enum ctr_e ctr)
static int reset_array(int *arr, int size)
{
int *fds, ec, rc = 0;
int ec, rc = 0, i;
for (i = 0; i < size; ++i) {
ec = ioctl(arr[i], PERF_EVENT_IOC_RESET, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
return rc;
}
int perf_reset_ctr(enum ctr_e ctr, uint64_t *value)
{
struct percpucounter *pcpu;
int ec, rc = 0;
if (ctr == ALL_COUNTER) {
for (ctr = 0; ctr < ALL_COUNTER; ctr++) {
rc = perf_reset_ctr(ctr);
rc = perf_reset_ctr(ctr, value);
if (rc != 0)
return rc;
}
} else {
for (fds = ctr_fds[ctr]; fds && *fds; fds++) {
ec = ioctl(*fds, PERF_EVENT_IOC_RESET, 0);
} else if (ctr < ALL_COUNTER) {
foreachcpu(pcpu) {
ec = ioctl(pcpu->ctr_fds[ctr], PERF_EVENT_IOC_RESET, 0);
if (ec < 0) {
eprint("Ioctl(PERF_EVENT_IOC_RESET) failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
}
}
endforeachcpu();
} else if (ctr == PAI_USER) {
foreachcpu(pcpu) {
ec = reset_array(pcpu->pai_user, NUM_PAI_USER);
if (ec < 0)
rc = -1;
}
endforeachcpu();
} else if (ctr == PAI_KERNEL) {
foreachcpu(pcpu) {
ec = reset_array(pcpu->pai_kernel, NUM_PAI_KERNEL);
if (ec < 0)
rc = -1;
}
endforeachcpu();
} else {
rc = -1;
}
if (rc == 0)
rc = perf_read_ctr(ctr, value);
return rc;
}
int perf_read_ctr(enum ctr_e ctr, uint64_t *value)
{
int *fds, ec, rc = -1;
struct percpucounter *pcpu;
int ec, rc = 0;
uint64_t val;
if (!value)
return -1;
if (ctr == HOTPLUG_DETECTED) {
*value = hotplugdetected;
return 0;
}
if (ctr == PAI_USER) {
*value = NUM_PAI_USER;
return 0;
}
if (ctr == PAI_KERNEL) {
*value = NUM_PAI_KERNEL;
return 0;
}
if (ctr >= ALL_COUNTER)
return -1;
*value = 0;
for (fds = ctr_fds[ctr]; fds && *fds; fds++) {
ec = read(*fds, &val, sizeof(val));
foreachcpu(pcpu) {
ec = read(pcpu->ctr_fds[ctr], &val, sizeof(val));
if (ec != sizeof(val)) {
eprint("Read() on perf file descriptor failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
} else {
*value += val;
rc = 0;
}
}
endforeachcpu();
return rc;
}
int perf_ecc_supported(void)
{
return ecc_supported;
return ctr_state[ECC_FUNCTIONS] != UNSUPPORTED;
}
int perf_ctr_state(enum ctr_e ctr) {
if (ctr < NUM_COUNTER)
return ctr_state[ctr];
return UNSUPPORTED;
}
int perf_read_pai_ctr(unsigned int ctrnum, int user, uint64_t *value)
{
struct percpucounter *pcpu;
unsigned int maxctr;
int *arr, ec, rc = 0;
uint64_t val;
*value = 0;
maxctr = user ? NUM_PAI_USER : NUM_PAI_KERNEL;
if (ctrnum >= maxctr)
return -1;
foreachcpu(pcpu) {
arr = user ? pcpu->pai_user : pcpu->pai_kernel;
ec = read(arr[ctrnum], &val, sizeof(val));
if (ec != sizeof(val)) {
eprint("Read() on perf file descriptor failed with errno=%d [%s]\n",
errno, strerror(errno));
rc = -1;
} else {
*value += val;
}
}
endforeachcpu();
return rc;
}

View File

@@ -3,7 +3,7 @@
*
* basic socket and receive/send functions
*
* Copyright IBM Corp. 2015, 2017
* Copyright IBM Corp. 2015, 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -13,6 +13,7 @@
#include <endian.h>
#include <errno.h>
#include <grp.h>
#include <poll.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/socket.h>
@@ -148,7 +149,51 @@ static int __read(int fd, void *buf, int buflen)
}
int send_msg(int sfd, struct msg *m)
static int __timedwrite(int fd, const void *buf, int buflen, int timeout)
{
struct pollfd pfd = { .fd = fd, .events = POLLOUT };
int i = 0, n;
while (poll(&pfd, 1, timeout) == 1) {
n = write(fd, buf + i, buflen - i);
if (n < 0) {
if (errno == EINTR)
continue;
else
return n;
} else if (n == 0) {
return i;
}
i += n;
if (buflen == i)
return i;
}
return -1;
}
static int __timedread(int fd, void *buf, int buflen, int timeout)
{
struct pollfd pfd = { .fd = fd, .events = POLLIN };
int i = 0, n;
while (poll(&pfd, 1, timeout) == 1) {
n = read(fd, buf + i, buflen - i);
if (n < 0) {
if (errno == EINTR)
continue;
else
return n;
} else if (n == 0) {
return i;
}
i += n;
if (buflen == i)
return i;
}
return -1;
}
int send_msg(int sfd, struct msg *m, int timeout)
{
int n, len;
@@ -166,7 +211,7 @@ int send_msg(int sfd, struct msg *m)
return -1;
}
n = __write(sfd, m, len);
n = timeout ? __timedwrite(sfd, m, len, timeout) : __write(sfd, m, len);
if (n != len) {
eprint("Write() error: write()=%d expected %d, errno=%d [%s]\n",
n, len, errno, strerror(errno));
@@ -176,12 +221,12 @@ int send_msg(int sfd, struct msg *m)
return 0;
}
int recv_msg(int sfd, struct msg *m)
int recv_msg(int sfd, struct msg *m, int timeout)
{
int n, len;
len = sizeof(m->head);
n = __read(sfd, m, len);
n = timeout ? __timedread(sfd, m, len, timeout) : __read(sfd, m, len);
if (n != len) {
eprint("Recv() error: read()=%d expected %d, errno=%d [%s]\n",
n, len, errno, strerror(errno));
@@ -200,7 +245,8 @@ int recv_msg(int sfd, struct msg *m)
return -1;
}
n = __read(sfd, ((char *)m) + sizeof(m->head), len);
n = timeout ? __timedread(sfd, ((char *)m) + sizeof(m->head), len, timeout) :
__read(sfd, ((char *)m) + sizeof(m->head), len);
if (n != len) {
eprint("Recv() error: recv()=%d expected %d, errno=%d [%s]\n",
n, len, errno, strerror(errno));

View File

@@ -26,6 +26,7 @@
#include "lib/util_arch.h"
#include "lib/util_base.h"
#include "lib/util_opt.h"
#include "lib/util_path.h"
#include "lib/util_prg.h"
#include "lib/libcpumf.h"
@@ -3318,17 +3319,18 @@ static void show_info(struct cpumf_info *p, int details)
* counter was renamed from CCERROR to CCFINISH in linux version 5.8.
* Check for existence of file /sys/devices/cpum_cf/events/DLFT_CCERROR.
*/
#define CCERROR "/sys/devices/cpum_cf/events/DFLT_CCERROR"
static void read_ccerror(struct counters *cp, size_t cp_cnt)
{
char *ctrname, *path;
struct stat sbuf;
char *ctrname;
size_t i = 0;
if (!stat(CCERROR, &sbuf))
path = util_path_sysfs("devices/cpum_cf/events/DFLT_CCERROR");
if (!stat(path, &sbuf))
ctrname = "DFLT_CCERROR";
else
ctrname = "DFLT_CCFINISH";
free(path);
/* Find DFLT_CC{FINISH,ERROR} in table and set name */
for (struct counters *p = cp; i < cp_cnt; ++i, ++p)
if (p->ctrnum == 265) {

View File

@@ -356,6 +356,8 @@ static void line(char *header)
putchar(',');
printf("%ld", ctrname[i].total);
comma = true;
ctrname[i].total = 0;
ctrname[i].hitcnt = false;
}
putchar('\n');
}
@@ -446,7 +448,7 @@ static bool add_countervalue(size_t idx, unsigned int cpu, unsigned long value)
ctrname[idx].ccv = calloc(max_possible_cpus,
sizeof(unsigned long));
if (ctrname[idx].ccv)
ctrname[idx].ccv[cpu] += value;
ctrname[idx].ccv[cpu] = value;
ctrname[idx].total += value;
ctrname[idx].hitcnt = true;
return true;
@@ -458,10 +460,8 @@ static int test_read(struct s390_hwctr_read *read)
size_t offset = 0;
/* Clear previous hit counters */
for (unsigned int i = 0; i < max_possible_cpus; ++i) {
check[i].sets_hit = 0;
for (unsigned int i = 0; i < max_possible_cpus; ++i)
check[i].cpu_hit = false;
}
/* Iterate over all CPUs */
for (unsigned int i = 0; i < read->no_cpus; ++i) {

View File

@@ -32,6 +32,7 @@
#include <linux/perf_event.h>
#include "lib/util_base.h"
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_list.h"
#include "lib/util_opt.h"
@@ -56,6 +57,7 @@ static cpu_set_t cpu_online_mask;
static int verbose, humantime;
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,
@@ -114,7 +116,7 @@ static void ev_alloc(int enr, int cpu, int flags)
warnx("NNPA does not support kernel/user space selector");
flags &= ~as;
}
event->attr.type = libcpumf_pmutype(S390_SYSFS_PAI_NNPA);
event->attr.type = libcpumf_pmutype(S390_SYSFS_PAI_EXT);
break;
}
event->attr.sample_type = PERF_SAMPLE_TID | PERF_SAMPLE_CPU |
@@ -263,9 +265,11 @@ static int savemap(int fd, void *data, struct data_pos *dp)
int wrapped;
d_head_old = d_head;
printf("Data head:%#llx tail:%#llx offset:%#llx size:%#llx\n",
dp->data_head, dp->data_tail, dp->data_offset,
dp->data_size);
if (verbose) {
printf("Data head:%#llx tail:%#llx offset:%#llx size:%#llx\n",
dp->data_head, dp->data_tail, dp->data_offset,
dp->data_size);
}
if (!diff)
return 0;
wrapped = d_head / dp->data_size != d_prev / dp->data_size;
@@ -280,13 +284,16 @@ static int savemap(int fd, void *data, struct data_pos *dp)
int part2 = dp->data_size - d_prev;
diff -= part2;
printf("Write %d bytes [%ld,%lld)\n", part2, d_prev,
dp->data_size);
if (verbose) {
printf("Write %d bytes [%ld,%lld)\n", part2, d_prev,
dp->data_size);
}
if (write(fd, data + d_prev, part2) == -1)
err(EXIT_FAILURE, "write error for event file");
d_prev = 0; /* Start at position zero */
}
printf("Write %d bytes [%ld,%ld)\n", diff, d_prev, d_head);
if (verbose)
printf("Write %d bytes [%ld,%ld)\n", diff, d_prev, d_head);
if (write(fd, data + d_prev, diff) == -1)
err(EXIT_FAILURE, "write error for event file");
@@ -299,7 +306,10 @@ static void readmap(int fd)
struct pai_event *p = perffd_2_event(fd);
struct perf_event_mmap_page *area;
printf("Ring buffer for fd %d %s(%d)\n", fd, p->file_name, p->file_fd);
if (verbose) {
printf("Ring buffer for fd %d %s(%d)\n", fd, p->file_name,
p->file_fd);
}
area = p->map_addr;
savemap(p->file_fd, p->map_addr + area->data_offset,
(struct data_pos *)&area->data_head);
@@ -383,7 +393,10 @@ static int evtraw_show(__u64 evtnum, unsigned char *p)
offset += sizeof(ctr);
value = *(__u64 *)(p + offset);
offset += sizeof(value);
printf("%c%hd:%#llx", offset > 14 ? ',' : ' ', ctr, value);
if (!summary) {
printf("%c%hd:%#llx", offset > 14 ? ',' : ' ', ctr,
value);
}
lookup_event(evtnum, ctr, value);
if (offset + sizeof(ctr) + sizeof(value) > bytes)
break;
@@ -412,6 +425,12 @@ static const char *evt_selector(struct perf_event_attr *pa)
static void evt_show(__u64 evtnum, const char *evtsel, struct pai_event_out *ev)
{
if (summary) {
if (ev->type == PERF_RECORD_SAMPLE && ev->raw)
evtraw_show(evtnum, ev->raw);
return;
}
timestamp(ev->time);
printf("%d ", ev->cpu);
@@ -633,30 +652,13 @@ bypass:
return 0;
}
/* Read perf_event_open() config value for event. */
static int read_event(char *dirname, char *filename)
{
int config, rc = 0;
char *pathname;
FILE *fp;
util_asprintf(&pathname, "%s/%s", dirname, filename);
fp = fopen(pathname, "r");
if (fp) {
rc = fscanf(fp, "event=%x", &config);
fclose(fp);
}
free(pathname);
return rc == 1 ? config : -1;
}
/* Scan event directory and fill event list. */
static int scan_events(struct pmu_events *p)
{
char *evtname, *evtdir, *path;
struct dirent **de_vec;
struct event_name *ep;
char *evtdir, *path;
int count, rc;
int evtnr, count, rc;
path = util_path_sysfs("devices");
rc = util_asprintf(&evtdir, "%s/%s/events", path, p->name);
@@ -677,8 +679,10 @@ static int scan_events(struct pmu_events *p)
if (de_vec[i]->d_type == DT_DIR)
continue;
ep->name = util_strdup(de_vec[i]->d_name);
rc = read_event(evtdir, de_vec[i]->d_name);
if (rc == -1 || !ep->name) {
util_asprintf(&evtname, "%s/%s", evtdir, de_vec[i]->d_name);
rc = util_file_read_va(evtname, "event=%x", &evtnr);
free(evtname);
if (rc != 1) {
for (ep = p->lst, rc = 0; rc < p->lstlen; ++rc, ++ep)
free(ep->name);
free(p->lst);
@@ -686,7 +690,7 @@ static int scan_events(struct pmu_events *p)
rc = -1;
goto out;
}
ep->config = rc;
ep->config = evtnr;
if (p->base > ep->config)
p->base = ep->config;
++p->lstlen;
@@ -1005,7 +1009,7 @@ static unsigned long check_mapsize(unsigned long n)
int main(int argc, char **argv)
{
bool crypto_record = false, report = false, summary = false;
bool crypto_record = false, report = false;
bool nnpa_record = false;
unsigned long loop_count = 1;
int ch, group = 0;

View File

@@ -1107,8 +1107,8 @@ static void dasdfmt_write_labels(volume_label_t *vlabel,
} else {
vlabel->ldl_version = 0xf2; /* EBCDIC '2' */
vlabel->formatted_blocks = cylinders * heads * geo.sectors;
rc = write(fd, &vlabel->vollbl, (sizeof(*vlabel)
- sizeof(vlabel->volkey)));
rc = write(fd, (void *)vlabel + sizeof(vlabel->volkey),
(sizeof(*vlabel) - sizeof(vlabel->volkey)));
}
if (((rc != sizeof(*vlabel) - sizeof(vlabel->formatted_blocks)) &&

View File

@@ -29,6 +29,7 @@
#include "lib/dasd_sys.h"
#include "lib/libzds.h"
#include "lib/util_base.h"
#include "lib/util_libc.h"
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_sys.h"
@@ -1788,10 +1789,8 @@ dasdview_print_format1(unsigned int size, unsigned char *dumpstr)
for (i = 0; i < size; i++) {
if ((i / 16) * 16 == i) {
printf("\n| ");
strncpy(asc, (char *)dumpstr + i, 16);
strncpy(ebc, (char *)dumpstr + i, 16);
asc[16] = '\0';
ebc[16] = '\0';
util_strlcpy(asc, (char *)dumpstr + i, 16);
util_strlcpy(ebc, (char *)dumpstr + i, 16);
}
printf("%02X", dumpstr[i]);
if (((i + 1) / 4) * 4 == i + 1)
@@ -1822,8 +1821,8 @@ dasdview_print_format2(unsigned int size, unsigned char *dumpstr,
begin + (unsigned long long)i,
begin + (unsigned long long)i);
strncpy(asc, (char *)dumpstr + i, 8);
strncpy(ebc, (char *)dumpstr + i, 8);
util_strlcpy(asc, (char *)dumpstr + i, 8);
util_strlcpy(ebc, (char *)dumpstr + i, 8);
}
printf("%02X", dumpstr[i]);
if (((i + 1) / 4) * 4 == i + 1)

View File

@@ -62,7 +62,8 @@ host.
Specifies the certificate that is used to establish a chain of trust
for the verification of the host-key documents. Specify this option
twice to specify the IBM Z signing key and the intermediate CA
certificate (signed by the root CA). Required.
certificate (signed by the root CA).
Required. Ignored if \fB--no-verify\fP is specified.
.TP
\fB\-o\fR, \fB\-\-output\fR=\fI\,OUTPUT_FILE\/\fR
Specifies the output file. Required.
@@ -91,8 +92,9 @@ the system wide root CAs installed on the system is used. Use
this only if you trust the specified certificate. Optional.
.TP
\fB\-\-no-verify\fR
Do not require the host-key documents to be valid. For testing
purposes, do not use for a production image. Optional.
Does not require the host-key documents to be valid.
Do not use for a production image unless you verified
the host-key document before. Optional.
.TP
\fB\-\-comm\-key\fR=\fI\,FILE\/\fR
Specifies the encryption key you want to use for the PV guest dump. Use a

View File

@@ -10,7 +10,7 @@
#define GETTEXT_PACKAGE "genprotimg"
#include <glib.h>
#include <glib/gi18n-lib.h>
#include <glib/gi18n.h>
#include "boot/linux_layout.h"
#include "boot/s390.h"

View File

@@ -280,7 +280,8 @@ gint pv_args_parse_options(PvArgs *args, gint *argc, gchar **argv[],
.arg_data = &args->host_keys,
.description =
_("FILE specifies a host-key document. At least\n" INDENT
"one is required."),
"one is required Specify this option multiple times\n" INDENT
"to enable the image to run on more than one host."),
.arg_description = _("FILE") },
{ .long_name = "cert",
.short_name = 'C',

View File

@@ -447,7 +447,7 @@ static X509_CRL *load_crl_from_bio(BIO *bio)
return g_steal_pointer(&crl);
ERR_clear_error();
rc = BIO_reset(bio);
if (rc != 1 || (rc != 0 && BIO_method_type(bio) == BIO_TYPE_FILE))
if (rc != 1 && !(rc == 0 && BIO_method_type(bio) == BIO_TYPE_FILE))
return NULL;
/* maybe the CRL is stored in DER format */
@@ -533,7 +533,7 @@ X509 *load_cert_from_file(const char *path, GError **err)
return g_steal_pointer(&cert);
ERR_clear_error();
rc = BIO_reset(bio);
if (rc != 1 || (rc != 0 && BIO_method_type(bio) == BIO_TYPE_FILE)) {
if (rc != 1 && !(rc == 0 && BIO_method_type(bio) == BIO_TYPE_FILE)) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_READ_CERTIFICATE,
_("unable to load certificate: '%s'"), path);
return NULL;

View File

@@ -57,11 +57,41 @@ struct linear_blockptr {
uint8_t reserved[4];
} __packed;
/*
* Format of a boot record on ECKD DASD for List-Directed IPL
*/
struct eckd_boot_record {
uint8_t magic[4];
uint32_t version_id;
uint8_t unused[8];
uint8_t program_table_pointer[16];
uint8_t reserved[478];
uint16_t os_id;
} __packed;
/*
* Layout of block pointer for cylinder/head/sector devices
* e.g. ECKD
*/
struct eckd_blockptr {
enum blkptr_format_id {
/*
* this is the old format which serves only CCW-type IPL,
* and doesn't fit List-Directed IPL. Still supported for
* compatibility reasons.
*/
LEGACY_BLKPTR_FORMAT_ID,
/*
* this is the "new" format which serves only List-Directed IPL,
* but is also suitable for CCW-type IPL.
*/
BLKPTR_FORMAT_ID
};
/*
* Block pointers format identified as LEGACY_BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr_legacy {
uint16_t cyl;
uint16_t head;
uint8_t sec;
@@ -70,10 +100,22 @@ struct eckd_blockptr {
uint8_t reserved[8];
} __packed;
/*
* Block pointers format identified as BLKPTR_FORMAT_ID.
*/
struct eckd_blockptr {
uint32_t cyl;
uint8_t head;
uint8_t sec;
uint8_t reserved1[4];
uint16_t blockct;
uint8_t reserved2[4];
} __packed;
typedef enum {
COMPONENT_EXECUTE = 0x01,
COMPONENT_LOAD = 0x02,
COMPONENT_SIGNATURE = 0x03
COMPONENT_TYPE_EXECUTE = 0x01,
COMPONENT_TYPE_LOAD = 0x02,
COMPONENT_TYPE_SIGNATURE = 0x03
} component_type;
typedef enum {
@@ -117,7 +159,8 @@ struct scsi_dump_sb {
uint64_t csum_offset;
uint64_t csum_size;
uint64_t csum;
} __packed;
};
STATIC_ASSERT(sizeof(struct scsi_dump_sb) == 72);
#define SCSI_DUMP_SB_MAGIC 0x5a46435044554d50ULL /* ZFCPDUMP */
/* To avoid a csum entry of 0 a seed is used */
@@ -153,6 +196,7 @@ struct boot_info_bp_dump {
struct boot_info_bp_ipl {
union {
struct eckd_blockptr_legacy eckd_legacy;
struct eckd_blockptr eckd;
struct linear_blockptr lin;
} bm_ptr;

View File

@@ -90,5 +90,6 @@ void ap_list_remove_all(struct util_list *list);
int ap_get_lock(void);
int ap_get_lock_callout(void);
int ap_release_lock(void);
int ap_release_lock_callout(void);
#endif /* LIB_AP_H */

View File

@@ -20,8 +20,8 @@
#include <stdio.h>
#include <sys/ioctl.h>
/* A bus id of a DASD is 8 characters long. E.g. 0.0.4711 */
#define DASD_BUS_ID_SIZE 9
/* the definition of a BUSID in the DASD driver is 20 */
#define DASD_BUS_ID_SIZE 20
typedef struct dasd_information2_t {
unsigned int devno; /* S/390 devno */
@@ -187,6 +187,68 @@ typedef struct format_check_t {
#define DASD_FMT_ERR_RECORD_ID 4
#define DASD_FMT_ERR_KEY_LENGTH 5
/*
* struct profile_info_t
* holds the profiling information
*/
typedef struct dasd_profile_info_t {
unsigned int dasd_io_reqs; /* # of requests processed at all */
unsigned int dasd_io_sects; /* # of sectors processed at all */
unsigned int dasd_io_secs[32]; /* request's sizes */
unsigned int dasd_io_times[32]; /* requests's times */
unsigned int dasd_io_timps[32]; /* requests's times per sector */
unsigned int dasd_io_time1[32]; /* time from build to start */
unsigned int dasd_io_time2[32]; /* time from start to irq */
unsigned int dasd_io_time2ps[32]; /* time from start to irq */
unsigned int dasd_io_time3[32]; /* time from irq to end */
unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */
} dasd_profile_info_t;
/*
* struct attrib_data_t
* represents the operation (cache) bits for the device.
* Used in DE to influence caching of the DASD.
*/
typedef struct attrib_data_t {
unsigned char operation : 3; /* cache operation mode */
unsigned char reserved : 5;
unsigned short nr_cyl; /* no of cyliners for read ahaed */
unsigned char reserved2[29]; /* for future use */
} __attribute__((packed)) attrib_data_t;
/* definition of operation (cache) bits within attributes of DE */
#define DASD_NORMAL_CACHE 0x0
#define DASD_BYPASS_CACHE 0x1
#define DASD_INHIBIT_LOAD 0x2
#define DASD_SEQ_ACCESS 0x3
#define DASD_SEQ_PRESTAGE 0x4
#define DASD_REC_ACCESS 0x5
/*
* Data returned by Sense Path Group ID (SNID)
*/
struct dasd_snid_data {
struct {
__u8 group : 2;
__u8 reserve : 2;
__u8 mode : 1;
__u8 res : 3;
} __attribute__((packed)) path_state;
__u8 pgid[11];
} __attribute__((packed));
struct dasd_snid_ioctl_data {
struct dasd_snid_data data;
__u8 path_mask;
} __attribute__((packed));
struct dasd_copypair_swap_data {
char primary[DASD_BUS_ID_SIZE]; /* BUSID of primary */
char secondary[DASD_BUS_ID_SIZE]; /* BUSID of secondary */
/* Reserved for future updates. */
char reserved[64];
};
#ifndef __linux__
/* definition from hdreg.h */
struct hd_geometry {
@@ -207,27 +269,29 @@ struct hd_geometry {
#define BIODASDRSRV _IO(DASD_IOCTL_LETTER, 2)
/* Release the device for the current LPAR */
#define BIODASDRLSE _IO(DASD_IOCTL_LETTER, 3)
/* Unconditional reserve the device for the current LPAR */
#define BIODASDSLCK _IO(DASD_IOCTL_LETTER, 4)
/* reset profiling information of a device */
#define BIODASDPRRST _IO(DASD_IOCTL_LETTER, 5)
/* retrieve profiling information of a device */
#define BIODASDPRRD _IOR(DASD_IOCTL_LETTER, 2, dasd_profile_info_t)
/* Get information on a dasd device (enhanced) */
#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
/* Get Attributes (cache operations) */
#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER, 5, attrib_data_t)
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER, 1, format_data_t)
/* Set Attributes (cache operations) */
#define BIODASDSATTR _IOW(DASD_IOCTL_LETTER, 2, attrib_data_t)
/* Release Allocated Space */
#define BIODASDRAS _IOW(DASD_IOCTL_LETTER, 3, format_data_t)
/* Swap copy pair */
#define BIODASDPPRCSWAP _IOW(DASD_IOCTL_LETTER, 4, struct dasd_copypair_swap_data)
/* Get Sense Path Group ID (SNID) data */
#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
/* Check device format according to format_data_t */
#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
/********************************************************************************
* SECTION: Further IOCTL Definitions (see fs.h and hdreq.h)
*******************************************************************************/
/* get read-only status (0 = read_write) */
#define BLKROGET _IO(0x12, 94)
/* re-read partition table */
#define BLKRRPART _IO(0x12, 95)
/* get block device sector size */
#define BLKSSZGET _IO(0x12, 104)
/* return device size in bytes (u64 *arg) */
#define BLKGETSIZE64 _IOR(0x12, 114, size_t)
#ifndef __linux__ /* from <linux/hdreg.h> */
#define HDIO_GETGEO 0x0301
#endif
@@ -245,5 +309,12 @@ int dasd_is_ro(const char *device, bool *ro);
int dasd_reread_partition_table(const char *device, int ntries);
int dasd_disk_reserve(const char *device);
int dasd_disk_release(const char *device);
int dasd_slock(const char *device);
int dasd_get_cache(const char *device, attrib_data_t *attrib_data);
int dasd_set_cache(const char *device, attrib_data_t *attrib_data);
int dasd_query_reserve(const char *device);
int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info);
int dasd_reset_profile(const char *device);
int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data);
#endif /* LIB_DASD_BASE_H */

View File

@@ -17,7 +17,8 @@
#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_NNPA "/sys/devices/pai_nnpa/"
#define S390_SYSFS_PAI_EXT "/sys/devices/pai_ext/"
#define S390_SYSFS_PAI_NNPA S390_SYSFS_PAI_EXT "events/NNPA_ALL"
/**
* Read out the PMU type from a given file.
@@ -146,6 +147,14 @@ bool libcpumf_sfb_info(unsigned long *min, unsigned long *max);
*/
bool libcpumf_have_pai_crypto(void);
/**
* Return true if PAI_EXTENSION Facility is supported.
*
* @retval true PAI_EXTENSION counter Facility is available
* @retval false PAI_EXTENSION counter Facility is not available
*/
bool libcpumf_have_pai_ext(void);
/**
* Return true if PAI_NNPA counter Facility is supported. This PMU facility
* supports the Neural Network Processing Assist (NNPA) counter set.

View File

@@ -0,0 +1,26 @@
/**
* @defgroup util_lockfile_h util_lockfile: File locking utility
* @{
* @brief Create file-based locks
*
* Copyright IBM Corp. 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIB_UTIL_LOCKFILE_H
#define LIB_UTIL_LOCKFILE_H
#define UTIL_LOCKFILE_OK 0 /* Lock acquired/released successfully */
#define UTIL_LOCKFILE_LOCK_FAIL 1 /* Lock already held, ran out of retries */
#define UTIL_LOCKFILE_RELEASE_NONE 2 /* Lock not held */
#define UTIL_LOCKFILE_RELEASE_FAIL 3 /* Lock not held by specified pid */
#define UTIL_LOCKFILE_ERR 4 /* Other, unexpected error conditions */
int util_lockfile_lock(char *lockfile, int retries);
int util_lockfile_parent_lock(char *lockfile, int retries);
int util_lockfile_release(char *lockfile);
int util_lockfile_parent_release(char *lockfile);
#endif /** LIB_UTIL_LOCKFILE_H @} */

View File

@@ -97,6 +97,24 @@ typedef struct volume_label
unsigned long long formatted_blocks; /* valid when ldl_version >= f2 */
} __attribute__ ((packed)) volume_label_t;
/**
* This represents a volume label specific for OS/390 compatible disk layout
*/
struct vol_label_cdl {
char volkey[4];
char vollbl[4];
char opaq[70];
cchhb_t br; /* boot record address */
char stdv[1]; /* standard version ID */
} __attribute__ ((packed));
static inline int is_vol1(char *this)
{
char vol1[] = {0xe5, 0xd6, 0xd3, 0xf1, 0x00} /* "VOL1" in EBCDIC */;
return !strncmp(this, vol1, 4);
}
typedef struct extent
{
u_int8_t typeind; /* extent type indicator */

View File

@@ -21,15 +21,21 @@
* Usage example:
* #define IMAGE_ENTRY _AC(0x10000, UL)
*/
#ifndef _AC
#ifdef __ASSEMBLER__
#define _AC(X, TYPE) X
#else
#define _AC(X, TYPE) X##TYPE
#endif
#endif
#ifndef __ASSEMBLER__
#ifndef sizeof_field
#define sizeof_field(type, field) (sizeof((type *)0)->field)
#endif
#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
@@ -48,6 +54,10 @@
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#ifndef ROUNDUP
# define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#endif
#define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE)
#define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR)
#define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR)
@@ -60,6 +70,7 @@
#define __may_alias __attribute__((may_alias))
#define __section(x) __attribute__((__section__(#x)))
#define __noinline __attribute__((__noinline__))
#define __big_endian
/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define
* __always_inline. Therefore undefine it first to allow the headers
* to be included first.

View File

@@ -68,6 +68,7 @@ typedef enum {
PV_CERT_ERROR_MALFORMED_ROOT_CA,
PV_CERT_ERROR_NO_CRL,
PV_CERT_ERROR_NO_CRLDP,
PV_CERT_ERROR_NO_IBM_Z_SIGNING_KEY,
PV_CERT_ERROR_NO_ISSUER_IBM_Z_FOUND,
PV_CERT_ERROR_NO_PUBLIC_KEY,
PV_CERT_ERROR_READ_CERTIFICATE,

View File

@@ -15,7 +15,7 @@
*/
#include "libpv/glib-helper.h"
#include <glib/gi18n-lib.h>
#include <glib/gi18n.h>
#include "libpv/openssl-compat.h"
#include "libpv/macros.h"

View File

@@ -42,11 +42,14 @@ enum PvCryptoMode {
PV_DECRYPT,
};
/** pv_get_openssl_error:
/** pv_get_openssl_errors:
*
* Returns: (transfer full): String representing the error.
* Returns the last OpenSSL error messages.
* Caller is responsible to free the returned value.
*
* Returns: String representing the error.
*/
const char *pv_get_openssl_error(void);
char *pv_get_openssl_errors(void);
/**
* pv_BIO_reset:
@@ -181,7 +184,6 @@ typedef enum {
PV_CRYPTO_ERROR_KEYGENERATION,
PV_CRYPTO_ERROR_RANDOMIZATION,
PV_CRYPTO_ERROR_READ_FILE,
PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
PV_CRYPTO_ERROR_NO_MATCH_TAG,
} PvCryptoErrors;

View File

@@ -102,9 +102,12 @@ FILE *pv_file_open(const char *filename, const char *mode, GError **error);
/** pv_gbytes_memcpy:
*
* memcpy with size check.
* memcpy with size check. In case @dst_size is smaller than the size of @src
* the error value %NULL is returned and @copied and @dst are left unchanged.
*
* If @dst and @src data overlap, the behavior is undefined.
*/
void *pv_gbytes_memcpy(void *dst, size_t dst_size, GBytes *src);
void *pv_gbytes_memcpy(void *dst, size_t dst_size, GBytes *src, size_t *copied);
#define PV_GLIB_HELPER_ERROR g_quark_from_static_string("pv-glib-helper_error-quark")
typedef enum {

View File

@@ -10,7 +10,12 @@
#ifndef LIBPV_MACROS_H
#define LIBPV_MACROS_H
#include <stdint.h>
#define PV_NONNULL(...)
#define DO_PRAGMA(x) _Pragma(#x)
/* Most significant bit */
#define PV_MSB(idx) ((uint64_t)1 << (63 - (idx)))
#endif /* LIBPV_MACROS_H */

View File

@@ -15,6 +15,7 @@
#include "boot/s390.h"
#include "libpv/crypto.h"
#include "libpv/macros.h"
/* Magic number which is used to identify the file containing the PV
* header
@@ -22,20 +23,17 @@
#define PV_MAGIC_NUMBER 0x49424d5365634578ULL
#define PV_VERSION_1 0x00000100U
/* Internal helper macro */
#define __PV_BIT(nr) (1ULL << (63 - (nr)))
/* Plaintext control flags */
/* dumping of the configuration is allowed */
#define PV_PCF_ALLOW_DUMPING __PV_BIT(34)
#define PV_PCF_ALLOW_DUMPING PV_MSB(34)
/* prevent Ultravisor decryption during unpack operation */
#define PV_PCF_NO_DECRYPTION __PV_BIT(35)
#define PV_PCF_NO_DECRYPTION PV_MSB(35)
/* PCKMO encrypt-DEA/TDEA-key functions allowed */
#define PV_PCF_PCKMO_DEA_TDEA __PV_BIT(56)
#define PV_PCF_PCKMO_DEA_TDEA PV_MSB(56)
/* PCKMO encrypt-AES-key functions allowed */
#define PV_PCF_PCKMO_AES __PV_BIT(57)
#define PV_PCF_PCKMO_AES PV_MSB(57)
/* PCKMO encrypt-ECC-key functions allowed */
#define PV_PCF_PCKM_ECC __PV_BIT(58)
#define PV_PCF_PCKM_ECC PV_MSB(58)
/* maxima for the PV version 1 */
#define PV_V1_IPIB_MAX_SIZE PAGE_SIZE

View File

@@ -75,6 +75,7 @@ extern void fcp_busid_get(const char *device, char *devno);
* NVME
*/
#define FID_MAX_LEN 11 /* 8 characters + 0x + null */
#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);

View File

@@ -18,15 +18,31 @@
#include "lib/util_file.h"
#include "ipl_tools.h"
static void nvme_dev_from_bdev(char *dev_name)
{
char *delim = strrchr(dev_name, 'n');
if (delim)
*delim = 0;
}
/*
* Return the fid of a device
*/
void nvme_fid_get(const char *device, char *fid)
{
char path[PATH_MAX], buf[FID_MAX_LEN];
char nvme_dev[NVME_DEV_MAX_LEN];
snprintf(path, PATH_MAX, "/sys/block/%s/device/device/function_id",
device);
/*
* An NVMe may present multiple namespaces and thus block devices, even
* before partitioning, so we need the nvme<NUM> part of the block
* device name to get to the PCI function ID.
*/
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);
if (util_file_read_line(buf, FID_MAX_LEN, path))
ERR_EXIT_ERRNO("Could not read from \"%s\"", path);

View File

@@ -62,7 +62,7 @@ extern ssize_t __write(int, const void*, size_t);
extern int strmatch(const char *, const char *);
extern int is_regex_valid(const char *);
extern int is_client_allowed(const char *, const struct iucvterm_cfg *);
extern void userid_cpy(char [8], const char [8]);
extern void userid_cpy(char [9], const char [8]);
extern void iucv_msg_error(const char *, uint32_t);
extern void program_error(const char *, const char *);

View File

@@ -2,17 +2,6 @@ include ../common.mak
lib = libap.a
check-dep-lock:
touch check-dep-lock
ifneq (${HAVE_LOCKFILE},0)
$(call check_dep, \
"libap", \
"lockfile.h", \
"liblockfile-devel", \
"HAVE_LOCKFILE=0")
ALL_CPPFLAGS += -DHAVE_LOCKFILE
endif
check-dep-json:
touch check-dep-json
ifneq (${HAVE_JSONC},0)
@@ -29,7 +18,7 @@ objects = ap.o
$(lib): $(objects)
$(objects): check-dep-lock check-dep-json
$(objects): check-dep-json
install: all

View File

@@ -22,13 +22,10 @@
#include <json-c/json.h>
#endif /* HAVE_JSONC */
#ifdef HAVE_LOCKFILE
#include <lockfile.h>
#endif /* HAVE_LOCKFILE */
#include "lib/ap.h"
#include "lib/util_file.h"
#include "lib/util_libc.h"
#include "lib/util_lockfile.h"
#include "lib/util_panic.h"
#include "lib/util_path.h"
#include "lib/util_udev.h"
@@ -701,33 +698,28 @@ void ap_list_remove_all(struct util_list *list)
}
}
#ifdef HAVE_LOCKFILE
static int ap_lockfile_create(int flags)
{
return lockfile_create(AP_LOCKFILE, AP_LOCK_RETRIES, flags);
}
/**
* Acquire the ap config lock using this process PID (L_PID)
* Acquire the ap config lock using this Process ID
*
* @retval 0 Lock acquired on behalf of this process
*
* @retval 0 Lock successfully acquired on behalf of L_PID
* @retval != 0 Error, lock was not obtained
*/
int ap_get_lock(void)
{
return ap_lockfile_create(L_PID);
return util_lockfile_lock(AP_LOCKFILE, AP_LOCK_RETRIES);
}
/**
* Acquire the ap config lock using the parent process PID (L_PPID) -- intended
* for use by the mdevctl callout ap-check utility
* Acquire the ap config lock using the Parent Process ID -- intended for use
* by the mdevctl callout ap-check utility
*
* @retval 0 Lock successfully acquired on behalf of L_PPID
* @retval 0 Lock acquired on behalf of parent process
* @retval != 0 Error, lock was not obtained
*/
int ap_get_lock_callout(void)
{
return ap_lockfile_create(L_PPID);
return util_lockfile_parent_lock(AP_LOCKFILE, AP_LOCK_RETRIES);
}
/**
@@ -738,23 +730,10 @@ int ap_get_lock_callout(void)
*/
int ap_release_lock(void)
{
return lockfile_remove(AP_LOCKFILE);
}
#else
/* If no liblockfile, actions are performed without acquiring the file lock */
int ap_get_lock(void)
{
return 0;
return util_lockfile_release(AP_LOCKFILE);
}
int ap_get_lock_callout(void)
int ap_release_lock_callout(void)
{
return 0;
return util_lockfile_parent_release(AP_LOCKFILE);
}
int ap_release_lock(void)
{
return 0;
}
#endif /* HAVE_LOCKFILE */

View File

@@ -85,5 +85,6 @@ int main(void)
}
printf("PAI NNPA support %d\n", libcpumf_have_pai_nnpa());
printf("PAI EXTENSION support %d\n", libcpumf_have_pai_ext());
return EXIT_SUCCESS;
}

View File

@@ -147,6 +147,13 @@ bool libcpumf_have_pai_crypto(void)
return (stat(S390_SYSFS_PAI_CRYPTO, &statbuf) == -1) ? false : true;
}
bool libcpumf_have_pai_ext(void)
{
struct stat statbuf;
return (stat(S390_SYSFS_PAI_EXT, &statbuf) == -1) ? false : true;
}
bool libcpumf_have_pai_nnpa(void)
{
struct stat statbuf;

View File

@@ -15,7 +15,9 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <unistd.h>
#include <string.h>
#include "lib/dasd_base.h"
@@ -27,11 +29,13 @@
#define RUN_IOCTL(fd, req, argp) \
do { \
if (ioctl(fd, req, argp) != 0) { \
int err = errno; \
if (err != EBADF) \
int rc = ioctl(fd, req, argp); \
if (rc != 0) { \
if (rc == -1) \
rc = errno; \
if (rc != EBADF) \
dasd_close_device(fd); \
return err; \
return rc; \
} \
} while (0)
@@ -321,3 +325,159 @@ int dasd_disk_release(const char *device)
return 0;
}
/*
* Unconditionally reserve DASD disk
*
* An existing reserve lock is lifted (steal lock) and the device
* is reserved.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_slock(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSLCK, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Get the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[out] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_get_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDGATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Set the caching algorithm used for the channel programs of this device.
*
* @param[in] device node device node's name
* @param[in] attrib_data pointer to dasd attrib data with:
* 'cache' is the caching mode
* 'no_cyl' the number of cylinders to be cached.
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_set_cache(const char *device, attrib_data_t *attrib_data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSATTR, attrib_data);
dasd_close_device(fd);
return 0;
}
/*
* Get reserve status of device.
*
* @param[in] device node device node's name
*
* @retval errno in case of failure
* @retval 0 unreserved
* @retval 1 implicit reserved
* @retval 2 other reservation
* @retval 3 reserved
*/
int dasd_query_reserve(const char *device)
{
struct dasd_snid_ioctl_data snid = { 0 };
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDSNID, &snid);
dasd_close_device(fd);
return snid.data.path_state.reserve;
}
/*
* Get and print the profiling info of the device.
*
* @param[in] device node device node's name
* @param[in] dasd_profile_info pointer to dasd profile info
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_profile(const char *device, dasd_profile_info_t *dasd_profile_info)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRD, dasd_profile_info);
dasd_close_device(fd);
return 0;
}
/*
* Reset the profiling counters of the device.
*
* @param[in] device node device node's name
*
* @retval 0 in case of success
* @retval errno in case of failure
*/
int dasd_reset_profile(const char *device)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPRRST, NULL);
dasd_close_device(fd);
return 0;
}
/*
* Initiate the swap of a copy pairs primary,secondary relation.
* The old secondary will become the new primary and vice versa.
*
* @param[in] device node device node's name
* @param[in] copy_pair data pointer to dasd copypair data with:
* 'primary' old primary, becoming secondary
* 'secondary' old secondary, becoming primary.
*
* @retval errno in case of failure
* @retval 0 in case of success
* @retval 1 swap data invalid
* @retval 2 no active device found
* @retval 3 wrong primary specified
* @retval 4 secondary device not found
* @retval 5 swap already running
*/
int dasd_copy_swap(const char *device, struct dasd_copypair_swap_data *data)
{
int fd;
fd = dasd_open_device(device, O_RDONLY);
RUN_IOCTL(fd, BIODASDPPRCSWAP, data);
dasd_close_device(fd);
return 0;
}

View File

@@ -51,7 +51,7 @@ endif
sources := $(wildcard *.c)
objects := $(patsubst %.c,%.o,$(sources))
all: $(BUILD_TARGETS) .check_dep-$(LIB)
all: $(BUILD_TARGETS)
$(LIB): $(objects)
$(LIB): ALL_CFLAGS += -fPIC
@@ -74,7 +74,7 @@ skip-$(LIB):
.detect-openssl.dep.c:
echo "#include <openssl/evp.h>" > $@
echo "#if OPENSSL_VERSION_NUMBER < 0x10101000L" >> $@
echo " #error openssl version 1.1.0 is required" >> $@
echo " #error openssl version 1.1.1 is required" >> $@
echo "#endif" >> $@
echo "static void __attribute__((unused)) test(void) {" >> $@
echo " EVP_MD_CTX *ctx = EVP_MD_CTX_new();" >> $@
@@ -90,7 +90,7 @@ skip-$(LIB):
$(call check_dep, \
"$(LIB)", \
$^, \
"openssl-devel / libssl-dev version >= 1.1.0", \
"openssl-devel / libssl-dev version >= 1.1.1", \
"HAVE_OPENSSL=0", \
"-I.")
$(call check_dep, \

View File

@@ -290,7 +290,9 @@ static char *pv_X509_NAME_oneline(const X509_NAME *name)
long len;
if (X509_NAME_print_ex(key_bio, name, 0, XN_FLAG_RFC2253) == -1) {
g_warning(_("Cannot receive X509-NAME from CRL: %s"), pv_get_openssl_error());
g_autofree char *openssl_err_msg = pv_get_openssl_errors();
g_warning(_("Cannot receive X509-NAME from CRL: %s"), openssl_err_msg);
return NULL;
}
@@ -492,7 +494,9 @@ static X509_CRL *load_crl_by_dist_point(DIST_POINT *crldp, GError **error)
X509_CRL *pv_load_first_crl_by_cert(X509 *cert, GError **error)
{
g_autoptr(STACK_OF_DIST_POINT) crldps = NULL;
g_autoptr(GError) last_error = NULL;
g_autoptr(X509_CRL) ret = NULL;
int dist_points_cnt;
g_assert(cert);
@@ -503,19 +507,24 @@ X509_CRL *pv_load_first_crl_by_cert(X509 *cert, GError **error)
return NULL;
}
for (int i = 0; i < sk_DIST_POINT_num(crldps); i++) {
dist_points_cnt = sk_DIST_POINT_num(crldps);
for (int i = 0; i < dist_points_cnt; i++) {
DIST_POINT *crldp = sk_DIST_POINT_value(crldps, i);
g_assert(crldp);
/* ignore error */
ret = load_crl_by_dist_point(crldp, NULL);
g_clear_error(&last_error);
ret = load_crl_by_dist_point(crldp, &last_error);
if (ret)
return g_steal_pointer(&ret);
}
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_FAILED_DOWNLOAD_CRL,
_("failed to download CRL"));
/* relabel error */
if (last_error)
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_FAILED_DOWNLOAD_CRL,
"%s", last_error->message);
else
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_FAILED_DOWNLOAD_CRL,
_("failed to download CRL"));
return NULL;
}
@@ -783,7 +792,7 @@ int pv_store_set_verify_param(X509_STORE *store, GError **error)
return 0;
error:
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_INTERNAL,
_("X509 store initialization failed"));
return -1;
}
@@ -1368,14 +1377,14 @@ int pv_check_chain_parameters(const STACK_OF_X509 *chain, GError **error)
ca_x509_subject = X509_get_subject_name(ca);
if (!ca_x509_subject) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_INTERNAL,
_("subject of the root CA cannot be retrieved"));
return -1;
}
ca_subject = pv_X509_NAME_oneline(ca_x509_subject);
if (!ca_subject) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_INTERNAL,
_("subject name of the root CA cannot be retrieved"));
return -1;
}
@@ -1469,11 +1478,11 @@ static STACK_OF_X509 *get_ibm_signing_certs(STACK_OF_X509 *certs, GError **error
ibm_signing_certs = pv_remove_ibm_signing_certs(certs);
ibm_signing_certs_count = sk_X509_num(ibm_signing_certs);
if (ibm_signing_certs_count < 1) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_IBM_Z_SIGNING_KEY,
_("Specify at least one IBM Z signing key"));
return NULL;
} else if (ibm_signing_certs_count > 1) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_IBM_Z_SIGNING_KEY,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_IBM_Z_SIGNING_KEY,
_("Specify only one IBM Z signing key"));
return NULL;
}
@@ -1504,7 +1513,7 @@ static gboolean download_crls(X509_STORE *trusted, PvCertWithPathList *host_key_
X509_CRL *crl = sk_X509_CRL_value(downloaded_ibm_signing_crls, i);
if (X509_STORE_add_crl(trusted, crl) != 1) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_INTERNAL,
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_INTERNAL,
_("failed to load CRL"));
return FALSE;
}

View File

@@ -19,18 +19,18 @@
#include "libpv/glib-helper.h"
#include "libpv/hash.h"
const char *pv_get_openssl_error(void)
char *pv_get_openssl_errors(void)
{
const char *ret;
BIO *bio;
char *ret;
char *buf;
BIO *bio;
long len;
bio = BIO_new(BIO_s_mem());
ERR_print_errors(bio);
len = BIO_get_mem_data(bio, &buf);
if (len < 0)
ret = "Cannot receive OpenSSL error message.";
if (len <= 0 || !buf)
ret = g_strdup("Cannot receive OpenSSL error message.");
else
ret = g_strndup(buf, (size_t)len);
BIO_free(bio);
@@ -41,7 +41,7 @@ int pv_BIO_reset(BIO *b)
{
int rc = BIO_reset(b);
if (rc != 1 && (BIO_method_type(b) == BIO_TYPE_FILE && rc != 0))
if (rc != 1 && !(BIO_method_type(b) == BIO_TYPE_FILE && rc == 0))
return -1;
return 1;
}
@@ -276,7 +276,7 @@ int64_t pv_gcm_decrypt(GBytes *cipher, GBytes *aad, GBytes *tag, const PvCipherP
}
GBytes *pv_hkdf_extract_and_expand(size_t derived_key_len, GBytes *key, GBytes *salt, GBytes *info,
const EVP_MD *md, G_GNUC_UNUSED GError **error)
const EVP_MD *md, GError **error)
{
const unsigned char *salt_data, *key_data, *info_data;
g_autoptr(EVP_PKEY_CTX) ctx = NULL;
@@ -354,7 +354,6 @@ GBytes *pv_hkdf_extract_and_expand(size_t derived_key_len, GBytes *key, GBytes *
if (EVP_PKEY_derive(ctx, derived_key, &derived_key_len) != 1) {
g_set_error(error, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_HKDF_FAIL,
"FAILED to derive key via HKDF");
printf("%s\n", pv_get_openssl_error());
return NULL;
}

View File

@@ -168,12 +168,14 @@ GBytes *pv_file_get_content_as_secure_bytes(const char *filename)
return pv_sec_gbytes_new_take(g_steal_pointer(&data), data_size);
}
void *pv_gbytes_memcpy(void *dst, size_t dst_size, GBytes *src)
void *pv_gbytes_memcpy(void *dst, size_t dst_size, GBytes *src, size_t *copied)
{
size_t src_size;
const void *src_data = g_bytes_get_data(src, &src_size);
if (dst_size < src_size)
return NULL;
if (copied)
*copied = src_size;
return memcpy(dst, src_data, src_size);
}

View File

@@ -97,8 +97,10 @@ HMAC_CTX *pv_hmac_ctx_new(GBytes *key, const EVP_MD *md, GError **error)
key_data = g_bytes_get_data(key, &key_size);
if (HMAC_Init_ex(ctx, key_data, (int)key_size, md, NULL) != 1) {
g_autofree char *openssl_err_msg = pv_get_openssl_errors();
g_set_error(error, PV_HASH_ERROR, PV_HASH_ERROR_INTERNAL,
"unable to create HMAC context: %s", pv_get_openssl_error());
"unable to create HMAC context: %s", openssl_err_msg);
return NULL;
}
return g_steal_pointer(&ctx);
@@ -110,8 +112,10 @@ int pv_hmac_ctx_update_raw(HMAC_CTX *ctx, const void *buf, size_t size, GError *
return 0;
if (HMAC_Update(ctx, buf, size) != 1) {
g_autofree char *openssl_err_msg = pv_get_openssl_errors();
g_set_error(error, PV_HASH_ERROR, PV_HASH_ERROR_INTERNAL,
"unable to add data to HMAC context: %s", pv_get_openssl_error());
"unable to add data to HMAC context: %s", openssl_err_msg);
return -1;
}
return 0;
@@ -139,8 +143,10 @@ GBytes *pv_hamc_ctx_finalize(HMAC_CTX *ctx, GError **error)
hmac = g_malloc0((unsigned int)md_size);
if (HMAC_Final(ctx, hmac, &hmac_size) != 1) {
g_autofree char *openssl_err_msg = pv_get_openssl_errors();
g_set_error(error, PV_HASH_ERROR, PV_HASH_ERROR_INTERNAL,
"unable to calculate HMAC: %s", pv_get_openssl_error());
"unable to calculate HMAC: %s", openssl_err_msg);
return NULL;
}
return g_bytes_new_take(g_steal_pointer(&hmac), hmac_size);

View File

@@ -107,13 +107,12 @@ const char *util_arch_machine_type_to_str(int type)
*/
unsigned long util_arch_hsa_maxsize(void)
{
unsigned long size = HSA_SIZE_32M;
int type;
type = util_arch_machine_type();
if (type != UTIL_ARCH_MACHINE_TYPE_UNKNOWN &&
type >= UTIL_ARCH_MACHINE_TYPE_Z15)
size = HSA_SIZE_512M;
return size;
switch (util_arch_machine_type()) {
case UTIL_ARCH_MACHINE_TYPE_Z15:
case UTIL_ARCH_MACHINE_TYPE_Z15_T02:
case UTIL_ARCH_MACHINE_TYPE_Z16:
return HSA_SIZE_512M;
default:
return HSA_SIZE_32M;
}
}

301
libutil/util_lockfile.c Normal file
View File

@@ -0,0 +1,301 @@
/*
* util - Utility function library
*
* Created file-based locks
*
* Copyright IBM Corp. 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "lib/util_libc.h"
#include "lib/util_lockfile.h"
#include "lib/util_panic.h"
#define WAITPID 120 /* Time to wait for pid to be written */
#define WAITINC 5 /* Additional time to wait each retry */
#define MAXWAIT 60 /* Maximum wait between retries */
#define BUFSIZE 40 /* Buffer must be large enough to fit pid string */
/**
* Check if there is a process that exists with the specified identifier.
*
* @param[in] pid Process Identifier to check
*
* @retval true Process exists or we lack privelege to check
* @retval false Process does not exist
*/
static bool pid_exists(int pid)
{
int rc;
/* Use sig 0 to determine if the owner is still alive */
rc = kill(pid, 0);
if (rc != 0) {
switch (errno) {
case EPERM:
/* Privilege issue, just assume PID exists */
break;
case ESRCH:
/* PID does not exist, this lock is stale */
return false;
default:
util_assert(false, "Unexpected return from kill: %d\n", rc);
break;
}
}
return true;
}
/**
* Check for an existing lock that is deemed stale (either the associated PID
* is gone or no PID has been written to the file in a reasonable timeframe).
* In the case a stale lock is found, remove it.
*
* @param[in] lockfile Path to the lock file
*
* @retval 0 Either no lock or stale lock was found and removed
* @retval 1 Lock is held by another PID and is not stale
*/
static int handle_stale_lock(char *lockfile)
{
int fd, rc, pid, len;
struct stat info;
char buf[BUFSIZE];
time_t curr;
fd = open(lockfile, O_RDONLY);
if (fd >= 0) {
/* Lock exists, see who owns it */
len = read(fd, buf, sizeof(buf));
if (len > 0) {
buf[len] = 0; /* Ensure null terminated string */
pid = atoi(buf);
if (!pid_exists(pid)) {
/* Stale lock detected unlink and retry now */
close(fd);
unlink(lockfile);
return 0;
} else if (pid != 0) {
/* Lock is held by an active pid, delay */
close(fd);
return 1;
}
/*
* If we reach this point, the PID was 0 which is
* unexpected. Proceed under the assumption that the
* proper PID hasn't been written yet.
*/
}
/*
* PID hasn't been written yet? Either a bad lock or a very
* new one.
*/
time(&curr);
rc = fstat(fd, &info);
close(fd);
if (rc != 0) {
/* Can't read file anymore, retry now */
return 0;
}
if (curr > info.st_mtime + WAITPID) {
/*
* PID should be in the file within 2 minutes,
* something went wrong. Treat as stale.
*/
unlink(lockfile);
return 0;
}
/* Otherwise, assume file was newly created and delay */
return 1;
}
/* Couldn't open, try again immediately */
return 0;
}
/**
* Attempt to create a lockfile at the specified path.
*
* @param[in] lockfile Path to the lock file
* @param[in] retries Number of times to retry if lock fails initially
* @param[in] pid PID to use for lock ownership
*
* @retval 0 Lock created with PID as owner
* @retval !=0 Lock was not created
*/
static int do_lockfile_lock(char *lockfile, unsigned int retries, int pid)
{
int fd, plen, len, rc = 0, snooze = 0;
unsigned int tries = retries + 1;
char buf[BUFSIZE];
char *tpath;
if (!lockfile)
return UTIL_LOCKFILE_ERR;
plen = snprintf(buf, sizeof(buf), "%d\n", pid);
if (plen < 0 || (plen > ((int)sizeof(buf) - 1)))
return UTIL_LOCKFILE_ERR;
/* Allocate temporary lock file with a sufficiently unique path */
len = util_asprintf(&tpath, "%s%05d%02x", lockfile, getpid(),
(unsigned int)time(NULL) & 255);
if (len < 0)
return UTIL_LOCKFILE_ERR;
/* Open the temporary lockfile, write the specified pid */
fd = open(tpath, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0644);
if (fd < 0) {
rc = UTIL_LOCKFILE_ERR;
goto out;
}
len = write(fd, buf, plen);
if (close(fd) != 0) {
rc = UTIL_LOCKFILE_ERR;
goto cleanup;
}
if (len != plen) {
/* Failed to write the temp lockfile, bail out */
rc = UTIL_LOCKFILE_ERR;
goto cleanup;
}
/* Link the temprorary file to the real path */
do {
rc = link(tpath, lockfile);
if (rc == 0) {
/* Lock successfully acquired */
rc = UTIL_LOCKFILE_OK;
goto cleanup;
}
/* Lock already held - check for stale lock */
rc = handle_stale_lock(lockfile);
/* Only wait if the lock was not stale */
if (rc != 0) {
tries--;
if (tries > 0) {
snooze += WAITINC;
snooze = (snooze > MAXWAIT) ? MAXWAIT : snooze;
sleep(snooze);
}
}
} while (tries > 0);
/* Exhausted specified number of retries, exit on failure */
rc = UTIL_LOCKFILE_LOCK_FAIL;
cleanup:
unlink(tpath);
free(tpath);
out:
return rc;
}
/**
* Attempt to release a lockfile at the specified path.
*
* @param[in] lockfile Path to the lock file
* @param[in] pid PID that should own the lock
*
* @retval 0 Lock released
* @retval !=0 Lock was not released or did not exist
*/
static int do_lockfile_release(char *lockfile, int pid)
{
int fd, len, lpid;
char buf[BUFSIZE];
if (!lockfile)
return UTIL_LOCKFILE_ERR;
/* Open lockfile, read the owning pid if it exists */
fd = open(lockfile, O_RDONLY);
if (fd < 0)
return UTIL_LOCKFILE_RELEASE_NONE;
len = read(fd, buf, sizeof(buf));
close(fd);
if (len <= 0)
return UTIL_LOCKFILE_RELEASE_FAIL;
buf[len] = 0;
lpid = atoi(buf);
/* Only release the lock if its held by the right pid */
if (pid != lpid)
return UTIL_LOCKFILE_RELEASE_FAIL;
unlink(lockfile);
return 0;
}
/**
* Attempt to create a lockfile owned by this process at the specified path.
*
* @param[in] lockfile Path to the lock file
* @param[in] retries Number of times to retry if lock fails initially
*
* @retval 0 Lock created
* @retval !=0 Lock was not created
*/
int util_lockfile_lock(char *lockfile, int retries)
{
return do_lockfile_lock(lockfile, retries, getpid());
}
/**
* Attempt to create a lockfile owned by the parent of this process at the
* specified path.
*
* @param[in] lockfile Path to the lock file
* @param[in] retries Number of times to retry if lock fails initially
*
* @retval 0 Lock created
* @retval !=0 Lock was not created
*/
int util_lockfile_parent_lock(char *lockfile, int retries)
{
return do_lockfile_lock(lockfile, retries, getppid());
}
/**
* Attempt to release a lockfile owned by this process at the specified path.
*
* @param[in] lockfile Path to the lock file
*
* @retval 0 Lock released
* @retval !=0 Lock was not released or did not exist
*/
int util_lockfile_release(char *lockfile)
{
return do_lockfile_release(lockfile, getpid());
}
/**
* Attempt to release a lockfile owned by the parent of this process at the
* specified path.
*
* @param[in] lockfile Path to the lock file
*
* @retval 0 Lock released
* @retval !=0 Lock was not released or did not exist
*/
int util_lockfile_parent_release(char *lockfile)
{
return do_lockfile_release(lockfile, getppid());
}

View File

@@ -0,0 +1,232 @@
/**
* util_lockfile_example - Example program for util_lockfile
*
* Copyright IBM Corp. 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
//! [code]
#include <stdio.h>
#include <stdlib.h>
#include "lib/util_opt.h"
#include "lib/util_prg.h"
#include "lib/util_lockfile.h"
static const struct util_prg prg = {
.desc = "Example for util_lockfile.",
.copyright_vec = { {
.owner = "IBM Corp.",
.pub_first = 2022,
.pub_last = 2022,
},
UTIL_PRG_COPYRIGHT_END }
};
static struct util_opt opt_vec[] = {
UTIL_OPT_SECTION("OPTIONS"),
{
.option = { "file", required_argument, NULL, 'f' },
.argument = "PATH",
.desc = "Use the specified path for a lockfile.",
},
{
.option = { "lock", required_argument, NULL, 'l' },
.argument = "RETRIES",
.desc = "Acquire the specified file lock using the parent "
"process id of this process. If not immediately "
"successful, retry for the specified number of times",
},
{
.option = { "release", 0, NULL, 'r' },
.desc = "Release the specified lock file using the parent "
"process id",
},
{
.option = { "lock-and-release", required_argument, NULL, 'L' },
.argument = "RETRIES",
.desc = "Acquire the specified file lock using this process "
"id, then release it. If not immediately successful, "
"retry for the specified number of times.",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
enum prg_action {
ACTION_NONE = 0,
ACTION_LOCK,
ACTION_RELEASE,
ACTION_LOCK_AND_RELEASE,
};
static void print_single_action_error(void)
{
warnx("Only a single action (--lock, --lock-parent, --release, "
"--release-parent) is allowed");
}
int main(int argc, char *argv[])
{
enum prg_action action_id = ACTION_NONE;
int opt, rc, retries = 0;
char *endp, *path = NULL;
util_prg_init(&prg);
util_opt_init(opt_vec, NULL);
while (1) {
opt = util_opt_getopt_long(argc, argv);
if (opt == -1)
break;
switch (opt) {
case 'f':
path = optarg;
break;
case 'L':
if (action_id != ACTION_NONE) {
print_single_action_error();
return EXIT_FAILURE;
}
retries = strtol(optarg, &endp, 0);
if (*optarg == '\0' || *endp != '\0' || retries < 0) {
warnx("Invalid retry value for "
"--lock-and-release: '%s'",
optarg);
util_prg_print_parse_error();
return EXIT_FAILURE;
}
action_id = ACTION_LOCK_AND_RELEASE;
break;
case 'l':
if (action_id != ACTION_NONE) {
print_single_action_error();
return EXIT_FAILURE;
}
retries = strtol(optarg, &endp, 0);
if (*optarg == '\0' || *endp != '\0' || retries < 0) {
warnx("Invalid retry value for "
"--parent-lock: '%s'",
optarg);
util_prg_print_parse_error();
return EXIT_FAILURE;
}
action_id = ACTION_LOCK;
break;
case 'r':
if (action_id != ACTION_NONE) {
print_single_action_error();
return EXIT_FAILURE;
}
action_id = ACTION_RELEASE;
break;
case 'h':
util_prg_print_help();
util_opt_print_help();
exit(EXIT_SUCCESS);
case 'v':
util_prg_print_version();
exit(EXIT_SUCCESS);
default:
util_opt_print_parse_error(opt, argv);
return EXIT_FAILURE;
}
}
if (!path) {
warnx("--file is required, see --help for more information");
return EXIT_FAILURE;
}
if (action_id == ACTION_NONE) {
warnx("One of the following actions must be specified: "
"--lock, --release, --lock-and-release");
return EXIT_FAILURE;
}
/* Determine which util_lockfile function to call */
switch (action_id) {
case ACTION_LOCK:
rc = util_lockfile_parent_lock(path, retries);
switch (rc) {
case UTIL_LOCKFILE_OK:
printf("lock acquired successfully\n");
break;
case UTIL_LOCKFILE_LOCK_FAIL:
warnx("lock was not acquired; already held");
return EXIT_FAILURE;
case UTIL_LOCKFILE_ERR:
warnx("lock was not acquired; file error");
return EXIT_FAILURE;
default:
warnx("Unknown util_lockfile rc %d", rc);
return EXIT_FAILURE;
}
break;
case ACTION_RELEASE:
rc = util_lockfile_parent_release(path);
switch (rc) {
case UTIL_LOCKFILE_OK:
printf("lock released successfully\n");
break;
case UTIL_LOCKFILE_RELEASE_NONE:
warnx("lock file did not exist");
return EXIT_FAILURE;
case UTIL_LOCKFILE_RELEASE_FAIL:
warnx("lock was not held by the specified pid");
return EXIT_FAILURE;
case UTIL_LOCKFILE_ERR:
warnx("lock was not released; file error");
return EXIT_FAILURE;
default:
warnx("Unknown util_lockfile rc %d", rc);
return EXIT_FAILURE;
}
break;
case ACTION_LOCK_AND_RELEASE:
rc = util_lockfile_lock(path, retries);
switch (rc) {
case UTIL_LOCKFILE_OK:
printf("lock acquired successfully, holding for 2 seconds\n");
break;
case UTIL_LOCKFILE_LOCK_FAIL:
warnx("lock was not acquired; already held");
return EXIT_FAILURE;
case UTIL_LOCKFILE_ERR:
warnx("lock was not acquired; file error");
return EXIT_FAILURE;
default:
warnx("Unknown util_lockfile rc %d", rc);
return EXIT_FAILURE;
}
/* Briefly sleep while holding the lock */
sleep(2);
rc = util_lockfile_release(path);
switch (rc) {
case UTIL_LOCKFILE_OK:
printf("lock released successfully\n");
break;
case UTIL_LOCKFILE_RELEASE_NONE:
warnx("lock file did not exist");
return EXIT_FAILURE;
case UTIL_LOCKFILE_RELEASE_FAIL:
warnx("lock was not held by the specified pid");
return EXIT_FAILURE;
case UTIL_LOCKFILE_ERR:
warnx("lock was not released; file error");
return EXIT_FAILURE;
default:
warnx("Unknown util_lockfile rc %d", rc);
return EXIT_FAILURE;
}
break;
default:
warnx("Unknown util_lockfile action");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
//! [code]

View File

@@ -22,7 +22,7 @@
/*
* Obtain a backtrace and print it to stderr
*
* To get symbols, compile the code with "-rdynamic".
* To get symbols, link the code with "-rdynamic".
*/
static void print_backtrace(void)
{

View File

@@ -50,6 +50,7 @@ public:
RegisterSet64 getRegisterSet(int cpu);
void addRegisterSet(const RegisterSet64&);
inline int getNumCpus(void) const { return nrCpus; }
RegisterContent64& operator=(const RegisterContent64&) = default;
RegisterSet64 regSets[MAX_CPUS];
private:
@@ -64,6 +65,7 @@ public:
RegisterSet32 getRegisterSet(int cpu);
void addRegisterSet(const RegisterSet32&);
inline int getNumCpus(void) const { return nrCpus; }
RegisterContent32& operator=(const RegisterContent32&) = default;
RegisterSet32 regSets[MAX_CPUS];
private:

View File

@@ -1419,7 +1419,6 @@ int lzds_dasd_read_rawvtoc(struct dasd *dasd, struct raw_vtoc *rawvtoc)
volume_label_t *vlabel = NULL;
char *trackdata = NULL;
char vol1[] = {0xe5, 0xd6, 0xd3, 0xf1, 0x00}; /* "VOL1" in EBCDIC */
errorlog_clear(dasd->log);
@@ -1431,8 +1430,7 @@ int lzds_dasd_read_rawvtoc(struct dasd *dasd, struct raw_vtoc *rawvtoc)
goto cleanup;
}
/* verify that we have a proper VOL1 label */
if (strncmp(vlabel->volkey, vol1, 4) ||
strncmp(vlabel->vollbl, vol1, 4)) {
if (!is_vol1(vlabel->volkey) || !is_vol1(vlabel->vollbl)) {
rc = EINVAL;
errorlog_add_message(
&dasd->log, NULL, rc,

View File

@@ -1,5 +1,7 @@
include ../common.mak
ALL_CFLAGS += -Wno-address-of-packed-member
all: mon_fsstatd mon_procd
mon_fsstatd: mon_fsstatd.o

View File

@@ -248,7 +248,7 @@ static void count_users(void)
proc_sum.users = 0;
setutent();
while ((temp = getutent())) {
if ((temp->ut_type == USER_PROCESS) && (temp->ut_name))
if (temp->ut_type == USER_PROCESS)
proc_sum.users++;
}
endutent();
@@ -859,8 +859,6 @@ static void read_tasks(void)
}
while ((entry = readdir(proc_dir))) {
if (!entry->d_name)
break;
if (!isdigit(entry->d_name[0]) || !atoi(entry->d_name))
continue;
memset(&task, 0, sizeof(struct task_t));

View File

@@ -9,16 +9,22 @@
\fBpvattest [OPTION?] create [OPTIONS] \fP- create an attestation measurement request
\fB
.SH DESCRIPTION
Prepare attestation measurement requests for an IBM Secure Execution guest. Only prepare attestation requests in a trusted environment, such as your workstation. The 'pvattest create' command creates a randomly generated key to protect the attestation request. This key is only valid for this specific request.In order to avoid compromising the attestation, do not publish the protection key and delete it after verification. Every 'create' command generates a new, random protection key.
Prepare attestation measurement requests for an IBM Secure Execution guest.
Only prepare attestation requests in a trusted environment, such as your workstation.
The 'pvattest create' command creates a randomly generated key to protect the attestation request.
This key is only valid for this specific request. In order to avoid compromising the attestation,
do not publish the protection key and delete it after verification.
Every 'create' command generates a new, random protection key.
.SH OPTIONS
.TP
.B
\fB-h\fP, \fB--help\fP
Show help options
Prints usage information, then exits.
.TP
.B
\fB-k\fP, \fB--host-key-document\fP=\fBFILE\fP
Specify one or more host key documents.
Specify one or more host key documents. At least one is required.
Specify this option multiple times to create an attestation request control block that is usable on multiple hosts.
.TP
.B
\fB-C\fP, \fB--cert\fP=\fBFILE\fP
@@ -26,11 +32,14 @@ Specifies the certificate that is used to establish a chain of trust for the v
.TP
.B
\fB--crl\fP=\fBFILE\fP
Specify \fBFILE\fP to be a certificate revocation list (optional).
Specifies the revocation list that is used to check whether a certificate of the chain of trust is
revoked. Specify this option multiple times to use multiple CRLs (optional).
.TP
.B
\fB--root-ca\fP=\fBFILE\fP
Use \fBFILE\fP as the trusted root CA instead the root CAs that are installed on the system (optional).
Specifies the root CA certificate for the verification. If omitted,
the system wide root CAs installed on the system are used. Use
this only if you trust the specified certificate. Optional.
.TP
.B
\fB-o\fP, \fB--output\fP=\fBFILE\fP
@@ -42,15 +51,16 @@ Save the protection key as GCM-AES256 key in \fBFILE\fP Do not publish this key,
.TP
.B
\fB--no-verify\fP
Disable the host-key-document verification. Does not require the host-key documents to be valid. For testing purposes, do not use for a production image. (Optional)
Disable the host-key document verification. Does not require the host-key documents to be valid. Do
not use for a production request unless you verified the host-key document before (optional).
.TP
.B
\fB--offline\fP
Don't download CRLs (optional).
Specifies offline mode, in which no attempt is made to download CRLs. (optional).
.TP
.B
\fB-V\fP, \fB--verbose\fP
Provide more detailed output (optional)
Provide more detailed output (optional).
.SH EXAMPLE
Create an attestation request with the protection key 'arp.key', write the request to 'arcb.bin', and verify the host-key document using the CA-signed key 'DigiCertCA.crt' and the intermediate key 'IbmSigningKey.crt'.
.PP

View File

@@ -9,7 +9,10 @@
\fBpvattest [OPTION?] perform [OPTIONS] \fP- execute an attestation measurement request
\fB
.SH DESCRIPTION
Run a measurement of this system using '/dev/uv'. Works only if this device is available and the attestation Ultravisor facility is present. The input must be an attestation request created with 'pvattest create'. Output will contain the original request, the attestation measurement result, the configuration UID, and if requested in the request Additional Data.
Run a measurement of this system using '/dev/uv'. Works only if this device is
available and the attestation Ultravisor facility is present.
The input must be an attestation request created with 'pvattest create'.
Output will contain the original request and the response from the Ultravisor.
.RE
.PP

View File

@@ -4,12 +4,11 @@ BIN_PROGRAM = pvattest
PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/$(BIN_PROGRAM)"
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
ROOT_DIR = $(rootdir)
PVATTESTDIR := $(ROOT_DIR)/pvattest
INCLUDE_PATHS = "$(SRC_DIR)" "$(ROOT_DIR)/include"
PVATTESTDIR := $(rootdir)/pvattest
INCLUDE_PATHS = "$(SRC_DIR)" "$(rootdir)/include"
INCLUDE_PARMS = $(addprefix -I,$(INCLUDE_PATHS))
LIBPV_DIR = $(ROOT_DIR)/libpv
LIBPV_DIR = $(rootdir)/libpv
LIBPV = $(LIBPV_DIR)/libpv.a
WARNINGS := -Wall -Wextra -Wshadow \
@@ -73,7 +72,7 @@ endif
endif
endif
all: $(BUILD_TARGETS) .check-dep-$(BIN_PROGRAM)
all: $(BUILD_TARGETS)
install: $(INSTALL_TARGETS)
@@ -97,7 +96,7 @@ $($(BIN_PROGRAM)_OBJS): .check-dep-$(BIN_PROGRAM)
.detect-openssl.dep.c:
echo "#include <openssl/evp.h>" > $@
echo "#if OPENSSL_VERSION_NUMBER < 0x10101000L" >> $@
echo " #error openssl version 1.1.0 is required" >> $@
echo " #error openssl version 1.1.1 is required" >> $@
echo "#endif" >> $@
echo "static void __attribute__((unused)) test(void) {" >> $@
echo " EVP_MD_CTX *ctx = EVP_MD_CTX_new();" >> $@
@@ -112,8 +111,8 @@ $($(BIN_PROGRAM)_OBJS): .check-dep-$(BIN_PROGRAM)
"HAVE_GLIB2=0")
$(call check_dep, \
"$(BIN_PROGRAM)", \
"openssl/evp.h", \
"openssl-devel / libssl-dev version >= 1.1.0", \
$^, \
"openssl-devel / libssl-dev version >= 1.1.1", \
"HAVE_OPENSSL=0", \
"-I.")
$(call check_dep, \

View File

@@ -171,9 +171,9 @@ int arcb_v1_add_key_slot(arcb_v1_t *arcb, EVP_PKEY *evp_host, GError **error)
g_assert(g_bytes_get_size(phkh) == sizeof(key_slot->phkh));
key_slot = g_malloc0(sizeof(*key_slot));
pv_gbytes_memcpy(key_slot->warpk, sizeof(key_slot->warpk), warpk);
pv_gbytes_memcpy(key_slot->kst, sizeof(key_slot->warpk), tag);
pv_gbytes_memcpy(key_slot->phkh, sizeof(key_slot->warpk), phkh);
pv_gbytes_memcpy(key_slot->warpk, sizeof(key_slot->warpk), warpk, NULL);
pv_gbytes_memcpy(key_slot->kst, sizeof(key_slot->warpk), tag, NULL);
pv_gbytes_memcpy(key_slot->phkh, sizeof(key_slot->warpk), phkh, NULL);
arcb->host_key_slots = g_slist_prepend(arcb->host_key_slots, g_steal_pointer(&key_slot));
return 0;
@@ -246,7 +246,7 @@ GBytes *arcb_v1_serialize(const arcb_v1_t *arcb, GError **error)
/* copy plain data to contiguous memory */
hdr.arl = GUINT32_TO_BE((uint32_t)att_req_len);
pv_gbytes_memcpy(hdr.iv, ARCB_V1_IV_SIZE, arcb->iv);
pv_gbytes_memcpy(hdr.iv, ARCB_V1_IV_SIZE, arcb->iv, NULL);
hdr.nks = (uint8_t)nks;
hdr.sea = GUINT32_TO_BE((uint32_t)sea);
ecdh_cpk = pv_evp_pkey_to_ecdh_pub_key(arcb->evp_cust_pub_key, error);

View File

@@ -15,6 +15,7 @@
#include "lib/zt_common.h"
#include "libpv/crypto.h"
#include "libpv/macros.h"
#include "types.h"
@@ -28,18 +29,17 @@
#define ARCB_V1_IV_SIZE 12
#define ARCB_V1_PHKH_SIZE 32
#define BIT(bit) ((uint64_t)1 << (63 - (bit)))
/* Optional nonce in ARCB */
#define ARCB_V1_PAF_NONCE BIT(1)
#define ARCB_V1_PAF_NONCE PV_MSB(1)
/* Public host key hash used to unseal SE header added to additional data to be measured */
#define ARCB_V1_PAF_AAD_PHKH_HEADER BIT(2)
#define ARCB_V1_PAF_AAD_PHKH_HEADER PV_MSB(2)
/* Public host key hash used to unseal this attestation added to additional data to be measured */
#define ARCB_V1_PAF_AAD_PHKH_ATTEST BIT(3)
#define ARCB_V1_PAF_AAD_PHKH_ATTEST PV_MSB(3)
/* Temporary backup-host-key use allowed */
#define ARCB_V1_PAF_TMP_BACKUP_ALLOWED BIT(62)
#define ARCB_V1_PAF_TMP_BACKUP_ALLOWED PV_MSB(62)
/* Global not-host-specific key allowed */
#define ARCB_V1_PAF_GLOBAL_NHS_KEY_ALLOWED BIT(63)
#define ARCB_V1_PAF_GLOBAL_NHS_KEY_ALLOWED PV_MSB(63)
#define ARCB_V1_PAF_ALL \
(ARCB_V1_PAF_NONCE | ARCB_V1_PAF_AAD_PHKH_HEADER | ARCB_V1_PAF_AAD_PHKH_ATTEST | \

View File

@@ -156,76 +156,75 @@ static gboolean hex_str_toull(const char *nptr, uint64_t *dst, GError **error)
/************************* SHARED OPTIONS *************************************/
/* NOTE REQUIRED */
#define _entry_host_key_document(__arg_data, __indent) \
{ \
.long_name = "host-key-document", .short_name = 'k', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "Specify one or more host key documents.\n", \
.arg_description = "FILE", \
#define _entry_host_key_document(__arg_data, __indent) \
{ \
.long_name = "host-key-document", .short_name = 'k', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = \
"FILE specifies a host-key document. At least one is required.\n" __indent \
"Specify this option multiple times to enable the request for\n" __indent \
"more than one host.\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_certs(__arg_data, __indent) \
{ \
.long_name = "cert", .short_name = 'C', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = \
"Specifies the certificate that is used to establish a chain\n" __indent \
"of trust for the verification of the host-key documents. Specify\n" __indent \
"this option twice to specify the IBM Z signing key and the\n" __indent \
"intermediate CA certificate (signed by the root CA). Required.\n" __indent \
"Ignored when --no-verify is specified.\n", \
.arg_description = "FILE", \
#define _entry_certs(__arg_data, __indent) \
{ \
.long_name = "cert", .short_name = 'C', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "FILE contains a certificate that is used to\n" __indent \
"establish a chain of trust for the verification\n" __indent \
"of the host-key documents. The IBM Z signing\n" __indent \
"key and intermediate CA certificate (signed\n" __indent \
"by the root CA) are required.\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_crls(__arg_data, __indent) \
{ \
.long_name = "crl", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "Specify FILE to be a certificate revocation list\n" __indent \
"(optional).", \
.arg_description = "FILE", \
#define _entry_crls(__arg_data, __indent) \
{ \
.long_name = "crl", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "FILE contains a certificate revocation list (optional).\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_root_ca(__arg_data, __indent) \
{ \
.long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "Use FILE as the trusted root CA instead the\n" __indent \
"root CAs that are installed on the system (optional).", \
.arg_description = "FILE", \
#define _entry_root_ca(__arg_data, __indent) \
{ \
.long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "Use FILE as the trusted root CA instead the\n" __indent \
"root CAs that are installed on the system (optional).\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_guest_hdr(__arg_data, __indent) \
{ \
.long_name = "hdr", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = \
"Specify the header of the guest image. Exactly one is required.\n", \
.arg_description = "FILE", \
#define _entry_guest_hdr(__arg_data, __indent) \
{ \
.long_name = "hdr", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "FILE specifies the header of the guest image.\n" __indent \
"Exactly one is required.\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_input(__arg_data, __additional_text, __indent) \
{ \
.long_name = "input", .short_name = 'i', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "FILE specifies the " __additional_text "\n" __indent \
" as input.\n", \
.arg_description = "FILE", \
#define _entry_input(__arg_data, __additional_text, __indent) \
{ \
.long_name = "input", .short_name = 'i', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "FILE specifies the " __additional_text " as input.\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
#define _entry_output(__arg_data, __additional_text, __indent) \
{ \
.long_name = "output", .short_name = 'o', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "FILE specifies the output for the\n" __indent __additional_text \
".\n", \
.arg_description = "FILE", \
#define _entry_output(__arg_data, __additional_text, __indent) \
{ \
.long_name = "output", .short_name = 'o', .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "FILE specifies the output for the " __additional_text "\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */
@@ -254,7 +253,7 @@ static gboolean hex_str_toull(const char *nptr, uint64_t *dst, GError **error)
{ \
.long_name = "x-phkh-img", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_NONE, .arg_data = __arg_data, \
.description = "add the public host key hash of the\n" __indent \
.description = "Add the public host key hash of the\n" __indent \
"image header used to decrypt\n" __indent \
"the secure guest to the measurement. (optional)\n" \
}
@@ -263,34 +262,31 @@ static gboolean hex_str_toull(const char *nptr, uint64_t *dst, GError **error)
{ \
.long_name = "x-phkh-att", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_NONE, .arg_data = __arg_data, \
.description = "add the public host key hash of the\n" __indent \
.description = "Add the public host key hash of the\n" __indent \
"attestation header used to decrypt\n" __indent \
"the attestation request to the measurement. (optional)\n" \
}
#define _entry_no_verify(__arg_data, __indent) \
{ \
.long_name = "no-verify", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_NONE, .arg_data = __arg_data, \
.description = \
"Disable the host-key-document verification.\n" __indent \
"Does not require the host-key documents to be valid.\n" __indent \
"For testing purposes, do not use for a production image.\n" __indent \
"(optional)\n", \
#define _entry_no_verify(__arg_data, __indent) \
{ \
.long_name = "no-verify", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_NONE, .arg_data = __arg_data, \
.description = "Disable the host-key document verification.\n" __indent \
"(optional)\n", \
}
#define _entry_offline_maps_to_online(__arg_data, __indent) \
{ \
.long_name = "offline", .short_name = 0, .flags = G_OPTION_FLAG_REVERSE, \
.arg = G_OPTION_ARG_NONE, .arg_data = __arg_data, \
.description = "Don't download CRLs (optional).\n", \
.description = "Don't download CRLs. (optional)\n", \
}
#define _entry_verbose(__indent) \
{ \
.long_name = "verbose", .short_name = 'V', .flags = G_OPTION_FLAG_NO_ARG, \
.arg = G_OPTION_ARG_CALLBACK, .arg_data = &increase_log_lvl, \
.description = "Provide more detailed output (optional)\n", \
.description = "Provide more detailed output. (optional)\n", \
.arg_description = NULL, \
}

View File

@@ -130,7 +130,7 @@ void att_add_uid(att_meas_ctx_t *meas_ctx, GBytes *config_uid)
pv_wrapped_g_assert(config_uid);
g_assert(g_bytes_get_size(config_uid) == ATT_CONFIG_UID_SIZE);
pv_gbytes_memcpy(meas_ctx->config_uid, ATT_CONFIG_UID_SIZE, config_uid);
pv_gbytes_memcpy(meas_ctx->config_uid, ATT_CONFIG_UID_SIZE, config_uid, NULL);
}
gboolean att_verify_measurement(const GBytes *calculated_measurement,

View File

@@ -11,7 +11,7 @@
/* Must be included before any other header */
#include "config.h"
#include <glib/gi18n-lib.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include "libpv/glib-helper.h"

View File

@@ -191,7 +191,7 @@ exchange_format_ctx_t *exchange_ctx_from_file(const char *filename, GError **err
}
ctx->req_meas_size = GUINT32_FROM_BE(hdr_v1->measurement.size);
ctx->req_add_size = GUINT32_FROM_BE(hdr_v1->additional_data.size);
ctx->version = GUINT32_TO_BE(hdr->version);
ctx->version = GUINT32_FROM_BE(hdr->version);
return g_steal_pointer(&ctx);
}
@@ -455,8 +455,8 @@ static void print_entry(const char *name, GBytes *data, const gboolean print_dat
fprintf(stream, _("%s (%#lx bytes)"), name, g_bytes_get_size(data));
if (print_data) {
fprintf(stream, ":\n");
printf_hexdump(g_bytes_get_data(data, NULL), g_bytes_get_size(data), 16, " ",
stream);
pvattest_hexdump(g_bytes_get_data(data, NULL), g_bytes_get_size(data), 16, " ",
stream);
}
fprintf(stream, "\n");
}

View File

@@ -131,26 +131,35 @@ void pvattest_log_plain_logger(const char *log_domain G_GNUC_UNUSED, GLogLevelFl
_log_logger(level, message, log_level, FALSE, "");
}
void hexdump(const void *data, size_t size, size_t len, const char *prefix, GLogLevelFlags log_lvl)
void pvattest_log_bytes(const void *data, size_t size, size_t width, const char *prefix,
gboolean beautify, GLogLevelFlags log_lvl)
{
const uint8_t *data_b = data;
pv_wrapped_g_assert(data);
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, log_lvl, "%s0x0000 ", prefix);
if (beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%s0x0000 ", prefix);
else
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%s", prefix);
for (size_t i = 0; i < size; i++) {
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, log_lvl, "%02x", data_b[i]);
if (i % 2 == 1)
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, log_lvl, " ");
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "%02x", data_b[i]);
if (i % 2 == 1 && beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, " ");
if (i == size - 1)
break;
if (i % len == len - 1)
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, log_lvl, "\n%s0x%04lx ", prefix, i + 1);
if (i % width == width - 1) {
if (beautify)
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n%s0x%04lx ", prefix,
i + 1);
else
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n%s", prefix);
}
}
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, log_lvl, "\n");
g_log(PVATTEST_BYTES_LOG_DOMAIN, log_lvl, "\n");
}
void printf_hexdump(const void *data, size_t size, size_t len, const char *prefix, FILE *stream)
void pvattest_hexdump(const void *data, size_t size, size_t width, const char *prefix, FILE *stream)
{
const uint8_t *data_b = data;
@@ -164,7 +173,7 @@ void printf_hexdump(const void *data, size_t size, size_t len, const char *prefi
fprintf(stream, " ");
if (i == size - 1)
break;
if (i % len == len - 1)
if (i % width == width - 1)
fprintf(stream, "\n%s0x%04lx ", prefix, i + 1);
}
fprintf(stream, "\n");

View File

@@ -23,7 +23,7 @@
#define PVATTEST_LOG_LVL_DEFAULT PVATTEST_LOG_LVL_WARNING
#define PVATTEST_LOG_LVL_MAX PVATTEST_LOG_LVL_DEBUG
#define PVATTEST_HEXDUMP_LOG_DOMAIN "pvattest_hdump"
#define PVATTEST_BYTES_LOG_DOMAIN "pvattest_bytes"
void pvattest_log_increase_log_lvl(int *log_lvl);
void pvattest_log_error(const char *format, ...);
@@ -45,22 +45,22 @@ void pvattest_log_default_logger(const char *log_domain, GLogLevelFlags level, c
*/
void pvattest_log_plain_logger(const char *log_domain, GLogLevelFlags level, const char *message,
void *user_data);
#define dhexdump(v, s) \
{ \
pvattest_log_debug("%s (%li byte):", #v, s); \
hexdump(v, s, 16L, " ", PVATTEST_LOG_LVL_DEBUG); \
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, PVATTEST_LOG_LVL_DEBUG, "\n"); \
}
#define gbhexdump(v) \
#define dhexdump(v, s) \
{ \
pvattest_log_debug("%s:(%li byte):", #v, g_bytes_get_size(v)); \
hexdump(g_bytes_get_data(v, NULL), g_bytes_get_size(v), 16L, " ", \
PVATTEST_LOG_LVL_DEBUG); \
g_log(PVATTEST_HEXDUMP_LOG_DOMAIN, PVATTEST_LOG_LVL_DEBUG, "\n"); \
pvattest_log_debug("%s (%li byte):", #v, s); \
pvattest_log_bytes(v, s, 16L, " ", TRUE, PVATTEST_LOG_LVL_DEBUG); \
g_log(PVATTEST_BYTES_LOG_DOMAIN, PVATTEST_LOG_LVL_DEBUG, "\n"); \
}
void hexdump(const void *data, size_t size, size_t len, const char *prefix, GLogLevelFlags log_lvl)
PV_NONNULL(1);
void printf_hexdump(const void *data, size_t size, size_t len, const char *prefix, FILE *stream)
#define gbhexdump(v) \
{ \
pvattest_log_debug("%s:(%li byte):", #v, g_bytes_get_size(v)); \
pvattest_log_bytes(g_bytes_get_data(v, NULL), g_bytes_get_size(v), 16L, " ", \
TRUE, PVATTEST_LOG_LVL_DEBUG); \
g_log(PVATTEST_BYTES_LOG_DOMAIN, PVATTEST_LOG_LVL_DEBUG, "\n"); \
}
void pvattest_log_bytes(const void *data, size_t size, size_t width, const char *prefix,
gboolean beautify, GLogLevelFlags log_lvl) PV_NONNULL(1);
void pvattest_hexdump(const void *data, size_t size, size_t width, const char *prefix, FILE *stream)
PV_NONNULL(1, 5);
void pvattest_log_GError(const char *info, GError *error) PV_NONNULL(1);

View File

@@ -322,8 +322,17 @@ static int do_verify(pvattest_verify_config_t *verify_config)
return PVATTEST_EXIT_MEASURE_NOT_VERIFIED;
}
pvattest_log_debug(_("Measurement verified."));
pvattest_log_info(_("Attestation measurement verified"));
pvattest_log_info(_("Config UID:"));
pvattest_log_bytes(g_bytes_get_data(config_uid, NULL), g_bytes_get_size(config_uid), 16L,
"", FALSE, PVATTEST_LOG_LVL_INFO);
if (additional_data) {
pvattest_log_info(_("\nAdditional Data:"));
pvattest_log_bytes(g_bytes_get_data(additional_data, NULL),
g_bytes_get_size(additional_data), 16L, "", FALSE,
PVATTEST_LOG_LVL_INFO);
}
return EXIT_SUCCESS;
err_exit:
@@ -355,7 +364,7 @@ int main(int argc, char *argv[])
* message)to filter messages based on the log level specified by the
* user.
*/
g_log_set_handler(PVATTEST_HEXDUMP_LOG_DOMAIN,
g_log_set_handler(PVATTEST_BYTES_LOG_DOMAIN,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
&pvattest_log_plain_logger, &appl_log_lvl);

View File

@@ -9,6 +9,7 @@
*/
/* Must be included before any other header */
#include "config.h"
#include "lib/zt_common.h"
#ifdef PVATTEST_COMPILE_PERFORM
#include <stdio.h>
@@ -42,26 +43,29 @@ uvio_attest_t *build_attestation_v1_ioctl(GBytes *serialized_arcb, GBytes *user_
uvio_attest = g_malloc0(sizeof(*uvio_attest));
uvio_attest->arcb_addr = PTR_TO_U64(g_steal_pointer(&arcb));
g_assert_cmpuint(arcb_size, <, UINT32_MAX);
uvio_attest->arcb_len = GUINT32_TO_BE((uint32_t)arcb_size);
uvio_attest->arcb_len = (uint32_t)arcb_size;
/* transferred the local ownership of the arcb from this function to uvio_attest; nullify pointer */
g_steal_pointer(&serialized_arcb);
if (user_data) {
if (g_bytes_get_size(user_data) > sizeof(uvio_attest->user_data)) {
size_t copied_data_size;
if (pv_gbytes_memcpy(uvio_attest->user_data, sizeof(uvio_attest->user_data),
user_data, &copied_data_size) == NULL) {
g_set_error(error, ATT_ERROR, ATT_ERR_INVALID_USER_DATA,
_("User data larger than %li bytes"),
sizeof(uvio_attest->user_data));
_("User data %li bytes is larger than %li bytes"),
g_bytes_get_size(user_data), sizeof(uvio_attest->user_data));
return NULL;
}
uvio_attest->user_data_len = GUINT16_TO_BE((uint16_t)g_bytes_get_size(user_data));
pv_gbytes_memcpy(uvio_attest->user_data, uvio_attest->user_data_len, user_data);
STATIC_ASSERT(sizeof(uvio_attest->user_data) <= UINT16_MAX);
uvio_attest->user_data_len = (uint16_t)copied_data_size;
}
uvio_attest->meas_len = GUINT32_TO_BE(measurement_size);
uvio_attest->meas_addr = PTR_TO_U64(g_malloc0(uvio_attest->meas_len));
uvio_attest->meas_addr = PTR_TO_U64(g_malloc0(measurement_size));
uvio_attest->meas_len = measurement_size;
uvio_attest->add_data_len = GUINT32_TO_BE(add_data_size);
uvio_attest->add_data_addr = PTR_TO_U64(g_malloc0(uvio_attest->add_data_len));
uvio_attest->add_data_addr = PTR_TO_U64(g_malloc0(add_data_size));
uvio_attest->add_data_len = add_data_size;
return g_steal_pointer(&uvio_attest);
}
@@ -83,7 +87,7 @@ GBytes *uvio_get_measurement(const uvio_attest_t *attest)
if (attest->meas_addr == (__u64)0)
return NULL;
return g_bytes_new(U64_TO_PTR(attest->meas_addr), GUINT32_FROM_BE(attest->meas_len));
return g_bytes_new(U64_TO_PTR(attest->meas_addr), attest->meas_len);
}
GBytes *uvio_get_additional_data(const uvio_attest_t *attest)
@@ -92,8 +96,7 @@ GBytes *uvio_get_additional_data(const uvio_attest_t *attest)
if (attest->add_data_addr == (__u64)0)
return NULL;
return g_bytes_new(U64_TO_PTR(attest->add_data_addr),
GUINT32_FROM_BE(attest->add_data_len));
return g_bytes_new(U64_TO_PTR(attest->add_data_addr), attest->add_data_len);
}
GBytes *uvio_get_config_uid(const uvio_attest_t *attest)
@@ -127,7 +130,7 @@ uint16_t uvio_ioctl(const int uv_fd, const unsigned int cmd, const uint32_t flag
g_set_error(error, UVIO_ERROR, UVIO_ERR_UV_NOT_OK,
_("Ultravisor call returned '%#x' (%s)"), uv_ioctl->uv_rc,
uvio_uv_rc_to_str(uv_ioctl->uv_rc));
return GUINT16_FROM_BE(uv_ioctl->uv_rc);
return uv_ioctl->uv_rc;
}
uint16_t uvio_ioctl_attest(const int uv_fd, uvio_attest_t *attest, GError **error)
@@ -156,6 +159,8 @@ int uvio_open(const char *uv_path, GError **error)
const char *uvio_uv_rc_to_str(const int rc)
{
switch (rc) {
case 0x02:
return _("Invalid UV command");
case 0x106:
return _("Unsupported attestation request version");
case 0x108:

94
pvattest/tools/pvattest-info Executable file
View File

@@ -0,0 +1,94 @@
#!/bin/bash
#
# pvattest-info - get additional information from an attestation measurement
#
# Sample:
# ./pvattest-info attestresp.bin
#
# Copyright IBM Corp. 2022
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
set -o pipefail
set -o nounset
set -e
XDUMP='od -A x -t x2z -v'
usage() {
cat <<-EOF
Usage: $(basename "$0") FILE
Prints config UID and additional data if available.
EOF
}
function check_is_pvattest_binary() {
local input="$1"
local size
local version
size=$(wc -c <"$input")
if [ "$size" -lt 64 ]; then
echo "ERROR: Input file is too small." >&2
exit 1
fi
${XDUMP} --read-bytes 16 -- "${input}" 2>/dev/null | grep -q pvattest ||
{ echo "ERROR: ${input} does not contain a pvattest binary output." >&2 && exit 1; }
size=$(${XDUMP} --skip-bytes 12 --read-bytes 4 -- "${input}" 2>/dev/null | awk 'NR==1 {print "0x" $2 $3}')
if [ $((size)) -lt 64 ]; then
echo "ERROR: ${input} does not contain a pvattest binary output." >&2
exit 1
fi
version=$(${XDUMP} --skip-bytes 8 --read-bytes 4 -- "$input" 2>/dev/null)
echo "$version" | grep -q "0000 0100" ||
{ echo -n "WARNING: unknown hdr version " >&2 &&
echo "$version" | awk '{print "0x" $2 $3}'>&2 ; }
}
function print_entry() {
local file_off="$1"
local text="$2"
local input="$3"
local size
local off
size=$(${XDUMP} --skip-bytes $((file_off)) --read-bytes 4 -- "${input}" 2>/dev/null |
awk 'NR==1 {print "0x" $2 $3}')
off=$(${XDUMP} --skip-bytes $((file_off + 4)) --read-bytes 4 -- "${input}" 2>/dev/null |
awk 'NR==1 {print "0x" $2 $3}')
if [[ $size != "0x00000000" ]] || [[ $off != "0x00000000" ]]; then
echo "${text}:"
od -A n -w$((size)) -t x8 --skip-bytes $((off)) --read-bytes $((size)) -- "${input}" 2>/dev/null |\
sed -e 's/\s//g'
fi
}
function require_command() {
local cmd="$1"
command -v "$cmd" >/dev/null 2>&1 || \
{ echo >&2 "ERROR: $cmd required but not installed."; exit 1; }
}
require_command awk
require_command wc
require_command od
if [ $# -eq 0 ]; then
echo "ERROR: Input not set. Use '$(basename "$0") [FILE]' to specify the Input file" >&2
exit 1
fi
input="$1"
[ -e "$input" ] || { echo "ERROR: File '$1' not found" >&2 && exit 1; }
check_is_pvattest_binary "$input"
print_entry 0x38 "Config UID" "$input"
print_entry 0x28 "Additional Data" "$input"

View File

@@ -14,7 +14,9 @@ set -o pipefail
set -o nounset
set -e
def_output="sehdr.bin"
XDUMP='od -A x -t x2z -v'
def_output='sehdr.bin'
def_skip=0x14
def_len=0x4
@@ -37,11 +39,22 @@ function check_file() {
function check_hdr_ver() {
local hdr_start="$1"
local input="$2"
xxd -s $((hdr_start + 8)) -l 4 "$input" | grep -q "000 0100" ||
${XDUMP} --skip-bytes $((hdr_start + 8)) --read-bytes 4 -- "$input" 2>/dev/null | grep -q "000 0100" ||
{ echo -n "WARNING: unknown hdr version " &&
xxd -s $((hdr_start + 8)) -l 4 "$input" | awk '{print "0x" $2 $3}'; }
${XDUMP} --skip-bytes $((hdr_start + 8)) --read_bytes 4 -- "$input" 2>/dev/null | awk '{print "0x" $2 $3}'; }
}
function require_command() {
local cmd="$1"
command -v "$cmd" >/dev/null 2>&1 || \
{ echo >&2 "ERROR: $cmd required but not installed."; exit 1; }
}
require_command od
require_command awk
require_command grep
output=${def_output}
parsed_skip=${def_skip}
parsed_len=${def_len}
@@ -77,13 +90,15 @@ if [ $# -eq 0 ]; then
fi
check_file "$input"
hdr_start=$(xxd -s $((skip)) -l $((len)) "${input}" | grep IBMSecEx || { echo ERROR: "${input} does not contain an SE header." >&2 && exit 1; })
hdr_start=$(${XDUMP} --skip-bytes $((skip)) --read-bytes $((len)) -- "${input}" 2>/dev/null | grep IBMSecEx ||
{ echo ERROR: "${input} does not contain an SE header." >&2 && exit 1; })
hdr_start=$(echo "${hdr_start}" | awk '{print "0x" $1}' | cut -c 1-10)
echo "SE header found at offset ${hdr_start}"
check_hdr_ver "$hdr_start" "$input"
size=$(xxd -s $((hdr_start + 12)) -l 4 "${input}" | awk 'NR==1 {print "0x" $2 $3}')
size=$(${XDUMP} --skip-bytes $((hdr_start + 12)) --read-bytes 4 -- "${input}" 2>/dev/null |
awk 'NR==1 {print "0x" $2 $3}')
dd if="${input}" of="${output}" bs=1 count=$((size)) skip=$((hdr_start)) status=none
echo "SE header written to '${output}' ($((size)) bytes)"

View File

@@ -17,7 +17,8 @@ export LC_ALL
readonly SCRIPTNAME="${0##*/}" # general name of this script
#
readonly DATETIME="$(date +%Y-%m-%d-%H-%M-%S 2>/dev/null)"
readonly DOCKER=$(if type -t docker >/dev/null; then echo "YES"; else echo "NO"; fi)
readonly DOCKER=$(if type docker >/dev/null 2>&1; then echo "YES"; else echo "NO"; fi)
readonly DUMP2TAR_OK=$(if type dump2tar >/dev/null 2>&1; then echo "YES"; else echo "NO"; fi)
readonly HW="$(uname -i 2>/dev/null)"
# retrieve and split kernel version
readonly KERNEL_BASE="$(uname -r 2>/dev/null)"
@@ -25,7 +26,9 @@ readonly KERNEL_VERSION=$(echo ${KERNEL_BASE} | cut -d'.' -f1 )
readonly KERNEL_MAJOR_REVISION=$(echo ${KERNEL_BASE} | cut -d'.' -f2 )
readonly KERNEL_MINOR_REVISION=$(echo ${KERNEL_BASE} | cut -d'.' -f3 | sed 's/[^0-9].*//g')
readonly KERNEL_INFO=${KERNEL_VERSION}.${KERNEL_MAJOR_REVISION}.${KERNEL_MINOR_REVISION}
readonly KVM=$(if type -t virsh >/dev/null; then echo "YES"; else echo "NO"; fi)
readonly KUBERNETES=$(if type kubectl >/dev/null 2>&1; then echo "YES"; else echo "NO"; fi)
readonly KUBERNETES_LOG_LINES=50
readonly KVM=$(if type virsh >/dev/null 2>&1; then echo "YES"; else echo "NO"; fi)
# The file to indicate that another instance of the script is already running
readonly LOCKFILE="/tmp/${SCRIPTNAME}.lock"
# check limits for logfiles like /var/log/messages
@@ -43,14 +46,20 @@ readonly PROCESSORVERSION="$(grep -E ".*processor 0:.*" /proc/cpuinfo | \
sed 's/.*version[[:space:]]*\=[[:space:]]*\([[:alnum:]]*\).*/\1/g')"
if test "x${PROCESSORVERSION}" = "xFF" || test "x${PROCESSORVERSION}" = "xff"; then
RUNTIME_ENVIRONMENT=$(grep -E "VM00.*Control Program.*" /proc/sysinfo | \
sed 's/.*:[[:space:]]*\([[:graph:]]*\).*/\1/g')
sed 's/.*:[[:space:]]*\([[:graph:]]*\).*/\1/g')
else
RUNTIME_ENVIRONMENT="LPAR"
fi
readonly SYSTEMHOSTNAME="$(hostname -s 2>/dev/null)" # hostname of system being analysed
readonly TERMINAL="$(tty 2>/dev/null)"
# The processor version for the first processor and resulting vitrtualization RUNTIME
readonly TOS=15 # timeout seconds for command execution
# timeout seconds TOS / kill timeout TOKS
readonly TOS=15
readonly TOKS=30
readonly TIMEOUT=$(if type timeout >/dev/null 2>&1; then echo "YES"; else echo "NO"; fi)
readonly TIMEOUT_OK=$(if test "x${TIMEOUT}" = "xYES"; then
if test $(timeout -k ${TOKS} ${TOS} uname 2>/dev/null) = $(uname); then
echo "YES"; else echo "WRONG_VERSION"; fi
else echo "NO"; fi)
readonly ZDEV_CONF=$(lszdev --configured 2>/dev/null | wc -l)
readonly ZDEV_OFF=$(lszdev --offline 2>/dev/null | wc -l)
readonly ZDEV_ONL=$(lszdev --online 2>/dev/null | wc -l)
@@ -79,7 +88,7 @@ This script collects runtime, configuration and trace information on
a Linux on IBM Z installation for debugging purposes.
It also traces information about z/VM if the Linux runs under z/VM.
KVM or DOCKER data ist collected on a host serving this.
Virtualization platform data is collected on a host serving this.
Default location for data collection and final tar file is "/tmp/".
The collected information is written to a TAR archive named
@@ -96,7 +105,7 @@ Options:
stores the temporary data and the final archive.
-h|--help print this help
-v|--version print version information
-c|--check online quick check (no data collection)
-c|--check online base system information (no data collection)
Please report bugs to: linux390@de.ibm.com
@@ -150,7 +159,7 @@ $(cat /proc/sysinfo | grep 'Name')
Kernel version = ${KERNEL_INFO}
OS version / distro = ${OS_NAME}
KVM host = ${KVM}
DOCKER host = ${DOCKER}
container host Kubernetes: ${KUBERNETES} - docker: ${DOCKER}
Current user = $(whoami) (must be root for data collection)
Date and time = $(date)
@@ -162,6 +171,9 @@ Log file check =$(logfile_checker "/var/log*")
Working directory = $(ls -d ${paramWORKDIR_BASE} 2>&1 && df -k ${paramWORKDIR_BASE})
$(ls -ltr ${paramWORKDIR_BASE}/DBGINFO*tgz 2>/dev/null | tail -2)
$(ls ${LOCKFILE} 2>/dev/null && echo " Warning: dbginfo running since: $(cat ${LOCKFILE})")
Tool/command dependency check successful:
timeout = ${TIMEOUT_OK}
dump2tar = ${DUMP2TAR_OK}
This is a console output only - no data was saved using option -c !
@@ -213,7 +225,8 @@ done
# finally verification to run as root
if test "$(/usr/bin/id -u 2>/dev/null)" -ne 0; then
echo "${SCRIPTNAME}: Error: You must be user root to run \"${SCRIPTNAME}\"!"
echo "${SCRIPTNAME}: Error: You must be user root to run data collection \"${SCRIPTNAME}\"!"
echo "${SCRIPTNAME}: Hint: for base system information you may run \"${SCRIPTNAME} -c\""
exit 1
fi
@@ -249,6 +262,7 @@ readonly OUTPUT_FILE_ISW="${WORKPATH}installed_sw.out"
readonly OUTPUT_FILE_TC="${WORKPATH}network.out"
readonly OUTPUT_FILE_VMCMD="${WORKPATH}zvm_runtime.out"
# Base file names for different output files - no extension !
readonly OUTPUT_FILE_KUBERNETES="${WORKPATH}kubernetes"
readonly OUTPUT_FILE_OSAOAT="${WORKPATH}network"
readonly OUTPUT_FILE_SYSFS="${WORKPATH}sysfs"
@@ -268,7 +282,7 @@ ALL_STEPS="\
collect_bridge\
collect_ovs\
collect_kvm\
collect_docker\
collect_container\
collect_nvme\
collect_logfiles\
post_processing\
@@ -329,14 +343,18 @@ fi
########################################
LOGFILES="\
/root/anaconda-ks.cfg\
/root/original-ks.cfg\
/run/containerd/events.log\
/run/docker/libcontainerd/containerd/events.log\
/run/udev/chreiplzfcpmp-[0-9][0-9][a-z][a-z][a-z][a-z]-*\
/var/log/anaconda\
/var/log/anaconda.*\
/var/log/audit\
/var/log/boot*\
/var/log/cron*\
/var/log/dmesg*\
/var/log/dnf.*\
/var/log/dracut.log*\
/var/log/IBMtape.trace\
/var/log/IBMtape.errorlog\
@@ -346,9 +364,12 @@ LOGFILES="\
/var/log/messages*\
/var/log/openvswitch/ovs-vswitchd.log\
/var/log/openvswitch/ovsdb-server.log\
/var/log/pbl.log\
/var/log/sa\
/var/log/syslog*\
/var/log/yum.log\
/var/log/YaST2\
/var/log/zypp*\
"
########################################
@@ -368,6 +389,7 @@ CONFIGFILES="\
/etc/crypttab\
/etc/default\
/etc/depmod.d\
/etc/dnf/dnf.conf\
/etc/docker\
/etc/dracut.conf.d\
/etc/exports\
@@ -450,7 +472,7 @@ CMDS="${CMDS}\
:lszdev\
:find /dev -print0 | sort -z | xargs -0 -n 10 ls -ld\
:lspci -t\
:lspci -vv\
:lspci -vvv\
:lstape\
:smc_dbg\
"
@@ -468,6 +490,7 @@ CMDS="${CMDS}\
:dmsetup table --target multipath\
:dmsetup status\
:multipathd -k'show config'\
:multipathd -k'show config local'\
:multipathd -k'show maps'\
:multipathd -k'show topo'\
:multipathd -k'show paths'\
@@ -557,6 +580,18 @@ DOCKER_CMDS="docker version\
:systemctl status docker.service\
"
########################################
KUBERNETES_CMDS="kubectl version\
:oc version # get also OCP version if installed\
:kubectl top pod\
:kubectl top node\
:kubectl describe pod -A\
:kubectl describe node -A\
:kubectl describe endpoints\
:ls -l /var/log/containers # list of logs is sufficent\
:kubectl cluster-info dump >>${OUTPUT_FILE_KUBERNETES}.dmp\
"
########################################
VM_CMDS="q userid\
:q users\
@@ -676,18 +711,18 @@ collect_vmcmdsout() {
local vm_userid
local module_loaded=1
local ifs_orig="${IFS}"
local cp_buffer_size=2
local rc_buffer_size=2
local cp_buffer_size
local rc_buffer_check
if echo "${RUNTIME_ENVIRONMENT}" | grep -qi "z/VM" >/dev/null 2>&1; then
pr_collect_output "z/VM"
if type -t vmcp >/dev/null; then
if type vmcp >/dev/null; then
cp_command="vmcp"
if ! lsmod 2>/dev/null | grep -q vmcp && modinfo vmcp >/dev/null 2>&1; then
modprobe vmcp && module_loaded=0 && sleep 2
fi
elif type -t hcp >/dev/null; then
elif type hcp >/dev/null; then
cp_command="hcp"
if ! lsmod 2>/dev/null | grep -q cpint; then
modprobe cpint && module_loaded=0 && sleep 2
@@ -703,11 +738,14 @@ collect_vmcmdsout() {
IFS=:
for vm_command in ${vm_cmds}; do
IFS="${ifs_orig}"
while test ${rc_buffer_size} -eq 2 && test ${cp_buffer_size} -lt 1024; do
# initialize buffer values for automatic resizing
cp_buffer_size=2
rc_buffer_check=2
while test ${rc_buffer_check} -eq 2 && test ${cp_buffer_size} -lt 1024; do
cp_buffer_size=$(( cp_buffer_size * 2 ))
eval ${cp_command} -b ${cp_buffer_size}k "${vm_command}" \
>/dev/null 2>&1
rc_buffer_size=$?
rc_buffer_check=$?
done
call_run_command "${cp_command} -b ${cp_buffer_size}k ${vm_command}" \
"${OUTPUT_FILE_VMCMD}"
@@ -781,11 +819,12 @@ collect_sysfs() {
# files known to block on read (-x). Stop reading a file that takes
# more than 5 seconds (-T 5) such as an active ftrace buffer.
# error messages are not written to the log
if type -t dump2tar >/dev/null; then
if test "x${DUMP2TAR_OK}" = "xYES"; then
dump2tar /sys -z -o "${OUTPUT_FILE_SYSFS}.tgz" \
-x '*/tracing/trace_pipe*' \
-x '*/page_idle/bitmap*' \
-x '*/tracing/per_cpu/*' \
-x '*/tracing/free_buffer' \
--ignore-failed-read -J 1 -T 5 2>>${OUTPUT_FILE_SYSFS}.err
rc=$?
else
@@ -812,6 +851,7 @@ collect_sysfs() {
-a -not \( -path '*tracing*' -a -name "trace_pipe*" \) \
-a -not \( -path '*page_idle*' -a -name 'bitmap*' \) \
-a -not -path '*tracing/per_cpu*' \
-a -not -path '*/tracing/free_buffer' \
2>/dev/null | while IFS= read -r file_name; do
echo " ${file_name}"
if ! dd if="${file_name}" status=noxfer iflag=nonblock \
@@ -857,7 +897,7 @@ collect_osaoat() {
network_devices=$(lsqeth 2>/dev/null | grep "Device name" \
| sed 's/D.*:[[:space:]]*\([^[:space:]]*\)[[:space:]]\+/\1/g')
if type -t qethqoat >/dev/null; then
if type qethqoat >/dev/null; then
if test -n "${network_devices}"; then
pr_collect_output "osa oat"
for network_device in ${network_devices}; do
@@ -880,7 +920,7 @@ collect_ethtool() {
local network_device
network_devices=$(ls /sys/class/net 2>/dev/null)
if type -t ethtool >/dev/null; then
if type ethtool >/dev/null; then
if test -n "${network_devices}"; then
pr_collect_output "ethtool"
for network_device in ${network_devices}; do
@@ -921,7 +961,7 @@ collect_tc() {
local network_device
network_devices=$(ls /sys/class/net 2>/dev/null)
if type -t tc >/dev/null; then
if type tc >/dev/null; then
if test -n "${network_devices}"; then
pr_collect_output "Trafic Control"
for network_device in ${network_devices}; do
@@ -942,7 +982,7 @@ collect_bridge() {
local network_device
network_devices=$(ls /sys/class/net 2>/dev/null)
if type -t bridge >/dev/null; then
if type bridge >/dev/null; then
if test -n "${network_devices}"; then
pr_collect_output "bridge"
for network_device in ${network_devices}; do
@@ -974,7 +1014,7 @@ collect_ovs() {
:ovs-vsctl -t 5 show\
:ovsdb-client dump\
"
if type -t ovs-vsctl >/dev/null; then
if type ovs-vsctl >/dev/null; then
pr_collect_output "OpenVSwitch"
IFS=:
for ovscmd in ${ovscmds}; do
@@ -999,14 +1039,21 @@ collect_ovs() {
}
########################################
collect_docker() {
collect_container() {
local container_list
local network_list
local item
# check if docker command exists
# check if container environment exists
if test "x${DOCKER}" = "xYES" || test "x${KUBERNETES}" = "xYES"; then
pr_collect_output "container host"
else
pr_skip "container host: not found"
fi
# for docker command exists
if [ "x${DOCKER}" = "xYES" ]; then
pr_collect_output "docker"
pr_syslog_stdout " docker ..."
container_list=$(docker ps -qa)
network_list=$(docker network ls -q)
ifs_orig="${IFS}"
@@ -1028,8 +1075,25 @@ collect_docker() {
"${OUTPUT_FILE_DOCKER}"
done
fi
else
pr_skip "docker: not available"
fi
# for kubectl command exists
if [ "x${KUBERNETES}" = "xYES" ]; then
pr_syslog_stdout " Kubernetes ..."
container_list=$(kubectl top pod | grep -v "MEMORY(bytes)" | cut -d' ' -f1)
ifs_orig="${IFS}"
IFS=:
for item in ${KUBERNETES_CMDS}; do
IFS=${ifs_orig} call_run_command "${item}" "${OUTPUT_FILE_KUBERNETES}.out"
done
IFS="${ifs_orig}"
if test -n "${container_list}"; then
for item in ${container_list}; do
call_run_command "kubectl logs --tail=${KUBERNETES_LOG_LINES} ${item}"\
"${OUTPUT_FILE_KUBERNETES}.log"
done
fi
fi
}
@@ -1037,7 +1101,7 @@ collect_docker() {
collect_nvme() {
local device
if type -t nvme >/dev/null; then
if type nvme >/dev/null; then
pr_collect_output "NVME storage"
call_run_command "nvme list" "${OUTPUT_FILE_NVME}"
for device in /dev/nvme[0-9]*; do
@@ -1078,7 +1142,7 @@ collect_kvm() {
call_run_command "virsh domstats ${domain}" "${OUTPUT_FILE_KVM}"
done
else
echo "no KVM doamins found" | tee -a ${OUTPUT_FILE_KVM}
echo "no KVM domains found" | tee -a ${OUTPUT_FILE_KVM}
fi
else
pr_skip "KVM: no virsh command"
@@ -1128,6 +1192,10 @@ post_processing() {
rm -f "${file_name}"
fi
done
echo "log work directory state after post processing:"
echo "du summary: $(du -ks ${WORKPATH})"
df -k ${WORKPATH}
}
########################################
@@ -1137,23 +1205,23 @@ call_run_command() {
local rc=0
local cmd="${1}"
local logfile="${2}"
# extract the raw_command and set cmd_type
local raw_cmd=$(echo "${cmd}" | sed -ne 's/^\([^[:space:]]*\).*$/\1/p')
local cmd_type=$(type -t ${raw_cmd})
# timeout_ok - like a boolean - is not empty if command exists
local timeout_ok=$(type -t timeout)
# extract the raw_command and set cmd_type, as some shell might split into
# several lines restrict the cmd echo to the first line only
local raw_cmd=$(echo "${cmd}" | head -1 | sed -ne 's/^\([^[:space:]]*\).*$/\1/p')
local cmd_type=$(type ${raw_cmd} | cut -d' ' -sf4,5)
echo "#######################################################" >> "${logfile}"
echo "${USER}@${SYSTEMHOSTNAME:-localhost}> ${cmd}" >> "${logfile}"
# check calling command type
if [ "X${cmd_type}" = "Xbuiltin" ]; then
if [ "X${cmd_type}" = "Xshell builtin" ]; then
# command is a builtin (no use of timeout possible)
eval "${cmd}" >> ${logfile} 2>&1
rc=$?
elif [ "X${cmd_type}" != "X" ]; then
if [ "X${timeout_ok}" = "Xfile" ]; then
eval timeout -k ${TOS} ${TOS} "${cmd}" >> ${logfile} 2>&1
elif [ "X${cmd_type}" != "Xnot found" ]; then
if [ "x${TIMEOUT_OK}" = "xYES" ]; then
eval timeout -k ${TOKS} ${TOS} "${cmd}" >> ${logfile} 2>&1
rc=$?
else
# fall back - call all existing commands without timeout
@@ -1345,6 +1413,9 @@ print_version
# saving stdout/stderr and redirecting stdout/stderr into log file
exec 8>&1 9>&2 >"${LOGFILE}" 2>&1
# run print_version again to be logged in dbginfo.log
print_version
# trap on SIGHUP=1 SIGINT=2 SIGTERM=15
trap emergency_exit SIGHUP SIGINT SIGTERM

View File

@@ -1,4 +1,4 @@
.TH DBGINFO.SH 8 "May 2022" "s390-tools"
.TH DBGINFO.SH 8 "Sep 2022" "s390-tools"
.SH NAME
dbginfo.sh \- collect runtime, configuration and trace information
@@ -8,13 +8,13 @@ for debugging Linux on IBM Z
.br
\fBdbginfo.sh\fP [OPTIONS]
.br
\fBdbginfo.sh\fP {\-h|\-v}
\fBdbginfo.sh\fP {\-h|\-c|\-v}
.SH DESCRIPTION
This script collects runtime, configuration and trace information that can
be used to debug a Linux on IBM Z instance.
For Linux on z/VM, the script also traces information about the z/VM system.
KVM or DOCKER data ist collected on a host serving this.
Virtualization platform data is collected on a host serving this.
The debug information is written to a file
/<DIRECTORY>/DBGINFO\-<date>\-<time>\-<hostname>\-<processorid>.tgz
@@ -59,7 +59,7 @@ Sample invocation:
.br
dbginfo.sh: Debug information script version %S390_TOOLS_VERSION%
.br
Copyright IBM Corp. 2002, 2021
Copyright IBM Corp. 2002, 2022
.PP
Hardware platform = s390x
.br
@@ -97,8 +97,10 @@ Date and time of info = 2021-08-26-15-27-58
.PP
13 of 18: Skip KVM: no virsh command
.PP
14 of 18: Collecting docker output
14 of 18: Collecting container host output
.PP
Kubernetes ...
.br
15 of 18: Collecting NVME storage output
.PP
16 of 18: Collecting log files

View File

@@ -9,6 +9,7 @@
[Unit]
Description=Configure dump on panic for System z
ConditionVirtualization=!container
After=network.target
[Service]

View File

@@ -31,6 +31,7 @@ int disk_query_reserve_status(char* device);
int disk_profile (char* device, char* prof_item);
int disk_reset_prof(char *device);
int disk_reset_chpid(char *device, char *chpid);
int disk_copy_swap(char *device, char *copy_pair);
#endif /* not DISK_H */

View File

@@ -174,6 +174,14 @@ Reset all channel paths of the selected device. The channel paths
might be suspended due to high IFCC error rates or a High Performance
FICON failure. Use this option to resume considering all defined
channel paths for I/O.
.TP
.BR "\-s" " or " "\-\-copy\-pair\-swap <copy_pair>"
Swap the copy roles of the specified copy pair. The <copy_pair> has to
be a comma separated pair of \fBPRIMARY,SECONDARY\fR where
\fBPRIMARY\fR is the old primary device that will become a secondary
automatically. The old \fBSECONDARY\fR device will become the new
primary device. Both devices have to be online for this operation to
succeed.
.\"
.\".TP
.\".BR "\-o" " or " "\-\-online"
@@ -197,6 +205,12 @@ channel paths for I/O.
.br
tunedasd -p 45 /dev/dasdc
.br
4. Scenario: Swap copy pair 0.0.9700 and 0.0.9740
.br
tunedasd -s 0.0.9700,0.0.9740 /dev/dasdc
.br
.SH "SEE ALSO"
.BR dasdview (8),

View File

@@ -19,98 +19,13 @@
#include <sys/types.h>
#include <unistd.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
#include "lib/util_libc.h"
#include "disk.h"
#include "tunedasd.h"
#define BUS_ID_SIZE 30
/*
* DASD DEFINITIONS (copied from dasd.h)
*/
#define DASD_IOCTL_LETTER 'D'
/*
* struct profile_info_t
* holds the profiling information
*/
typedef struct dasd_profile_info_t {
unsigned int dasd_io_reqs; /* # of requests processed at all */
unsigned int dasd_io_sects; /* # of sectors processed at all */
unsigned int dasd_io_secs[32]; /* request's sizes */
unsigned int dasd_io_times[32]; /* requests's times */
unsigned int dasd_io_timps[32]; /* requests's times per sector */
unsigned int dasd_io_time1[32]; /* time from build to start */
unsigned int dasd_io_time2[32]; /* time from start to irq */
unsigned int dasd_io_time2ps[32]; /*time from start to irq */
unsigned int dasd_io_time3[32]; /* time from irq to end */
unsigned int dasd_io_nr_req[32]; /* # of requests in chanq */
} dasd_profile_info_t;
/*
* struct attrib_data_t
* represents the operation (cache) bits for the device.
* Used in DE to influence caching of the DASD.
*/
typedef struct attrib_data_t {
unsigned char operation:3; /* cache operation mode */
unsigned char reserved:5;
unsigned short nr_cyl; /* no of cyliners for read ahaed */
unsigned char reserved2[29]; /* for future use */
} __attribute__ ((packed)) attrib_data_t;
/* definition of operation (cache) bits within attributes of DE */
#define DASD_NORMAL_CACHE 0x0
#define DASD_BYPASS_CACHE 0x1
#define DASD_INHIBIT_LOAD 0x2
#define DASD_SEQ_ACCESS 0x3
#define DASD_SEQ_PRESTAGE 0x4
#define DASD_REC_ACCESS 0x5
/*
* Data returned by Sense Path Group ID (SNID)
*/
struct dasd_snid_data {
struct {
__u8 group:2;
__u8 reserve:2;
__u8 mode:1;
__u8 res:3;
} __attribute__ ((packed)) path_state;
__u8 pgid[11];
} __attribute__ ((packed));
struct dasd_snid_ioctl_data {
struct dasd_snid_data data;
__u8 path_mask;
} __attribute__ ((packed));
/*
* DASD-IOCTLs (copied from dasd.h)
*/
/* Issue a reserve/release command, rsp. */
#define BIODASDRSRV _IO (DASD_IOCTL_LETTER,2) /* reserve */
#define BIODASDRLSE _IO (DASD_IOCTL_LETTER,3) /* release */
#define BIODASDSLCK _IO (DASD_IOCTL_LETTER,4) /* steal lock */
/* reset profiling information of a device */
#define BIODASDPRRST _IO (DASD_IOCTL_LETTER,5)
/* retrieve profiling information of a device */
#define BIODASDPRRD _IOR (DASD_IOCTL_LETTER,2,dasd_profile_info_t)
/* Get Attributes (cache operations) */
#define BIODASDGATTR _IOR(DASD_IOCTL_LETTER,5,attrib_data_t)
/* Set Attributes (cache operations) */
#define BIODASDSATTR _IOW (DASD_IOCTL_LETTER,2,attrib_data_t)
/* Get Sense Path Group ID (SNID) data */
#define BIODASDSNID _IOWR(DASD_IOCTL_LETTER, 1, struct dasd_snid_ioctl_data)
/* id definition for profile items */
enum prof_id {
prof_reqs = 0,
@@ -241,48 +156,33 @@ check_prof_item (char* prof_item)
* 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl'
* the number of cylinders to be cached.
*/
int
disk_get_cache (char* device)
int disk_get_cache(char *device)
{
int fd;
attrib_data_t attrib_data;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
int rc;
/* Get the given caching attributes */
if (ioctl (fd, BIODASDGATTR, &attrib_data)) {
error_print ("Could not get cache attributes for device <%s>",
device);
close (fd);
return -1;
}
rc = dasd_get_cache(device, &attrib_data);
if (rc)
return rc;
printf ("%s (%i cyl)\n",
get_cache_name(attrib_data.operation),
attrib_data.nr_cyl);
close (fd);
return 0;
}
/*
* Set the caching algorithm used for the channel programs of this device.
* 'cache' is the caching mode (see ESS docu for more info) and 'no_cyl'
* the number of cylinders to be cached.
*/
int
disk_set_cache (char* device, char* cache, char* no_cyl)
int disk_set_cache(char *device, char *cache, char *no_cyl)
{
int fd;
attrib_data_t attrib_data;
/* get caching mode and # cylinders */
int rc;
/* get caching mode and # cylinders */
attrib_data.operation = check_cache (cache);
attrib_data.nr_cyl = check_no_cyl (no_cyl);
@@ -292,52 +192,34 @@ disk_set_cache (char* device, char* cache, char* no_cyl)
attrib_data.nr_cyl);
}
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Set the given caching attributes */
printf ("Setting cache mode for device <%s>...\n", device);
if (ioctl (fd, BIODASDSATTR, &attrib_data)) {
error_print ("Could not set caching for device <%s>", device);
close (fd);
rc = dasd_set_cache(device, &attrib_data);
if (rc) {
error_print("Could not set caching for device <%s>", device);
return -1;
}
printf ("Done.\n");
close (fd);
return 0;
}
/*
* Reserve the device.
*/
int
disk_reserve (char* device)
int disk_reserve(char *device)
{
int fd;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
int rc;
/* Reserve device */
printf ("Reserving device <%s>...\n", device);
if (ioctl (fd, BIODASDRSRV)) {
error_print ("Could not reserve device <%s>", device);
close (fd);
rc = dasd_disk_reserve(device);
if (rc) {
error_print("Could not reserve device <%s>", device);
return -1;
}
printf ("Done.\n");
close (fd);
printf("Done.\n");
return 0;
}
@@ -345,28 +227,18 @@ disk_reserve (char* device)
/*
* Release the device.
*/
int
disk_release (char* device)
int disk_release(char *device)
{
int fd;
int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
/* Release device */
printf ("Releasing device <%s>...\n", device);
if (ioctl (fd, BIODASDRLSE)) {
error_print ("Could not release device <%s>", device);
close (fd);
rc = dasd_disk_release(device);
if (rc) {
error_print("Could not release device <%s>", device);
return -1;
}
printf ("Done.\n");
close (fd);
printf("Done.\n");
return 0;
}
@@ -376,29 +248,19 @@ disk_release (char* device)
* This means to reserve the device even if it was already reserved.
* The current reserve is broken (steal lock).
*/
int
disk_slock (char* device)
int disk_slock(char *device)
{
int fd;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
int rc;
/* Unconditional reserve device */
printf ("Unconditional reserving device <%s>...\n", device);
if (ioctl (fd, BIODASDSLCK)) {
error_print ("Could not unconditional reserve device <%s>",
device);
close (fd);
rc = dasd_slock(device);
if (rc) {
error_print("Could not unconditional reserve device <%s>", device);
return -1;
}
printf ("Done.\n");
close (fd);
return 0;
}
@@ -407,27 +269,16 @@ disk_slock (char* device)
* Uses the Sense Path Group ID (SNID) ioctl to find out if
* a device is reserved to it's path group.
*/
int
disk_query_reserve_status(char* device)
int disk_query_reserve_status(char *device)
{
int fd;
struct dasd_snid_ioctl_data snid;
int rc;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
rc = dasd_query_reserve(device);
if (rc < 0) {
error_print("Could not read reserve status for device <%s>", device);
return -1;
}
snid.path_mask = 0;
/* Release device */
if (ioctl(fd, BIODASDSNID, &snid)) {
error_print("Could not read reserve status"
" for device <%s>", device);
close (fd);
return -1;
}
switch (snid.data.path_state.reserve) {
switch (rc) {
case 0:
printf("none\n");
break;
@@ -441,7 +292,7 @@ disk_query_reserve_status(char* device)
printf("reserved\n");
break;
}
close (fd);
return 0;
}
@@ -615,21 +466,14 @@ static int disk_profile_item(dasd_profile_info_t dasd_profile_info,
/*
* Get and print the profiling info of the device.
*/
int
disk_profile (char* device, char* prof_item)
int disk_profile(char *device, char *prof_item)
{
int fd, rc;
dasd_profile_info_t dasd_profile_info;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
int rc;
/* Get the profile info */
if (ioctl (fd, BIODASDPRRD, &dasd_profile_info)) {
rc = dasd_profile(device, &dasd_profile_info);
if (rc) {
switch (errno) {
case EIO: /* profiling is not active */
error_print ("Profiling (on device <%s>) is not "
@@ -639,7 +483,6 @@ disk_profile (char* device, char* prof_item)
error_print ("Could not get profile info for device "
"<%s>.", device);
}
close (fd);
return -1;
}
/* Check for profile item or summary */
@@ -648,38 +491,26 @@ disk_profile (char* device, char* prof_item)
} else {
rc = disk_profile_item (dasd_profile_info, prof_item);
}
close (fd);
return rc;
}
/*
* Reset the profiling counters of the device.
*/
int
disk_reset_prof (char* device)
int disk_reset_prof(char *device)
{
int fd;
/* Open device file */
fd = open (device, O_RDONLY);
if (fd == -1) {
error_print ("<%s> - %s", device, strerror (errno));
return -1;
}
int rc;
/* reset profile info */
printf ("Resetting profile info for device <%s>...\n", device);
if (ioctl (fd, BIODASDPRRST)) {
error_print ("Could not reset profile info for device <%s>",
device);
close (fd);
rc = dasd_reset_profile(device);
if (rc) {
error_print("Could not reset profile info for device <%s>", device);
return -1;
}
printf ("Done.\n");
close (fd);
return 0;
}
@@ -717,3 +548,50 @@ int disk_reset_chpid(char *device, char *chpid)
return -1;
}
int disk_copy_swap(char *device, char *copy_pair)
{
struct dasd_copypair_swap_data data = { 0 };
char *primary, *secondary;
int rc = 0;
primary = strtok(copy_pair, ",");
secondary = strtok(NULL, ",");
if (!primary || !secondary) {
error_print("%s: Error parsing Copy Pair %s", device, copy_pair);
return -1;
}
util_strlcpy(data.primary, primary, DASD_BUS_ID_SIZE);
util_strlcpy(data.secondary, secondary, DASD_BUS_ID_SIZE);
printf("Swapping copy pair %s %s on device <%s>...\n", primary, secondary, device);
rc = dasd_copy_swap(device, &data);
switch (rc) {
case 0:
printf("Done.\n");
return 0;
case 1:
error_print("Swap data invalid");
break;
case 2:
error_print("No active device found");
break;
case 3:
error_print("Wrong primary device specified");
break;
case 4:
error_print("Secondary device not found");
break;
case 5:
error_print("Swap already running");
break;
default:
error_print("Swap not successful rc %d", rc);
break;
}
return -1;
}

View File

@@ -119,12 +119,17 @@ static struct util_opt opt_vec[] = {
.desc = "Reset all channel paths of a device",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = { "copy-pair-swap", required_argument, NULL, 's' },
.argument = "COPY_PAIR",
.desc = "Swap a specified, comma separated copy pair.",
},
UTIL_OPT_HELP,
UTIL_OPT_VERSION,
UTIL_OPT_END
};
#define CMD_KEYWORD_NUM 16
#define CMD_KEYWORD_NUM 17
#define DEVICES_NUM 256
enum cmd_keyword_id {
@@ -144,6 +149,7 @@ enum cmd_keyword_id {
cmd_keyword_path_all,
cmd_keyword_enable_stats,
cmd_keyword_disable_stats,
cmd_keyword_copy_swap,
};
@@ -167,7 +173,8 @@ static const struct {
{ "path_reset", cmd_keyword_path },
{ "path_reset_all", cmd_keyword_path_all },
{ "enable-stats", cmd_keyword_enable_stats },
{ "disable-stats", cmd_keyword_disable_stats }
{ "disable-stats", cmd_keyword_disable_stats },
{ "copy-swap", cmd_keyword_copy_swap },
};
@@ -180,26 +187,27 @@ enum cmd_key_state {
/* Determines which combination of keywords are valid */
static enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = {
/* help vers get_ cach no_c rese rele sloc prof prof rese quer path path
* ion cach e yl rve ase k ile _ite t_pr y_re _all
* e m of serv
/* help vers get_ cach no_c rese rele sloc prof prof rese quer path path enab disa copy
* ion cach e yl rve ase k ile _ite t_pr y_re _all le-s ble- -swa
* e m of serv tats stat p
*/
/* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv },
/* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv },
/* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv },
/* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv },
/* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv },
/* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv },
/* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv },
/* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv },
/* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
/* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
/* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv, inv, inv, inv },
/* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
/* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv, inv, inv, inv },
/* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv, inv, inv, inv },
/* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
/* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv },
/* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv, inv },
/* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv },
/* enable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv },
/* disable-stats */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
/* copy-swap */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
};
struct parameter {
@@ -439,7 +447,9 @@ static int get_command_line(int argc, char *argv[], struct command_line *line)
rc = store_option (&cmdline, cmd_keyword_query_reserve,
optarg);
break;
case 's':
rc = store_option(&cmdline, cmd_keyword_copy_swap, optarg);
break;
case -1:
/* End of options string - start of devices list */
cmdline.device_id = optind;
@@ -508,6 +518,9 @@ static int do_command(char *device, struct command_line cmdline)
case cmd_keyword_path_all:
rc = disk_reset_chpid(device, NULL);
break;
case cmd_keyword_copy_swap:
rc = disk_copy_swap(device, cmdline.parm[cmd_keyword_copy_swap].data);
break;
default:
error_print ("Unknown command '%s' specified",
get_keyword_name (i));

View File

@@ -35,6 +35,8 @@ function PrintUsage() {
Print extended information about DASDs.
-H|--host-access-list
Print information about hosts accessing DASDs.
-P|--copy-pairs
Print information about copy pairs.
-v|--verbose
For compatibility/future use. Currently ignored.
--version
@@ -146,6 +148,62 @@ function findDASDDebugfsDirectorie() {
fi
}
#------------------------------------------------------------------------------
# The blockpath can usually be found over the DEVPATH
# In case of a swapped Copy Pair device the blockdev is likely associated
# with one of the secondary devices
# this function checks if the blockdev is associated with the primary device
# and if not search for it in the secondary device list
#------------------------------------------------------------------------------
function setCorrectBlockPath() {
local DRIVERECKD="$SYSFSDIR/bus/ccw/drivers/dasd-eckd/"
local DRIVERFBA="$SYSFSDIR/bus/ccw/drivers/dasd-fba/"
local SEARCHDIRS=
local SEARCHLIST=
if [[ "$COPYROLE" == "none" ]] || [[ -d "$DEVPATH/block" ]]; then
BLOCKPATH="$DEVPATH"/block/dasd*
return
fi
if [[ -d "$DRIVERECKD" ]]; then
SEARCHDIRS="$DRIVERECKD"
fi
if [[ -d "$DRIVERFBA" ]]; then
SEARCHDIRS="$SEARCHDIRS $DRIVERFBA"
fi
SEARCHLIST=$(echo $SECONDARY_LIST | sed 's/,/ /g')
for SEARCHDEV in $SEARCHLIST
do
if [[ -n "$SEARCHDIRS" ]]; then
PRIM_DEVPATH=$(find $SEARCHDIRS -type l -name $SEARCHDEV \
-printf "%h/%l\n" 2> /dev/null)
if [[ -d "$PRIM_DEVPATH/block" ]]; then
break
fi
else
# The above paths may become invalid in the future, so we keep the
# following query as backup:
PRIM_DEVPATH=$(find "$SYSFSDIR/devices" -type l -name $SEARCHDEV \
"driver" -lname "*/dasd*" -printf "%h\n" \
2> /dev/null)
fi
done
BLOCKPATH="$PRIM_DEVPATH"/block/dasd*
}
#------------------------------------------------------------------------------
# gather Copy Pair related data
#------------------------------------------------------------------------------
function gatherCopyPairData() {
read COPYPAIR 2> /dev/null < $DEVPATH/copy_pair
PRIMARY_UID=`echo $COPYPAIR | cut -d " " -f1 | cut -d "," -f1`
COPYPAIR=`echo "$COPYPAIR" | sed 's/ /,/g' | sed 's/^,//' `
SECONDARY_LIST=`echo ${COPYPAIR//$PRIMARY_UID","/} `
}
#------------------------------------------------------------------------------
# gather device data and call appropriate output function
#------------------------------------------------------------------------------
@@ -165,16 +223,18 @@ function gatherDeviceData() {
read READONLY 2> /dev/null < $DEVPATH/readonly || continue
read DISCIPLINE 2> /dev/null < $DEVPATH/discipline || continue
read ESE 2> /dev/null < $DEVPATH/ese
read COPYROLE 2> /dev/null < $DEVPATH/copy_role
if [[ "$COPYROLE" != "none" ]]; then
gatherCopyPairData
fi
# Block device specific information is only available for
# devices that are online and not a PAV alias
if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]]; then
#find device Path to the block device
if [[ -d "$DEVPATH/block" ]]; then
set - "$DEVPATH"/block/dasd*
else
set - "$DEVPATH"/block:dasd*
fi
if [[ ! "$ONLINE" == 0 ]] && [[ ! "$ALIAS" == 1 ]] &&
[[ ! "$COPYROLE" == "secondary" ]]; then
#find device Path to the block device
setCorrectBlockPath
set - $BLOCKPATH
MAJMIN=
MAJOR=
MINOR=
@@ -194,10 +254,12 @@ function gatherDeviceData() {
fi
fi
else
# BLOCKNAME for offline and alias devices will not be
# printed, it's just a key for sorting
# BLOCKNAME for offline, alias and secondary devices
# will not be printed, it's just a key for sorting
if [[ "$ONLINE" == 0 ]]; then
BLOCKNAME=""
elif [[ "$COPYROLE" == "secondary" ]]; then
BLOCKNAME="b"
else
BLOCKNAME="a"
fi
@@ -232,6 +294,8 @@ function gatherDeviceData() {
uid
elif [[ "$OUTPUT" == "host" ]]; then
host
elif [[ "$OUTPUT" == "copy" ]]; then
copy
else
newoutput
fi
@@ -261,6 +325,15 @@ function newoutput()
return
fi
if [[ "$COPYROLE" == "secondary" ]]; then
printf "%s:%s:%-8s secondary %-8s %13s\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$PRIMARY_BLOCKNAME" \
"$DISCIPLINE"
return
fi
if [[ "$READONLY" == 0 ]]; then
ROSTRING=""
else
@@ -519,10 +592,14 @@ function extended()
"${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ;
return
elif [[ "$ALIAS" == 1 ]]; then
if [[ "$BASEONLY" == "false" ]]; then
ACTIVE="alias"
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
elif [[ "$ALIAS" == 1 ]] || [[ "$COPYROLE" == "secondary" ]]; then
if [[ "$BASEONLY" == "false" ]] || [[ "$COPYROLE" == "secondary" ]]; then
if [[ "$COPYROLE" == "secondary" ]]; then
ACTIVE="secondary"
else
ACTIVE="alias"
fi
printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$ACTIVE" \
@@ -540,7 +617,8 @@ function extended()
"${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \
"${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ;
"${IFCC_PATHS[@]}" \
"${COPYPAIR}" ;
fi
return
elif [[ -z "$BLOCKNAME" ]] || [[ -z "$SIZE" ]]; then
@@ -565,7 +643,7 @@ function extended()
DISCIPLINE="${DISCIPLINE} (ESE)"
fi
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# extent_size:\t\t\t\t%s# logical_capacity:\t\t\t%s# space_allocated:\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# fc_security: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s# copy_pairs:\t\t\t\t%s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$BLOCKNAME" \
@@ -593,7 +671,8 @@ function extended()
"${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \
"${HPF_PATHS[@]}" \
"${IFCC_PATHS[@]}" ;
"${IFCC_PATHS[@]}" \
"${COPYPAIR}" ;
}
function host()
@@ -694,6 +773,41 @@ printf "\n";
rm -f $temp
}
# pad sortkey with given number zeroes
function padSortKey()
{
local LEN=$1
for (( i=0; i<$LEN; i++ ))
do
printf -v SORTKEY "%s0" $SORTKEY
done
}
function copy()
{
if [[ "$COPYROLE" == "none" ]]; then
return
fi
SORTKEYLEN=$((${#PRIMARY_UID}+${#DEV_UID}))
if [[ "$COPYROLE" == "secondary" ]]; then
SORTKEY=$PRIMARY_UID$DEV_UID
PAIREDDEVICES=$PRIMARY_UID
BLOCKNAME=""
else
SORTKEY=$PRIMARY_UID
padSortKey ${#DEV_UID}
PAIREDDEVICES=$SECONDARY_LIST
fi
printf "%s:%s:%-8s %-10s %-8s %-8s %s \n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$COPYROLE" \
"$BLOCKNAME" \
"$PAIREDDEVICES";
}
function uid()
{
#-------------------------------------------#
@@ -710,7 +824,11 @@ function uid()
fi
fi
printf "%s:%s:%-8s %-8s %s\n" \
if [[ "$COPYROLE" == "secondary" ]]; then
BLOCKNAME="secondary"
fi
printf "%s:%s:%-8s %-10s %s\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$BLOCKNAME" \
@@ -756,6 +874,9 @@ while [ $# -gt 0 ]; do
--host-access-list|-H)
OUTPUT="host"
;;
--copy-pairs|-P)
OUTPUT="copy"
;;
--version)
PrintVersion
exit 0
@@ -810,6 +931,9 @@ if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
elif [[ "$OUTPUT" == "new" ]]; then
printf "Bus-ID Status Name Device Type BlkSz Size Blocks\n"
printf "================================================================================\n"
elif [[ "$OUTPUT" == "copy" ]]; then
printf "Bus-ID Role Name Paired devices\n";
printf "================================================================================\n";
elif [[ "$OUTPUT" == "extended" ]]; then
PROCESSING=" $PROCESSING | sed 's/#/\n/g' "
fi

View File

@@ -872,7 +872,7 @@ static void show_devices_argv(char *argv[])
show_device(rec, card);
free(card);
}
return;
continue;
}
if (sscanf(argv[i]+1, "%x", &dom) == 1) {
/* list specific domains of all adapters */
@@ -897,7 +897,7 @@ static void show_devices_argv(char *argv[])
}
free(path);
}
return;
continue;
}
printf("Invalid adpater id!\n");
}

View File

@@ -55,9 +55,22 @@ install() {
chzdev --export - --persistent --by-attrib "zdev:early=1" --quiet \
--type 2>/dev/null >> "$_tempfile"
# Obtain early device configuration for site-specific settings
for (( site=0; site<10; site++ ))
do
chzdev --export - --persistent --by-attrib "zdev:early=1" --site $site \
--quiet 2>/dev/null >> "$_tempfile"
done
# Apply via --import to prevent other devices from being configured
chzdev --import "$_tempfile" --persistent --base "/etc=$initdir/etc" \
--yes --quiet --no-root-update --force >/dev/null
# Apply site-specific configurations via --import
for (( site=0; site<10; site++ ))
do
chzdev --import "$_tempfile" --persistent --base "/etc=$initdir/etc" \
--site $site --yes --quiet --no-root-update --force >/dev/null
done
rm -f "$_tempfile"

View File

@@ -1,7 +1,6 @@
# Common definitions
include ../../common.mak
MODDIR := /usr/lib/dracut/modules.d/
ZDEVDIR := 95zdev
# HAVE_DRACUT
@@ -16,9 +15,9 @@ ZDEVDIR := 95zdev
#
ifeq ($(HAVE_DRACUT),1)
install:
$(INSTALL) -m 755 -d $(DESTDIR)$(MODDIR)
$(INSTALL) -m 755 -d $(DESTDIR)$(MODDIR)/$(ZDEVDIR)
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVDIR)
$(INSTALL) -m 755 $(ZDEVDIR)/module-setup.sh \
$(ZDEVDIR)/parse-zdev.sh \
$(DESTDIR)$(MODDIR)/$(ZDEVDIR)/
$(DESTDIR)$(DRACUTMODDIR)/$(ZDEVDIR)/
endif

View File

@@ -19,6 +19,20 @@
struct subtype;
struct setting_list;
/**
* Currently zdev supports 10 sites. Which means, zdev support 10 different
* set of attributes which are specific to each site. When the user does
* not provide any site information, the common set will be used which is
* not specific to any site. So, total we have 11 persistent attribute sets
* Where,
* 0- 9: Site specific attributes
* 10: Common attributes which do not belong to any sites
*/
#define NUM_SITES 11
#define NUM_USER_SITES (NUM_SITES - 1)
#define SITE_FALLBACK NUM_USER_SITES
/**
* struct device_state - Represent the state of a device in a configuration
* @settings: List of attribute settings
@@ -61,6 +75,7 @@ struct device {
struct device_state active;
struct device_state persistent;
struct device_state autoconf;
struct device_state site_specific[NUM_SITES];
unsigned int processed:1;
};
@@ -97,8 +112,11 @@ struct device *device_list_find(struct device_list *, const char *,
struct device *);
void device_list_print(struct device_list *, int);
struct setting_list *device_get_setting_list(struct device *dev,
config_t config);
config_t config,
int site_id);
config_t device_get_config(struct device *dev);
char *device_get_sites(struct device *dev);
bool is_dev_pers(struct device *dev);
#endif /* DEVICE_H */

View File

@@ -38,6 +38,7 @@ extern struct devtype *devtypes[];
* devtypes with empty title will not be shown with --list-types.
* @devname: Short name for devices of this device type
* @modules: (Optional) Array of kernel modules required for this devtype
* @site_support: Support for site-specific configuration for the device-type
* @subtypes: Array of subtypes
* @type_attribs: Array of device type attributes (may point to empty array)
* @unknown_type_attribs: Allow specification of unknown device type attributes
@@ -59,6 +60,7 @@ struct devtype {
const char title[DEVTYPE_TITLE_LEN + 1];
const char *devname;
const char **modules;
unsigned int site_support:1;
struct subtype **subtypes;
struct attrib **type_attribs;

View File

@@ -103,6 +103,8 @@ extern int delayed_warnings;
extern unsigned long longrun_total;
extern unsigned long longrun_current;
extern int global_site_id;
void misc_exit(void);
void indent(unsigned int, const char *, ...);
void error(const char *, ...);
@@ -239,6 +241,7 @@ void longrun_stop(void);
char *skip_comp(char *);
void byte_swap(uint8_t *, unsigned int *, unsigned);
bool valid_hex(const char *);
bool is_valid_site(const char *);
void debug_init(int, char **);
#endif /* MISC_H */

View File

@@ -18,6 +18,7 @@
#define MODPROBE_PREFIX "s390x"
#define UDEV_PREFIX "41"
#define UDEV_SUFFIX ".rules"
#define ZDEV_PREFIX "40"
#define PATH_MODPROBE_CONF "/etc/modprobe.d"
#define PATH_MODPROBE "/sbin/modprobe"
@@ -65,6 +66,7 @@ char *path_get_zfcp_lun_dev(struct zfcp_lun_devid *);
char *path_get_zfcp_port_dev(struct zfcp_lun_devid *);
char *path_get_scsi_hctl_dev(const char *);
char *path_get_bus_attr(const char *, const char *);
char *path_get_zdev_rule(const char *name);
exit_code_t path_for_each(const char *,
exit_code_t (*callback)(const char *, const char *,

View File

@@ -12,6 +12,6 @@
#include "exit_code.h"
exit_code_t initrd_check(bool all_pers);
exit_code_t initrd_check(bool all_pers, int site_validate);
#endif /* ROOT_H */

View File

@@ -66,7 +66,7 @@ typedef char *(*table_value_cb_t)(void *item, int id, const char *heading,
struct column *table_get_column(struct column *, const char *);
exit_code_t table_print(struct column *, table_value_cb_t, void *,
struct util_list *, struct util_list *, int, int, int,
int);
int, int);
exit_code_t table_check_columns(struct column *, struct util_list *);
void table_print_columns(struct column *, struct util_list *, int, int);
void table_set_default(struct column *, int, int);

View File

@@ -23,7 +23,7 @@ struct table_attrib {
};
struct table_attrib *table_attrib_new(struct subtype *, struct attrib *);
void table_attribs_show(struct util_list *, int, int, struct devtype *);
void table_attribs_show(struct util_list *, int, int, int, struct devtype *);
void table_attribs_show_details(struct util_list *, struct devtype *);
#endif /* TABLE_ATTRIBS_H */

View File

@@ -19,6 +19,9 @@ struct setting_list;
extern int udev_need_settle;
extern int udev_no_settle;
#define SITE_BLOCK_START "# site_start"
#define SITE_BLOCK_END "# site_end"
bool udev_file_is_empty(struct util_udev_file *file);
void udev_get_device_ids(const char *type, struct util_list *list,
@@ -31,4 +34,7 @@ void udev_add_internal_from_entry(struct setting_list *list,
struct util_udev_entry_node *entry,
struct attrib **attribs);
exit_code_t udev_write_site_rule(void);
bool is_legacy_rule(struct util_udev_file *file);
#endif /* UDEV_H */

15
zdev/include/zdev_id.h Normal file
View File

@@ -0,0 +1,15 @@
/*
* zdev - Modify and display the persistent configuration of devices
*
* Copyright IBM Corp. 2022
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef ZDEV_ID_H
#define ZDEV_ID_H
#define ZDEV_SITE_ID_FILE "/run/zdev_id.env"
#endif /* ZDEV_ID_H */

View File

@@ -82,6 +82,42 @@ when a device driver is loaded.
.PP
By default chzdev applies changes to both the active and the persistent
configuration.
.
.SS "Site-specific configurations"
In some high-availability setups, root and boot disks of a Linux installation are
copied to remote sites that can take over execution of a Linux workload in case of
an outage of the original site. A
.B site
in this context is an execution environment such as an
.B LPAR or
.B z/VM guest.
Each site may provide a different set of devices, or require different parameters to be
applied per device.
chzdev supports site-specific device configuration for up to
.B 10
sites. Each site is identified by a number in the range 0 to 9. You can provide a separate
set of persistent device configuration for each site. The IPL Load Parameter value specified
during boot determines the currently active site. Only the device configuration of the active
site is applied during boot and when new devices become available. A common configuration can
be provided that is applied when no site-specific configuration is available for a device in
the active site.
You can use the
.B --site
parameter to configure devices for a specific site only. Configuration actions without a site
parameter apply to the common configuration.
Linux supports the following IPL Load Parameter values for selecting the active site:
.B S<n>
Site with number <n> becomes the active site. Example: "S2" specifies site 2 as active site.
.B SS
The Subchannel-Set ID (SSID) of the IPL device specifies the number of the active site.
If no site is specified in the Load Parameter, only the common configuration is applied.
.PP
.
.SS "Tool actions"
@@ -392,6 +428,10 @@ Removes configuration files and settings associated with the
selected device.
.PP
.
.OD disable-all "D" ""
Disable device in all configurations.
.PP
.
.OD enable "e" ""
Enable device.
@@ -583,6 +623,34 @@ Apply changes to persistent configuration only.
The persistent configuration is put into effect when the system boots, or
when a device becomes available, or when a device driver is loaded.
.PP
.
.OD site "s" "SITE-ID"
Apply the persistent configuration to the specified site only.
This option can be used to configure the device in such a way that, the
same configuration can be used on multiple different sites with different
device hardwares, without any modification. With the site information, we
can add different configurations which are specific to different sites. Where
each site represents different systems or different hardware devices which
are even located in different locations.
For example, having
the configuration of main-site or failover-site in the same place, but these
configurations used only on the respective sites. Currently a user can define
10 different configurations for 10 different sites with
.I SITE-ID
0 to 9.
The configuration settings is put into effect only on the system with the
site number which is mentioned in
.I SITE-ID.
This parameter is only effective only for persistent configurations and for
dasd device-types.
.B Example:
.CL chzdev -ep 0.0.f001 --site 3
.PP
.
.OD quiet "q" ""
@@ -690,6 +758,29 @@ Answer all confirmation questions with 'yes'.
.RE
.PP
.
If you intend to assign a cryptographic (AP) adapter or domain to a KVM
guest you must first release its usage by the zcrypt driver in the host
operating system using chzdev commands similar to the following examples:
.
.PP
.B Remove AP adapters 1 and 20 through 22 from host usage:
.RS 4
.CL chzdev \-\-type ap apmask=-1,-20-22
.RE
.PP
.
.B Return AP domains 5 and 8 through 10 to host usage:
.RS 4
.CL chzdev \-\-type ap aqmask=+5,+8-10
.RE
.PP
.
.B Specify the list of AP adapters and domains available for host usage:
.RS 4
.CL chzdev \-\-type ap apmask=0-120,129-255 aqmask=0-200,220-255
.RE
.PP
.
.
.SH "EXIT CODES"
.TP

View File

@@ -74,9 +74,43 @@ of the currently running system, the persistent configuration stored in
configuration files, and the auto-configuration that is provided by some
machine types to automatically enable I/O devices.
.PP
Persistent configuration data is of two different types. Site-specific configuration
and common-configuration. Common configuration refers to the persistent configuration
which is not bound to any site. In many use cases, this configuration is being
used as a fallback configuration.
Refer the
.B site
section below to learn more about site-specific configuration.
.PP
By default lszdev displays information from both the active and the persistent
configuration, and, if available, from the auto-configuration.
.PP
.SS Output Format
In list format, lszdev uses values with the following meaning for the persistent colums (PERS):
.B yes
.CL A persistent, non-site specific configuration exists; No site specific configurations available.
.B no
.CL No persistent configurations is available.
.B auto
.CL Machine-provided auto-configuration is available.
.B s<n>
.CL A site-specific configuration is available for site-id n.
.B s+
.CL Site specific configurations are available for multiple sites.
.B Example
.CL TYPE ID ON PERS NAMES
.CL dasd-eckd 0.0.f001 no s+ dasda
.CL dasd-eckd 0.0.f002 no s4 dasdb
.CL dasd-eckd 0.0.f003 no no
.CL qeth 0.0.1200:0.0.1201:0.0.1202 no yes encbdf0
.
.
.SH TYPE
@@ -123,6 +157,7 @@ comma (,).
.PP
.
.
.SH SELECTION
In addition to specifying devices by their ID, you can also select devices by
their state or by the Linux functions they provide.
@@ -292,6 +327,7 @@ Display detailed information.
Displays detailed information about the configuration of the selected device
or device type. Specifying \-\-info twice will display additional device
information.
.PP
.
.OD list-columns "l" ""
@@ -387,11 +423,41 @@ with the name of the corresponding column. Values are enclosed in double
quotation marks. Any quotation marks or slashes in the value string are
escaped by placing a slash in front of it.
.PP
.OD shell "" ""
Produces KEY="VALUE" format usable as shell variables.
You can use this option together with the --pairs option to generate
output that is suitable to be sourced in a shell environment. This
option generates similar output as it would be provided by the --pairs
option but it would take care of replacing any character of a column
name that would not be appropriate to be used as part of a shell
variable name by an underscore.
.PP
.
.OD persistent "p" ""
List information from the persistent configuration only.
Restricts output to information obtained from configuration files.
.PP
.
.OD site "s" "SITE-ID"
List the persistent configuration from the specified site only.
The resulted persistent configuration details are filtered based on the
.ID SITE-ID
value. The site specific information can be found in a basic lszdev output.
For example, the PERS column may show "s+" which indicates that the device
has multiple configurations for multiple sites, and "sn" where 'n' is an
number between 0 to 9, which indicates that the persistent configuration
for the device is available only for site 'n'.
.B Example:
.CL lszdev --site 3
.CL lszdev -i --site 2
.CL lszdev f001 --site 9
.PP
.
.OD quiet "q" ""
@@ -429,6 +495,12 @@ Print additional run-time information.
.RE
.PP
.
.B Display cryptographic (AP) adapter and domain assignments:
.RS 4
.CL lszdev \-\-type ap
.RE
.PP
.
.SH "EXIT CODES"
lszdev returns a subset of the exit codes returned by the chzdev tool. See
.MP chzdev 8

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