s390/ap/zcrypt: New xflag parameter
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 24 Apr 2025 13:35:59 +0000 (15:35 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 30 Apr 2025 09:34:00 +0000 (11:34 +0200)
Introduce a new flag parameter for the both cprb send functions
zcrypt_send_cprb() and zcrypt_send_ep11_cprb(). This new
xflags parameter ("execution flags") shall be used to provide
execution hints and flags for this crypto request.

There are two flags implemented to be used with these functions:
* ZCRYPT_XFLAG_USERSPACE - indicates to the lower layers that
  all the ptrs address userspace. So when construction the ap msg
  copy_from_user() is to be used. If this flag is NOT set, the ptrs
  address kernel memory and thus memcpy() is to be used.
* ZCRYPT_XFLAG_NOMEMALLOC - indicates that this task must not
  allocate memory which may be allocated with io operations.

For the AP bus and zcrypt message layer this means:
* The ZCRYPT_XFLAG_USERSPACE is mapped to the already existing
  bool variable "userspace" which is propagated to the zcrypt
  proto implementations.
* The ZCRYPT_XFLAG_NOMEMALLOC results in setting the AP flag
  AP_MSG_FLAG_MEMPOOL when the AP msg buffer is initialized.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Link: https://lore.kernel.org/r/20250424133619.16495-6-freude@linux.ibm.com
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_ep11misc.c

index 1e4784e9efd1ac7f8b036462262cd030bd12f8fa..288734cd8f4b953d7a523954212e37b4cd8c865b 100644 (file)
@@ -572,18 +572,18 @@ static void ap_poll_thread_stop(void)
 /*
  * ap_init_apmsg() - Initialize ap_message.
  */
-int ap_init_apmsg(struct ap_message *ap_msg, bool use_mempool)
+int ap_init_apmsg(struct ap_message *ap_msg, u32 flags)
 {
        unsigned int maxmsgsize;
 
        memset(ap_msg, 0, sizeof(*ap_msg));
+       ap_msg->flags = flags;
 
-       if (use_mempool) {
+       if (flags & AP_MSG_FLAG_MEMPOOL) {
                ap_msg->msg = mempool_alloc_preallocated(ap_msg_pool);
                if (!ap_msg->msg)
                        return -ENOMEM;
                ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
-               ap_msg->flags |= AP_MSG_FLAG_MEMPOOL;
                return 0;
        }
 
index 60c41d8116ad3ae4c0871b24c8808296142ed6bd..88b625ba197802d32e051a6866939e4febe90fa7 100644 (file)
@@ -238,7 +238,7 @@ struct ap_message {
 #define AP_MSG_FLAG_ADMIN    0x0004    /* CCA, EP11: admin (=control) msg */
 #define AP_MSG_FLAG_MEMPOOL  0x0008 /* ap msg buffer allocated via mempool */
 
-int ap_init_apmsg(struct ap_message *ap_msg, bool use_mempool);
+int ap_init_apmsg(struct ap_message *ap_msg, u32 flags);
 void ap_release_apmsg(struct ap_message *ap_msg);
 
 enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
index b299cdb73826f945c9a2daf1162cb39c08029657..3a75c3b6c004457daddb59f68421e5464ddc1ab6 100644 (file)
@@ -648,7 +648,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
 
        trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO);
 
-       rc = ap_init_apmsg(&ap_msg, false);
+       rc = ap_init_apmsg(&ap_msg, 0);
        if (rc)
                goto out;
 
@@ -753,7 +753,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
 
        trace_s390_zcrypt_req(crt, TP_ICARSACRT);
 
-       rc = ap_init_apmsg(&ap_msg, false);
+       rc = ap_init_apmsg(&ap_msg, 0);
        if (rc)
                goto out;
 
@@ -844,10 +844,11 @@ out:
        return rc;
 }
 
-static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
+static long _zcrypt_send_cprb(u32 xflags, struct ap_perms *perms,
                              struct zcrypt_track *tr,
                              struct ica_xcRB *xcrb)
 {
+       bool userspace = xflags & ZCRYPT_XFLAG_USERSPACE;
        struct zcrypt_card *zc, *pref_zc;
        struct zcrypt_queue *zq, *pref_zq;
        struct ap_message ap_msg;
@@ -861,7 +862,8 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
 
        xcrb->status = 0;
 
-       rc = ap_init_apmsg(&ap_msg, false);
+       rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
+                          AP_MSG_FLAG_MEMPOOL : 0);
        if (rc)
                goto out;
 
@@ -977,7 +979,7 @@ out:
        return rc;
 }
 
-long zcrypt_send_cprb(struct ica_xcRB *xcrb)
+long zcrypt_send_cprb(struct ica_xcRB *xcrb, u32 xflags)
 {
        struct zcrypt_track tr;
        int rc;
@@ -985,13 +987,13 @@ long zcrypt_send_cprb(struct ica_xcRB *xcrb)
        memset(&tr, 0, sizeof(tr));
 
        do {
-               rc = _zcrypt_send_cprb(false, &ap_perms, &tr, xcrb);
+               rc = _zcrypt_send_cprb(xflags, &ap_perms, &tr, xcrb);
        } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
 
        /* on ENODEV failure: retry once again after a requested rescan */
        if (rc == -ENODEV && zcrypt_process_rescan())
                do {
-                       rc = _zcrypt_send_cprb(false, &ap_perms, &tr, xcrb);
+                       rc = _zcrypt_send_cprb(xflags, &ap_perms, &tr, xcrb);
                } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
        if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
                rc = -EIO;
@@ -1029,10 +1031,11 @@ static bool is_desired_ep11_queue(unsigned int dev_qid,
        return false;
 }
 
-static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
+static long _zcrypt_send_ep11_cprb(u32 xflags, struct ap_perms *perms,
                                   struct zcrypt_track *tr,
                                   struct ep11_urb *xcrb)
 {
+       bool userspace = xflags & ZCRYPT_XFLAG_USERSPACE;
        struct zcrypt_card *zc, *pref_zc;
        struct zcrypt_queue *zq, *pref_zq;
        struct ep11_target_dev *targets = NULL;
@@ -1045,7 +1048,8 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
 
        trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);
 
-       rc = ap_init_apmsg(&ap_msg, false);
+       rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
+                          AP_MSG_FLAG_MEMPOOL : 0);
        if (rc)
                goto out;
 
@@ -1177,7 +1181,7 @@ out:
        return rc;
 }
 
