From 26251ccda8351529b8f1e8cb2aa5e73a8e9c4685 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Mon, 8 May 2023 14:52:54 +0200 Subject: [PATCH 1/3] zdev: add support for autoquiesce related sysfs attributes (#2196510) Autoquiesce is a mechanism that tells Linux to stop issuing I/Os to a specific DASD after certain events. Add support for configuring related DASD device attributes that govern the following aspects of autoquiesce: aq_mask - Configure which events lead to autoquiesce. aq_requeue - Configure if autoquiesce will requeue all I/O to blocklayer. aq_timeouts - Configure the number of timeouts before autoquiesce. Signed-off-by: Stefan Haberland Reviewed-by: Peter Oberparleiter Signed-off-by: Steffen Eiden (cherry picked from commit 493af760ed47454f5719f05a6e6316f43a3be98a) --- zdev/src/dasd.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/zdev/src/dasd.c b/zdev/src/dasd.c index f9fd231..4330229 100644 --- a/zdev/src/dasd.c +++ b/zdev/src/dasd.c @@ -344,6 +344,68 @@ static struct attrib dasd_attr_fc_security = { .readonly = 1, }; +static struct attrib dasd_attr_aq_mask = { + .name = "aq_mask", + .title = "Specify autoquiesce triggers", + .desc = + "Use the aq_mask attribute to automatically quiesce a device and block\n" + "new I/O after certain events.\n" + "\n" + "The value is a bitmask in decimal or hexadecimal format where each set bit\n" + "indicates that the associated event shown in the table below triggers an\n" + "autoquiesce.\n" + " Bit 0 is not used.\n" + " 1 - 0x02 - A terminal I/O error occurred\n" + " 2 - 0x04 - No active channel paths remain for the device\n" + " 3 - 0x08 - A state change interrupt occurred\n" + " 4 - 0x10 - The device is PPRC suspended\n" + " 5 - 0x20 - No space is left on an ESE device\n" + " 6 - 0x40 – The number of timeouts specified in aq_timeouts is reached\n" + " 7 - 0x80 - I/O was not started because of an error in the start function\n" + "\n" + "For example bits 1,3 and 5 set (0010 1010) lead to an integer value of 42\n" + "or 0x2A.\n" + "An integer value of 0 turns off the autoquiesce function.\n", + .order_cmp = ccw_online_only_order_cmp, + .check = ccw_online_only_check, + .defval = "0", + /* + * Currently only 8 bits are defined and the max value is 255. + * This needs to be adjusted if more bits are defined. + */ + .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 255)), +}; + +static struct attrib dasd_attr_aq_requeue = { + .name = "aq_requeue", + .title = "Control I/O requeing during autoquiesce", + .desc = + "Use the aq_requeue attribute to control whether outstanding I/O\n" + "operations to the blocklayer should be automatically requeued after\n" + "an autoquiesce event.\n" + "Valid values are 1 for requeuing, or 0 for no requeueing.\n" + "Requeing the I/O requests to the blocklayer might benefit I/O\n" + "in case of a copy_pair swap operation.\n", + .order_cmp = ccw_online_only_order_cmp, + .check = ccw_online_only_check, + .defval = "0", + .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 1)), +}; + +static struct attrib dasd_attr_aq_timeouts = { + .name = "aq_timeouts", + .title = "Specify timeout retry threshold", + .desc = + "Specify the number of sequential timeout events for an I/O operation\n" + "before an autoquiesce is triggered on a device.\n" + "This requires that the corresponding trigger bit 6 is set\n" + "in the aq_mask attribute.\n", + .order_cmp = ccw_online_only_order_cmp, + .check = ccw_online_only_check, + .defval = "32768", + .accept = ACCEPT_ARRAY(ACCEPT_RANGE(0, 32768)), +}; + /* * DASD subtype methods. */ @@ -725,6 +787,9 @@ struct subtype dasd_subtype_eckd = { &dasd_attr_safe_offline, &dasd_attr_fc_security, &dasd_attr_copy_pair, + &dasd_attr_aq_mask, + &dasd_attr_aq_requeue, + &dasd_attr_aq_timeouts, &internal_attr_early, ), .unknown_dev_attribs = 1, -- 2.40.1 From d26696e5bfbc0c95b9ca70c3bd4b8fff0e36e38f Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 17 May 2023 11:43:08 +0200 Subject: [PATCH 2/3] lszcrypt: Support for SE AP pass-through support (#2110510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for Secure Execution with AP pass-through support for lszcrypt. lszcrypt details: * extension to -b: list AP bus features * extension to -c: now also valid for queue devices, shows bind and assoicate state in SE environment; shows MK states (only for current MKs). * extension to -V: new column SESTAT within an SE guest, shows text for the BS bits within an SE environment: "usable", "bond", "avail", "unuse". Signed-off-by: Harald Freudenberger Reviewed-by: Holger Dengler Signed-off-by: Jan Höppner (cherry picked from commit f821f31a51e395c0d0b048413360eeff92eaee9c) --- zconf/zcrypt/lszcrypt.8 | 195 +++++++++++++++++++++++++--------------- zconf/zcrypt/lszcrypt.c | 136 ++++++++++++++++++++++++---- zconf/zcrypt/misc.c | 38 +++++++- zconf/zcrypt/misc.h | 3 +- 4 files changed, 278 insertions(+), 94 deletions(-) diff --git a/zconf/zcrypt/lszcrypt.8 b/zconf/zcrypt/lszcrypt.8 index e1de2e9..536a3e3 100644 --- a/zconf/zcrypt/lszcrypt.8 +++ b/zconf/zcrypt/lszcrypt.8 @@ -1,6 +1,6 @@ .\" lszcrypt.8 .\" -.\" Copyright IBM Corp. 2019, 2022 +.\" Copyright IBM Corp. 2019, 2023 .\" s390-tools is free software; you can redistribute it and/or modify .\" it under the terms of the MIT license. See LICENSE for details. .\" @@ -10,7 +10,7 @@ .\" nroff -man lszcrypt.8 .\" to process this source .\" -.TH LSZCRYPT 8 "FEB 2022" "s390-tools" +.TH LSZCRYPT 8 "MAY 2023" "s390-tools" .SH NAME lszcrypt \- display zcrypt device and configuration information .SH SYNOPSIS @@ -24,7 +24,7 @@ lszcrypt \- display zcrypt device and configuration information .TP .B lszcrypt .B -c - + .TP .B lszcrypt -b .TP @@ -41,43 +41,60 @@ lszcrypt \- display zcrypt device and configuration information .SH DESCRIPTION The .B lszcrypt -command is used to display information about cryptographic devices managed by -zcrypt and the AP bus attributes of zcrypt. Displayed information depends on the -kernel version. +command is used to display information about cryptographic devices +managed by zcrypt and the AP bus attributes of zcrypt. Displayed +information depends on the kernel version. .B lszcrypt requires that sysfs is mounted. .P The following information can be displayed for each cryptographic device: card ID, domain ID, card type (symbolic), mode, online status, -hardware card type (numeric), installed function facilities, card capability, -hardware queue depth, request count, number of requests in hardware queue, and -the number of outstanding requests. -The following AP bus attributes can be displayed: AP domain, Max AP domain, -configuration timer, poll thread status, poll timeout, and AP interrupt -status. +hardware card type (numeric), installed function facilities, card +capability, hardware queue depth, request count, number of requests in +hardware queue, and the number of outstanding requests. The following +AP bus attributes can be displayed: AP domain, Max AP domain, +configuration timer, poll thread status, poll timeout, and AP +interrupt status. .SH OPTIONS .TP 8 .B -V, --verbose -The verbose level for cryptographic device information. -With this verbose level additional information like hardware card type, -hardware queue depth, pending requests count, installed function -facilities and driver binding is displayed. +The verbose level for cryptographic device information. With this +verbose level additional information like hardware card type, hardware +queue depth, pending requests count, installed function facilities and +driver binding is displayed. .TP 8 .B -Specifies a cryptographic device to display. A cryptographic device can be -either a card device or a queue device. If no devices are specified information -about all available devices is displayed. +Specifies a cryptographic device to display. A cryptographic device +can be either a card device or a queue device. If no devices are +specified information about all available devices is displayed. Please note that the card device representation and the queue device are both in hexadecimal notation. .TP 8 .B -b, --bus Displays the AP bus attributes and exits. + +There is also a list of AP bus features shown here: +.RS +.IP "o" 3 +APSC - Extended TAPQ (Test AP Queue) support. +.IP "o" +APXA - Support for more than 16 domains per card. +.IP "o" +QACT - QACT support for toleration of new unknown crypto cards. +.IP "o" +RC8A - Firmware reports 0x8A instead of 0x42 on some error conditions. +.IP "o" +APSB - AP bus has Secure Execution AP pass-through support. +.RE .TP 8 -.B -c, --capability -Shows the capabilities of a cryptographic card device of hardware type 6 or -higher. The card device id value may be given as decimal or hex value (with -a leading 0x). The capabilities of a cryptographic card device depend on -the card type and the installed function facilities. A cryptographic card +.B -c, --capability +Shows the capabilities of a cryptographic card or queue device of +hardware type 6 or higher. A card device id value may be given as +decimal or hex value (with a leading 0x), a queue device needs to be +given as xy.abcd (as it is displayed by lszcrypt). + +The capabilities of a cryptographic card device depend on the card +type and the installed function facilities. A cryptographic card device can provide one or more of the following capabilities: .RS .IP "o" 3 @@ -94,14 +111,25 @@ Long RNG .RS 8 The CCA Secure Key capability may be limited by a hypervisor -layer. The remarks 'full function set' or 'restricted function set' may -reflect this. For details about these limitations please check the +layer. The remarks 'full function set' or 'restricted function set' +may reflect this. For details about these limitations please check the hypervisor documentation. .RE + +.RS 8 +The capabilities of a cryptographic queue device may vary depending +on some state or environment. However if a queue device is given here, +and the runtime environment is a KVM guest in Secure Execution mode +with AP pass-through support, then the AP queue bind state and AP +queue association state is shown here. Furthermore the state(s) and +mkvp(s) (Master Key Verification Pattern) of the current master WK +(Wrapping Key - EP11 mode) or current master AES, APKA and ASYM (CCA +mode) are shown here. +.RE .TP 8 .B -d, --domains -Shows the usage and control domains of the cryptographic devices. -The displayed domains of the cryptographic device depends on the initial +Shows the usage and control domains of the cryptographic devices. The +displayed domains of the cryptographic device depends on the initial cryptographic configuration. .RS .IP "o" 3 @@ -140,18 +168,20 @@ Here is an explanation of the columns displayed. Please note that some of the columns show up in verbose mode only. .TP .B CARD.DOM -The crypto card number in hexadecimal for a crypto card line or -the crypto card number and the domain id both in hex separated by a single +The crypto card number in hexadecimal for a crypto card line or the +crypto card number and the domain id both in hex separated by a single dot for a queue line. .TP .B TYPE and HWTYPE -The HWTYPE is a numeric value showing which type of hardware the zcrypt -device driver presumes that this crypto card is. The currently known values -are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5, 12=CEX6, 13=CEX7 and 14=CEX8. +The HWTYPE is a numeric value showing which type of hardware the +zcrypt device driver presumes that this crypto card is. The currently +known values are 7=CEX3C, 8=CEX3A, 10=CEX4, 11=CEX5, 12=CEX6, 13=CEX7 +and 14=CEX8. .br -The TYPE is a human readable value showing the hardware type and the basic -function type (A=Accelerator, C=CCA Coprocessor, P=EP11 Coprocessor). So -for example CEX6P means a CEX6 card in EP11 Coprocessor mode. +The TYPE is a human readable value showing the hardware type and the +basic function type (A=Accelerator, C=CCA Coprocessor, P=EP11 +Coprocessor). So for example CEX6P means a CEX6 card in EP11 +Coprocessor mode. .TP .B MODE A crypto card can be configured to run into one of 3 modes: @@ -170,13 +200,13 @@ online/offline state is kept by the zcrypt device driver and can be switched on or off with the help of the chzcrypt application. .br A crypto card can also be 'configured' or 'deconfigured'. This state -may be adjusted on the HMC or SE. The chzcrypt application can also -trigger this state with the --config-on and --config-off options. +may be adjusted on the HMC. The chzcrypt application can also trigger +this state with the --config-on and --config-off options. .br lszcrypt shows 'online' when a card or queue is available for cryptographic operations. 'offline' is displayed when a card or queue is switched to (software) offline. If a card is 'deconfigured' via -HMC, SE or chzcrypt the field shows 'deconfig'. +HMC or chzcrypt the field shows 'deconfig'. .br A crypto card may also reach a 'checkstopped' state. lszcrypt shows this as 'chkstop'. @@ -184,21 +214,22 @@ this as 'chkstop'. If a queue is not bound to a device driver there is no detailed information available and thus the status shows only '-'. .br -If a queue is bound to the vfio-ap device driver it is up to this driver -to give some status information and what exactly this means. So lszcrypt -shows the text retrieved from the underlying sysfs attribute here. +If a queue is bound to the vfio-ap device driver it is up to this +driver to give some status information and what exactly this means. So +lszcrypt shows the text retrieved from the underlying sysfs attribute +here. .TP .B REQUESTS -This is the counter value of successful processed requests on card or queue -level. Successful here means the request was processed without any failure -in the whole processing chain. +This is the counter value of successful processed requests on card or +queue level. Successful here means the request was processed without +any failure in the whole processing chain. .TP .B PENDING -The underlying firmware and hardware layer usually provide some queuing -space for requests. When this queue is already filled up, the zcrypt device -driver maintains a software queue of pending requests. The sum of these -both values is displayed here and shows the amount of requests waiting for -processing on card or queue level. +The underlying firmware and hardware layer usually provide some +queuing space for requests. When this queue is already filled up, the +zcrypt device driver maintains a software queue of pending +requests. The sum of these both values is displayed here and shows the +amount of requests waiting for processing on card or queue level. .TP .B FUNCTIONS This column shows firmware and hardware function details: @@ -224,48 +255,64 @@ F - Full function support (opposed to restricted function support, see below). .br R - Restricted function support. The F and R flag both reflect if a hypervisor is somehow restricting this crypto resource in a virtual -environment. Dependent on the hypervisor configuration the crypto requests -may be filtered by the hypervisor to allow only a subset of functions -within the virtual runtime environment. For example a shared CCA -Coprocessor may be restricted by the hypervisor to allow only clear key -operations within the guests. +environment. Dependent on the hypervisor configuration the crypto +requests may be filtered by the hypervisor to allow only a subset of +functions within the virtual runtime environment. For example a shared +CCA Coprocessor may be restricted by the hypervisor to allow only +clear key operations within the guests. .TP .B DRIVER .br Shows which card or queue device driver currently handles this crypto resource. Currently known drivers are cex4card/cex4queue (CEX4-CEX8 hardware), cex2card/cex2cqueue (CEX2C and CEX3C hardware), -cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue reserved -for use by kvm hypervisor for kvm guests and not accessible to host -applications). It is also valid to have no driver handling a queue which is -shown as a -no-driver- entry. +cex2acard/cex2aqueue (CEX2A and CEX3A hardware) and vfio_ap (queue +reserved for use by KVM hypervisor for KVM guests and not accessible +to host applications). It is also valid to have no driver handling a +queue which is shown as a -no-driver- entry. +.TP +.B SESTAT +.br +Shows the state of the BS bits associated with every AP queue within a +Secure Execution guest when AP Pass-through support is available: +.br +usable - AP queue is usable for crypto load. +.br +bound - AP queue is bound but not yet associated. +.br +unbound - AP queue is unbound and needs to get bound to this Secure +Execution guest. +.br +illicit - AP queue is not available for this Secure Execution guest. .SH NOTES -Use only one of the mode filtering options --accelonly, --ccaonly, --ep11only. -Same with card/queue filtering: Use only one of --cardonly, --queueonly. -However, one of the mode filtering options and one of the card/queue filtering -can be combined. +Use only one of the mode filtering options --accelonly, --ccaonly, +--ep11only. Same with card/queue filtering: Use only one of +--cardonly, --queueonly. However, one of the mode filtering options +and one of the card/queue filtering can be combined. .SH EXAMPLES .TP .B lszcrypt -Displays the card/domain ID, card type (short name), mode (long name), online -status and request count of all available cryptographic devices. +Displays the card/domain ID, card type (short name), mode (long name), +online status and request count of all available cryptographic +devices. .TP .B lszcrypt 1 3 5 -Displays the card/domain ID, card type, mode, online status and request count -for cryptographic devices 1, 3, and 5. +Displays the card/domain ID, card type, mode, online status and +request count for cryptographic devices 1, 3, and 5. .TP .B lszcrypt -V 3 7 11 -Displays the card/domain ID, card type, mode, online status, request count, -number of requests in the hardware queue, number of outstanding requests and -installed function facilities for cryptographic devices 3, 7 and 17 (0x11). +Displays the card/domain ID, card type, mode, online status, request +count, number of requests in the hardware queue, number of outstanding +requests and installed function facilities for cryptographic devices +3, 7 and 17 (0x11). .TP .B lszcrypt 10.0038 -Displays information of the cryptographic device '10.0038' respectively card -id 16 (0x10) with domain 56 (0x38). +Displays information of the cryptographic device '10.0038' +respectively card id 16 (0x10) with domain 56 (0x38). .TP .B lszcrypt .0038 -Displays information of all available queue devices (potentially multiple -adapters) with domain 56 (0x38). +Displays information of all available queue devices (potentially +multiple adapters) with domain 56 (0x38). .TP .B lszcrypt -b Displays AP bus information. diff --git a/zconf/zcrypt/lszcrypt.c b/zconf/zcrypt/lszcrypt.c index 43a3c39..09de77e 100644 --- a/zconf/zcrypt/lszcrypt.c +++ b/zconf/zcrypt/lszcrypt.c @@ -1,7 +1,7 @@ /** * lszcrypt - Display zcrypt devices and configuration settings * - * Copyright IBM Corp. 2008, 2022 + * Copyright IBM Corp. 2008, 2023 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -55,7 +55,7 @@ static struct lszcrypt_l { #define MASK_COPRO 0x10000000 #define MASK_ACCEL 0x08000000 #define MASK_EP11 0x04000000 -#define MASK_HSL 0x01000000 +#define MASK_HSL 0x01000000 /* * Classification @@ -85,6 +85,8 @@ static struct fac_bits_s { { 0x00400000, 'R' }, /* bit 9, restricted function set */ }; +#define EXTRACT_BS_BITS(f) (((f) & 0x0000c000UL) >> 14) + /* * Program configuration */ @@ -95,7 +97,7 @@ static const struct util_prg prg = { { .owner = "IBM Corp.", .pub_first = 2008, - .pub_last = 2020, + .pub_last = 2023, }, UTIL_PRG_COPYRIGHT_END } @@ -169,8 +171,9 @@ static struct util_opt opt_vec[] = { static void show_bus(void) { long domain, max_domain, config_time, value; - unsigned long long poll_timeout; const char *poll_thread, *ap_interrupts; + unsigned long long poll_timeout; + char features[256]; char *ap; /* check if ap driver is available */ @@ -178,6 +181,10 @@ static void show_bus(void) if (!util_path_is_dir(ap)) errx(EXIT_FAILURE, "Crypto device driver not available."); + if (util_path_is_readable("%s/features", ap)) + util_file_read_line(features, sizeof(features), "%s/features", ap); + else + features[0] = '\0'; util_file_read_l(&domain, 10, "%s/ap_domain", ap); util_file_read_l(&max_domain, 10, "%s/ap_max_domain_id", ap); util_file_read_l(&config_time, 10, "%s/config_time", ap); @@ -192,6 +199,8 @@ static void show_bus(void) ap_interrupts = "enabled"; else ap_interrupts = "disabled"; + if (features[0]) + printf("features: %s\n", features); printf("ap_domain=0x%lx\n", domain); printf("ap_max_domain_id=0x%lx\n", max_domain); if (util_path_is_reg_file("%s/ap_interrupts", ap)) @@ -374,23 +383,15 @@ next: } /* - * Show capability + * Show card capability */ -static void show_capability(const char *id_str) +static void show_card_capability(int id) { unsigned long func_val; - long hwtype, id, max_msg_size; - char *p, *ap, *dev, card[16], cbuf[256]; - - /* check if ap driver is available */ - ap = util_path_sysfs("bus/ap"); - if (!util_path_is_dir(ap)) - errx(EXIT_FAILURE, "Crypto device driver not available."); + long hwtype, max_msg_size; + char *dev, card[16], cbuf[256]; - id = strtol(id_str, &p, 0); - if (id < 0 || id > 255 || p == id_str || *p != '\0') - errx(EXIT_FAILURE, "Error - '%s' is an invalid cryptographic device id.", id_str); - snprintf(card, sizeof(card), "card%02lx", id); + snprintf(card, sizeof(card), "card%02x", id); dev = util_path_sysfs("devices/ap/%s", card); if (!util_path_is_dir(dev)) errx(EXIT_FAILURE, "Error - cryptographic device %s does not exist.", card); @@ -464,6 +465,78 @@ static void show_capability(const char *id_str) card, hwtype); break; } + + free(dev); +} + +/* + * Show queue capability + */ +static void show_queue_capability(int id, int dom) +{ + char *dev, card[16], queue[16], buf[256]; + + snprintf(card, sizeof(card), "card%02x", id); + snprintf(queue, sizeof(queue), "%02x.%04x", id, dom); + dev = util_path_sysfs("devices/ap/%s/%s", card, queue); + if (!util_path_is_dir(dev)) + errx(EXIT_FAILURE, "Error - cryptographic queue device %02x.%04x does not exist.", + id, dom); + + printf("queue %02x.%04x capabilities:\n", id, dom); + + if (util_path_is_reg_file("%s/se_bind", dev)) { + util_file_read_line(buf, sizeof(buf), "%s/se_bind", dev); + printf("SE bind state: %s\n", buf); + } + if (util_path_is_reg_file("%s/se_associate", dev)) { + util_file_read_line(buf, sizeof(buf), "%s/se_associate", dev); + printf("SE association state: %s\n", buf); + } + if (util_path_is_reg_file("%s/mkvps", dev)) { + char *mkvps = util_path_sysfs("devices/ap/%s/%s/mkvps", card, queue); + FILE *f = fopen(mkvps, "r"); + + if (!f) + errx(EXIT_FAILURE, "Error - failed to open sysfs file %s.", + mkvps); + while (fgets(buf, sizeof(buf), f)) { + if (strstr(buf, "WK CUR") || + strstr(buf, "AES CUR") || + strstr(buf, "APKA CUR") || + strstr(buf, "ASYM CUR")) + printf("MK %s", buf); /* no newline here */ + } + fclose(f); + free(mkvps); + } + + free(dev); +} + +/* + * Show capability + */ +static void show_capability(const char *id_str) +{ + char *p, *ap; + int id, dom; + + /* check if ap driver is available */ + ap = util_path_sysfs("bus/ap"); + if (!util_path_is_dir(ap)) + errx(EXIT_FAILURE, "Crypto device driver not available."); + + if (sscanf(id_str, "%x.%x", &id, &dom) == 2) { + show_queue_capability(id, dom); + } else { + id = strtol(id_str, &p, 0); + if (id < 0 || id > 255 || p == id_str || *p != '\0') + errx(EXIT_FAILURE, + "Error - '%s' is an invalid cryptographic device id.", + id_str); + show_card_capability(id); + } } /* @@ -601,11 +674,33 @@ static void read_subdev_rec_verbose(struct util_rec *rec, const char *grp_dev, util_file_read_l(&depth, 10, "%s/depth", grp_dev); util_rec_set(rec, "depth", "%02d", depth + 1); - util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev); + if (util_path_is_readable("%s/%s/ap_functions", grp_dev, sub_dev)) + util_file_read_ul(&facility, 16, "%s/%s/ap_functions", grp_dev, sub_dev); + else + util_file_read_ul(&facility, 16, "%s/ap_functions", grp_dev); for (i = 0; i < MAX_FAC_BITS; i++) buf[i] = facility & fac_bits[i].mask ? fac_bits[i].c : '-'; buf[i] = '\0'; util_rec_set(rec, "facility", buf); + + if (ap_bus_has_SB_support()) { + switch (EXTRACT_BS_BITS(facility)) { + case 0: + util_rec_set(rec, "sestat", "usable"); + break; + case 1: + util_rec_set(rec, "sestat", "bound"); + break; + case 2: + util_rec_set(rec, "sestat", "unbound"); + break; + case 3: + util_rec_set(rec, "sestat", "illicit"); + break; + default: + util_rec_set(rec, "sestat", "-"); + } + } } /* @@ -750,6 +845,9 @@ static void read_rec_verbose(struct util_rec *rec, const char *grp_dev) i = read_driver(grp_dev, NULL, buf, sizeof(buf)); util_rec_set(rec, "driver", i > 0 ? buf : "-no-driver-"); + + if (ap_bus_has_SB_support()) + util_rec_set(rec, "sestat", "-"); } /* @@ -818,6 +916,8 @@ static void define_rec_verbose(struct util_rec *rec) util_rec_def(rec, "depth", UTIL_REC_ALIGN_RIGHT, 6, "QDEPTH"); util_rec_def(rec, "facility", UTIL_REC_ALIGN_LEFT, 10, "FUNCTIONS"); util_rec_def(rec, "driver", UTIL_REC_ALIGN_LEFT, 11, "DRIVER"); + if (ap_bus_has_SB_support()) + util_rec_def(rec, "sestat", UTIL_REC_ALIGN_LEFT, 11, "SESTAT"); } /* diff --git a/zconf/zcrypt/misc.c b/zconf/zcrypt/misc.c index 4296cb1..05913d6 100644 --- a/zconf/zcrypt/misc.c +++ b/zconf/zcrypt/misc.c @@ -1,16 +1,20 @@ /* * Misc - Local helper functions * - * Copyright IBM Corp. 2016, 2017 + * Copyright IBM Corp. 2016, 2023 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include +#include #include +#include "lib/util_base.h" +#include "lib/util_file.h" #include "lib/util_panic.h" +#include "lib/util_path.h" #include "misc.h" /** @@ -35,3 +39,35 @@ bool misc_regex_match(const char *str, const char *regex) regfree(&preg); return rc == 0 ? true : false; } + +/** + * Test if AP bus has SB support available. + * + * @returns true Yes, SB support is available + * false No + */ +bool ap_bus_has_SB_support(void) +{ + static int sb_support = -1; + + if (sb_support < 0) { + char *ap, buf[256]; + + ap = util_path_sysfs("bus/ap"); + if (!util_path_is_dir(ap)) { + sb_support = 0; + } else { + if (!util_path_is_readable("%s/features", ap)) { + sb_support = 0; + } else { + util_file_read_line(buf, sizeof(buf), + "%s/features", ap); + if (strstr(buf, "APSB")) + sb_support = 1; + } + } + free(ap); + } + + return sb_support > 0 ? true : false; +} diff --git a/zconf/zcrypt/misc.h b/zconf/zcrypt/misc.h index 502a687..92cf453 100644 --- a/zconf/zcrypt/misc.h +++ b/zconf/zcrypt/misc.h @@ -1,7 +1,7 @@ /* * misc - Local helper functions * - * Copyright IBM Corp. 2016, 2017 + * Copyright IBM Corp. 2016, 2023 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -13,5 +13,6 @@ #include bool misc_regex_match(const char *str, const char *regex); +bool ap_bus_has_SB_support(void); #endif /* MISC_H */ -- 2.40.1 From 4b8726135731ee039d8eb33566bfa051b66b7bfb Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Wed, 17 May 2023 13:13:09 +0200 Subject: [PATCH 3/3] chzcrypt: Support for SE bind, unbind and associate (#2110510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for Secure Execution with AP pass-through support for chzcrypt. chzcrypt details: * new command: --se-associate * new command: --se-bind * new command: --se-unbind Signed-off-by: Harald Freudenberger Reviewed-by: Holger Dengler Signed-off-by: Jan Höppner (cherry picked from commit e35e73d2a3f60d43b109168cc37f9c43bc35b0a4) --- zconf/zcrypt/chzcrypt.8 | 72 +++++++---- zconf/zcrypt/chzcrypt.c | 278 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 310 insertions(+), 40 deletions(-) diff --git a/zconf/zcrypt/chzcrypt.8 b/zconf/zcrypt/chzcrypt.8 index a73ff27..94e32fb 100644 --- a/zconf/zcrypt/chzcrypt.8 +++ b/zconf/zcrypt/chzcrypt.8 @@ -1,10 +1,16 @@ .\" chzcrypt.8 .\" -.\" Copyright 2020 IBM Corp. +.\" Copyright 2020, 2023 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. .\" -.TH CHZCRYPT 8 "OCT 2020" "s390-tools" +.\" use +.\" groff -man -Tutf8 chzcrypt.8 +.\" or +.\" nroff -man chzcrypt.8 +.\" to process this source +.\" +.TH CHZCRYPT 8 "MAY 2023" "s390-tools" .SH NAME chzcrypt \- modify zcrypt configuration .SH SYNOPSIS @@ -46,8 +52,8 @@ chzcrypt \- modify zcrypt configuration .SH DESCRIPTION The .B chzcrypt -command is used to configure cryptographic devices managed by zcrypt and -modify zcrypt's AP bus attributes. +command is used to configure cryptographic devices managed by zcrypt +and modify zcrypt's AP bus attributes. Attributes may vary depending on the kernel version. @@ -70,19 +76,6 @@ Set the given cryptographic card device(s) config on ('configured'). .B --config-off Set the given cryptographic card device(s) config off ('deconfigured'). .TP 8 -.B -Specifies a cryptographic device which will be set either online or -offline or configured on or off. For online and offline the device can -either be a card device or a queue device. A queue device can only get -switched online when the providing card is online. -.br -For config on/off the device needs to be a card device. A card or -queue device cannot get switched online if the card is in deconfigured -state. -.br -Please note that the card device and queue device representation are both -in hexadecimal notation. -.TP 8 .B -p, --poll-thread-enable Enable zcrypt's poll thread. .TP 8 @@ -94,15 +87,28 @@ Set configuration timer for re-scanning the AP bus to .I seconds. .TP 8 +.B --se-associate +Associate the given queue device with the given association +index. This command is only valid within an Secure Execution guest +with AP pass-through support enabled. +.TP 8 +.B --se-bind +Bind the given queue device. This command is only valid within an +Secure Execution guest with AP pass-through support enabled. +.TP 8 +.B --se-unbind +Unbind the given queue device. This command is only valid within an +Secure Execution guest with AP pass-through support enabled. +.TP 8 .BI "-t, --poll-timeout" " " Set poll timer to run poll tasklet all .I nanoseconds. .TP 8 .BI "-q, --default-domain" " " -Set the new default domain of the AP bus to . -The number of available domains can be retrieved with the lszcrypt -command ('-d' option). +Set the new default domain of the AP bus to . The number of +available domains can be retrieved with the lszcrypt command ('-d' +option). .TP 8 .B -V, --verbose Print verbose messages. @@ -112,6 +118,22 @@ Print help text and exit. .TP 8 .B -v, --version Print version information and exit. +.TP 8 +.B +Specifies a cryptographic device which will be set either online or +offline or configured on or off. For online and offline the device can +either be a card device or a queue device. A queue device can only get +switched online when the providing card is online. +.br +For config on/off the device needs to be a card device. A card or +queue device cannot get switched online if the card is in deconfigured +state. +.br +Please note that the card device and queue device representation are +both in hexadecimal notation. +.TP 8 +.B +An APQN queue device given as xy.abcd as it is listed by lszcrypt -V. .SH EXAMPLES .TP .B chzcrypt -e 0 1 12 @@ -131,8 +153,8 @@ Set all available crypto cards to config on, be verbose. Switch the two crypto cards 1 and 3 to deconfigured, be verbose. .TP .B chzcrypt -c 60 -n -Will set configuration timer for re-scanning the AP bus to 60 seconds and -disable zcrypt's poll thread. +Will set configuration timer for re-scanning the AP bus to 60 seconds +and disable zcrypt's poll thread. .TP .B chzcrypt -q 67 Will set the default domain to 67. @@ -144,5 +166,11 @@ chzcrypt exits with an appropriate message. Even more config on/off may require support from a hypervisor like KVM or zVM and may fail if the Linux kernel is unable to perform the SCLP command. Check syslog on failure. +.TP +Bind, associate and unbind command on an queue device are only +available and valid within an Secure Execution environment with AP +pass-through enabled and a Linux kernel providing the low level sysfs +API. If these conditions are not fulfilled, the command will fail with +an appropriate error messages. .SH SEE ALSO \fBlszcrypt\fR(8) diff --git a/zconf/zcrypt/chzcrypt.c b/zconf/zcrypt/chzcrypt.c index 68b36a5..b04bcfa 100644 --- a/zconf/zcrypt/chzcrypt.c +++ b/zconf/zcrypt/chzcrypt.c @@ -1,7 +1,7 @@ /* * chzcrypt - Tool to modify zcrypt configuration * - * Copyright IBM Corp. 2008, 2020 + * Copyright IBM Corp. 2008, 2023 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -28,6 +28,12 @@ #include "misc.h" +/* max seconds the se-association command will wait for completion */ +#define MAX_ASSOC_POLL_TIME_IN_S 30 + +/* max seconds the se-unbind command will wait for unbind complete */ +#define MAX_UNBIND_POLL_TIME_IN_S 30 + /* * Private data */ @@ -45,7 +51,7 @@ static const struct util_prg prg = { { .owner = "IBM Corp.", .pub_first = 2008, - .pub_last = 2020, + .pub_last = 2023, }, UTIL_PRG_COPYRIGHT_END } @@ -57,6 +63,9 @@ static const struct util_prg prg = { #define OPT_CONFIG_ON 0x80 #define OPT_CONFIG_OFF 0x81 +#define OPT_SE_ASSOC 0x82 +#define OPT_SE_BIND 0x83 +#define OPT_SE_UNBIND 0x84 static struct util_opt opt_vec[] = { { @@ -116,6 +125,22 @@ static struct util_opt opt_vec[] = { .option = { "verbose", no_argument, NULL, 'V'}, .desc = "Print verbose messages", }, + { + .option = { "se-associate", required_argument, NULL, OPT_SE_ASSOC}, + .argument = "assoc_idx", + .flags = UTIL_OPT_FLAG_NOSHORT, + .desc = "SE guest with AP support only: Associate the given queue device", + }, + { + .option = { "se-bind", no_argument, NULL, OPT_SE_BIND}, + .flags = UTIL_OPT_FLAG_NOSHORT, + .desc = "SE guest with AP support only: Bind the given queue device", + }, + { + .option = { "se-unbind", no_argument, NULL, OPT_SE_UNBIND}, + .flags = UTIL_OPT_FLAG_NOSHORT, + .desc = "SE guest with AP support only: Unbind the given queue device", + }, UTIL_OPT_HELP, UTIL_OPT_VERSION, UTIL_OPT_END @@ -336,6 +361,186 @@ next: } } +static void se_assoc(const char *assoc_idx, const char *dev) +{ + int i, idx, rc, ap, dom, loop; + char *dev_path, *attr; + char buf[256]; + + if (!ap_bus_has_SB_support()) + errx(EXIT_FAILURE, "Error - AP bus: SE bind support is not available."); + + if (sscanf(dev, "%02x.%04x", &ap, &dom) != 2) + errx(EXIT_FAILURE, "Error - Can't parse queue device '%s' as xy.abcd.", + dev); + dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x", + ap, ap, dom); + if (!util_path_is_dir(dev_path)) + errx(EXIT_FAILURE, "Error - Queue device %s does not exist.", + dev); + + if (sscanf(assoc_idx, "%i", &idx) != 1) + errx(EXIT_FAILURE, "Error - Can't parse association index '%s' as number.", + assoc_idx); + if (idx < 0 || idx > 0xFFFF) + errx(EXIT_FAILURE, "Error - Association index needs to be in range [0...%d].", + 0xffff); + + attr = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/se_associate", + ap, ap, dom); + if (!util_path_is_writable(attr)) + errx(EXIT_FAILURE, "Error - Can't write to %s (errno '%s').", + attr, strerror(errno)); + + /* read se_associate attribute and check for 'unassociated' */ + rc = util_file_read_line(buf, sizeof(buf), attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure reading from %s (errno '%s').", + attr, strerror(errno)); + if (strcmp(buf, "unassociated")) + errx(EXIT_FAILURE, + "Error - Queue device %s is NOT in 'unassociated' state (state '%s' found).", + dev, buf); + + /* write assocition index to the se_associate attribute */ + rc = util_file_write_l(idx, 10, attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure writing to %s (errno '%s').", + attr, strerror(errno)); + + /* loop up to MAX_ASSOC_POLL_TIME_IN_S seconds for completion */ + for (loop = 0; loop < 2 * MAX_ASSOC_POLL_TIME_IN_S; usleep(500000), loop++) { + rc = util_file_read_line(buf, sizeof(buf), attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure reading from %s (errno '%s').", + attr, strerror(errno)); + if (!strncmp(buf, "associated", strlen("associated"))) + break; + if (!strcmp(buf, "unassociated")) + errx(EXIT_FAILURE, + "Error - Failure associating queue device %s (state '%s' found).", + dev, buf); + } + if (loop >= 2 * MAX_ASSOC_POLL_TIME_IN_S) + errx(EXIT_FAILURE, + "Error - Failure associating queue device %s (timeout after %d s).", + dev, MAX_ASSOC_POLL_TIME_IN_S); + + if (sscanf(buf, "associated %d", &i) != 1 || idx != i) + errx(EXIT_FAILURE, + "Error - Failure associating queue device %s (state '%s' found).", + dev, buf); + + verbose("Queue device %s successful associated with index %d.\n", + dev, idx); + + free(dev_path); + free(attr); +} + +static void se_bind(const char *dev) +{ + char *dev_path, *attr; + int rc, ap, dom; + char buf[256]; + + if (!ap_bus_has_SB_support()) + errx(EXIT_FAILURE, "Error - AP bus: SE bind support is not available."); + + if (sscanf(dev, "%02x.%04x", &ap, &dom) != 2) + errx(EXIT_FAILURE, "Error - Can't parse queue device '%s' as xy.abcd.", + dev); + dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x", + ap, ap, dom); + if (!util_path_is_dir(dev_path)) + errx(EXIT_FAILURE, "Error - Queue device %s does not exist.", + dev); + + attr = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/se_bind", + ap, ap, dom); + if (!util_path_is_writable(attr)) + errx(EXIT_FAILURE, "Error - Can't write to %s (errno '%s').", + attr, strerror(errno)); + + /* read se_bind attribute and check for 'unboud' */ + rc = util_file_read_line(buf, sizeof(buf), attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure reading from %s (errno '%s').", + attr, strerror(errno)); + if (strcmp(buf, "unbound")) + errx(EXIT_FAILURE, + "Error - Queue device %s is NOT in 'unbound' state (state '%s' found).", + dev, buf); + + /* write se_bind attribute, check for 'bound' afterwards */ + rc = util_file_write_l(1, 10, attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure writing to %s (errno '%s').", + attr, strerror(errno)); + rc = util_file_read_line(buf, sizeof(buf), attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure reading from %s (errno '%s').", + attr, strerror(errno)); + if (strcmp(buf, "bound")) + errx(EXIT_FAILURE, "Error - Failure binding queue device %s (state '%s' found).", + dev, buf); + + verbose("Queue device %s successful bound.\n", dev); + + free(dev_path); + free(attr); +} + +static void se_unbind(const char *dev) +{ + int rc, ap, dom, loop; + char *dev_path, *attr; + char buf[256]; + + if (!ap_bus_has_SB_support()) + errx(EXIT_FAILURE, "Error - AP bus: SE bind support is not available."); + + if (sscanf(dev, "%02x.%04x", &ap, &dom) != 2) + errx(EXIT_FAILURE, "Error - Can't parse queue device '%s' as xy.abcd.", + dev); + dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x", + ap, ap, dom); + if (!util_path_is_dir(dev_path)) + errx(EXIT_FAILURE, "Error - Queue device %s does not exist.", + dev); + + attr = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/se_bind", + ap, ap, dom); + if (!util_path_is_writable(attr)) + errx(EXIT_FAILURE, "Error - Can't write to %s (errno '%s').", + attr, strerror(errno)); + + /* write se_bind attribute */ + rc = util_file_write_l(0, 10, attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure writing to %s (errno '%s').", + attr, strerror(errno)); + + /* loop up to MAX_UNBIND_POLL_TIME_IN_S seconds for completion */ + for (loop = 0; loop < 2 * MAX_UNBIND_POLL_TIME_IN_S; usleep(500000), loop++) { + rc = util_file_read_line(buf, sizeof(buf), attr); + if (rc) + errx(EXIT_FAILURE, "Error - Failure reading from %s (errno '%s').", + attr, strerror(errno)); + if (!strcmp(buf, "unbound")) + break; + } + if (loop >= 2 * MAX_UNBIND_POLL_TIME_IN_S) + errx(EXIT_FAILURE, + "Error - Failure unbinding queue device %s (timeout after %d s).", + dev, MAX_UNBIND_POLL_TIME_IN_S); + + verbose("Queue device %s successful unbound.\n", dev); + + free(dev_path); + free(attr); +} + /* * Print invalid commandline error message and then exit with error code */ @@ -389,10 +594,10 @@ static void print_adapter_id_help(void) printf("DEVICE_IDS\n"); printf(" List of cryptographic device ids separated by blanks which will be set\n"); printf(" online/offline. Must be used in conjunction with the enable or disable option.\n"); - printf(" DEVICE_ID could either be card device id ('') or queue device id\n"); - printf(" '.').\n"); - printf(" \n"); + printf(" '.').\n\n"); + printf("QUEUE_DEVICE:\n"); + printf(" An APQN queue device given as xy.abcd as it is listed by lszcrypt -V.\n\n"); printf("EXAMPLE:\n"); printf(" Disable the cryptographic device with card id '02' (inclusive all queues).\n"); printf(" #>chzcrypt -d 02\n"); @@ -407,13 +612,14 @@ static void print_adapter_id_help(void) */ int main(int argc, char *argv[]) { + const char *default_domain = NULL, *config = NULL, *config_text = NULL; const char *online = NULL, *online_text = NULL, *poll_thread = NULL; const char *config_time = NULL, *poll_timeout = NULL; - const char *default_domain = NULL, *config = NULL, *config_text = NULL; + const char *queue_device = NULL, *assoc_idx = NULL; + int c, i, j, action = 0; char *path, *dev_list; - bool all = false, actionset = false; + bool all = false; size_t len; - int c, i, j; for (i=0; i < argc; i++) for (j=2; j < (int) strlen(argv[i]); j++) @@ -428,12 +634,12 @@ int main(int argc, char *argv[]) break; switch (c) { case 'e': - actionset = true; + action = c; online = "1"; online_text = "online"; break; case 'd': - actionset = true; + action = c; online = "0"; online_text = "offline"; break; @@ -441,23 +647,23 @@ int main(int argc, char *argv[]) all = true; break; case 'p': - actionset = true; + action = c; poll_thread = "1"; break; case 'n': - actionset = true; + action = c; poll_thread = "0"; break; case 'c': - actionset = true; + action = c; config_time = optarg; break; case 't': - actionset = true; + action = c; poll_timeout = optarg; break; case 'q': - actionset = true; + action = c; default_domain = optarg; break; case 'V': @@ -472,21 +678,31 @@ int main(int argc, char *argv[]) util_prg_print_version(); return EXIT_SUCCESS; case OPT_CONFIG_ON: - actionset = true; + action = c; config = "1"; config_text = "config on"; break; case OPT_CONFIG_OFF: - actionset = true; + action = c; config = "0"; config_text = "config off"; break; + case OPT_SE_ASSOC: + action = c; + assoc_idx = optarg; + break; + case OPT_SE_BIND: + action = c; + break; + case OPT_SE_UNBIND: + action = c; + break; default: util_opt_print_parse_error(c, argv); return EXIT_FAILURE; } } - if (!actionset) + if (!action) invalid_cmdline_exit("Error - missing argument.\n"); path = util_path_sysfs("bus/ap"); if (!util_path_is_dir(path)) @@ -508,6 +724,32 @@ int main(int argc, char *argv[]) default_domain_set(default_domain); return EXIT_SUCCESS; } + + if (action == OPT_SE_ASSOC) { + if (optind >= argc) + errx(EXIT_FAILURE, + "Error - The --se-associate needs a queue device given."); + queue_device = argv[optind]; + se_assoc(assoc_idx, queue_device); + return EXIT_SUCCESS; + } + if (action == OPT_SE_BIND) { + if (optind >= argc) + errx(EXIT_FAILURE, + "Error - The --se-bind needs a queue device given."); + queue_device = argv[optind]; + se_bind(queue_device); + return EXIT_SUCCESS; + } + if (action == OPT_SE_UNBIND) { + if (optind >= argc) + errx(EXIT_FAILURE, + "Error - The --se-unbind needs a queue device given."); + queue_device = argv[optind]; + se_unbind(queue_device); + return EXIT_SUCCESS; + } + if (all) dev_list_all(&dev_list, &len); else -- 2.40.1