-long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
+long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb, u32 xflags)
 {
        struct zcrypt_track tr;
        int rc;
@@ -1185,13 +1189,13 @@ long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
        memset(&tr, 0, sizeof(tr));
 
        do {
-               rc = _zcrypt_send_ep11_cprb(false, &ap_perms, &tr, xcrb);
+               rc = _zcrypt_send_ep11_cprb(xflags, &ap_perms, &tr, xcrb);
        } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
 
        /* on ENODEV failure: retry once again after a requested rescan */
        if (rc == -ENODEV && zcrypt_process_rescan())
                do {
-                       rc = _zcrypt_send_ep11_cprb(false, &ap_perms, &tr, xcrb);
+                       rc = _zcrypt_send_ep11_cprb(xflags, &ap_perms, &tr, xcrb);
                } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
        if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
                rc = -EIO;
@@ -1215,7 +1219,7 @@ static long zcrypt_rng(char *buffer)
 
        trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
 
-       rc = ap_init_apmsg(&ap_msg, false);
+       rc = ap_init_apmsg(&ap_msg, 0);
        if (rc)
                goto out;
        rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);
@@ -1528,6 +1532,7 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg)
        int rc;
        struct ica_xcRB xcrb;
        struct zcrypt_track tr;
+       u32 xflags = ZCRYPT_XFLAG_USERSPACE;
        struct ica_xcRB __user *uxcrb = (void __user *)arg;
 
        memset(&tr, 0, sizeof(tr));
@@ -1535,13 +1540,13 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg)
                return -EFAULT;
 
        do {
-               rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb);
+               rc = _zcrypt_send_cprb(xflags, perms, &tr, &xcrb);
        } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
 
        /* on ENODEV failure: retry once again after a requested rescan */
        if (rc == -ENODEV && zcrypt_process_rescan())
                do {
-                       rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb);
+                       rc = _zcrypt_send_cprb(xflags, perms, &tr, &xcrb);
                } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
        if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
                rc = -EIO;
@@ -1558,6 +1563,7 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg)
        int rc;
        struct ep11_urb xcrb;
        struct zcrypt_track tr;
+       u32 xflags = ZCRYPT_XFLAG_USERSPACE;
        struct ep11_urb __user *uxcrb = (void __user *)arg;
 
        memset(&tr, 0, sizeof(tr));
@@ -1565,13 +1571,13 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg)
                return -EFAULT;
 
        do {
-               rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb);
+               rc = _zcrypt_send_ep11_cprb(xflags, perms, &tr, &xcrb);
        } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
 
        /* on ENODEV failure: retry once again after a requested rescan */
        if (rc == -ENODEV && zcrypt_process_rescan())
                do {
-                       rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb);
+                       rc = _zcrypt_send_ep11_cprb(xflags, perms, &tr, &xcrb);
                } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
        if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
                rc = -EIO;
@@ -1832,6 +1838,7 @@ static long trans_xcrb32(struct ap_perms *perms, struct file *filp,
                         unsigned int cmd, unsigned long arg)
 {
        struct compat_ica_xcrb __user *uxcrb32 = compat_ptr(arg);
+       u32 xflags = ZCRYPT_XFLAG_USERSPACE;
        struct compat_ica_xcrb xcrb32;
        struct zcrypt_track tr;
        struct ica_xcRB xcrb64;
@@ -1861,13 +1868,13 @@ static long trans_xcrb32(struct ap_perms *perms, struct file *filp,
        xcrb64.priority_window = xcrb32.priority_window;
        xcrb64.status = xcrb32.status;
        do {
-               rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb64);
+               rc = _zcrypt_send_cprb(xflags, perms, &tr, &xcrb64);
        } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
 
        /* on ENODEV failure: retry once again after a requested rescan */
        if (rc == -ENODEV && zcrypt_process_rescan())
                do {
-                       rc = _zcrypt_send_cprb(true, perms, &tr, &xcrb64);
+                       rc = _zcrypt_send_cprb(xflags, perms, &tr, &xcrb64);
                } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
        if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
                rc = -EIO;
index 4ed481df57ca4addaf914204bbeb17f54993c58b..44f158329545122362dca641bab9b17e403c4234 100644 (file)
@@ -76,6 +76,13 @@ struct zcrypt_track {
 #define TRACK_AGAIN_CARD_WEIGHT_PENALTY  1000
 #define TRACK_AGAIN_QUEUE_WEIGHT_PENALTY 10000
 
+/*
+ * xflags - to be used with zcrypt_send_cprb() and
+ * zcrypt_send_ep11_cprb() for the xflags parameter.
+ */
+#define ZCRYPT_XFLAG_USERSPACE 0x0001  /* data ptrs address userspace */
+#define ZCRYPT_XFLAG_NOMEMALLOC 0x0002 /* do not allocate memory via kmalloc */
+
 struct zcrypt_ops {
        long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *,
                            struct ap_message *);
@@ -161,8 +168,8 @@ void zcrypt_msgtype_unregister(struct zcrypt_ops *);
 struct zcrypt_ops *zcrypt_msgtype(unsigned char *, int);
 int zcrypt_api_init(void);
 void zcrypt_api_exit(void);
-long zcrypt_send_cprb(struct ica_xcRB *xcRB);
-long zcrypt_send_ep11_cprb(struct ep11_urb *urb);
+long zcrypt_send_cprb(struct ica_xcRB *xcRB, u32 xflags);
+long zcrypt_send_ep11_cprb(struct ep11_urb *urb, u32 xflags);
 void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus);
 int zcrypt_device_status_ext(int card, int queue,
                             struct zcrypt_device_status_ext *devstatus);
index 43a27cb3db847e17e048a0d19fc58d536a59f570..521baaea06ffefcd42311264ff3e00f33beb0730 100644 (file)
@@ -379,7 +379,7 @@ int cca_genseckey(u16 cardnr, u16 domain,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -517,7 +517,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -644,7 +644,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -872,7 +872,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -1038,7 +1038,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -1249,7 +1249,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -1412,7 +1412,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -1526,7 +1526,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
        prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
        /* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-       rc = zcrypt_send_cprb(&xcrb);
+       rc = zcrypt_send_cprb(&xcrb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
index cb7e6da43602d4ffb0839c0c9dfc8389dcf80b50..b60e262bcaa384be1679b34328cde2a6d787c399 100644 (file)
@@ -636,7 +636,7 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
                 req, sizeof(*req) + sizeof(*req_pl),
                 rep, sizeof(*rep) + sizeof(*rep_pl) + buflen);
 
-       rc = zcrypt_send_ep11_cprb(urb);
+       rc = zcrypt_send_ep11_cprb(urb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
                               __func__, (int)cardnr, (int)domain, rc);
@@ -892,7 +892,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
                 req, sizeof(*req) + req_pl_size,
                 rep, sizeof(*rep) + sizeof(*rep_pl));
 
-       rc = zcrypt_send_ep11_cprb(urb);
+       rc = zcrypt_send_ep11_cprb(urb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
                               __func__, (int)card, (int)domain, rc);
@@ -1049,7 +1049,7 @@ static int ep11_cryptsingle(u16 card, u16 domain,
                 req, sizeof(*req) + req_pl_size,
                 rep, sizeof(*rep) + rep_pl_size);
 
-       rc = zcrypt_send_ep11_cprb(urb);
+       rc = zcrypt_send_ep11_cprb(urb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
                               __func__, (int)card, (int)domain, rc);
@@ -1212,7 +1212,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
                 req, sizeof(*req) + req_pl_size,
                 rep, sizeof(*rep) + sizeof(*rep_pl));
 
-       rc = zcrypt_send_ep11_cprb(urb);
+       rc = zcrypt_send_ep11_cprb(urb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
                               __func__, (int)card, (int)domain, rc);
@@ -1372,7 +1372,7 @@ static int _ep11_wrapkey(u16 card, u16 domain,
                 req, sizeof(*req) + req_pl_size,
                 rep, sizeof(*rep) + sizeof(*rep_pl));
 
-       rc = zcrypt_send_ep11_cprb(urb);
+       rc = zcrypt_send_ep11_cprb(urb, 0);
        if (rc) {
                ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
                               __func__, (int)card, (int)domain, rc);