* [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches
@ 2025-02-23 9:54 Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct Harald Freudenberger
` (19 more replies)
0 siblings, 20 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
This series of patches has the goal to open up a do-not-allocate
memory path from the callers of the pkey in-kernel api down to
the crypto cards and back.
The asynch in-kernel cipher implementations (and the s390 PAES
cipher implementations are one of them) may be called in a
context where memory allocations which trigger IO is not acceptable.
So this patch series reworks the AP bus code, the zcrypt layer,
the pkey layer and the pkey handlers to respect this situation
by processing a new parameter xflags (execution hints flags).
There is a flag PKEY_XFLAG_NOMEMALLOC which tells the code to
not allocate memory which may lead to IO operations.
To reach this goal, the actual code changes have been differed.
The zcrypt misc functions which need memory for cprb build
use a pre allocated memory pool for this purpose. The findcard()
functions have one temp memory area preallocated and protected
with a mutex. Some smaller data is not allocated any more but went
to the stack instead. The AP bus also uses a pre-allocated
memory pool for building AP message requests.
Note that the PAES implementation still needs to get reworked
to run the protected key derivation in a real asynchronous way.
However, this rework of AP bus, zcrypt and pkey is the base work
required before reconsidering the PAES implementation.
The patch series starts bottom (AP bus) and goes up the call
chain (PKEY). At any time in the patch stack it should compile.
For easier review I tried to have one logic code change by
each patch and thus keep the patches "small". For the upstream
version I intend to fold them together into only a few commits.
Harald Freudenberger (20):
s390/ap: Move response_type struct into ap_msg struct
s390/ap/zcrypt: Rework AP message buffer allocation
s390/ap: Introduce ap message buffer pool
s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC
s390/zcrypt: Introduce cprb mempool for cca misc functions
s390/zcrypt: Introduce cprb mempool for ep11 misc functions
s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2
s390/zcrypt: Introduce pre-allocated device status array for cca misc
s390/zcrypt: Introduce pre-allocated device status array for ep11 misc
s390/zcrypt/pkey: Rework cca findcard() implementation and callers
s390/zcrypt/pkey: Rework ep11 findcard() implementation and callers
s390/zcrypt: Rework cca misc functions kmallocs to use the cprb
mempool
s390/zcrypt: Add small mempool for cca info list entries
s390/zcrypt: Locate ep11_domain_query_info onto the stack instead of
kmalloc
s390/zcrypt: Rework ep11 misc functions to use cprb mempool
s390/zcrypt: Add small mempool for ep11 card info list entries
s390/pkey: Rework CCA pkey handler to use stack for small memory
allocs
s390/pkey: Rework EP11 pkey handler to use stack for small memory
allocs
s390/zcrypt/pkey: Provide and pass xflags within pkey and zcrypt
layers
s390/pkey/crypto: Introduce xflags param for pkey in-kernel API
arch/s390/crypto/paes_s390.c | 2 +-
arch/s390/include/asm/pkey.h | 13 +-
drivers/s390/crypto/ap_bus.c | 71 +++++
drivers/s390/crypto/ap_bus.h | 34 +--
drivers/s390/crypto/pkey_api.c | 50 ++--
drivers/s390/crypto/pkey_base.c | 34 ++-
drivers/s390/crypto/pkey_base.h | 37 ++-
drivers/s390/crypto/pkey_cca.c | 121 ++++----
drivers/s390/crypto/pkey_ep11.c | 106 +++----
drivers/s390/crypto/pkey_pckmo.c | 9 +-
drivers/s390/crypto/pkey_sysfs.c | 4 +-
drivers/s390/crypto/pkey_uv.c | 16 +-
drivers/s390/crypto/zcrypt_api.c | 151 +++++++---
drivers/s390/crypto/zcrypt_api.h | 18 +-
drivers/s390/crypto/zcrypt_ccamisc.c | 343 +++++++++++++++-------
drivers/s390/crypto/zcrypt_ccamisc.h | 41 +--
drivers/s390/crypto/zcrypt_cex4.c | 16 +-
drivers/s390/crypto/zcrypt_ep11misc.c | 385 ++++++++++++++++---------
drivers/s390/crypto/zcrypt_ep11misc.h | 28 +-
drivers/s390/crypto/zcrypt_msgtype50.c | 36 ++-
drivers/s390/crypto/zcrypt_msgtype6.c | 119 ++++----
21 files changed, 988 insertions(+), 646 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-24 15:23 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation Harald Freudenberger
` (18 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Move the very small response_type struct into struct ap_msg.
So there is no need to kmalloc this tiny struct with each
ap message preparation.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/ap_bus.h | 12 ++-
drivers/s390/crypto/zcrypt_msgtype50.c | 22 +++---
drivers/s390/crypto/zcrypt_msgtype6.c | 101 ++++++++++---------------
3 files changed, 59 insertions(+), 76 deletions(-)
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index f4622ee4d894..a5d8f805625f 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -214,6 +214,15 @@ struct ap_queue {
typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
+struct ap_response_type {
+ struct completion work;
+ int type;
+};
+
+#define CEXXC_RESPONSE_TYPE_ICA 1
+#define CEXXC_RESPONSE_TYPE_XCRB 2
+#define CEXXC_RESPONSE_TYPE_EP11 3
+
struct ap_message {
struct list_head list; /* Request queueing. */
unsigned long psmid; /* Message id. */
@@ -222,7 +231,7 @@ struct ap_message {
size_t bufsize; /* allocated msg buffer size */
u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
int rc; /* Return code for this message */
- void *private; /* ap driver private pointer. */
+ struct ap_response_type response;
/* receive is called from tasklet context */
void (*receive)(struct ap_queue *, struct ap_message *,
struct ap_message *);
@@ -250,7 +259,6 @@ static inline void ap_init_message(struct ap_message *ap_msg)
static inline void ap_release_message(struct ap_message *ap_msg)
{
kfree_sensitive(ap_msg->msg);
- kfree_sensitive(ap_msg->private);
}
enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c
index adc65eddaa1e..222deb4040f3 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -438,7 +438,7 @@ static void zcrypt_msgtype50_receive(struct ap_queue *aq,
msg->len = sizeof(error_reply);
}
out:
- complete((struct completion *)msg->private);
+ complete(&msg->response.work);
}
static atomic_t zcrypt_step = ATOMIC_INIT(0);
@@ -454,25 +454,24 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
struct ica_rsa_modexpo *mex,
struct ap_message *ap_msg)
{
- struct completion work;
int rc;
ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
ap_msg->receive = zcrypt_msgtype50_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = &work;
rc = ICAMEX_msg_to_type50MEX_msg(zq, ap_msg, mex);
if (rc)
goto out;
- init_completion(&work);
+ init_completion(&ap_msg->response.work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out;
- rc = wait_for_completion_interruptible(&work);
+ rc = wait_for_completion_interruptible(&ap_msg->response.work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -485,7 +484,6 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
}
out:
- ap_msg->private = NULL;
if (rc)
pr_debug("send me cprb at dev=%02x.%04x rc=%d\n",
AP_QID_CARD(zq->queue->qid),
@@ -504,25 +502,24 @@ static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
struct ica_rsa_modexpo_crt *crt,
struct ap_message *ap_msg)
{
- struct completion work;
int rc;
ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
ap_msg->receive = zcrypt_msgtype50_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = &work;
rc = ICACRT_msg_to_type50CRT_msg(zq, ap_msg, crt);
if (rc)
goto out;
- init_completion(&work);
+ init_completion(&ap_msg->response.work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out;
- rc = wait_for_completion_interruptible(&work);
+ rc = wait_for_completion_interruptible(&ap_msg->response.work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -535,7 +532,6 @@ static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
}
out:
- ap_msg->private = NULL;
if (rc)
pr_debug("send crt cprb at dev=%02x.%04x rc=%d\n",
AP_QID_CARD(zq->queue->qid),
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index b64c9d9fc613..21ee311cf33d 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -31,15 +31,6 @@
#define CEIL4(x) ((((x) + 3) / 4) * 4)
-struct response_type {
- struct completion work;
- int type;
-};
-
-#define CEXXC_RESPONSE_TYPE_ICA 0
-#define CEXXC_RESPONSE_TYPE_XCRB 1
-#define CEXXC_RESPONSE_TYPE_EP11 2
-
MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
"Copyright IBM Corp. 2001, 2023");
@@ -856,7 +847,7 @@ static void zcrypt_msgtype6_receive(struct ap_queue *aq,
.type = TYPE82_RSP_CODE,
.reply_code = REP82_ERROR_MACHINE_FAILURE,
};
- struct response_type *resp_type = msg->private;
+ struct ap_response_type *resp_type = &msg->response;
struct type86x_reply *t86r;
int len;
@@ -920,7 +911,7 @@ static void zcrypt_msgtype6_receive_ep11(struct ap_queue *aq,
.type = TYPE82_RSP_CODE,
.reply_code = REP82_ERROR_MACHINE_FAILURE,
};
- struct response_type *resp_type = msg->private;
+ struct ap_response_type *resp_type = &msg->response;
struct type86_ep11_reply *t86r;
int len;
@@ -967,9 +958,7 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
struct ica_rsa_modexpo *mex,
struct ap_message *ap_msg)
{
- struct response_type resp_type = {
- .type = CEXXC_RESPONSE_TYPE_ICA,
- };
+ struct ap_response_type *resp_type = &ap_msg->response;
int rc;
ap_msg->msg = (void *)get_zeroed_page(GFP_KERNEL);
@@ -979,15 +968,15 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = &resp_type;
rc = icamex_msg_to_type6mex_msgx(zq, ap_msg, mex);
if (rc)
goto out_free;
- init_completion(&resp_type.work);
+ resp_type->type = CEXXC_RESPONSE_TYPE_ICA;
+ init_completion(&resp_type->work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out_free;
- rc = wait_for_completion_interruptible(&resp_type.work);
+ rc = wait_for_completion_interruptible(&resp_type->work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -1001,7 +990,6 @@ static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
out_free:
free_page((unsigned long)ap_msg->msg);
- ap_msg->private = NULL;
ap_msg->msg = NULL;
return rc;
}
@@ -1017,9 +1005,7 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
struct ica_rsa_modexpo_crt *crt,
struct ap_message *ap_msg)
{
- struct response_type resp_type = {
- .type = CEXXC_RESPONSE_TYPE_ICA,
- };
+ struct ap_response_type *resp_type = &ap_msg->response;
int rc;
ap_msg->msg = (void *)get_zeroed_page(GFP_KERNEL);
@@ -1029,15 +1015,15 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = &resp_type;
rc = icacrt_msg_to_type6crt_msgx(zq, ap_msg, crt);
if (rc)
goto out_free;
- init_completion(&resp_type.work);
+ resp_type->type = CEXXC_RESPONSE_TYPE_ICA;
+ init_completion(&resp_type->work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out_free;
- rc = wait_for_completion_interruptible(&resp_type.work);
+ rc = wait_for_completion_interruptible(&resp_type->work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -1051,7 +1037,6 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
out_free:
free_page((unsigned long)ap_msg->msg);
- ap_msg->private = NULL;
ap_msg->msg = NULL;
return rc;
}
@@ -1061,28 +1046,26 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
* Prepare a CCA AP msg: fetch the required data from userspace,
* prepare the AP msg, fill some info into the ap_message struct,
* extract some data from the CPRB and give back to the caller.
- * This function allocates memory and needs an ap_msg prepared
- * by the caller with ap_init_message(). Also the caller has to
- * make sure ap_release_message() is always called even on failure.
+ * This function may allocate memory if the ap_msg msg buffer is
+ * not preallocated and needs an ap_msg prepared by the caller
+ * with ap_init_message(). Also the caller has to make sure
+ * ap_release_message() is always called even on failure.
*/
int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
struct ap_message *ap_msg,
unsigned int *func_code, unsigned short **dom)
{
- struct response_type resp_type = {
- .type = CEXXC_RESPONSE_TYPE_XCRB,
- };
+ struct ap_response_type *resp_type = &ap_msg->response;
ap_msg->bufsize = atomic_read(&ap_max_msg_size);
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private)
- return -ENOMEM;
+ resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
return xcrb_msg_to_type6cprb_msgx(userspace, ap_msg, xcrb, func_code, dom);
}
@@ -1097,7 +1080,7 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
struct ica_xcRB *xcrb,
struct ap_message *ap_msg)
{
- struct response_type *rtype = ap_msg->private;
+ struct ap_response_type *resp_type = &ap_msg->response;
struct {
struct type6_hdr hdr;
struct CPRBX cprbx;
@@ -1128,11 +1111,11 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
msg->hdr.fromcardlen1 -= delta;
}
- init_completion(&rtype->work);
+ init_completion(&resp_type->work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out;
- rc = wait_for_completion_interruptible(&rtype->work);
+ rc = wait_for_completion_interruptible(&resp_type->work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -1158,28 +1141,26 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
* Prepare an EP11 AP msg: fetch the required data from userspace,
* prepare the AP msg, fill some info into the ap_message struct,
* extract some data from the CPRB and give back to the caller.
- * This function allocates memory and needs an ap_msg prepared
- * by the caller with ap_init_message(). Also the caller has to
- * make sure ap_release_message() is always called even on failure.
+ * This function may allocate memory if the ap_msg msg buffer is
+ * not preallocated and needs an ap_msg prepared by the caller
+ * with ap_init_message(). Also the caller has to make sure
+ * ap_release_message() is always called even on failure.
*/
int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
struct ap_message *ap_msg,
unsigned int *func_code, unsigned int *domain)
{
- struct response_type resp_type = {
- .type = CEXXC_RESPONSE_TYPE_EP11,
- };
+ struct ap_response_type *resp_type = &ap_msg->response;
ap_msg->bufsize = atomic_read(&ap_max_msg_size);
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
ap_msg->receive = zcrypt_msgtype6_receive_ep11;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private)
- return -ENOMEM;
+ resp_type->type = CEXXC_RESPONSE_TYPE_EP11;
return xcrb_msg_to_type6_ep11cprb_msgx(userspace, ap_msg, xcrb,
func_code, domain);
}
@@ -1197,7 +1178,7 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
{
int rc;
unsigned int lfmt;
- struct response_type *rtype = ap_msg->private;
+ struct ap_response_type *resp_type = &ap_msg->response;
struct {
struct type6_hdr hdr;
struct ep11_cprb cprbx;
@@ -1251,11 +1232,11 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
msg->hdr.fromcardlen1 = zq->reply.bufsize -
sizeof(struct type86_hdr) - sizeof(struct type86_fmt2_ext);
- init_completion(&rtype->work);
+ init_completion(&resp_type->work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out;
- rc = wait_for_completion_interruptible(&rtype->work);
+ rc = wait_for_completion_interruptible(&resp_type->work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
@@ -1279,20 +1260,18 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
unsigned int *domain)
{
- struct response_type resp_type = {
- .type = CEXXC_RESPONSE_TYPE_XCRB,
- };
+ struct ap_response_type *resp_type = &ap_msg->response;
ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
- ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
- if (!ap_msg->private)
- return -ENOMEM;
+
+ resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
rng_type6cprb_msgx(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain);
@@ -1319,16 +1298,16 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq,
short int verb_length;
short int key_length;
} __packed * msg = ap_msg->msg;
- struct response_type *rtype = ap_msg->private;
+ struct ap_response_type *resp_type = &ap_msg->response;
int rc;
msg->cprbx.domain = AP_QID_QUEUE(zq->queue->qid);
- init_completion(&rtype->work);
+ init_completion(&resp_type->work);
rc = ap_queue_message(zq->queue, ap_msg);
if (rc)
goto out;
- rc = wait_for_completion_interruptible(&rtype->work);
+ rc = wait_for_completion_interruptible(&resp_type->work);
if (rc == 0) {
rc = ap_msg->rc;
if (rc == 0)
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-25 8:12 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool Harald Freudenberger
` (17 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Slight rework on the way how AP message buffers are allocated.
Instead of having multiple places with kmalloc() calls all
the AP message buffers are now allocated and freed on exactyl
one place ap_init_apmsg() allocates the current AP bus max
limit of ap_max_msg_size (defaults to 12KB). The preparation
functions only check for their payload to fit in. The AP
message buffer is freed in ap_release_apmsg().
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/ap_bus.c | 30 ++++++++++++++++
drivers/s390/crypto/ap_bus.h | 21 ++---------
drivers/s390/crypto/zcrypt_api.c | 49 +++++++++++++++-----------
drivers/s390/crypto/zcrypt_msgtype50.c | 22 ++++++------
drivers/s390/crypto/zcrypt_msgtype6.c | 46 ++++++++++++------------
5 files changed, 96 insertions(+), 72 deletions(-)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 26e1ea1940ec..4940eaf538e9 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -546,6 +546,36 @@ static void ap_poll_thread_stop(void)
#define is_card_dev(x) ((x)->parent == ap_root_device)
#define is_queue_dev(x) ((x)->parent != ap_root_device)
+/**
+ * ap_init_apmsg() - Initialize ap_message.
+ * Initialize a message before using. Otherwise this might result in
+ * unexpected behaviour.
+ */
+int ap_init_apmsg(struct ap_message *ap_msg)
+{
+ unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
+
+ memset(ap_msg, 0, sizeof(*ap_msg));
+ ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
+ if (!ap_msg->msg)
+ return -ENOMEM;
+ ap_msg->bufsize = maxmsgsize;
+
+ return 0;
+}
+EXPORT_SYMBOL(ap_init_apmsg);
+
+/**
+ * ap_release_apmsg() - Release ap_message.
+ * Releases all memory used internal within the ap_message struct
+ * Currently this is the message and private field.
+ */
+void ap_release_apmsg(struct ap_message *ap_msg)
+{
+ kfree_sensitive(ap_msg->msg);
+}
+EXPORT_SYMBOL(ap_release_apmsg);
+
/**
* ap_bus_match()
* @dev: Pointer to device
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index a5d8f805625f..3956a5e945bd 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -241,25 +241,8 @@ struct ap_message {
#define AP_MSG_FLAG_USAGE 0x0002 /* CCA, EP11: usage (no admin) msg */
#define AP_MSG_FLAG_ADMIN 0x0004 /* CCA, EP11: admin (=control) msg */
-/**
- * ap_init_message() - Initialize ap_message.
- * Initialize a message before using. Otherwise this might result in
- * unexpected behaviour.
- */
-static inline void ap_init_message(struct ap_message *ap_msg)
-{
- memset(ap_msg, 0, sizeof(*ap_msg));
-}
-
-/**
- * ap_release_message() - Release ap_message.
- * Releases all memory used internal within the ap_message struct
- * Currently this is the message and private field.
- */
-static inline void ap_release_message(struct ap_message *ap_msg)
-{
- kfree_sensitive(ap_msg->msg);
-}
+int ap_init_apmsg(struct ap_message *ap_msg);
+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);
enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event);
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 5020696f1379..78df25da0b95 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -642,16 +642,17 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
struct zcrypt_queue *zq, *pref_zq;
struct ap_message ap_msg;
unsigned int wgt = 0, pref_wgt = 0;
- unsigned int func_code;
- int cpen, qpen, qid = 0, rc = -ENODEV;
+ unsigned int func_code = 0;
+ int cpen, qpen, qid = 0, rc;
struct module *mod;
trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO);
- ap_init_message(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg);
+ if (rc)
+ goto out;
if (mex->outputdatalength < mex->inputdatalength) {
- func_code = 0;
rc = -EINVAL;
goto out;
}
@@ -728,7 +729,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
spin_unlock(&zcrypt_list_lock);
out:
- ap_release_message(&ap_msg);
+ ap_release_apmsg(&ap_msg);
if (tr) {
tr->last_rc = rc;
tr->last_qid = qid;
@@ -746,16 +747,17 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
struct zcrypt_queue *zq, *pref_zq;
struct ap_message ap_msg;
unsigned int wgt = 0, pref_wgt = 0;
- unsigned int func_code;
- int cpen, qpen, qid = 0, rc = -ENODEV;
+ unsigned int func_code = 0;
+ int cpen, qpen, qid = 0, rc;
struct module *mod;
trace_s390_zcrypt_req(crt, TP_ICARSACRT);
- ap_init_message(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg);
+ if (rc)
+ goto out;
if (crt->outputdatalength < crt->inputdatalength) {
- func_code = 0;
rc = -EINVAL;
goto out;
}
@@ -832,7 +834,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
spin_unlock(&zcrypt_list_lock);
out:
- ap_release_message(&ap_msg);
+ ap_release_apmsg(&ap_msg);
if (tr) {
tr->last_rc = rc;
tr->last_qid = qid;
@@ -850,15 +852,18 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
struct zcrypt_queue *zq, *pref_zq;
struct ap_message ap_msg;
unsigned int wgt = 0, pref_wgt = 0;
- unsigned int func_code;
+ unsigned int func_code = 0;
unsigned short *domain, tdom;
- int cpen, qpen, qid = 0, rc = -ENODEV;
+ int cpen, qpen, qid = 0, rc;
struct module *mod;
trace_s390_zcrypt_req(xcrb, TB_ZSECSENDCPRB);
xcrb->status = 0;
- ap_init_message(&ap_msg);
+
+ rc = ap_init_apmsg(&ap_msg);
+ if (rc)
+ goto out;
rc = prep_cca_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain);
if (rc)
@@ -962,7 +967,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
spin_unlock(&zcrypt_list_lock);
out:
- ap_release_message(&ap_msg);
+ ap_release_apmsg(&ap_msg);
if (tr) {
tr->last_rc = rc;
tr->last_qid = qid;
@@ -1033,14 +1038,16 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
struct ep11_target_dev *targets;
unsigned short target_num;
unsigned int wgt = 0, pref_wgt = 0;
- unsigned int func_code, domain;
+ unsigned int func_code = 0, domain;
struct ap_message ap_msg;
- int cpen, qpen, qid = 0, rc = -ENODEV;
+ int cpen, qpen, qid = 0, rc;
struct module *mod;
trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);
- ap_init_message(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg);
+ if (rc)
+ goto out;
target_num = (unsigned short)xcrb->targets_num;
@@ -1164,7 +1171,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
out_free:
kfree(targets);
out:
- ap_release_message(&ap_msg);
+ ap_release_apmsg(&ap_msg);
if (tr) {
tr->last_rc = rc;
tr->last_qid = qid;
@@ -1212,7 +1219,9 @@ static long zcrypt_rng(char *buffer)
trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
- ap_init_message(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg);
+ if (rc)
+ goto out;
rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);
if (rc)
goto out;
@@ -1258,7 +1267,7 @@ static long zcrypt_rng(char *buffer)
spin_unlock(&zcrypt_list_lock);
out:
- ap_release_message(&ap_msg);
+ ap_release_apmsg(&ap_msg);
trace_s390_zcrypt_rep(buffer, func_code, rc,
AP_QID_CARD(qid), AP_QID_QUEUE(qid));
return rc;
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c
index 222deb4040f3..098cf5496f06 100644
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -449,6 +449,10 @@ static atomic_t zcrypt_step = ATOMIC_INIT(0);
* @zq: pointer to zcrypt_queue structure that identifies the
* CEXxA device to the request distributor
* @mex: pointer to the modexpo request buffer
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
*/
static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
struct ica_rsa_modexpo *mex,
@@ -456,11 +460,8 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
{
int rc;
- ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
- if (!ap_msg->msg)
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
- if (!ap_msg->msg)
- return -ENOMEM;
+ if (ap_msg->bufsize < MSGTYPE50_CRB3_MAX_MSG_SIZE)
+ return -EMSGSIZE;
ap_msg->receive = zcrypt_msgtype50_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
@@ -497,6 +498,10 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
* @zq: pointer to zcrypt_queue structure that identifies the
* CEXxA device to the request distributor
* @crt: pointer to the modexpoc_crt request buffer
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
*/
static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
struct ica_rsa_modexpo_crt *crt,
@@ -504,11 +509,8 @@ static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
{
int rc;
- ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
- if (!ap_msg->msg)
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
- if (!ap_msg->msg)
- return -ENOMEM;
+ if (ap_msg->bufsize < MSGTYPE50_CRB3_MAX_MSG_SIZE)
+ return -EMSGSIZE;
ap_msg->receive = zcrypt_msgtype50_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
index 21ee311cf33d..0e91d403a93c 100644
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -1046,22 +1046,20 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
* Prepare a CCA AP msg: fetch the required data from userspace,
* prepare the AP msg, fill some info into the ap_message struct,
* extract some data from the CPRB and give back to the caller.
- * This function may allocate memory if the ap_msg msg buffer is
- * not preallocated and needs an ap_msg prepared by the caller
- * with ap_init_message(). Also the caller has to make sure
- * ap_release_message() is always called even on failure.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
*/
int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
struct ap_message *ap_msg,
unsigned int *func_code, unsigned short **dom)
{
struct ap_response_type *resp_type = &ap_msg->response;
+ unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
- ap_msg->bufsize = atomic_read(&ap_max_msg_size);
- if (!ap_msg->msg)
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
- if (!ap_msg->msg)
- return -ENOMEM;
+ if (ap_msg->bufsize < maxmsgsize)
+ return -EMSGSIZE;
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
@@ -1141,22 +1139,20 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
* Prepare an EP11 AP msg: fetch the required data from userspace,
* prepare the AP msg, fill some info into the ap_message struct,
* extract some data from the CPRB and give back to the caller.
- * This function may allocate memory if the ap_msg msg buffer is
- * not preallocated and needs an ap_msg prepared by the caller
- * with ap_init_message(). Also the caller has to make sure
- * ap_release_message() is always called even on failure.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
*/
int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
struct ap_message *ap_msg,
unsigned int *func_code, unsigned int *domain)
{
struct ap_response_type *resp_type = &ap_msg->response;
+ unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
- ap_msg->bufsize = atomic_read(&ap_max_msg_size);
- if (!ap_msg->msg)
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
- if (!ap_msg->msg)
- return -ENOMEM;
+ if (ap_msg->bufsize < maxmsgsize)
+ return -EMSGSIZE;
ap_msg->receive = zcrypt_msgtype6_receive_ep11;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
@@ -1257,16 +1253,20 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
return rc;
}
+/*
+ * Prepare a CEXXC get random request ap message.
+ * This function assumes that ap_msg has been initialized with
+ * ap_init_apmsg() and thus a valid buffer with the size of
+ * ap_max_msg_size is available within ap_msg. Also the caller has
+ * to make sure ap_release_apmsg() is always called even on failure.
+ */
int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
unsigned int *domain)
{
struct ap_response_type *resp_type = &ap_msg->response;
- ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
- if (!ap_msg->msg)
- ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
- if (!ap_msg->msg)
- return -ENOMEM;
+ if (ap_msg->bufsize < AP_DEFAULT_MAX_MSG_SIZE)
+ return -EMSGSIZE;
ap_msg->receive = zcrypt_msgtype6_receive;
ap_msg->psmid = (((unsigned long)current->pid) << 32) +
atomic_inc_return(&zcrypt_step);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-25 13:52 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC Harald Freudenberger
` (16 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
There is a need for a do-not-allocate-memory path through the
ap bus layer. When ap_init_apmsg() with the AP_MSG_FLAG_MEMPOOL
xflag is called, instead of kmalloc() the ap message buffer is
allocated from the ap_msg_pool. This pool only holds a limited
amount of buffers: AP_MSG_POOL_MIN_ITEMS with the item size
AP_DEFAULT_MAX_MSG_SIZE and exactly one of these items (if available)
is returned if ap_init_apmsg() with the MEMPOOL flag is called.
When this pool is exhausted and the MEMPOOL flag is effective,
ap_init_apmsg() returns -ENOMEM without any attempt to allocate
memory.
The zcrypt layer may use this flag to indicate to the ap bus
that the processing path for this message should not allocate
memory. This is to prevent deadlocks with crypto and io for
example with encrypted swap volumes.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/ap_bus.c | 59 +++++++++++++++++++++++++++-----
drivers/s390/crypto/ap_bus.h | 3 +-
drivers/s390/crypto/zcrypt_api.c | 10 +++---
3 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 4940eaf538e9..b585b5d11074 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -40,6 +40,7 @@
#include <linux/module.h>
#include <asm/uv.h>
#include <asm/chsc.h>
+#include <linux/mempool.h>
#include "ap_bus.h"
#include "ap_debug.h"
@@ -101,6 +102,21 @@ static struct ap_config_info *const ap_qci_info_old = &qci[1];
*/
debug_info_t *ap_dbf_info;
+/*
+ * There is a need for a do-not-allocate-memory path through the
+ * ap bus layer. When ap_init_apmsg() with the AP_MSG_FLAG_MEMPOOL
+ * xflag is called, instead of kmalloc() the ap message buffer is
+ * allocated from the ap_msg_pool. This pool only holds a limited
+ * amount of buffers: AP_MSG_POOL_MIN_ITEMS with the item size
+ * AP_DEFAULT_MAX_MSG_SIZE and exactly one of these items (if available)
+ * is returned if ap_init_apmsg() with the MEMPOOL flag is called.
+ * When this pool is exhausted and the MEMPOOL flag is effective,
+ * ap_init_apmsg() returns -ENOMEM without any attempt to allocate
+ * memory.
+ */
+#define AP_MSG_POOL_MIN_ITEMS 4
+static mempool_t *ap_msg_pool;
+
/*
* AP bus rescan related things.
*/
@@ -546,16 +562,27 @@ static void ap_poll_thread_stop(void)
#define is_card_dev(x) ((x)->parent == ap_root_device)
#define is_queue_dev(x) ((x)->parent != ap_root_device)
-/**
+/*
* ap_init_apmsg() - Initialize ap_message.
- * Initialize a message before using. Otherwise this might result in
- * unexpected behaviour.
+ * Initialize struct ap_message and allocate buffer to construct
+ * the ap message.
*/
-int ap_init_apmsg(struct ap_message *ap_msg)
+int ap_init_apmsg(struct ap_message *ap_msg, u32 xflags)
{
- unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
+ unsigned int maxmsgsize;
memset(ap_msg, 0, sizeof(*ap_msg));
+
+ if (xflags & 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;
+ }
+
+ maxmsgsize = atomic_read(&ap_max_msg_size);
ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
if (!ap_msg->msg)
return -ENOMEM;
@@ -565,14 +592,18 @@ int ap_init_apmsg(struct ap_message *ap_msg)
}
EXPORT_SYMBOL(ap_init_apmsg);
-/**
+/*
* ap_release_apmsg() - Release ap_message.
- * Releases all memory used internal within the ap_message struct
- * Currently this is the message and private field.
+ * Cleanup struct ap_message and release all memory held.
*/
void ap_release_apmsg(struct ap_message *ap_msg)
{
- kfree_sensitive(ap_msg->msg);
+ if (ap_msg->flags & AP_MSG_FLAG_MEMPOOL) {
+ memzero_explicit(ap_msg->msg, ap_msg->bufsize);
+ mempool_free(ap_msg->msg, ap_msg_pool);
+ } else {
+ kfree_sensitive(ap_msg->msg);
+ }
}
EXPORT_SYMBOL(ap_release_apmsg);
@@ -2461,6 +2492,14 @@ static int __init ap_module_init(void)
/* init ap_queue hashtable */
hash_init(ap_queues);
+ /* create ap msg buffer memory pool */
+ ap_msg_pool = mempool_create_kmalloc_pool(AP_MSG_POOL_MIN_ITEMS,
+ AP_DEFAULT_MAX_MSG_SIZE);
+ if (IS_ERR(ap_msg_pool)) {
+ ap_msg_pool = NULL;
+ goto out;
+ }
+
/* set up the AP permissions (ioctls, ap and aq masks) */
ap_perms_init();
@@ -2507,6 +2546,7 @@ static int __init ap_module_init(void)
out_bus:
bus_unregister(&ap_bus_type);
out:
+ mempool_destroy(ap_msg_pool);
ap_debug_exit();
return rc;
}
@@ -2517,6 +2557,7 @@ static void __exit ap_module_exit(void)
ap_irq_exit();
root_device_unregister(ap_root_device);
bus_unregister(&ap_bus_type);
+ mempool_destroy(ap_msg_pool);
ap_debug_exit();
}
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 3956a5e945bd..8b20506d6a60 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -240,8 +240,9 @@ struct ap_message {
#define AP_MSG_FLAG_SPECIAL 0x0001 /* flag msg as 'special' with NQAP */
#define AP_MSG_FLAG_USAGE 0x0002 /* CCA, EP11: usage (no admin) msg */
#define AP_MSG_FLAG_ADMIN 0x0004 /* CCA, EP11: admin (=control) msg */
+#define AP_MSG_FLAG_MEMPOOL 0x0008 /* ap msg buffer via mempool */
-int ap_init_apmsg(struct ap_message *ap_msg);
+int ap_init_apmsg(struct ap_message *ap_msg, u32 xflags);
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);
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 78df25da0b95..ce5f7cb974b9 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -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);
+ 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);
+ rc = ap_init_apmsg(&ap_msg, 0);
if (rc)
goto out;
@@ -861,7 +861,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
xcrb->status = 0;
- rc = ap_init_apmsg(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg, 0);
if (rc)
goto out;
@@ -1045,7 +1045,7 @@ 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);
+ rc = ap_init_apmsg(&ap_msg, 0);
if (rc)
goto out;
@@ -1219,7 +1219,7 @@ static long zcrypt_rng(char *buffer)
trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
- rc = ap_init_apmsg(&ap_msg);
+ rc = ap_init_apmsg(&ap_msg, 0);
if (rc)
goto out;
rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (2 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-27 8:21 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions Harald Freudenberger
` (15 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
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.
One flag is implemented: The xflag ZCRYPT_XFLAG_NOMEMALLOC
tells the zcrypt_send_*() functions to not allocate memory
via kmalloc() and friends with the goal to not trigger any
IO operations. If this xflag is given, it is also forwarded
to the AP bus functions as AP_MSG_FLAG_MEMPOOL when the
ap_init_apmsg() is invoked.
If the ZCRYPT_XFLAG_NOMEMALLOC is given, the zcrypt layer
does not allocate any memory but may fail to send a crypto
load:
- The number of EP11 targets if given must not exceed 16 APQNs.
- As the flag is passed down to the AP bus functions the
AP bus uses a limited mem pool (with limited item size)
to construct the AP msg. The AP bus mem pool may be depleted
and/or the message size may exceed the item size of the
AP bus mem pool. Currently the AP bus mem pool is limited
to 4 mem pool items of 12KB each. On not being able to process
a crypto request without memory allocation the result will
be -ENOMEM returned from the zcrypt_send_cprb_*() functions.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_api.c | 65 +++++++++++++++------------
drivers/s390/crypto/zcrypt_api.h | 12 ++++-
drivers/s390/crypto/zcrypt_ccamisc.c | 16 +++----
drivers/s390/crypto/zcrypt_ep11misc.c | 10 ++---
4 files changed, 59 insertions(+), 44 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index ce5f7cb974b9..f6deb10329e6 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -846,7 +846,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
struct zcrypt_track *tr,
- struct ica_xcRB *xcrb)
+ struct ica_xcRB *xcrb, u32 xflags)
{
struct zcrypt_card *zc, *pref_zc;
struct zcrypt_queue *zq, *pref_zq;
@@ -861,7 +861,8 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
xcrb->status = 0;
- rc = ap_init_apmsg(&ap_msg, 0);
+ rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
+ AP_MSG_FLAG_MEMPOOL : 0);
if (rc)
goto out;
@@ -977,7 +978,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
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 +986,14 @@ 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(false, &ap_perms, &tr, xcrb, xflags);
} 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(false, &ap_perms,
+ &tr, xcrb, xflags);
} while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
rc = -EIO;
@@ -1031,11 +1033,11 @@ static bool is_desired_ep11_queue(unsigned int dev_qid,
static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
struct zcrypt_track *tr,
- struct ep11_urb *xcrb)
+ struct ep11_urb *xcrb, u32 xflags)
{
struct zcrypt_card *zc, *pref_zc;
struct zcrypt_queue *zq, *pref_zq;
- struct ep11_target_dev *targets;
+ struct ep11_target_dev targetbuf[16], *targets = NULL;
unsigned short target_num;
unsigned int wgt = 0, pref_wgt = 0;
unsigned int func_code = 0, domain;
@@ -1045,36 +1047,39 @@ 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, 0);
+ rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
+ AP_MSG_FLAG_MEMPOOL : 0);
if (rc)
goto out;
target_num = (unsigned short)xcrb->targets_num;
/* empty list indicates autoselect (all available targets) */
- targets = NULL;
+ rc = -ENOMEM;
if (target_num != 0) {
struct ep11_target_dev __user *uptr;
- targets = kcalloc(target_num, sizeof(*targets), GFP_KERNEL);
- if (!targets) {
- func_code = 0;
- rc = -ENOMEM;
+ if (target_num <= ARRAY_SIZE(targetbuf)) {
+ targets = targetbuf;
+ } else if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
goto out;
+ } else {
+ targets = kcalloc(target_num,
+ sizeof(*targets), GFP_KERNEL);
+ if (!targets)
+ goto out;
}
-
uptr = (struct ep11_target_dev __force __user *)xcrb->targets;
if (z_copy_from_user(userspace, targets, uptr,
target_num * sizeof(*targets))) {
- func_code = 0;
rc = -EFAULT;
- goto out_free;
+ goto out;
}
}
rc = prep_ep11_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain);
if (rc)
- goto out_free;
+ goto out;
print_hex_dump_debug("ep11req: ", DUMP_PREFIX_ADDRESS, 16, 1,
ap_msg.msg, ap_msg.len, false);
@@ -1082,11 +1087,11 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
if (ap_msg.flags & AP_MSG_FLAG_ADMIN) {
if (!test_bit_inv(domain, perms->adm)) {
rc = -ENODEV;
- goto out_free;
+ goto out;
}
} else if ((ap_msg.flags & AP_MSG_FLAG_USAGE) == 0) {
rc = -EOPNOTSUPP;
- goto out_free;
+ goto out;
}
}
@@ -1154,7 +1159,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
pr_debug("no match for address ff.ffff => ENODEV\n");
}
rc = -ENODEV;
- goto out_free;
+ goto out;
}
qid = pref_zq->queue->qid;
@@ -1168,9 +1173,9 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
spin_unlock(&zcrypt_list_lock);
-out_free:
- kfree(targets);
out:
+ if (targets && targets != targetbuf)
+ kfree(targets);
ap_release_apmsg(&ap_msg);
if (tr) {
tr->last_rc = rc;
@@ -1181,7 +1186,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
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;
@@ -1189,13 +1194,15 @@ 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(false, &ap_perms,
+ &tr, xcrb, xflags);
} 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(false, &ap_perms,
+ &tr, xcrb, xflags);
} while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
rc = -EIO;
@@ -1539,13 +1546,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(true, perms, &tr, &xcrb, 0);
} 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(true, perms, &tr, &xcrb, 0);
} while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
rc = -EIO;
@@ -1569,13 +1576,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(true, perms, &tr, &xcrb, 0);
} 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(true, perms, &tr, &xcrb, 0);
} while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
rc = -EIO;
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 4ed481df57ca..06ff697d171c 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -76,6 +76,14 @@ struct zcrypt_track {
#define TRACK_AGAIN_CARD_WEIGHT_PENALTY 1000
#define TRACK_AGAIN_QUEUE_WEIGHT_PENALTY 10000
+/*
+ * Do not allocate memory xflag. To be used with
+ * zcrypt_send_cprb() and zcrypt_send_ep11_cprb().
+ * Currently only available and used for the in-kernel
+ * zcrpyt api.
+ */
+#define ZCRYPT_XFLAG_NOMEMALLOC 0x0001
+
struct zcrypt_ops {
long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *,
struct ap_message *);
@@ -161,8 +169,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);
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 43a27cb3db84..521baaea06ff 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -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);
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index cb7e6da43602..b60e262bcaa3 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -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);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (3 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-03-03 8:07 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 " Harald Freudenberger
` (14 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Intruduce a cprb mempool for the zcrypt cca misc functions
(zcrypt_ccamisc.*) do some preparation rework to support
a do-not-allocate path through some zcrypt cca misc functions.
This is only part of an rework to support a new xflag
ZCRYPT_XFLAG_NOMEMALLOC but not jet complete.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_api.c | 9 ++-
drivers/s390/crypto/zcrypt_ccamisc.c | 115 ++++++++++++++++++++-------
drivers/s390/crypto/zcrypt_ccamisc.h | 1 +
3 files changed, 94 insertions(+), 31 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index f6deb10329e6..6be60b9dc83f 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -2154,7 +2154,11 @@ int __init zcrypt_api_init(void)
rc = zcdn_init();
if (rc)
- goto out;
+ goto out_zcdn_init_failed;
+
+ rc = zcrypt_ccamisc_init();
+ if (rc)
+ goto out_ccamisc_init_failed;
/* Register the request sprayer. */
rc = misc_register(&zcrypt_misc_device);
@@ -2167,7 +2171,10 @@ int __init zcrypt_api_init(void)
return 0;
out_misc_register_failed:
+ zcrypt_ccamisc_exit();
+out_ccamisc_init_failed:
zcdn_exit();
+out_zcdn_init_failed:
zcrypt_debug_exit();
out:
return rc;
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 521baaea06ff..e604a69e40fc 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -11,6 +11,7 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/init.h>
+#include <linux/mempool.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
@@ -40,6 +41,17 @@ struct cca_info_list_entry {
static LIST_HEAD(cca_info_list);
static DEFINE_SPINLOCK(cca_info_list_lock);
+/*
+ * Cprb memory pool held for urgend cases where no memory
+ * can be allocated via kmalloc. This pool is only used
+ * when alloc_and_prep_cprbmem() is called with the xflag
+ * ZCRYPT_XFLAG_NOMEMALLOC. The cprb memory needs to hold
+ * space for request AND reply!
+ */
+#define CPRB_MEMPOOL_MIN_ITEMS 4
+#define CPRB_MEMPOOL_ITEM_SIZE (16 * 1024)
+static mempool_t *cprb_mempool;
+
/*
* Simple check if the token is a valid CCA secure AES data key
* token. If keybitsize is given, the bitsize of the key is
@@ -219,9 +231,10 @@ EXPORT_SYMBOL(cca_check_sececckeytoken);
static int alloc_and_prep_cprbmem(size_t paramblen,
u8 **p_cprb_mem,
struct CPRBX **p_req_cprb,
- struct CPRBX **p_rep_cprb)
+ struct CPRBX **p_rep_cprb,
+ u32 xflags)
{
- u8 *cprbmem;
+ u8 *cprbmem = NULL;
size_t cprbplusparamblen = sizeof(struct CPRBX) + paramblen;
struct CPRBX *preqcblk, *prepcblk;
@@ -229,7 +242,13 @@ static int alloc_and_prep_cprbmem(size_t paramblen,
* allocate consecutive memory for request CPRB, request param
* block, reply CPRB and reply param block
*/
- cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL);
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
+ if (cprb_mempool &&
+ 2 * cprbplusparamblen <= CPRB_MEMPOOL_ITEM_SIZE)
+ cprbmem = mempool_alloc_preallocated(cprb_mempool);
+ } else {
+ cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL);
+ }
if (!cprbmem)
return -ENOMEM;
@@ -261,11 +280,15 @@ static int alloc_and_prep_cprbmem(size_t paramblen,
* with zeros before freeing (useful if there was some
* clear key material in there).
*/
-static void free_cprbmem(void *mem, size_t paramblen, int scrub)
+static void free_cprbmem(void *mem, size_t paramblen, bool scrub, u32 xflags)
{
if (scrub)
memzero_explicit(mem, 2 * (sizeof(struct CPRBX) + paramblen));
- kfree(mem);
+
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC)
+ mempool_free(mem, cprb_mempool);
+ else
+ kfree(mem);
}
/*
@@ -330,9 +353,11 @@ int cca_genseckey(u16 cardnr, u16 domain,
} keyblock;
} lv3;
} __packed * prepparm;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -379,7 +404,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -424,7 +449,7 @@ int cca_genseckey(u16 cardnr, u16 domain,
memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE);
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, false, xflags);
return rc;
}
EXPORT_SYMBOL(cca_genseckey);
@@ -471,9 +496,11 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
} keyblock;
} lv3;
} __packed * prepparm;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -517,7 +544,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -563,7 +590,7 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
memcpy(seckey, prepparm->lv3.keyblock.tok, SECKEYBLOBSIZE);
out:
- free_cprbmem(mem, PARMBSIZE, 1);
+ free_cprbmem(mem, PARMBSIZE, true, xflags);
return rc;
}
EXPORT_SYMBOL(cca_clr2seckey);
@@ -617,9 +644,11 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
} ckb;
} lv3;
} __packed * prepparm;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -644,7 +673,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -712,7 +741,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
*protkeylen = prepparm->lv3.ckb.len;
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, true, xflags);
return rc;
}
EXPORT_SYMBOL(cca_sec2protkey);
@@ -811,9 +840,11 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
} kb;
} __packed * prepparm;
struct cipherkeytoken *t;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -872,7 +903,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -923,7 +954,7 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
*keybufsize = t->len;
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, false, xflags);
return rc;
}
EXPORT_SYMBOL(cca_gencipherkey);
@@ -987,9 +1018,11 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
} __packed * prepparm;
struct cipherkeytoken *t;
int complete = strncmp(rule_array_2, "COMPLETE", 8) ? 0 : 1;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -1038,7 +1071,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -1077,7 +1110,7 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
*key_token_size = t->len;
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, false, xflags);
return rc;
}
@@ -1217,9 +1250,11 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
} kb;
} __packed * prepparm;
int keytoklen = ((struct cipherkeytoken *)ckey)->len;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -1249,7 +1284,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -1323,7 +1358,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
*protkeylen = prepparm->vud.ckb.keylen;
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, true, xflags);
return rc;
}
EXPORT_SYMBOL(cca_cipher2protkey);
@@ -1380,9 +1415,11 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
/* followed by a key block */
} __packed * prepparm;
int keylen = ((struct eccprivkeytoken *)key)->len;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -1412,7 +1449,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -1470,7 +1507,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
*protkeytype = PKEY_KEYTYPE_ECC;
out:
- free_cprbmem(mem, PARMBSIZE, 0);
+ free_cprbmem(mem, PARMBSIZE, true, xflags);
return rc;
}
EXPORT_SYMBOL(cca_ecc2protkey);
@@ -1503,9 +1540,11 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
u8 subfunc_code[2];
u8 lvdata[];
} __packed * prepparm;
+ const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
- rc = alloc_and_prep_cprbmem(parmbsize, &mem, &preqcblk, &prepcblk);
+ rc = alloc_and_prep_cprbmem(parmbsize, &mem,
+ &preqcblk, &prepcblk, xflags);
if (rc)
return rc;
@@ -1526,7 +1565,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, 0);
+ rc = zcrypt_send_cprb(&xcrb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -1573,7 +1612,7 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
}
out:
- free_cprbmem(mem, parmbsize, 0);
+ free_cprbmem(mem, parmbsize, false, xflags);
return rc;
}
EXPORT_SYMBOL(cca_query_crypto_facility);
@@ -1959,7 +1998,23 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
}
EXPORT_SYMBOL(cca_findcard2);
-void __exit zcrypt_ccamisc_exit(void)
+int __init zcrypt_ccamisc_init(void)
+{
+ /* Pre-allocate a small memory pool for cca cprbs. */
+ cprb_mempool = mempool_create_kmalloc_pool(CPRB_MEMPOOL_MIN_ITEMS,
+ CPRB_MEMPOOL_ITEM_SIZE);
+ if (IS_ERR(cprb_mempool)) {
+ ZCRYPT_DBF_ERR("%s mempool_create(%d,%d) failed: %ld\n",
+ __func__, CPRB_MEMPOOL_MIN_ITEMS,
+ CPRB_MEMPOOL_ITEM_SIZE, PTR_ERR(cprb_mempool));
+ cprb_mempool = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void zcrypt_ccamisc_exit(void)
{
mkvp_cache_free();
+ mempool_destroy(cprb_mempool);
}
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index 26bdca702523..273edf2bb036 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -272,6 +272,7 @@ struct cca_info {
*/
int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify);
+int zcrypt_ccamisc_init(void);
void zcrypt_ccamisc_exit(void);
#endif /* _ZCRYPT_CCAMISC_H_ */
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 misc functions
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (4 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-03-03 8:29 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2 Harald Freudenberger
` (13 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Introduce a cprb mempool for zcrypt ep11 misc functions
(zcrpyt_ep11misc.*) and do some preparation rework to
support a do-not-allocate memory path through some
zcrypt ep11 misc functions.
This is only part one of a rework to support a new xflag
ZCRYPT_XFLAG_NOMEMALLOC but not jet complete.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_api.c | 6 +
drivers/s390/crypto/zcrypt_ep11misc.c | 159 ++++++++++++++++----------
drivers/s390/crypto/zcrypt_ep11misc.h | 1 +
3 files changed, 105 insertions(+), 61 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 6be60b9dc83f..3a521e65f3fe 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -2160,6 +2160,10 @@ int __init zcrypt_api_init(void)
if (rc)
goto out_ccamisc_init_failed;
+ rc = zcrypt_ep11misc_init();
+ if (rc)
+ goto out_ep11misc_init_failed;
+
/* Register the request sprayer. */
rc = misc_register(&zcrypt_misc_device);
if (rc < 0)
@@ -2171,6 +2175,8 @@ int __init zcrypt_api_init(void)
return 0;
out_misc_register_failed:
+ zcrypt_ep11misc_exit();
+out_ep11misc_init_failed:
zcrypt_ccamisc_exit();
out_ccamisc_init_failed:
zcdn_exit();
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index b60e262bcaa3..3d96bd236c16 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -10,9 +10,10 @@
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/init.h>
+#include <linux/mempool.h>
#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/random.h>
+#include <linux/slab.h>
#include <asm/zcrypt.h>
#include <asm/pkey.h>
#include <crypto/aes.h>
@@ -30,6 +31,15 @@
static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+/*
+ * Cprb memory pool held for urgend cases where no memory
+ * can be allocated via kmalloc. This pool is only used when
+ * alloc_cprbmem() is called with the xflag ZCRYPT_XFLAG_NOMEMALLOC.
+ */
+#define CPRB_MEMPOOL_MIN_ITEMS 8
+#define CPRB_MEMPOOL_ITEM_SIZE (8 * 1024)
+static mempool_t *cprb_mempool;
+
/* ep11 card info cache */
struct card_list_entry {
struct list_head list;
@@ -411,12 +421,19 @@ EXPORT_SYMBOL(ep11_check_aes_key);
/*
* Allocate and prepare ep11 cprb plus additional payload.
*/
-static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
+static void *alloc_cprbmem(size_t payload_len, u32 xflags)
{
size_t len = sizeof(struct ep11_cprb) + payload_len;
- struct ep11_cprb *cprb;
+ struct ep11_cprb *cprb = NULL;
- cprb = kzalloc(len, GFP_KERNEL);
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
+ if (cprb_mempool && len <= CPRB_MEMPOOL_ITEM_SIZE) {
+ cprb = mempool_alloc_preallocated(cprb_mempool);
+ memset(cprb, 0, len);
+ }
+ } else {
+ cprb = kzalloc(len, GFP_KERNEL);
+ }
if (!cprb)
return NULL;
@@ -429,6 +446,20 @@ static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
return cprb;
}
+/*
+ * Free ep11 cprb buffer space.
+ */
+static void free_cprbmem(void *mem, size_t payload_len, bool scrub, u32 xflags)
+{
+ if (scrub)
+ memzero_explicit(mem, sizeof(struct ep11_cprb) + payload_len);
+
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC)
+ mempool_free(mem, cprb_mempool);
+ else
+ kfree(mem);
+}
+
/*
* Some helper functions related to ASN1 encoding.
* Limited to length info <= 2 byte.
@@ -605,11 +636,12 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
struct ep11_target_dev target;
- struct ep11_urb *urb = NULL;
+ struct ep11_urb urb;
int api = EP11_API_V1, rc = -ENOMEM;
+ const u32 xflags = 0;
/* request cprb and payload */
- req = alloc_cprb(sizeof(struct ep11_info_req_pl));
+ req = alloc_cprbmem(sizeof(struct ep11_info_req_pl), xflags);
if (!req)
goto out;
req_pl = (struct ep11_info_req_pl *)(((u8 *)req) + sizeof(*req));
@@ -621,22 +653,20 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
req_pl->query_subtype_len = sizeof(u32);
/* reply cprb and payload */
- rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen);
+ rep = alloc_cprbmem(sizeof(struct ep11_info_rep_pl) + buflen, xflags);
if (!rep)
goto out;
rep_pl = (struct ep11_info_rep_pl *)(((u8 *)rep) + sizeof(*rep));
/* urb and target */
- urb = kmalloc(sizeof(*urb), GFP_KERNEL);
- if (!urb)
- goto out;
+ memset(&urb, 0, sizeof(urb));
target.ap_id = cardnr;
target.dom_id = domain;
- prep_urb(urb, &target, 1,
+ prep_urb(&urb, &target, 1,
req, sizeof(*req) + sizeof(*req_pl),
rep, sizeof(*rep) + sizeof(*rep_pl) + buflen);
- rc = zcrypt_send_ep11_cprb(urb, 0);
+ rc = zcrypt_send_ep11_cprb(&urb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int)cardnr, (int)domain, rc);
@@ -667,9 +697,8 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
memcpy(buf, ((u8 *)rep_pl) + sizeof(*rep_pl), rep_pl->data_len);
out:
- kfree(req);
- kfree(rep);
- kfree(urb);
+ free_cprbmem(req, 0, false, xflags);
+ free_cprbmem(rep, 0, false, xflags);
return rc;
}
@@ -823,9 +852,10 @@ static int _ep11_genaeskey(u16 card, u16 domain,
struct ep11_cprb *req = NULL, *rep = NULL;
size_t req_pl_size, pinblob_size = 0;
struct ep11_target_dev target;
- struct ep11_urb *urb = NULL;
+ struct ep11_urb urb;
int api, rc = -ENOMEM;
u8 *p;
+ const u32 xflags = 0;
switch (keybitsize) {
case 128:
@@ -851,7 +881,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
pinblob_size = EP11_PINBLOB_V1_BYTES;
}
req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size);
- req = alloc_cprb(req_pl_size);
+ req = alloc_cprbmem(req_pl_size, xflags);
if (!req)
goto out;
req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req));
@@ -877,22 +907,20 @@ static int _ep11_genaeskey(u16 card, u16 domain,
*p++ = pinblob_size;
/* reply cprb and payload */
- rep = alloc_cprb(sizeof(struct keygen_rep_pl));
+ rep = alloc_cprbmem(sizeof(struct keygen_rep_pl), xflags);
if (!rep)
goto out;
rep_pl = (struct keygen_rep_pl *)(((u8 *)rep) + sizeof(*rep));
/* urb and target */
- urb = kmalloc(sizeof(*urb), GFP_KERNEL);
- if (!urb)
- goto out;
+ memset(&urb, 0, sizeof(urb));
target.ap_id = card;
target.dom_id = domain;
- prep_urb(urb, &target, 1,
+ prep_urb(&urb, &target, 1,
req, sizeof(*req) + req_pl_size,
rep, sizeof(*rep) + sizeof(*rep_pl));
- rc = zcrypt_send_ep11_cprb(urb, 0);
+ rc = zcrypt_send_ep11_cprb(&urb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int)card, (int)domain, rc);
@@ -925,9 +953,8 @@ static int _ep11_genaeskey(u16 card, u16 domain,
*keybufsize = rep_pl->data_len;
out:
- kfree(req);
- kfree(rep);
- kfree(urb);
+ free_cprbmem(req, 0, false, xflags);
+ free_cprbmem(rep, sizeof(struct keygen_rep_pl), true, xflags);
return rc;
}
@@ -1000,10 +1027,11 @@ static int ep11_cryptsingle(u16 card, u16 domain,
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
struct ep11_target_dev target;
- struct ep11_urb *urb = NULL;
+ struct ep11_urb urb;
size_t req_pl_size, rep_pl_size;
int n, api = EP11_API_V1, rc = -ENOMEM;
u8 *p;
+ const u32 xflags = 0;
/* the simple asn1 coding used has length limits */
if (keysize > 0xFFFF || inbufsize > 0xFFFF)
@@ -1012,7 +1040,7 @@ static int ep11_cryptsingle(u16 card, u16 domain,
/* request cprb and payload */
req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0)
+ ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize);
- req = alloc_cprb(req_pl_size);
+ req = alloc_cprbmem(req_pl_size, xflags);
if (!req)
goto out;
req_pl = (struct crypt_req_pl *)(((u8 *)req) + sizeof(*req));
@@ -1034,22 +1062,20 @@ static int ep11_cryptsingle(u16 card, u16 domain,
/* reply cprb and payload, assume out data size <= in data size + 32 */
rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32);
- rep = alloc_cprb(rep_pl_size);
+ rep = alloc_cprbmem(rep_pl_size, xflags);
if (!rep)
goto out;
rep_pl = (struct crypt_rep_pl *)(((u8 *)rep) + sizeof(*rep));
/* urb and target */
- urb = kmalloc(sizeof(*urb), GFP_KERNEL);
- if (!urb)
- goto out;
+ memset(&urb, 0, sizeof(urb));
target.ap_id = card;
target.dom_id = domain;
- prep_urb(urb, &target, 1,
+ prep_urb(&urb, &target, 1,
req, sizeof(*req) + req_pl_size,
rep, sizeof(*rep) + rep_pl_size);
- rc = zcrypt_send_ep11_cprb(urb, 0);
+ rc = zcrypt_send_ep11_cprb(&urb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int)card, (int)domain, rc);
@@ -1095,9 +1121,8 @@ static int ep11_cryptsingle(u16 card, u16 domain,
*outbufsize = n;
out:
- kfree(req);
- kfree(rep);
- kfree(urb);
+ free_cprbmem(req, req_pl_size, true, xflags);
+ free_cprbmem(rep, rep_pl_size, true, xflags);
return rc;
}
@@ -1143,9 +1168,10 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
struct ep11_cprb *req = NULL, *rep = NULL;
size_t req_pl_size, pinblob_size = 0;
struct ep11_target_dev target;
- struct ep11_urb *urb = NULL;
+ struct ep11_urb urb;
int api, rc = -ENOMEM;
u8 *p;
+ const u32 xflags = 0;
/* request cprb and payload */
api = (!keygenflags || keygenflags & 0x00200000) ?
@@ -1161,7 +1187,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0)
+ ASN1TAGLEN(keksize) + ASN1TAGLEN(0)
+ ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize);
- req = alloc_cprb(req_pl_size);
+ req = alloc_cprbmem(req_pl_size, xflags);
if (!req)
goto out;
req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req));
@@ -1197,22 +1223,20 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
p += asn1tag_write(p, 0x04, enckey, enckeysize);
/* reply cprb and payload */
- rep = alloc_cprb(sizeof(struct uw_rep_pl));
+ rep = alloc_cprbmem(sizeof(struct uw_rep_pl), xflags);
if (!rep)
goto out;
rep_pl = (struct uw_rep_pl *)(((u8 *)rep) + sizeof(*rep));
/* urb and target */
- urb = kmalloc(sizeof(*urb), GFP_KERNEL);
- if (!urb)
- goto out;
+ memset(&urb, 0, sizeof(urb));
target.ap_id = card;
target.dom_id = domain;
- prep_urb(urb, &target, 1,
+ prep_urb(&urb, &target, 1,
req, sizeof(*req) + req_pl_size,
rep, sizeof(*rep) + sizeof(*rep_pl));
- rc = zcrypt_send_ep11_cprb(urb, 0);
+ rc = zcrypt_send_ep11_cprb(&urb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int)card, (int)domain, rc);
@@ -1245,9 +1269,8 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
*keybufsize = rep_pl->data_len;
out:
- kfree(req);
- kfree(rep);
- kfree(urb);
+ free_cprbmem(req, req_pl_size, true, xflags);
+ free_cprbmem(rep, sizeof(struct uw_rep_pl), true, xflags);
return rc;
}
@@ -1319,15 +1342,16 @@ static int _ep11_wrapkey(u16 card, u16 domain,
} __packed * rep_pl;
struct ep11_cprb *req = NULL, *rep = NULL;
struct ep11_target_dev target;
- struct ep11_urb *urb = NULL;
+ struct ep11_urb urb;
size_t req_pl_size;
int api, rc = -ENOMEM;
u8 *p;
+ const u32 xflags = 0;
/* request cprb and payload */
req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
+ ASN1TAGLEN(keysize) + 4;
- req = alloc_cprb(req_pl_size);
+ req = alloc_cprbmem(req_pl_size, xflags);
if (!req)
goto out;
if (!mech || mech == 0x80060001)
@@ -1357,22 +1381,20 @@ static int _ep11_wrapkey(u16 card, u16 domain,
*p++ = 0;
/* reply cprb and payload */
- rep = alloc_cprb(sizeof(struct wk_rep_pl));
+ rep = alloc_cprbmem(sizeof(struct wk_rep_pl), xflags);
if (!rep)
goto out;
rep_pl = (struct wk_rep_pl *)(((u8 *)rep) + sizeof(*rep));
/* urb and target */
- urb = kmalloc(sizeof(*urb), GFP_KERNEL);
- if (!urb)
- goto out;
+ memset(&urb, 0, sizeof(urb));
target.ap_id = card;
target.dom_id = domain;
- prep_urb(urb, &target, 1,
+ prep_urb(&urb, &target, 1,
req, sizeof(*req) + req_pl_size,
rep, sizeof(*rep) + sizeof(*rep_pl));
- rc = zcrypt_send_ep11_cprb(urb, 0);
+ rc = zcrypt_send_ep11_cprb(&urb, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
__func__, (int)card, (int)domain, rc);
@@ -1405,9 +1427,8 @@ static int _ep11_wrapkey(u16 card, u16 domain,
*datasize = rep_pl->data_len;
out:
- kfree(req);
- kfree(rep);
- kfree(urb);
+ free_cprbmem(req, req_pl_size, true, xflags);
+ free_cprbmem(rep, sizeof(struct wk_rep_pl), true, xflags);
return rc;
}
@@ -1459,7 +1480,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
encbuf, encbuflen, 0, def_iv,
keybitsize, 0, keybuf, keybufsize, keytype);
if (rc) {
- ZCRYPT_DBF_ERR("%s importing key value as new key failed,, rc=%d\n",
+ ZCRYPT_DBF_ERR("%s importing key value as new key failed, rc=%d\n",
__func__, rc);
goto out;
}
@@ -1658,7 +1679,23 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
}
EXPORT_SYMBOL(ep11_findcard2);
-void __exit zcrypt_ep11misc_exit(void)
+int __init zcrypt_ep11misc_init(void)
+{
+ /* Pre-allocate a small memory pool for ep11 cprbs. */
+ cprb_mempool = mempool_create_kmalloc_pool(CPRB_MEMPOOL_MIN_ITEMS,
+ CPRB_MEMPOOL_ITEM_SIZE);
+ if (IS_ERR(cprb_mempool)) {
+ ZCRYPT_DBF_ERR("%s mempool_create(%d,%d) failed: %ld\n",
+ __func__, CPRB_MEMPOOL_MIN_ITEMS,
+ CPRB_MEMPOOL_ITEM_SIZE, PTR_ERR(cprb_mempool));
+ cprb_mempool = NULL;
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+void zcrypt_ep11misc_exit(void)
{
card_cache_free();
+ mempool_destroy(cprb_mempool);
}
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index 9f1bdffdec68..a4b98eca8431 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -152,6 +152,7 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int ep11_kblob2protkey(u16 card, u16 dom, const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+int zcrypt_ep11misc_init(void);
void zcrypt_ep11misc_exit(void);
#endif /* _ZCRYPT_EP11MISC_H_ */
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (5 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 " Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-27 11:34 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 08/20] s390/zcrypt: Introduce pre-allocated device status array for cca misc Harald Freudenberger
` (12 subsequent siblings)
19 siblings, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Introduce a new function zcrypt_device_status_mask_ext2().
This function gives the possibility to provide upper limits
for cards and queues. The current implementation of
zcrypt_device_status_mask_ext() needs an array of
256 * 256 * 4 = 256 KB which is huge. The new function
is more flexible in the sense that the caller can decide
the upper limit for cards and domains to be stored into
the status array. So for example a caller may decide to
only query for cards 0...127 and queues 0...127 and thus
only an array of size 128 * 128 * 4 = 64 KB is needed.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_api.c | 26 ++++++++++++++++++++++++++
drivers/s390/crypto/zcrypt_api.h | 2 ++
2 files changed, 28 insertions(+)
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index 3a521e65f3fe..fd9666ae1d26 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -1330,6 +1330,32 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus)
}
EXPORT_SYMBOL(zcrypt_device_status_mask_ext);
+void zcrypt_device_status_mask_ext2(struct zcrypt_device_status_ext *devstatus,
+ int maxcard, int maxqueue)
+{
+ struct zcrypt_card *zc;
+ struct zcrypt_queue *zq;
+ struct zcrypt_device_status_ext *stat;
+ int card, queue;
+
+ spin_lock(&zcrypt_list_lock);
+ for_each_zcrypt_card(zc) {
+ for_each_zcrypt_queue(zq, zc) {
+ card = AP_QID_CARD(zq->queue->qid);
+ queue = AP_QID_QUEUE(zq->queue->qid);
+ if (card >= maxcard || queue >= maxqueue)
+ continue;
+ stat = &devstatus[card * maxqueue + queue];
+ stat->hwtype = zc->card->ap_dev.device_type;
+ stat->functions = zc->card->hwinfo.fac >> 26;
+ stat->qid = zq->queue->qid;
+ stat->online = zq->online ? 0x01 : 0x00;
+ }
+ }
+ spin_unlock(&zcrypt_list_lock);
+}
+EXPORT_SYMBOL(zcrypt_device_status_mask_ext2);
+
int zcrypt_device_status_ext(int card, int queue,
struct zcrypt_device_status_ext *devstat)
{
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 06ff697d171c..92027304f0d8 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -172,6 +172,8 @@ void zcrypt_api_exit(void);
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);
+void zcrypt_device_status_mask_ext2(struct zcrypt_device_status_ext *devstatus,
+ int maxcard, int maxqueue);
int zcrypt_device_status_ext(int card, int queue,
struct zcrypt_device_status_ext *devstatus);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 08/20] s390/zcrypt: Introduce pre-allocated device status array for cca misc
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (6 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2 Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 09/20] s390/zcrypt: Introduce pre-allocated device status array for ep11 misc Harald Freudenberger
` (11 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Introduce a pre-allocated device status array memory together with
a mutex controlling the occupation to be used by the two findcard()
functions. Limit the device status array to max 128 cards and max
128 domains to reduce the size of this pre-allocated memory to 64 KB.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ccamisc.c | 89 +++++++++++++++++++---------
1 file changed, 61 insertions(+), 28 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index e604a69e40fc..71cad7cf8656 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -52,6 +52,22 @@ static DEFINE_SPINLOCK(cca_info_list_lock);
#define CPRB_MEMPOOL_ITEM_SIZE (16 * 1024)
static mempool_t *cprb_mempool;
+/*
+ * This is a pre-allocated memory for the device status array
+ * used within the findcard() functions. It is currently
+ * 128 * 128 * 4 bytes = 64 KB big. Usage of this memory is
+ * controlled via dev_status_mem_mutex. Needs adaption if more
+ * than 128 cards or domains to be are supported.
+ */
+#define ZCRYPT_DEV_STATUS_CARD_MAX 128
+#define ZCRYPT_DEV_STATUS_QUEUE_MAX 128
+#define ZCRYPT_DEV_STATUS_ENTRIES (ZCRYPT_DEV_STATUS_CARD_MAX * \
+ ZCRYPT_DEV_STATUS_QUEUE_MAX)
+#define ZCRYPT_DEV_STATUS_EXT2_SIZE (ZCRYPT_DEV_STATUS_ENTRIES * \
+ sizeof(struct zcrypt_device_status_ext))
+static void *dev_status_mem;
+static DEFINE_MUTEX(dev_status_mem_mutex);
+
/*
* Simple check if the token is a valid CCA secure AES data key
* token. If keybitsize is given, the bitsize of the key is
@@ -1800,16 +1816,18 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
if (mkvp == 0 || minhwtype < 0)
return -EINVAL;
- /* fetch status of all crypto cards */
- device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT,
- sizeof(struct zcrypt_device_status_ext),
- GFP_KERNEL);
- if (!device_status)
- return -ENOMEM;
- zcrypt_device_status_mask_ext(device_status);
+ /* occupy the device status memory */
+ mutex_lock(&dev_status_mem_mutex);
+ memset(dev_status_mem, 0, ZCRYPT_DEV_STATUS_EXT2_SIZE);
+ device_status = (struct zcrypt_device_status_ext *)dev_status_mem;
+
+ /* fetch crypto device status into this struct */
+ zcrypt_device_status_mask_ext2(device_status,
+ ZCRYPT_DEV_STATUS_CARD_MAX,
+ ZCRYPT_DEV_STATUS_QUEUE_MAX);
/* walk through all crypto cards */
- for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+ for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
if (device_status[i].online &&
@@ -1836,9 +1854,9 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
cca_info_cache_scrub(card, dom);
}
}
- if (i >= MAX_ZDEV_ENTRIES_EXT) {
+ if (i >= ZCRYPT_DEV_STATUS_ENTRIES) {
/* nothing found, so this time without cache */
- for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+ for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
if (!(device_status[i].online &&
device_status[i].functions & 0x04))
continue;
@@ -1858,23 +1876,25 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
oi = i;
}
}
- if (i >= MAX_ZDEV_ENTRIES_EXT && oi >= 0) {
+ if (i >= ZCRYPT_DEV_STATUS_ENTRIES && oi >= 0) {
/* old mkvp matched, use this card then */
card = AP_QID_CARD(device_status[oi].qid);
dom = AP_QID_QUEUE(device_status[oi].qid);
}
}
- if (i < MAX_ZDEV_ENTRIES_EXT || oi >= 0) {
+ if (i < ZCRYPT_DEV_STATUS_ENTRIES || oi >= 0) {
if (pcardnr)
*pcardnr = card;
if (pdomain)
*pdomain = dom;
- rc = (i < MAX_ZDEV_ENTRIES_EXT ? 0 : 1);
+ rc = (i < ZCRYPT_DEV_STATUS_ENTRIES ? 0 : 1);
} else {
rc = -ENODEV;
}
- kvfree(device_status);
+ /* release the device status memory */
+ mutex_unlock(&dev_status_mem_mutex);
+
return rc;
}
@@ -1913,26 +1933,26 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
{
struct zcrypt_device_status_ext *device_status;
u32 *_apqns = NULL, _nr_apqns = 0;
- int i, card, dom, curmatch, oldmatch, rc = 0;
+ int i, card, dom, curmatch, oldmatch, rc = -ENOMEM;
struct cca_info ci;
- /* fetch status of all crypto cards */
- device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT,
- sizeof(struct zcrypt_device_status_ext),
- GFP_KERNEL);
- if (!device_status)
- return -ENOMEM;
- zcrypt_device_status_mask_ext(device_status);
+ /* occupy the device status memory */
+ mutex_lock(&dev_status_mem_mutex);
+ memset(dev_status_mem, 0, ZCRYPT_DEV_STATUS_EXT2_SIZE);
+ device_status = (struct zcrypt_device_status_ext *)dev_status_mem;
+
+ /* fetch crypto device status into this struct */
+ zcrypt_device_status_mask_ext2(device_status,
+ ZCRYPT_DEV_STATUS_CARD_MAX,
+ ZCRYPT_DEV_STATUS_QUEUE_MAX);
/* allocate 1k space for up to 256 apqns */
_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
- if (!_apqns) {
- kvfree(device_status);
- return -ENOMEM;
- }
+ if (!_apqns)
+ goto out;
/* walk through all the crypto apqnss */
- for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+ for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* check online state */
@@ -1993,7 +2013,10 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
rc = 0;
}
- kvfree(device_status);
+out:
+ /* release the device status memory */
+ mutex_unlock(&dev_status_mem_mutex);
+
return rc;
}
EXPORT_SYMBOL(cca_findcard2);
@@ -2010,11 +2033,21 @@ int __init zcrypt_ccamisc_init(void)
cprb_mempool = NULL;
return -ENOMEM;
}
+
+ /* Pre-allocate one crypto status card struct used in findcard() */
+ dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT2_SIZE, GFP_KERNEL);
+ if (!dev_status_mem) {
+ ZCRYPT_DBF_ERR("%s allocation of dev_status_mem failed\n", __func__);
+ mempool_destroy(cprb_mempool);
+ return -ENOMEM;
+ }
+
return 0;
}
void zcrypt_ccamisc_exit(void)
{
mkvp_cache_free();
+ kvfree(dev_status_mem);
mempool_destroy(cprb_mempool);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 09/20] s390/zcrypt: Introduce pre-allocated device status array for ep11 misc
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (7 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 08/20] s390/zcrypt: Introduce pre-allocated device status array for cca misc Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 10/20] s390/zcrypt/pkey: Rework cca findcard() implementation and callers Harald Freudenberger
` (10 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Introduce a pre-allocated device status array memory together with
a mutex controlling the occupation to be used by the findcard()
function. Limit the device status array to max 128 cards and max
128 domains to reduce the size of this pre-allocated memory to 64 KB.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ep11misc.c | 54 ++++++++++++++++++++-------
1 file changed, 41 insertions(+), 13 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index 3d96bd236c16..e9a705329ff8 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -40,6 +40,22 @@ static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
#define CPRB_MEMPOOL_ITEM_SIZE (8 * 1024)
static mempool_t *cprb_mempool;
+/*
+ * This is a pre-allocated memory for the device status array
+ * used within the findcard() functions. It is currently
+ * 128 * 128 * 4 bytes = 64 KB big. Usage of this memory is
+ * controlled via dev_status_mem_mutex. Needs adaption if more
+ * than 128 cards or domains to be are supported.
+ */
+#define ZCRYPT_DEV_STATUS_CARD_MAX 128
+#define ZCRYPT_DEV_STATUS_QUEUE_MAX 128
+#define ZCRYPT_DEV_STATUS_ENTRIES (ZCRYPT_DEV_STATUS_CARD_MAX * \
+ ZCRYPT_DEV_STATUS_QUEUE_MAX)
+#define ZCRYPT_DEV_STATUS_EXT2_SIZE (ZCRYPT_DEV_STATUS_ENTRIES * \
+ sizeof(struct zcrypt_device_status_ext))
+static void *dev_status_mem;
+static DEFINE_MUTEX(dev_status_mem_mutex);
+
/* ep11 card info cache */
struct card_list_entry {
struct list_head list;
@@ -1608,23 +1624,23 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
struct ep11_domain_info edi;
struct ep11_card_info eci;
- /* fetch status of all crypto cards */
- device_status = kvcalloc(MAX_ZDEV_ENTRIES_EXT,
- sizeof(struct zcrypt_device_status_ext),
- GFP_KERNEL);
- if (!device_status)
- return -ENOMEM;
- zcrypt_device_status_mask_ext(device_status);
+ /* occupy the device status memory */
+ mutex_lock(&dev_status_mem_mutex);
+ memset(dev_status_mem, 0, ZCRYPT_DEV_STATUS_EXT2_SIZE);
+ device_status = (struct zcrypt_device_status_ext *)dev_status_mem;
+
+ /* fetch crypto device status into this struct */
+ zcrypt_device_status_mask_ext2(device_status,
+ ZCRYPT_DEV_STATUS_CARD_MAX,
+ ZCRYPT_DEV_STATUS_QUEUE_MAX);
/* allocate 1k space for up to 256 apqns */
_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
- if (!_apqns) {
- kvfree(device_status);
- return -ENOMEM;
- }
+ if (!_apqns)
+ goto out;
/* walk through all the crypto apqnss */
- for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+ for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* check online state */
@@ -1674,7 +1690,9 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
rc = 0;
}
- kvfree(device_status);
+out:
+ mutex_unlock(&dev_status_mem_mutex);
+
return rc;
}
EXPORT_SYMBOL(ep11_findcard2);
@@ -1691,11 +1709,21 @@ int __init zcrypt_ep11misc_init(void)
cprb_mempool = NULL;
return -ENOMEM;
}
+
+ /* Pre-allocate one crypto status card struct used in findcard() */
+ dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT2_SIZE, GFP_KERNEL);
+ if (!dev_status_mem) {
+ ZCRYPT_DBF_ERR("%s allocation of dev_status_mem failed\n", __func__);
+ mempool_destroy(cprb_mempool);
+ return -ENOMEM;
+ }
+
return 0;
}
void zcrypt_ep11misc_exit(void)
{
card_cache_free();
+ kvfree(dev_status_mem);
mempool_destroy(cprb_mempool);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 10/20] s390/zcrypt/pkey: Rework cca findcard() implementation and callers
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (8 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 09/20] s390/zcrypt: Introduce pre-allocated device status array for ep11 misc Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 11/20] s390/zcrypt/pkey: Rework ep11 " Harald Freudenberger
` (9 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Rework the memory usage of the cca findcard() implementation:
- findcard does not allocate memory for the list of apqns
any more.
- the callers are now responsible to provide an array of
apqns to store the matching apqns into.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_cca.c | 25 +++++++++++--------------
drivers/s390/crypto/zcrypt_ccamisc.c | 19 +++++--------------
drivers/s390/crypto/zcrypt_ccamisc.h | 12 +++++-------
3 files changed, 21 insertions(+), 35 deletions(-)
diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c
index cda22db31f6c..8c9a0c5ca630 100644
--- a/drivers/s390/crypto/pkey_cca.c
+++ b/drivers/s390/crypto/pkey_cca.c
@@ -73,7 +73,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- u32 _nr_apqns, *_apqns = NULL;
+ u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
if (!flags)
@@ -107,7 +107,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
/* unknown CCA internal token type */
return -EINVAL;
}
- rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, AES_MK_SET,
cur_mkvp, old_mkvp, 1);
if (rc)
@@ -126,7 +126,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
/* unknown CCA internal 2 token type */
return -EINVAL;
}
- rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, APKA_MK_SET,
cur_mkvp, old_mkvp, 1);
if (rc)
@@ -147,7 +147,6 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
*nr_apqns = _nr_apqns;
out:
- kfree(_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -156,7 +155,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
- u32 _nr_apqns, *_apqns = NULL;
+ u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
zcrypt_wait_api_operational();
@@ -171,7 +170,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
old_mkvp = *((u64 *)alt_mkvp);
if (ktype == PKEY_TYPE_CCA_CIPHER)
minhwtype = ZCRYPT_CEX6;
- rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, AES_MK_SET,
cur_mkvp, old_mkvp, 1);
if (rc)
@@ -184,7 +183,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
cur_mkvp = *((u64 *)cur_mkvp);
if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
old_mkvp = *((u64 *)alt_mkvp);
- rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, APKA_MK_SET,
cur_mkvp, old_mkvp, 1);
if (rc)
@@ -205,7 +204,6 @@ static int cca_apqns4type(enum pkey_key_type ktype,
*nr_apqns = _nr_apqns;
out:
- kfree(_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -461,7 +459,7 @@ static int cca_verifykey(const u8 *key, u32 keylen,
u32 *keytype, u32 *keybitsize, u32 *flags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- u32 nr_apqns, *apqns = NULL;
+ u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
int rc;
if (keylen < sizeof(*hdr))
@@ -478,13 +476,13 @@ static int cca_verifykey(const u8 *key, u32 keylen,
goto out;
*keytype = PKEY_TYPE_CCA_DATA;
*keybitsize = t->bitsize;
- rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX3C, AES_MK_SET,
t->mkvp, 0, 1);
if (!rc)
*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
if (rc == -ENODEV) {
- rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX3C, AES_MK_SET,
0, t->mkvp, 1);
if (!rc)
@@ -511,13 +509,13 @@ static int cca_verifykey(const u8 *key, u32 keylen,
*keybitsize = PKEY_SIZE_AES_192;
else if (!t->plfver && t->wpllen == 640)
*keybitsize = PKEY_SIZE_AES_256;
- rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX6, AES_MK_SET,
t->mkvp0, 0, 1);
if (!rc)
*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
if (rc == -ENODEV) {
- rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX6, AES_MK_SET,
0, t->mkvp0, 1);
if (!rc)
@@ -535,7 +533,6 @@ static int cca_verifykey(const u8 *key, u32 keylen,
}
out:
- kfree(apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 71cad7cf8656..4fcc45048ee5 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -1927,14 +1927,14 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify)
}
EXPORT_SYMBOL(cca_findcard);
-int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
int verify)
{
struct zcrypt_device_status_ext *device_status;
- u32 *_apqns = NULL, _nr_apqns = 0;
- int i, card, dom, curmatch, oldmatch, rc = -ENOMEM;
+ int i, card, dom, curmatch, oldmatch, rc;
struct cca_info ci;
+ u32 _nr_apqns = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
@@ -1946,11 +1946,6 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
ZCRYPT_DEV_STATUS_CARD_MAX,
ZCRYPT_DEV_STATUS_QUEUE_MAX);
- /* allocate 1k space for up to 256 apqns */
- _apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
- if (!_apqns)
- goto out;
-
/* walk through all the crypto apqnss */
for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
@@ -1998,22 +1993,18 @@ int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
continue;
}
/* apqn passed all filtering criterons, add to the array */
- if (_nr_apqns < 256)
- _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
+ if (_nr_apqns < *nr_apqns)
+ apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
}
/* nothing found ? */
if (!_nr_apqns) {
- kfree(_apqns);
rc = -ENODEV;
} else {
- /* no re-allocation, simple return the _apqns array */
- *apqns = _apqns;
*nr_apqns = _nr_apqns;
rc = 0;
}
-out:
/* release the device status memory */
mutex_unlock(&dev_status_mem_mutex);
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index 273edf2bb036..bed647a42eb2 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -229,14 +229,12 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify);
* cur_mkvp or old_mkvp values of the apqn are used.
* The mktype determines which set of master keys to use:
* 0 = AES_MK_SET - AES MK set, 1 = APKA MK_SET - APKA MK set
- * The array of apqn entries is allocated with kmalloc and returned in *apqns;
- * the number of apqns stored into the list is returned in *nr_apqns. One apqn
- * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
- * may be casted to struct pkey_apqn. The return value is either 0 for success
- * or a negative errno value. If no apqn meeting the criteria is found,
- * -ENODEV is returned.
+ * The caller should set *nr_apqns to the nr of elements available in *apqns.
+ * On return *nr_apqns is then updated with the nr of apqns filled into *apqns.
+ * The return value is either 0 for success or a negative errno value.
+ * If no apqn meeting the criteria is found, -ENODEV is returned.
*/
-int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
int verify);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 11/20] s390/zcrypt/pkey: Rework ep11 findcard() implementation and callers
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (9 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 10/20] s390/zcrypt/pkey: Rework cca findcard() implementation and callers Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 12/20] s390/zcrypt: Rework cca misc functions kmallocs to use the cprb mempool Harald Freudenberger
` (8 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Rework the memory usage of the ep11 findcard() implementation:
- findcard does not allocate memory for the list of apqns
any more.
- the callers are now responsible to provide an array of
apqns to store the matching apqns into.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_ep11.c | 19 ++++++++-----------
drivers/s390/crypto/zcrypt_ep11misc.c | 19 +++++--------------
drivers/s390/crypto/zcrypt_ep11misc.h | 12 +++++-------
3 files changed, 18 insertions(+), 32 deletions(-)
diff --git a/drivers/s390/crypto/pkey_ep11.c b/drivers/s390/crypto/pkey_ep11.c
index 5b033ca3e828..b970f0be84be 100644
--- a/drivers/s390/crypto/pkey_ep11.c
+++ b/drivers/s390/crypto/pkey_ep11.c
@@ -73,7 +73,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- u32 _nr_apqns, *_apqns = NULL;
+ u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
if (!flags)
@@ -98,7 +98,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
minhwtype = ZCRYPT_CEX7;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
- rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, api, kb->wkvp);
if (rc)
goto out;
@@ -115,7 +115,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
minhwtype = ZCRYPT_CEX7;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
- rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, api, kb->wkvp);
if (rc)
goto out;
@@ -135,7 +135,6 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
*nr_apqns = _nr_apqns;
out:
- kfree(_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -144,7 +143,7 @@ static int ep11_apqns4type(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
struct pkey_apqn *apqns, size_t *nr_apqns)
{
- u32 _nr_apqns, *_apqns = NULL;
+ u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
zcrypt_wait_api_operational();
@@ -158,7 +157,7 @@ static int ep11_apqns4type(enum pkey_key_type ktype,
if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
wkvp = cur_mkvp;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
- rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+ rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, api, wkvp);
if (rc)
goto out;
@@ -178,7 +177,6 @@ static int ep11_apqns4type(enum pkey_key_type ktype,
*nr_apqns = _nr_apqns;
out:
- kfree(_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -423,7 +421,7 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
u32 *keytype, u32 *keybitsize, u32 *flags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- u32 nr_apqns, *apqns = NULL;
+ u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
int rc;
if (keylen < sizeof(*hdr))
@@ -443,7 +441,7 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
*keybitsize = kb->head.bitlen;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
- rc = ep11_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX7, api,
ep11_kb_wkvp(key, keylen));
if (rc)
@@ -467,7 +465,7 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
*keybitsize = kh->bitlen;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
- rc = ep11_findcard2(&apqns, &nr_apqns, *card, *dom,
+ rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX7, api,
ep11_kb_wkvp(key, keylen));
if (rc)
@@ -484,7 +482,6 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
}
out:
- kfree(apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index e9a705329ff8..09b5ab0d7174 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -1615,14 +1615,14 @@ int ep11_kblob2protkey(u16 card, u16 dom,
}
EXPORT_SYMBOL(ep11_kblob2protkey);
-int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int minapi, const u8 *wkvp)
{
struct zcrypt_device_status_ext *device_status;
- u32 *_apqns = NULL, _nr_apqns = 0;
- int i, card, dom, rc = -ENOMEM;
+ int i, card, dom, rc;
struct ep11_domain_info edi;
struct ep11_card_info eci;
+ u32 _nr_apqns = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
@@ -1634,11 +1634,6 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
ZCRYPT_DEV_STATUS_CARD_MAX,
ZCRYPT_DEV_STATUS_QUEUE_MAX);
- /* allocate 1k space for up to 256 apqns */
- _apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
- if (!_apqns)
- goto out;
-
/* walk through all the crypto apqnss */
for (i = 0; i < ZCRYPT_DEV_STATUS_ENTRIES; i++) {
card = AP_QID_CARD(device_status[i].qid);
@@ -1675,22 +1670,18 @@ int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
continue;
}
/* apqn passed all filtering criterons, add to the array */
- if (_nr_apqns < 256)
- _apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
+ if (_nr_apqns < *nr_apqns)
+ apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16)dom);
}
/* nothing found ? */
if (!_nr_apqns) {
- kfree(_apqns);
rc = -ENODEV;
} else {
- /* no re-allocation, simple return the _apqns array */
- *apqns = _apqns;
*nr_apqns = _nr_apqns;
rc = 0;
}
-out:
mutex_unlock(&dev_status_mem_mutex);
return rc;
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index a4b98eca8431..cbd615547bc2 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -136,14 +136,12 @@ int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
* key for this domain. When a wkvp is given there will always be a re-fetch
* of the domain info for the potential apqn - so this triggers an request
* reply to each apqn eligible.
- * The array of apqn entries is allocated with kmalloc and returned in *apqns;
- * the number of apqns stored into the list is returned in *nr_apqns. One apqn
- * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
- * may be casted to struct pkey_apqn. The return value is either 0 for success
- * or a negative errno value. If no apqn meeting the criteria is found,
- * -ENODEV is returned.
+ * The caller should set *nr_apqns to the nr of elements available in *apqns.
+ * On return *nr_apqns is then updated with the nr of apqns filled into *apqns.
+ * The return value is either 0 for success or a negative errno value.
+ * If no apqn meeting the criteria is found, -ENODEV is returned.
*/
-int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int minapi, const u8 *wkvp);
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 12/20] s390/zcrypt: Rework cca misc functions kmallocs to use the cprb mempool
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (10 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 11/20] s390/zcrypt/pkey: Rework ep11 " Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 13/20] s390/zcrypt: Add small mempool for cca info list entries Harald Freudenberger
` (7 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Rework two places in the zcrypt cca misc code using kmalloc() for
ephemeral memory allocation. As there is anyway now a cprb mempool
let's use this pool instead to satisfy these short term memory
allocations.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ccamisc.c | 44 +++++++++++++++++++---------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index 4fcc45048ee5..c1c255e45873 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -48,7 +48,7 @@ static DEFINE_SPINLOCK(cca_info_list_lock);
* ZCRYPT_XFLAG_NOMEMALLOC. The cprb memory needs to hold
* space for request AND reply!
*/
-#define CPRB_MEMPOOL_MIN_ITEMS 4
+#define CPRB_MEMPOOL_MIN_ITEMS 6
#define CPRB_MEMPOOL_ITEM_SIZE (16 * 1024)
static mempool_t *cprb_mempool;
@@ -1137,20 +1137,29 @@ int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags,
const u8 *clrkey, u8 *keybuf, u32 *keybufsize)
{
int rc;
- u8 *token;
+ void *mem;
int tokensize;
- u8 exorbuf[32];
+ u8 *token, exorbuf[32];
struct cipherkeytoken *t;
+ u32 xflags = 0;
/* fill exorbuf with random data */
get_random_bytes(exorbuf, sizeof(exorbuf));
- /* allocate space for the key token to build */
- token = kmalloc(MAXCCAVLSCTOKENSIZE, GFP_KERNEL);
- if (!token)
+ /*
+ * Allocate space for the key token to build.
+ * Also we only need up to MAXCCAVLSCTOKENSIZE bytes for this
+ * we use the already existing cprb mempool to solve this
+ * short term memory requirement.
+ */
+ mem = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(cprb_mempool) :
+ mempool_alloc(cprb_mempool, GFP_KERNEL);
+ if (!mem)
return -ENOMEM;
/* prepare the token with the key skeleton */
+ token = (u8 *)mem;
tokensize = SIZEOF_SKELETON;
memcpy(token, aes_cipher_key_skeleton, tokensize);
@@ -1207,7 +1216,7 @@ int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags,
*keybufsize = tokensize;
out:
- kfree(token);
+ mempool_free(mem, cprb_mempool);
return rc;
}
EXPORT_SYMBOL(cca_clr2cipherkey);
@@ -1713,10 +1722,12 @@ static void __exit mkvp_cache_free(void)
*/
static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci)
{
+ void *mem;
int rc, found = 0;
size_t rlen, vlen;
- u8 *rarray, *varray, *pg;
+ u8 *rarray, *varray;
struct zcrypt_device_status_ext devstat;
+ u32 xflags = 0;
memset(ci, 0, sizeof(*ci));
@@ -1726,12 +1737,17 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci)
return rc;
ci->hwtype = devstat.hwtype;
- /* prep page for rule array and var array use */
- pg = (u8 *)__get_free_page(GFP_KERNEL);
- if (!pg)
+ /*
+ * Prep memory for rule array and var array use.
+ * Use the cprb mempool for this.
+ */
+ mem = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(cprb_mempool) :
+ mempool_alloc(cprb_mempool, GFP_KERNEL);
+ if (!mem)
return -ENOMEM;
- rarray = pg;
- varray = pg + PAGE_SIZE / 2;
+ rarray = (u8 *)mem;
+ varray = (u8 *)mem + PAGE_SIZE / 2;
rlen = vlen = PAGE_SIZE / 2;
/* QF for this card/domain */
@@ -1778,7 +1794,7 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci)
}
out:
- free_page((unsigned long)pg);
+ mempool_free(mem, cprb_mempool);
return found == 2 ? 0 : -ENOENT;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 13/20] s390/zcrypt: Add small mempool for cca info list entries
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (11 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 12/20] s390/zcrypt: Rework cca misc functions kmallocs to use the cprb mempool Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 14/20] s390/zcrypt: Locate ep11_domain_query_info onto the stack instead of kmalloc Harald Freudenberger
` (6 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Add a small memory pool for (pre-)allocating cca info list
entries. These entries are rather small and the pool is a simple
way to support the xflag ZCRYPT_XFLAG_NOMEMALLOC to avoid mallocs.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ccamisc.c | 67 ++++++++++++++++++++--------
drivers/s390/crypto/zcrypt_ccamisc.h | 3 +-
drivers/s390/crypto/zcrypt_cex4.c | 4 +-
3 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index c1c255e45873..ccf8206ae42d 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -41,6 +41,10 @@ struct cca_info_list_entry {
static LIST_HEAD(cca_info_list);
static DEFINE_SPINLOCK(cca_info_list_lock);
+/* memory pool for cca_info_list entries */
+#define INFO_ENTRY_MEMPOOL_MIN_ITEMS 8
+static mempool_t *info_mempool;
+
/*
* Cprb memory pool held for urgend cases where no memory
* can be allocated via kmalloc. This pool is only used
@@ -1661,7 +1665,7 @@ static int cca_info_cache_fetch(u16 cardnr, u16 domain, struct cca_info *ci)
}
static void cca_info_cache_update(u16 cardnr, u16 domain,
- const struct cca_info *ci)
+ const struct cca_info *ci, u32 xflags)
{
int found = 0;
struct cca_info_list_entry *ptr;
@@ -1676,7 +1680,9 @@ static void cca_info_cache_update(u16 cardnr, u16 domain,
}
}
if (!found) {
- ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC);
+ ptr = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(info_mempool) :
+ mempool_alloc(info_mempool, GFP_ATOMIC);
if (!ptr) {
spin_unlock_bh(&cca_info_list_lock);
return;
@@ -1698,7 +1704,7 @@ static void cca_info_cache_scrub(u16 cardnr, u16 domain)
if (ptr->cardnr == cardnr &&
ptr->domain == domain) {
list_del(&ptr->list);
- kfree(ptr);
+ mempool_free(ptr, info_mempool);
break;
}
}
@@ -1712,7 +1718,7 @@ static void __exit mkvp_cache_free(void)
spin_lock_bh(&cca_info_list_lock);
list_for_each_entry_safe(ptr, pnext, &cca_info_list, list) {
list_del(&ptr->list);
- kfree(ptr);
+ mempool_free(ptr, info_mempool);
}
spin_unlock_bh(&cca_info_list_lock);
}
@@ -1720,14 +1726,14 @@ static void __exit mkvp_cache_free(void)
/*
* Fetch cca_info values via query_crypto_facility from adapter.
*/
-static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci)
+static int fetch_cca_info(u16 cardnr, u16 domain,
+ struct cca_info *ci, u32 xflags)
{
void *mem;
int rc, found = 0;
size_t rlen, vlen;
u8 *rarray, *varray;
struct zcrypt_device_status_ext devstat;
- u32 xflags = 0;
memset(ci, 0, sizeof(*ci));
@@ -1801,15 +1807,15 @@ static int fetch_cca_info(u16 cardnr, u16 domain, struct cca_info *ci)
/*
* Fetch cca information about a CCA queue.
*/
-int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify)
+int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify, u32 xflags)
{
int rc;
rc = cca_info_cache_fetch(card, dom, ci);
if (rc || verify) {
- rc = fetch_cca_info(card, dom, ci);
+ rc = fetch_cca_info(card, dom, ci, xflags);
if (rc == 0)
- cca_info_cache_update(card, dom, ci);
+ cca_info_cache_update(card, dom, ci, xflags);
}
return rc;
@@ -1827,6 +1833,7 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
u16 card, dom;
struct cca_info ci;
int i, rc, oi = -1;
+ u32 xflg = 0; /* xflags */
/* mkvp must not be zero, minhwtype needs to be >= 0 */
if (mkvp == 0 || minhwtype < 0)
@@ -1856,8 +1863,8 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
if (!verify)
break;
/* verify: refresh card info */
- if (fetch_cca_info(card, dom, &ci) == 0) {
- cca_info_cache_update(card, dom, &ci);
+ if (fetch_cca_info(card, dom, &ci, xflg) == 0) {
+ cca_info_cache_update(card, dom, &ci, xflg);
if (ci.hwtype >= minhwtype &&
ci.cur_aes_mk_state == '2' &&
ci.cur_aes_mkvp == mkvp)
@@ -1879,8 +1886,8 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
card = AP_QID_CARD(device_status[i].qid);
dom = AP_QID_QUEUE(device_status[i].qid);
/* fresh fetch mkvp from adapter */
- if (fetch_cca_info(card, dom, &ci) == 0) {
- cca_info_cache_update(card, dom, &ci);
+ if (fetch_cca_info(card, dom, &ci, xflg) == 0) {
+ cca_info_cache_update(card, dom, &ci, xflg);
if (ci.hwtype >= minhwtype &&
ci.cur_aes_mk_state == '2' &&
ci.cur_aes_mkvp == mkvp)
@@ -1951,6 +1958,7 @@ int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int i, card, dom, curmatch, oldmatch, rc;
struct cca_info ci;
u32 _nr_apqns = 0;
+ u32 xflags = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
@@ -1979,7 +1987,7 @@ int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
if (domain != 0xFFFF && dom != domain)
continue;
/* get cca info on this apqn */
- if (cca_get_info(card, dom, &ci, verify))
+ if (cca_get_info(card, dom, &ci, verify, xflags))
continue;
/* current master key needs to be valid */
if (mktype == AES_MK_SET && ci.cur_aes_mk_state != '2')
@@ -2030,6 +2038,8 @@ EXPORT_SYMBOL(cca_findcard2);
int __init zcrypt_ccamisc_init(void)
{
+ int rc = -ENOMEM;
+
/* Pre-allocate a small memory pool for cca cprbs. */
cprb_mempool = mempool_create_kmalloc_pool(CPRB_MEMPOOL_MIN_ITEMS,
CPRB_MEMPOOL_ITEM_SIZE);
@@ -2037,19 +2047,39 @@ int __init zcrypt_ccamisc_init(void)
ZCRYPT_DBF_ERR("%s mempool_create(%d,%d) failed: %ld\n",
__func__, CPRB_MEMPOOL_MIN_ITEMS,
CPRB_MEMPOOL_ITEM_SIZE, PTR_ERR(cprb_mempool));
+ rc = PTR_ERR(cprb_mempool);
cprb_mempool = NULL;
- return -ENOMEM;
+ goto out;
+ }
+
+ /* Pre-allocate a small memory pool for cca info list entries */
+ info_mempool = mempool_create_kmalloc_pool(INFO_ENTRY_MEMPOOL_MIN_ITEMS,
+ sizeof(struct cca_info_list_entry));
+ if (IS_ERR(info_mempool)) {
+ ZCRYPT_DBF_ERR("%s info entry mempool_create(%d,%d) failed: %ld\n",
+ __func__, INFO_ENTRY_MEMPOOL_MIN_ITEMS,
+ (int)sizeof(struct cca_info_list_entry),
+ PTR_ERR(info_mempool));
+ rc = PTR_ERR(info_mempool);
+ info_mempool = NULL;
+ goto out;
}
/* Pre-allocate one crypto status card struct used in findcard() */
dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT2_SIZE, GFP_KERNEL);
if (!dev_status_mem) {
ZCRYPT_DBF_ERR("%s allocation of dev_status_mem failed\n", __func__);
- mempool_destroy(cprb_mempool);
- return -ENOMEM;
+ goto out;
}
- return 0;
+ rc = 0;
+
+out:
+ if (rc) {
+ mempool_destroy(cprb_mempool);
+ mempool_destroy(info_mempool);
+ }
+ return rc;
}
void zcrypt_ccamisc_exit(void)
@@ -2057,4 +2087,5 @@ void zcrypt_ccamisc_exit(void)
mkvp_cache_free();
kvfree(dev_status_mem);
mempool_destroy(cprb_mempool);
+ mempool_destroy(info_mempool);
}
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index bed647a42eb2..966f0eaf3c4c 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -268,7 +268,8 @@ struct cca_info {
/*
* Fetch cca information about an CCA queue.
*/
-int cca_get_info(u16 card, u16 dom, struct cca_info *ci, int verify);
+int cca_get_info(u16 card, u16 dom, struct cca_info *ci,
+ int verify, u32 xflags);
int zcrypt_ccamisc_init(void);
void zcrypt_ccamisc_exit(void);
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
index 64df7d2f6266..49a638d373fa 100644
--- a/drivers/s390/crypto/zcrypt_cex4.c
+++ b/drivers/s390/crypto/zcrypt_cex4.c
@@ -86,7 +86,7 @@ static ssize_t cca_serialnr_show(struct device *dev,
memset(&ci, 0, sizeof(ci));
if (ap_domain_index >= 0)
- cca_get_info(ac->id, ap_domain_index, &ci, zc->online);
+ cca_get_info(ac->id, ap_domain_index, &ci, zc->online, 0);
return sysfs_emit(buf, "%s\n", ci.serial);
}
@@ -120,7 +120,7 @@ static ssize_t cca_mkvps_show(struct device *dev,
cca_get_info(AP_QID_CARD(zq->queue->qid),
AP_QID_QUEUE(zq->queue->qid),
- &ci, zq->online);
+ &ci, zq->online, 0);
if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3')
n += sysfs_emit_at(buf, n, "AES NEW: %s 0x%016llx\n",
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 14/20] s390/zcrypt: Locate ep11_domain_query_info onto the stack instead of kmalloc
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (12 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 13/20] s390/zcrypt: Add small mempool for cca info list entries Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 15/20] s390/zcrypt: Rework ep11 misc functions to use cprb mempool Harald Freudenberger
` (5 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Locate the relative small struct ep11_domain_query_info variable
onto the stack instead of kmalloc()/kfree().
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ep11misc.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index 09b5ab0d7174..ef5f69bda6c2 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -791,36 +791,31 @@ int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
u8 new_WK_VP[32];
u32 dom_flags;
u64 op_mode;
- } __packed * p_dom_info;
-
- p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL);
- if (!p_dom_info)
- return -ENOMEM;
+ } __packed dom_query_info;
rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
- sizeof(*p_dom_info), (u8 *)p_dom_info);
+ sizeof(dom_query_info), (u8 *)&dom_query_info);
if (rc)
goto out;
memset(info, 0, sizeof(*info));
info->cur_wk_state = '0';
info->new_wk_state = '0';
- if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) {
- if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) {
+ if (dom_query_info.dom_flags & 0x10 /* left imprint mode */) {
+ if (dom_query_info.dom_flags & 0x02 /* cur wk valid */) {
info->cur_wk_state = '1';
- memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32);
+ memcpy(info->cur_wkvp, dom_query_info.cur_WK_VP, 32);
}
- if (p_dom_info->dom_flags & 0x04 || /* new wk present */
- p_dom_info->dom_flags & 0x08 /* new wk committed */) {
+ if (dom_query_info.dom_flags & 0x04 || /* new wk present */
+ dom_query_info.dom_flags & 0x08 /* new wk committed */) {
info->new_wk_state =
- p_dom_info->dom_flags & 0x08 ? '2' : '1';
- memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32);
+ dom_query_info.dom_flags & 0x08 ? '2' : '1';
+ memcpy(info->new_wkvp, dom_query_info.new_WK_VP, 32);
}
}
- info->op_mode = p_dom_info->op_mode;
+ info->op_mode = dom_query_info.op_mode;
out:
- kfree(p_dom_info);
return rc;
}
EXPORT_SYMBOL(ep11_get_domain_info);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 15/20] s390/zcrypt: Rework ep11 misc functions to use cprb mempool
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (13 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 14/20] s390/zcrypt: Locate ep11_domain_query_info onto the stack instead of kmalloc Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 16/20] s390/zcrypt: Add small mempool for ep11 card info list entries Harald Freudenberger
` (4 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
There are two places in the ep11 misc code where a short term
memory buffer is needed. Rework this code to use the cprb mempool
to satisfy this ephemeral memory requirements.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_ep11.c | 3 +-
drivers/s390/crypto/zcrypt_cex4.c | 12 +--
drivers/s390/crypto/zcrypt_ep11misc.c | 104 ++++++++++++++++----------
drivers/s390/crypto/zcrypt_ep11misc.h | 8 +-
4 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/drivers/s390/crypto/pkey_ep11.c b/drivers/s390/crypto/pkey_ep11.c
index b970f0be84be..38aa0c7807c2 100644
--- a/drivers/s390/crypto/pkey_ep11.c
+++ b/drivers/s390/crypto/pkey_ep11.c
@@ -280,6 +280,7 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
{
struct pkey_apqn *local_apqns = NULL;
int i, len, rc;
+ const u32 xflags = 0;
/* check keytype, subtype, keybitsize */
switch (keytype) {
@@ -328,7 +329,7 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
rc = ep11_genaeskey(apqns[i].card, apqns[i].domain,
keybitsize, flags,
- keybuf, keybuflen, subtype);
+ keybuf, keybuflen, subtype, xflags);
}
out:
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c
index 49a638d373fa..83e277d18844 100644
--- a/drivers/s390/crypto/zcrypt_cex4.c
+++ b/drivers/s390/crypto/zcrypt_cex4.c
@@ -216,7 +216,7 @@ static ssize_t ep11_api_ordinalnr_show(struct device *dev,
memset(&ci, 0, sizeof(ci));
- ep11_get_card_info(ac->id, &ci, zc->online);
+ ep11_get_card_info(ac->id, &ci, zc->online, 0);
if (ci.API_ord_nr > 0)
return sysfs_emit(buf, "%u\n", ci.API_ord_nr);
@@ -237,7 +237,7 @@ static ssize_t ep11_fw_version_show(struct device *dev,
memset(&ci, 0, sizeof(ci));
- ep11_get_card_info(ac->id, &ci, zc->online);
+ ep11_get_card_info(ac->id, &ci, zc->online, 0);
if (ci.FW_version > 0)
return sysfs_emit(buf, "%d.%d\n",
@@ -260,7 +260,7 @@ static ssize_t ep11_serialnr_show(struct device *dev,
memset(&ci, 0, sizeof(ci));
- ep11_get_card_info(ac->id, &ci, zc->online);
+ ep11_get_card_info(ac->id, &ci, zc->online, 0);
if (ci.serial[0])
return sysfs_emit(buf, "%16.16s\n", ci.serial);
@@ -298,7 +298,7 @@ static ssize_t ep11_card_op_modes_show(struct device *dev,
memset(&ci, 0, sizeof(ci));
- ep11_get_card_info(ac->id, &ci, zc->online);
+ ep11_get_card_info(ac->id, &ci, zc->online, 0);
for (i = 0; ep11_op_modes[i].mode_txt; i++) {
if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
@@ -348,7 +348,7 @@ static ssize_t ep11_mkvps_show(struct device *dev,
if (zq->online)
ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
AP_QID_QUEUE(zq->queue->qid),
- &di);
+ &di, 0);
if (di.cur_wk_state == '0') {
n = sysfs_emit(buf, "WK CUR: %s -\n",
@@ -395,7 +395,7 @@ static ssize_t ep11_queue_op_modes_show(struct device *dev,
if (zq->online)
ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
AP_QID_QUEUE(zq->queue->qid),
- &di);
+ &di, 0);
for (i = 0; ep11_op_modes[i].mode_txt; i++) {
if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index ef5f69bda6c2..467449adb5ae 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -630,7 +630,7 @@ static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
* Helper function which does an ep11 query with given query type.
*/
static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
- size_t buflen, u8 *buf)
+ size_t buflen, u8 *buf, u32 xflags)
{
struct ep11_info_req_pl {
struct pl_head head;
@@ -654,7 +654,6 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
struct ep11_target_dev target;
struct ep11_urb urb;
int api = EP11_API_V1, rc = -ENOMEM;
- const u32 xflags = 0;
/* request cprb and payload */
req = alloc_cprbmem(sizeof(struct ep11_info_req_pl), xflags);
@@ -721,7 +720,8 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
/*
* Provide information about an EP11 card.
*/
-int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
+int ep11_get_card_info(u16 card, struct ep11_card_info *info,
+ int verify, u32 xflags)
{
int rc;
struct ep11_module_query_info {
@@ -753,12 +753,15 @@ int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
rc = card_cache_fetch(card, info);
if (rc || verify) {
- pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL);
+ /* use the cprb mempool to satisfy this short term mem alloc */
+ pmqi = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(cprb_mempool) :
+ mempool_alloc(cprb_mempool, GFP_KERNEL);
if (!pmqi)
return -ENOMEM;
rc = ep11_query_info(card, AUTOSEL_DOM,
0x01 /* module info query */,
- sizeof(*pmqi), (u8 *)pmqi);
+ sizeof(*pmqi), (u8 *)pmqi, xflags);
if (rc) {
if (rc == -ENODEV)
card_cache_scrub(card);
@@ -774,7 +777,7 @@ int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
}
out:
- kfree(pmqi);
+ mempool_free(pmqi, cprb_mempool);
return rc;
}
EXPORT_SYMBOL(ep11_get_card_info);
@@ -782,7 +785,8 @@ EXPORT_SYMBOL(ep11_get_card_info);
/*
* Provide information about a domain within an EP11 card.
*/
-int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
+int ep11_get_domain_info(u16 card, u16 domain,
+ struct ep11_domain_info *info, u32 xflags)
{
int rc;
struct ep11_domain_query_info {
@@ -794,7 +798,8 @@ int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
} __packed dom_query_info;
rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
- sizeof(dom_query_info), (u8 *)&dom_query_info);
+ sizeof(dom_query_info), (u8 *)&dom_query_info,
+ xflags);
if (rc)
goto out;
@@ -828,7 +833,7 @@ EXPORT_SYMBOL(ep11_get_domain_info);
static int _ep11_genaeskey(u16 card, u16 domain,
u32 keybitsize, u32 keygenflags,
- u8 *keybuf, size_t *keybufsize)
+ u8 *keybuf, size_t *keybufsize, u32 xflags)
{
struct keygen_req_pl {
struct pl_head head;
@@ -866,7 +871,6 @@ static int _ep11_genaeskey(u16 card, u16 domain,
struct ep11_urb urb;
int api, rc = -ENOMEM;
u8 *p;
- const u32 xflags = 0;
switch (keybitsize) {
case 128:
@@ -970,7 +974,7 @@ static int _ep11_genaeskey(u16 card, u16 domain,
}
int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
- u8 *keybuf, u32 *keybufsize, u32 keybufver)
+ u8 *keybuf, u32 *keybufsize, u32 keybufver, u32 xflags)
{
struct ep11kblob_header *hdr;
size_t hdr_size, pl_size;
@@ -991,7 +995,7 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
return rc;
rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags,
- pl, &pl_size);
+ pl, &pl_size, xflags);
if (rc)
return rc;
@@ -1011,7 +1015,8 @@ static int ep11_cryptsingle(u16 card, u16 domain,
u16 mode, u32 mech, const u8 *iv,
const u8 *key, size_t keysize,
const u8 *inbuf, size_t inbufsize,
- u8 *outbuf, size_t *outbufsize)
+ u8 *outbuf, size_t *outbufsize,
+ u32 xflags)
{
struct crypt_req_pl {
struct pl_head head;
@@ -1042,7 +1047,6 @@ static int ep11_cryptsingle(u16 card, u16 domain,
size_t req_pl_size, rep_pl_size;
int n, api = EP11_API_V1, rc = -ENOMEM;
u8 *p;
- const u32 xflags = 0;
/* the simple asn1 coding used has length limits */
if (keysize > 0xFFFF || inbufsize > 0xFFFF)
@@ -1142,7 +1146,7 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
const u8 *enckey, size_t enckeysize,
u32 mech, const u8 *iv,
u32 keybitsize, u32 keygenflags,
- u8 *keybuf, size_t *keybufsize)
+ u8 *keybuf, size_t *keybufsize, u32 xflags)
{
struct uw_req_pl {
struct pl_head head;
@@ -1182,7 +1186,6 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
struct ep11_urb urb;
int api, rc = -ENOMEM;
u8 *p;
- const u32 xflags = 0;
/* request cprb and payload */
api = (!keygenflags || keygenflags & 0x00200000) ?
@@ -1291,7 +1294,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
u32 mech, const u8 *iv,
u32 keybitsize, u32 keygenflags,
u8 *keybuf, u32 *keybufsize,
- u8 keybufver)
+ u8 keybufver, u32 xflags)
{
struct ep11kblob_header *hdr;
size_t hdr_size, pl_size;
@@ -1305,7 +1308,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize,
mech, iv, keybitsize, keygenflags,
- pl, &pl_size);
+ pl, &pl_size, xflags);
if (rc)
return rc;
@@ -1324,7 +1327,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
static int _ep11_wrapkey(u16 card, u16 domain,
const u8 *key, size_t keysize,
u32 mech, const u8 *iv,
- u8 *databuf, size_t *datasize)
+ u8 *databuf, size_t *datasize, u32 xflags)
{
struct wk_req_pl {
struct pl_head head;
@@ -1357,7 +1360,6 @@ static int _ep11_wrapkey(u16 card, u16 domain,
size_t req_pl_size;
int api, rc = -ENOMEM;
u8 *p;
- const u32 xflags = 0;
/* request cprb and payload */
req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
@@ -1448,8 +1450,10 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
u32 keytype)
{
int rc;
- u8 encbuf[64], *kek = NULL;
+ void *mem;
+ u8 encbuf[64], *kek;
size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
+ const u32 xflags = 0;
if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) {
clrkeylen = keybitsize / 8;
@@ -1459,18 +1463,24 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
return -EINVAL;
}
- /* allocate memory for the temp kek */
+ /*
+ * Allocate space for the temp kek.
+ * Also we only need up to MAXEP11AESKEYBLOBSIZE bytes for this
+ * we use the already existing cprb mempool to solve this
+ * short term memory requirement.
+ */
+ mem = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(cprb_mempool) :
+ mempool_alloc(cprb_mempool, GFP_KERNEL);
+ if (!mem)
+ return -ENOMEM;
+ kek = (u8 *)mem;
keklen = MAXEP11AESKEYBLOBSIZE;
- kek = kmalloc(keklen, GFP_ATOMIC);
- if (!kek) {
- rc = -ENOMEM;
- goto out;
- }
/* Step 1: generate AES 256 bit random kek key */
rc = _ep11_genaeskey(card, domain, 256,
0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
- kek, &keklen);
+ kek, &keklen, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s generate kek key failed, rc=%d\n",
__func__, rc);
@@ -1479,7 +1489,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
/* Step 2: encrypt clear key value with the kek key */
rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen,
- clrkey, clrkeylen, encbuf, &encbuflen);
+ clrkey, clrkeylen, encbuf, &encbuflen, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s encrypting key value with kek key failed, rc=%d\n",
__func__, rc);
@@ -1489,7 +1499,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
/* Step 3: import the encrypted key value as a new key */
rc = ep11_unwrapkey(card, domain, kek, keklen,
encbuf, encbuflen, 0, def_iv,
- keybitsize, 0, keybuf, keybufsize, keytype);
+ keybitsize, 0, keybuf, keybufsize, keytype, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s importing key value as new key failed, rc=%d\n",
__func__, rc);
@@ -1497,7 +1507,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
}
out:
- kfree(kek);
+ mempool_free(mem, cprb_mempool);
return rc;
}
EXPORT_SYMBOL(ep11_clr2keyblob);
@@ -1520,6 +1530,7 @@ int ep11_kblob2protkey(u16 card, u16 dom,
} __packed * wki;
u8 *wkbuf = NULL;
int rc = -EIO;
+ const u32 xflags = 0;
if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
return -EINVAL;
@@ -1530,15 +1541,29 @@ int ep11_kblob2protkey(u16 card, u16 dom,
}
/* !!! hdr is no longer a valid header !!! */
- /* alloc temp working buffer */
+ /* need a temp working buffer */
wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1));
- wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
- if (!wkbuf)
- return -ENOMEM;
+ if (wkbuflen > CPRB_MEMPOOL_ITEM_SIZE) {
+ /* this should never happen */
+ rc = -ENOMEM;
+ ZCRYPT_DBF_ERR("%s wkbuflen %d > cprb mempool item size %d, rc=%d\n",
+ __func__, (int)wkbuflen, CPRB_MEMPOOL_ITEM_SIZE, rc);
+ return rc;
+ }
+ /* use the cprb mempool to satisfy this short term mem allocation */
+ wkbuf = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(cprb_mempool) :
+ mempool_alloc(cprb_mempool, GFP_ATOMIC);
+ if (!wkbuf) {
+ rc = -ENOMEM;
+ ZCRYPT_DBF_ERR("%s allocating tmp buffer via cprb mempool failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
/* ep11 secure key -> protected key + info */
rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen,
- 0, def_iv, wkbuf, &wkbuflen);
+ 0, def_iv, wkbuf, &wkbuflen, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s rewrapping ep11 key to pkey failed, rc=%d\n",
__func__, rc);
@@ -1605,7 +1630,7 @@ int ep11_kblob2protkey(u16 card, u16 dom,
*protkeylen = wki->pkeysize;
out:
- kfree(wkbuf);
+ mempool_free(wkbuf, cprb_mempool);
return rc;
}
EXPORT_SYMBOL(ep11_kblob2protkey);
@@ -1618,6 +1643,7 @@ int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
struct ep11_domain_info edi;
struct ep11_card_info eci;
u32 _nr_apqns = 0;
+ const u32 xflags = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
@@ -1650,14 +1676,14 @@ int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
continue;
/* check min api version if given */
if (minapi > 0) {
- if (ep11_get_card_info(card, &eci, 0))
+ if (ep11_get_card_info(card, &eci, 0, xflags))
continue;
if (minapi > eci.API_ord_nr)
continue;
}
/* check wkvp if given */
if (wkvp) {
- if (ep11_get_domain_info(card, dom, &edi))
+ if (ep11_get_domain_info(card, dom, &edi, xflags))
continue;
if (edi.cur_wk_state != '1')
continue;
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index cbd615547bc2..7ef036759dc8 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -104,18 +104,20 @@ struct ep11_domain_info {
/*
* Provide information about an EP11 card.
*/
-int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify);
+int ep11_get_card_info(u16 card, struct ep11_card_info *info,
+ int verify, u32 xflags);
/*
* Provide information about a domain within an EP11 card.
*/
-int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info);
+int ep11_get_domain_info(u16 card, u16 domain,
+ struct ep11_domain_info *info, u32 xflags);
/*
* Generate (random) EP11 AES secure key.
*/
int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
- u8 *keybuf, u32 *keybufsize, u32 keybufver);
+ u8 *keybuf, u32 *keybufsize, u32 keybufver, u32 xflags);
/*
* Generate EP11 AES secure key with given clear key value.
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 16/20] s390/zcrypt: Add small mempool for ep11 card info list entries
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (14 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 15/20] s390/zcrypt: Rework ep11 misc functions to use cprb mempool Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 17/20] s390/pkey: Rework CCA pkey handler to use stack for small memory allocs Harald Freudenberger
` (3 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Add a small memory pool for (pre-)allocating ep11 card info list
entries. These entries are rather small and the pool is a simple
way to support the xflag ZCRYPT_XFLAG_NOMEMALLOC to avoid mallocs.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/zcrypt_ep11misc.c | 48 ++++++++++++++++++++++-----
1 file changed, 39 insertions(+), 9 deletions(-)
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index 467449adb5ae..a6ac0cac0c45 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -65,6 +65,10 @@ struct card_list_entry {
static LIST_HEAD(card_list);
static DEFINE_SPINLOCK(card_list_lock);
+/* memory pool for card_list_entry entries */
+#define INFO_ENTRY_MEMPOOL_MIN_ITEMS 4
+static mempool_t *info_mempool;
+
static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci)
{
int rc = -ENOENT;
@@ -83,7 +87,8 @@ static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci)
return rc;
}
-static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci)
+static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci,
+ u32 xflags)
{
int found = 0;
struct card_list_entry *ptr;
@@ -97,7 +102,9 @@ static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci)
}
}
if (!found) {
- ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC);
+ ptr = (xflags & ZCRYPT_XFLAG_NOMEMALLOC) ?
+ mempool_alloc_preallocated(info_mempool) :
+ mempool_alloc(info_mempool, GFP_ATOMIC);
if (!ptr) {
spin_unlock_bh(&card_list_lock);
return;
@@ -117,7 +124,7 @@ static void card_cache_scrub(u16 cardnr)
list_for_each_entry(ptr, &card_list, list) {
if (ptr->cardnr == cardnr) {
list_del(&ptr->list);
- kfree(ptr);
+ mempool_free(ptr, info_mempool);
break;
}
}
@@ -131,7 +138,7 @@ static void __exit card_cache_free(void)
spin_lock_bh(&card_list_lock);
list_for_each_entry_safe(ptr, pnext, &card_list, list) {
list_del(&ptr->list);
- kfree(ptr);
+ mempool_free(ptr, info_mempool);
}
spin_unlock_bh(&card_list_lock);
}
@@ -773,7 +780,7 @@ int ep11_get_card_info(u16 card, struct ep11_card_info *info,
(pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers;
memcpy(info->serial, pmqi->serial, sizeof(info->serial));
info->op_mode = pmqi->op_mode;
- card_cache_update(card, info);
+ card_cache_update(card, info, xflags);
}
out:
@@ -1711,6 +1718,8 @@ EXPORT_SYMBOL(ep11_findcard2);
int __init zcrypt_ep11misc_init(void)
{
+ int rc = -ENOMEM;
+
/* Pre-allocate a small memory pool for ep11 cprbs. */
cprb_mempool = mempool_create_kmalloc_pool(CPRB_MEMPOOL_MIN_ITEMS,
CPRB_MEMPOOL_ITEM_SIZE);
@@ -1718,19 +1727,39 @@ int __init zcrypt_ep11misc_init(void)
ZCRYPT_DBF_ERR("%s mempool_create(%d,%d) failed: %ld\n",
__func__, CPRB_MEMPOOL_MIN_ITEMS,
CPRB_MEMPOOL_ITEM_SIZE, PTR_ERR(cprb_mempool));
+ rc = PTR_ERR(cprb_mempool);
cprb_mempool = NULL;
- return -ENOMEM;
+ goto out;
+ }
+
+ /* Pre-allocate a very small memory pool for card info entries */
+ info_mempool = mempool_create_kmalloc_pool(INFO_ENTRY_MEMPOOL_MIN_ITEMS,
+ sizeof(struct card_list_entry));
+ if (IS_ERR(info_mempool)) {
+ ZCRYPT_DBF_ERR("%s card info entry mempool_create(%d,%d) failed: %ld\n",
+ __func__, INFO_ENTRY_MEMPOOL_MIN_ITEMS,
+ (int)sizeof(struct card_list_entry),
+ PTR_ERR(info_mempool));
+ rc = PTR_ERR(info_mempool);
+ info_mempool = NULL;
+ goto out;
}
/* Pre-allocate one crypto status card struct used in findcard() */
dev_status_mem = kvmalloc(ZCRYPT_DEV_STATUS_EXT2_SIZE, GFP_KERNEL);
if (!dev_status_mem) {
ZCRYPT_DBF_ERR("%s allocation of dev_status_mem failed\n", __func__);
- mempool_destroy(cprb_mempool);
- return -ENOMEM;
+ goto out;
}
- return 0;
+ rc = 0;
+
+out:
+ if (rc) {
+ mempool_destroy(cprb_mempool);
+ mempool_destroy(info_mempool);
+ }
+ return rc;
}
void zcrypt_ep11misc_exit(void)
@@ -1738,4 +1767,5 @@ void zcrypt_ep11misc_exit(void)
card_cache_free();
kvfree(dev_status_mem);
mempool_destroy(cprb_mempool);
+ mempool_destroy(info_mempool);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 17/20] s390/pkey: Rework CCA pkey handler to use stack for small memory allocs
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (15 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 16/20] s390/zcrypt: Add small mempool for ep11 card info list entries Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 18/20] s390/pkey: Rework EP11 " Harald Freudenberger
` (2 subsequent siblings)
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
There have been some places in the CCA handler code where relatively
small amounts of memory have been allocated an freed at the end
of the function. This code has been reworked to use the stack instead.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_cca.c | 43 ++++++++--------------------------
1 file changed, 10 insertions(+), 33 deletions(-)
diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c
index 8c9a0c5ca630..619d134b028d 100644
--- a/drivers/s390/crypto/pkey_cca.c
+++ b/drivers/s390/crypto/pkey_cca.c
@@ -213,7 +213,7 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, rc;
if (keylen < sizeof(*hdr))
@@ -251,14 +251,10 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns);
+ rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -283,7 +279,6 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -302,7 +297,7 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keybitsize, u32 flags,
u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
{
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
/* check keytype, subtype, keybitsize */
@@ -338,15 +333,10 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = cca_apqns4type(subtype, NULL, NULL, 0,
- local_apqns, &nr_apqns);
+ rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -363,7 +353,6 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -383,7 +372,7 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *clrkey, u32 clrkeylen,
u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
{
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
/* check keytype, subtype, clrkeylen, keybitsize */
@@ -424,15 +413,10 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = cca_apqns4type(subtype, NULL, NULL, 0,
- local_apqns, &nr_apqns);
+ rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -449,7 +433,6 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -552,8 +535,8 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
{
const struct keytoken_header *hdr = (const struct keytoken_header *)key;
const struct clearkeytoken *t = (const struct clearkeytoken *)key;
+ u8 tmpbuf[SECKEYBLOBSIZE]; /* 64 bytes */
u32 tmplen, keysize = 0;
- u8 *tmpbuf;
int i, rc;
if (keylen < sizeof(*hdr))
@@ -565,11 +548,6 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
if (!keysize || t->len != keysize)
return -EINVAL;
- /* alloc tmp key buffer */
- tmpbuf = kmalloc(SECKEYBLOBSIZE, GFP_ATOMIC);
- if (!tmpbuf)
- return -ENOMEM;
-
/* try two times in case of failure */
for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
tmplen = SECKEYBLOBSIZE;
@@ -584,7 +562,6 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
pr_debug("cca_key2protkey()=%d\n", rc);
}
- kfree(tmpbuf);
pr_debug("rc=%d\n", rc);
return rc;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 18/20] s390/pkey: Rework EP11 pkey handler to use stack for small memory allocs
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (16 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 17/20] s390/pkey: Rework CCA pkey handler to use stack for small memory allocs Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 19/20] s390/zcrypt/pkey: Provide and pass xflags within pkey and zcrypt layers Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 20/20] s390/pkey/crypto: Introduce xflags param for pkey in-kernel API Harald Freudenberger
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
There have been some places in the EP11 handler code where relatively
small amounts of memory have been allocated an freed at the end
of the function. This code has been reworked to use the stack instead.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_ep11.c | 43 ++++++++-------------------------
1 file changed, 10 insertions(+), 33 deletions(-)
diff --git a/drivers/s390/crypto/pkey_ep11.c b/drivers/s390/crypto/pkey_ep11.c
index 38aa0c7807c2..429c08facbfe 100644
--- a/drivers/s390/crypto/pkey_ep11.c
+++ b/drivers/s390/crypto/pkey_ep11.c
@@ -186,7 +186,7 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, rc;
if (keylen < sizeof(*hdr))
@@ -223,14 +223,10 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = ep11_apqns4key(key, keylen, 0, local_apqns, &nr_apqns);
+ rc = ep11_apqns4key(key, keylen, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -259,7 +255,6 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -278,7 +273,7 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keybitsize, u32 flags,
u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
{
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
const u32 xflags = 0;
@@ -315,15 +310,10 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = ep11_apqns4type(subtype, NULL, NULL, 0,
- local_apqns, &nr_apqns);
+ rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -333,7 +323,6 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -353,7 +342,7 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *clrkey, u32 clrkeylen,
u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
{
- struct pkey_apqn *local_apqns = NULL;
+ struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
/* check keytype, subtype, clrkeylen, keybitsize */
@@ -394,15 +383,10 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),
- GFP_KERNEL);
- if (!local_apqns)
- return -ENOMEM;
- rc = ep11_apqns4type(subtype, NULL, NULL, 0,
- local_apqns, &nr_apqns);
+ rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
if (rc)
goto out;
- apqns = local_apqns;
+ apqns = _apqns;
}
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
@@ -412,7 +396,6 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
}
out:
- kfree(local_apqns);
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -502,8 +485,8 @@ static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
{
const struct keytoken_header *hdr = (const struct keytoken_header *)key;
const struct clearkeytoken *t = (const struct clearkeytoken *)key;
+ u8 tmpbuf[MAXEP11AESKEYBLOBSIZE]; /* 336 bytes */
u32 tmplen, keysize = 0;
- u8 *tmpbuf;
int i, rc;
if (keylen < sizeof(*hdr))
@@ -515,11 +498,6 @@ static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
if (!keysize || t->len != keysize)
return -EINVAL;
- /* alloc tmp key buffer */
- tmpbuf = kmalloc(MAXEP11AESKEYBLOBSIZE, GFP_ATOMIC);
- if (!tmpbuf)
- return -ENOMEM;
-
/* try two times in case of failure */
for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
tmplen = MAXEP11AESKEYBLOBSIZE;
@@ -534,7 +512,6 @@ static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
pr_debug("ep11_key2protkey()=%d\n", rc);
}
- kfree(tmpbuf);
pr_debug("rc=%d\n", rc);
return rc;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 19/20] s390/zcrypt/pkey: Provide and pass xflags within pkey and zcrypt layers
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (17 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 18/20] s390/pkey: Rework EP11 " Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 20/20] s390/pkey/crypto: Introduce xflags param for pkey in-kernel API Harald Freudenberger
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Provide and pass the xflag parameter from pkey ioctls through
the pkey handler and further down to the implementations
(CCA, EP11, PCKMO and UV). So all the code is now prepared
and ready to support the currently only xflag ("execution flag"):
* ZCRYPT_XFLAG_NOMEMALLOC - If this flag is set, no memory
allocations which may trigger any IO operations are done.
The in-kernel pkey API still does not provide this xflag param.
That's intended to come with another patch which more or less
only enables this functionality.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
drivers/s390/crypto/pkey_api.c | 49 +++++++++++-----------
drivers/s390/crypto/pkey_base.c | 34 ++++++++-------
drivers/s390/crypto/pkey_base.h | 37 ++++++++++-------
drivers/s390/crypto/pkey_cca.c | 59 +++++++++++++++------------
drivers/s390/crypto/pkey_ep11.c | 49 ++++++++++++----------
drivers/s390/crypto/pkey_pckmo.c | 9 ++--
drivers/s390/crypto/pkey_sysfs.c | 4 +-
drivers/s390/crypto/pkey_uv.c | 16 +++++++-
drivers/s390/crypto/zcrypt_ccamisc.c | 53 +++++++++++-------------
drivers/s390/crypto/zcrypt_ccamisc.h | 25 +++++++-----
drivers/s390/crypto/zcrypt_ep11misc.c | 10 ++---
drivers/s390/crypto/zcrypt_ep11misc.h | 7 ++--
12 files changed, 196 insertions(+), 156 deletions(-)
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index 3a39e167bdbf..55a4e70b866b 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -24,7 +24,8 @@
*/
static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, size_t keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
int rc;
@@ -32,14 +33,14 @@ static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
rc = pkey_handler_key_to_protkey(apqns, nr_apqns,
key, keylen,
protkey, protkeylen,
- protkeytype);
+ protkeytype, xflags);
/* if this did not work, try the slowpath way */
if (rc == -ENODEV) {
rc = pkey_handler_slowpath_key_to_protkey(apqns, nr_apqns,
key, keylen,
protkey, protkeylen,
- protkeytype);
+ protkeytype, xflags);
if (rc)
rc = -ENODEV;
}
@@ -55,13 +56,14 @@ int pkey_key2protkey(const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen, u32 *protkeytype)
{
int rc;
+ const u32 xflags = 0;
rc = key2protkey(NULL, 0, key, keylen,
- protkey, protkeylen, protkeytype);
+ protkey, protkeylen, protkeytype, xflags);
if (rc == -ENODEV) {
pkey_handler_request_modules();
rc = key2protkey(NULL, 0, key, keylen,
- protkey, protkeylen, protkeytype);
+ protkey, protkeylen, protkeytype, xflags);
}
return rc;
@@ -103,7 +105,7 @@ static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)
keybuflen = sizeof(kgs.seckey.seckey);
rc = pkey_handler_gen_key(&apqn, 1,
kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
- kgs.seckey.seckey, &keybuflen, NULL);
+ kgs.seckey.seckey, &keybuflen, NULL, 0);
pr_debug("gen_key()=%d\n", rc);
if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
rc = -EFAULT;
@@ -129,7 +131,7 @@ static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)
kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
kcs.clrkey.clrkey,
pkey_keytype_aes_to_size(kcs.keytype),
- kcs.seckey.seckey, &keybuflen, NULL);
+ kcs.seckey.seckey, &keybuflen, NULL, 0);
pr_debug("clr_to_key()=%d\n", rc);
if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
rc = -EFAULT;
@@ -154,7 +156,8 @@ static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)
ksp.seckey.seckey,
sizeof(ksp.seckey.seckey),
ksp.protkey.protkey,
- &ksp.protkey.len, &ksp.protkey.type);
+ &ksp.protkey.len, &ksp.protkey.type,
+ 0);
pr_debug("key_to_protkey()=%d\n", rc);
if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
rc = -EFAULT;
@@ -198,7 +201,7 @@ static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)
rc = key2protkey(NULL, 0,
tmpbuf, sizeof(*t) + keylen,
kcp.protkey.protkey,
- &kcp.protkey.len, &kcp.protkey.type);
+ &kcp.protkey.len, &kcp.protkey.type, 0);
pr_debug("key2protkey()=%d\n", rc);
kfree_sensitive(tmpbuf);
@@ -228,12 +231,12 @@ static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)
rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
sizeof(kfc.seckey.seckey),
PKEY_FLAGS_MATCH_CUR_MKVP,
- apqns, &nr_apqns);
+ apqns, &nr_apqns, 0);
if (rc == -ENODEV)
rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
sizeof(kfc.seckey.seckey),
PKEY_FLAGS_MATCH_ALT_MKVP,
- apqns, &nr_apqns);
+ apqns, &nr_apqns, 0);
pr_debug("apqns_for_key()=%d\n", rc);
if (rc) {
kfree(apqns);
@@ -262,7 +265,7 @@ static int pkey_ioctl_skey2pkey(struct pkey_skey2pkey __user *usp)
sizeof(ksp.seckey.seckey),
ksp.protkey.protkey,
&ksp.protkey.len,
- &ksp.protkey.type);
+ &ksp.protkey.type, 0);
pr_debug("key_to_protkey()=%d\n", rc);
if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
rc = -EFAULT;
@@ -285,7 +288,7 @@ static int pkey_ioctl_verifykey(struct pkey_verifykey __user *uvk)
rc = pkey_handler_verify_key(kvk.seckey.seckey,
sizeof(kvk.seckey.seckey),
&kvk.cardnr, &kvk.domain,
- &keytype, &keybitsize, &flags);
+ &keytype, &keybitsize, &flags, 0);
pr_debug("verify_key()=%d\n", rc);
if (!rc && keytype != PKEY_TYPE_CCA_DATA)
rc = -EINVAL;
@@ -312,7 +315,7 @@ static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp)
rc = pkey_handler_gen_key(NULL, 0, kgp.keytype,
PKEY_TYPE_PROTKEY, 0, 0,
kgp.protkey.protkey, &kgp.protkey.len,
- &kgp.protkey.type);
+ &kgp.protkey.type, 0);
pr_debug("gen_key()=%d\n", rc);
if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))
rc = -EFAULT;
@@ -354,7 +357,7 @@ static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp)
memcpy(t->protkey, kvp.protkey.protkey, kvp.protkey.len);
rc = pkey_handler_verify_key(tmpbuf, sizeof(*t),
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL, 0);
pr_debug("verify_key()=%d\n", rc);
kfree_sensitive(tmpbuf);
@@ -377,7 +380,7 @@ static int pkey_ioctl_kblob2protk(struct pkey_kblob2pkey __user *utp)
ktp.protkey.len = sizeof(ktp.protkey.protkey);
rc = key2protkey(NULL, 0, kkey, ktp.keylen,
ktp.protkey.protkey, &ktp.protkey.len,
- &ktp.protkey.type);
+ &ktp.protkey.type, 0);
pr_debug("key2protkey()=%d\n", rc);
kfree_sensitive(kkey);
if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
@@ -414,7 +417,7 @@ static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs)
}
rc = pkey_handler_gen_key(apqns, kgs.apqn_entries,
u, kgs.type, kgs.size, kgs.keygenflags,
- kkey, &klen, NULL);
+ kkey, &klen, NULL, 0);
pr_debug("gen_key()=%d\n", rc);
kfree(apqns);
if (rc) {
@@ -471,7 +474,7 @@ static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)
rc = pkey_handler_clr_to_key(apqns, kcs.apqn_entries,
u, kcs.type, kcs.size, kcs.keygenflags,
kcs.clrkey.clrkey, kcs.size / 8,
- kkey, &klen, NULL);
+ kkey, &klen, NULL, 0);
pr_debug("clr_to_key()=%d\n", rc);
kfree(apqns);
if (rc) {
@@ -514,7 +517,7 @@ static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk)
rc = pkey_handler_verify_key(kkey, kvk.keylen,
&kvk.cardnr, &kvk.domain,
- &kvk.type, &kvk.size, &kvk.flags);
+ &kvk.type, &kvk.size, &kvk.flags, 0);
pr_debug("verify_key()=%d\n", rc);
kfree_sensitive(kkey);
@@ -544,7 +547,7 @@ static int pkey_ioctl_kblob2protk2(struct pkey_kblob2pkey2 __user *utp)
ktp.protkey.len = sizeof(ktp.protkey.protkey);
rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
ktp.protkey.protkey, &ktp.protkey.len,
- &ktp.protkey.type);
+ &ktp.protkey.type, 0);
pr_debug("key2protkey()=%d\n", rc);
kfree(apqns);
kfree_sensitive(kkey);
@@ -579,7 +582,7 @@ static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak)
return PTR_ERR(kkey);
}
rc = pkey_handler_apqns_for_key(kkey, kak.keylen, kak.flags,
- apqns, &nr_apqns);
+ apqns, &nr_apqns, 0);
pr_debug("apqns_for_key()=%d\n", rc);
kfree_sensitive(kkey);
if (rc && rc != -ENOSPC) {
@@ -626,7 +629,7 @@ static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat)
}
rc = pkey_handler_apqns_for_keytype(kat.type,
kat.cur_mkvp, kat.alt_mkvp,
- kat.flags, apqns, &nr_apqns);
+ kat.flags, apqns, &nr_apqns, 0);
pr_debug("apqns_for_keytype()=%d\n", rc);
if (rc && rc != -ENOSPC) {
kfree(apqns);
@@ -678,7 +681,7 @@ static int pkey_ioctl_kblob2protk3(struct pkey_kblob2pkey3 __user *utp)
return -ENOMEM;
}
rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
- protkey, &protkeylen, &ktp.pkeytype);
+ protkey, &protkeylen, &ktp.pkeytype, 0);
pr_debug("key2protkey()=%d\n", rc);
kfree(apqns);
kfree_sensitive(kkey);
diff --git a/drivers/s390/crypto/pkey_base.c b/drivers/s390/crypto/pkey_base.c
index 64a376501d26..9e6f319acc63 100644
--- a/drivers/s390/crypto/pkey_base.c
+++ b/drivers/s390/crypto/pkey_base.c
@@ -150,7 +150,8 @@ EXPORT_SYMBOL(pkey_handler_put);
int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
@@ -159,7 +160,7 @@ int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (h && h->key_to_protkey) {
rc = h->key_to_protkey(apqns, nr_apqns, key, keylen,
protkey, protkeylen,
- protkeytype);
+ protkeytype, xflags);
}
pkey_handler_put(h);
@@ -177,7 +178,7 @@ int pkey_handler_slowpath_key_to_protkey(const struct pkey_apqn *apqns,
size_t nr_apqns,
const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen,
- u32 *protkeytype)
+ u32 *protkeytype, u32 xflags)
{
const struct pkey_handler *h, *htmp[10];
int i, n = 0, rc = -ENODEV;
@@ -199,7 +200,7 @@ int pkey_handler_slowpath_key_to_protkey(const struct pkey_apqn *apqns,
rc = h->slowpath_key_to_protkey(apqns, nr_apqns,
key, keylen,
protkey, protkeylen,
- protkeytype);
+ protkeytype, xflags);
module_put(h->module);
}
@@ -210,7 +211,7 @@ EXPORT_SYMBOL(pkey_handler_slowpath_key_to_protkey);
int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo, u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
@@ -219,7 +220,7 @@ int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (h && h->gen_key) {
rc = h->gen_key(apqns, nr_apqns, keytype, keysubtype,
keybitsize, flags,
- keybuf, keybuflen, keyinfo);
+ keybuf, keybuflen, keyinfo, xflags);
}
pkey_handler_put(h);
@@ -231,7 +232,8 @@ int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
const u8 *clrkey, u32 clrkeylen,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo,
+ u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
@@ -240,7 +242,7 @@ int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (h && h->clr_to_key) {
rc = h->clr_to_key(apqns, nr_apqns, keytype, keysubtype,
keybitsize, flags, clrkey, clrkeylen,
- keybuf, keybuflen, keyinfo);
+ keybuf, keybuflen, keyinfo, xflags);
}
pkey_handler_put(h);
@@ -250,7 +252,8 @@ EXPORT_SYMBOL(pkey_handler_clr_to_key);
int pkey_handler_verify_key(const u8 *key, u32 keylen,
u16 *card, u16 *dom,
- u32 *keytype, u32 *keybitsize, u32 *flags)
+ u32 *keytype, u32 *keybitsize, u32 *flags,
+ u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
@@ -258,7 +261,7 @@ int pkey_handler_verify_key(const u8 *key, u32 keylen,
h = pkey_handler_get_keybased(key, keylen);
if (h && h->verify_key) {
rc = h->verify_key(key, keylen, card, dom,
- keytype, keybitsize, flags);
+ keytype, keybitsize, flags, xflags);
}
pkey_handler_put(h);
@@ -267,14 +270,16 @@ int pkey_handler_verify_key(const u8 *key, u32 keylen,
EXPORT_SYMBOL(pkey_handler_verify_key);
int pkey_handler_apqns_for_key(const u8 *key, u32 keylen, u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
h = pkey_handler_get_keybased(key, keylen);
if (h && h->apqns_for_key)
- rc = h->apqns_for_key(key, keylen, flags, apqns, nr_apqns);
+ rc = h->apqns_for_key(key, keylen, flags, apqns, nr_apqns,
+ xflags);
pkey_handler_put(h);
return rc;
@@ -283,7 +288,8 @@ EXPORT_SYMBOL(pkey_handler_apqns_for_key);
int pkey_handler_apqns_for_keytype(enum pkey_key_type keysubtype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags)
{
const struct pkey_handler *h;
int rc = -ENODEV;
@@ -292,7 +298,7 @@ int pkey_handler_apqns_for_keytype(enum pkey_key_type keysubtype,
if (h && h->apqns_for_keytype) {
rc = h->apqns_for_keytype(keysubtype,
cur_mkvp, alt_mkvp, flags,
- apqns, nr_apqns);
+ apqns, nr_apqns, xflags);
}
pkey_handler_put(h);
diff --git a/drivers/s390/crypto/pkey_base.h b/drivers/s390/crypto/pkey_base.h
index 7347647dfaa7..9cdb3e74477f 100644
--- a/drivers/s390/crypto/pkey_base.h
+++ b/drivers/s390/crypto/pkey_base.h
@@ -159,29 +159,33 @@ struct pkey_handler {
bool (*is_supported_keytype)(enum pkey_key_type);
int (*key_to_protkey)(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags);
int (*slowpath_key_to_protkey)(const struct pkey_apqn *apqns,
size_t nr_apqns,
const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen,
- u32 *protkeytype);
+ u32 *protkeytype, u32 xflags);
int (*gen_key)(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo);
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo, u32 xflags);
int (*clr_to_key)(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
const u8 *clrkey, u32 clrkeylen,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo);
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo, u32 xflags);
int (*verify_key)(const u8 *key, u32 keylen,
u16 *card, u16 *dom,
- u32 *keytype, u32 *keybitsize, u32 *flags);
+ u32 *keytype, u32 *keybitsize, u32 *flags,
+ u32 xflags);
int (*apqns_for_key)(const u8 *key, u32 keylen, u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns);
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags);
int (*apqns_for_keytype)(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns);
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags);
/* used internal by pkey base */
struct list_head list;
};
@@ -199,29 +203,34 @@ void pkey_handler_put(const struct pkey_handler *handler);
int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags);
int pkey_handler_slowpath_key_to_protkey(const struct pkey_apqn *apqns,
size_t nr_apqns,
const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen,
- u32 *protkeytype);
+ u32 *protkeytype, u32 xflags);
int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo);
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo, u32 xflags);
int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 keysubtype,
u32 keybitsize, u32 flags,
const u8 *clrkey, u32 clrkeylen,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo);
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo,
+ u32 xflags);
int pkey_handler_verify_key(const u8 *key, u32 keylen,
u16 *card, u16 *dom,
- u32 *keytype, u32 *keybitsize, u32 *flags);
+ u32 *keytype, u32 *keybitsize, u32 *flags,
+ u32 xflags);
int pkey_handler_apqns_for_key(const u8 *key, u32 keylen, u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns);
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags);
int pkey_handler_apqns_for_keytype(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns);
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags);
/*
* Unconditional try to load all handler modules
diff --git a/drivers/s390/crypto/pkey_cca.c b/drivers/s390/crypto/pkey_cca.c
index 619d134b028d..8761e3822ef2 100644
--- a/drivers/s390/crypto/pkey_cca.c
+++ b/drivers/s390/crypto/pkey_cca.c
@@ -70,7 +70,7 @@ static bool is_cca_keytype(enum pkey_key_type key_type)
}
static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns, u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
@@ -109,7 +109,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
}
rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, AES_MK_SET,
- cur_mkvp, old_mkvp, 1);
+ cur_mkvp, old_mkvp, 1, xflags);
if (rc)
goto out;
@@ -128,7 +128,7 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
}
rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, APKA_MK_SET,
- cur_mkvp, old_mkvp, 1);
+ cur_mkvp, old_mkvp, 1, xflags);
if (rc)
goto out;
@@ -153,7 +153,8 @@ static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
static int cca_apqns4type(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns,
+ u32 xflags)
{
u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
@@ -172,7 +173,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
minhwtype = ZCRYPT_CEX6;
rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
minhwtype, AES_MK_SET,
- cur_mkvp, old_mkvp, 1);
+ cur_mkvp, old_mkvp, 1, xflags);
if (rc)
goto out;
@@ -185,7 +186,7 @@ static int cca_apqns4type(enum pkey_key_type ktype,
old_mkvp = *((u64 *)alt_mkvp);
rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
ZCRYPT_CEX7, APKA_MK_SET,
- cur_mkvp, old_mkvp, 1);
+ cur_mkvp, old_mkvp, 1, xflags);
if (rc)
goto out;
@@ -210,7 +211,8 @@ static int cca_apqns4type(enum pkey_key_type ktype,
static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
struct pkey_apqn _apqns[MAXAPQNSINLIST];
@@ -251,7 +253,7 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns);
+ rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns, xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -262,16 +264,17 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
hdr->version == TOKVER_CCA_AES) {
rc = cca_sec2protkey(apqns[i].card, apqns[i].domain,
key, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype, xflags);
} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
hdr->version == TOKVER_CCA_VLSC) {
rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain,
key, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype,
+ xflags);
} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain,
key, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype, xflags);
} else {
rc = -EINVAL;
break;
@@ -295,7 +298,7 @@ static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 subtype,
u32 keybitsize, u32 flags,
- u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 xflags)
{
struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
@@ -333,7 +336,8 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
+ rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns,
+ xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -343,11 +347,11 @@ static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (subtype == PKEY_TYPE_CCA_CIPHER) {
rc = cca_gencipherkey(apqns[i].card, apqns[i].domain,
keybitsize, flags,
- keybuf, keybuflen);
+ keybuf, keybuflen, xflags);
} else {
/* PKEY_TYPE_CCA_DATA */
rc = cca_genseckey(apqns[i].card, apqns[i].domain,
- keybitsize, keybuf);
+ keybitsize, keybuf, xflags);
*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
}
}
@@ -370,7 +374,7 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 subtype,
u32 keybitsize, u32 flags,
const u8 *clrkey, u32 clrkeylen,
- u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 xflags)
{
struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
@@ -413,7 +417,8 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
+ rc = cca_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns,
+ xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -423,11 +428,11 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (subtype == PKEY_TYPE_CCA_CIPHER) {
rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain,
keybitsize, flags, clrkey,
- keybuf, keybuflen);
+ keybuf, keybuflen, xflags);
} else {
/* PKEY_TYPE_CCA_DATA */
rc = cca_clr2seckey(apqns[i].card, apqns[i].domain,
- keybitsize, clrkey, keybuf);
+ keybitsize, clrkey, keybuf, xflags);
*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
}
}
@@ -439,7 +444,7 @@ static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
static int cca_verifykey(const u8 *key, u32 keylen,
u16 *card, u16 *dom,
- u32 *keytype, u32 *keybitsize, u32 *flags)
+ u32 *keytype, u32 *keybitsize, u32 *flags, u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
@@ -461,13 +466,13 @@ static int cca_verifykey(const u8 *key, u32 keylen,
*keybitsize = t->bitsize;
rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX3C, AES_MK_SET,
- t->mkvp, 0, 1);
+ t->mkvp, 0, 1, xflags);
if (!rc)
*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
if (rc == -ENODEV) {
rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX3C, AES_MK_SET,
- 0, t->mkvp, 1);
+ 0, t->mkvp, 1, xflags);
if (!rc)
*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
}
@@ -494,13 +499,13 @@ static int cca_verifykey(const u8 *key, u32 keylen,
*keybitsize = PKEY_SIZE_AES_256;
rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX6, AES_MK_SET,
- t->mkvp0, 0, 1);
+ t->mkvp0, 0, 1, xflags);
if (!rc)
*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
if (rc == -ENODEV) {
rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX6, AES_MK_SET,
- 0, t->mkvp0, 1);
+ 0, t->mkvp0, 1, xflags);
if (!rc)
*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
}
@@ -531,7 +536,7 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
size_t nr_apqns,
const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen,
- u32 *protkeytype)
+ u32 *protkeytype, u32 xflags)
{
const struct keytoken_header *hdr = (const struct keytoken_header *)key;
const struct clearkeytoken *t = (const struct clearkeytoken *)key;
@@ -553,12 +558,12 @@ static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
tmplen = SECKEYBLOBSIZE;
rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA,
8 * keysize, 0, t->clearkey, t->len,
- tmpbuf, &tmplen, NULL);
+ tmpbuf, &tmplen, NULL, xflags);
pr_debug("cca_clr2key()=%d\n", rc);
if (rc)
continue;
rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen,
- protkey, protkeylen, protkeytype);
+ protkey, protkeylen, protkeytype, xflags);
pr_debug("cca_key2protkey()=%d\n", rc);
}
diff --git a/drivers/s390/crypto/pkey_ep11.c b/drivers/s390/crypto/pkey_ep11.c
index 429c08facbfe..82b01fbf08ae 100644
--- a/drivers/s390/crypto/pkey_ep11.c
+++ b/drivers/s390/crypto/pkey_ep11.c
@@ -70,7 +70,7 @@ static bool is_ep11_keytype(enum pkey_key_type key_type)
}
static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns, u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
@@ -99,7 +99,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
- minhwtype, api, kb->wkvp);
+ minhwtype, api, kb->wkvp, xflags);
if (rc)
goto out;
@@ -116,7 +116,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
}
rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
- minhwtype, api, kb->wkvp);
+ minhwtype, api, kb->wkvp, xflags);
if (rc)
goto out;
@@ -141,7 +141,7 @@ static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
static int ep11_apqns4type(enum pkey_key_type ktype,
u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
- struct pkey_apqn *apqns, size_t *nr_apqns)
+ struct pkey_apqn *apqns, size_t *nr_apqns, u32 xflags)
{
u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
int rc;
@@ -158,7 +158,7 @@ static int ep11_apqns4type(enum pkey_key_type ktype,
wkvp = cur_mkvp;
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
- ZCRYPT_CEX7, api, wkvp);
+ ZCRYPT_CEX7, api, wkvp, xflags);
if (rc)
goto out;
@@ -183,7 +183,8 @@ static int ep11_apqns4type(enum pkey_key_type ktype,
static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
struct pkey_apqn _apqns[MAXAPQNSINLIST];
@@ -223,7 +224,7 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = ep11_apqns4key(key, keylen, 0, _apqns, &nr_apqns);
+ rc = ep11_apqns4key(key, keylen, 0, _apqns, &nr_apqns, xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -235,19 +236,22 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
key, hdr->len, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype,
+ xflags);
} else if (hdr->type == TOKTYPE_NON_CCA &&
hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&
is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
key, hdr->len, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype,
+ xflags);
} else if (hdr->type == TOKTYPE_NON_CCA &&
hdr->version == TOKVER_EP11_AES &&
is_ep11_keyblob(key)) {
rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
key, hdr->len, protkey,
- protkeylen, protkeytype);
+ protkeylen, protkeytype,
+ xflags);
} else {
rc = -EINVAL;
break;
@@ -271,11 +275,10 @@ static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 subtype,
u32 keybitsize, u32 flags,
- u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 xflags)
{
struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
- const u32 xflags = 0;
/* check keytype, subtype, keybitsize */
switch (keytype) {
@@ -310,7 +313,8 @@ static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
+ rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns,
+ xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -340,7 +344,7 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
u32 keytype, u32 subtype,
u32 keybitsize, u32 flags,
const u8 *clrkey, u32 clrkeylen,
- u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 xflags)
{
struct pkey_apqn _apqns[MAXAPQNSINLIST];
int i, len, rc;
@@ -383,7 +387,8 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
if (!apqns || (nr_apqns == 1 &&
apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
nr_apqns = MAXAPQNSINLIST;
- rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns);
+ rc = ep11_apqns4type(subtype, NULL, NULL, 0, _apqns, &nr_apqns,
+ xflags);
if (rc)
goto out;
apqns = _apqns;
@@ -392,7 +397,7 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
rc = ep11_clr2keyblob(apqns[i].card, apqns[i].domain,
keybitsize, flags, clrkey,
- keybuf, keybuflen, subtype);
+ keybuf, keybuflen, subtype, xflags);
}
out:
@@ -402,7 +407,7 @@ static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
static int ep11_verifykey(const u8 *key, u32 keylen,
u16 *card, u16 *dom,
- u32 *keytype, u32 *keybitsize, u32 *flags)
+ u32 *keytype, u32 *keybitsize, u32 *flags, u32 xflags)
{
struct keytoken_header *hdr = (struct keytoken_header *)key;
u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
@@ -427,7 +432,7 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX7, api,
- ep11_kb_wkvp(key, keylen));
+ ep11_kb_wkvp(key, keylen), xflags);
if (rc)
goto out;
@@ -451,7 +456,7 @@ static int ep11_verifykey(const u8 *key, u32 keylen,
api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
ZCRYPT_CEX7, api,
- ep11_kb_wkvp(key, keylen));
+ ep11_kb_wkvp(key, keylen), xflags);
if (rc)
goto out;
@@ -481,7 +486,7 @@ static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
size_t nr_apqns,
const u8 *key, u32 keylen,
u8 *protkey, u32 *protkeylen,
- u32 *protkeytype)
+ u32 *protkeytype, u32 xflags)
{
const struct keytoken_header *hdr = (const struct keytoken_header *)key;
const struct clearkeytoken *t = (const struct clearkeytoken *)key;
@@ -503,12 +508,12 @@ static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
tmplen = MAXEP11AESKEYBLOBSIZE;
rc = ep11_clr2key(NULL, 0, t->keytype, PKEY_TYPE_EP11,
8 * keysize, 0, t->clearkey, t->len,
- tmpbuf, &tmplen, NULL);
+ tmpbuf, &tmplen, NULL, xflags);
pr_debug("ep11_clr2key()=%d\n", rc);
if (rc)
continue;
rc = ep11_key2protkey(NULL, 0, tmpbuf, tmplen,
- protkey, protkeylen, protkeytype);
+ protkey, protkeylen, protkeytype, xflags);
pr_debug("ep11_key2protkey()=%d\n", rc);
}
diff --git a/drivers/s390/crypto/pkey_pckmo.c b/drivers/s390/crypto/pkey_pckmo.c
index 835d59f4fbc5..00aabb1b3e18 100644
--- a/drivers/s390/crypto/pkey_pckmo.c
+++ b/drivers/s390/crypto/pkey_pckmo.c
@@ -406,7 +406,8 @@ static int pckmo_verify_key(const u8 *key, u32 keylen)
static int pkey_pckmo_key2protkey(const struct pkey_apqn *_apqns,
size_t _nr_apqns,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *keyinfo)
+ u8 *protkey, u32 *protkeylen, u32 *keyinfo,
+ u32 _xflags)
{
return pckmo_key2protkey(key, keylen,
protkey, protkeylen, keyinfo);
@@ -415,7 +416,8 @@ static int pkey_pckmo_key2protkey(const struct pkey_apqn *_apqns,
static int pkey_pckmo_gen_key(const struct pkey_apqn *_apqns, size_t _nr_apqns,
u32 keytype, u32 keysubtype,
u32 _keybitsize, u32 _flags,
- u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
+ u8 *keybuf, u32 *keybuflen, u32 *keyinfo,
+ u32 _xflags)
{
return pckmo_gen_protkey(keytype, keysubtype,
keybuf, keybuflen, keyinfo);
@@ -423,7 +425,8 @@ static int pkey_pckmo_gen_key(const struct pkey_apqn *_apqns, size_t _nr_apqns,
static int pkey_pckmo_verifykey(const u8 *key, u32 keylen,
u16 *_card, u16 *_dom,
- u32 *_keytype, u32 *_keybitsize, u32 *_flags)
+ u32 *_keytype, u32 *_keybitsize,
+ u32 *_flags, u32 _xflags)
{
return pckmo_verify_key(key, keylen);
}
diff --git a/drivers/s390/crypto/pkey_sysfs.c b/drivers/s390/crypto/pkey_sysfs.c
index 57edc97bafd2..cea772973649 100644
--- a/drivers/s390/crypto/pkey_sysfs.c
+++ b/drivers/s390/crypto/pkey_sysfs.c
@@ -29,13 +29,13 @@ static int sys_pkey_handler_gen_key(u32 keytype, u32 keysubtype,
rc = pkey_handler_gen_key(NULL, 0,
keytype, keysubtype,
keybitsize, flags,
- keybuf, keybuflen, keyinfo);
+ keybuf, keybuflen, keyinfo, 0);
if (rc == -ENODEV) {
pkey_handler_request_modules();
rc = pkey_handler_gen_key(NULL, 0,
keytype, keysubtype,
keybitsize, flags,
- keybuf, keybuflen, keyinfo);
+ keybuf, keybuflen, keyinfo, 0);
}
return rc;
diff --git a/drivers/s390/crypto/pkey_uv.c b/drivers/s390/crypto/pkey_uv.c
index 805817b14354..f36ff7531213 100644
--- a/drivers/s390/crypto/pkey_uv.c
+++ b/drivers/s390/crypto/pkey_uv.c
@@ -172,13 +172,19 @@ static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
size_t _nr_apqns __always_unused,
const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *keyinfo)
+ u8 *protkey, u32 *protkeylen, u32 *keyinfo,
+ u32 xflags)
{
struct uvsecrettoken *t = (struct uvsecrettoken *)key;
u32 pkeysize, pkeytype;
u16 secret_type;
int rc;
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
if (rc)
goto out;
@@ -214,13 +220,19 @@ static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
static int uv_verifykey(const u8 *key, u32 keylen,
u16 *_card __always_unused,
u16 *_dom __always_unused,
- u32 *keytype, u32 *keybitsize, u32 *flags)
+ u32 *keytype, u32 *keybitsize, u32 *flags,
+ u32 xflags)
{
struct uvsecrettoken *t = (struct uvsecrettoken *)key;
struct uv_secret_list_item_hdr secret_meta_data;
u32 pkeysize, pkeytype, bitsize;
int rc;
+ if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+
rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
if (rc)
goto out;
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
index ccf8206ae42d..57d77972da86 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.c
+++ b/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -333,7 +333,7 @@ static inline void prep_xcrb(struct ica_xcRB *pxcrb,
* Generate (random) CCA AES DATA secure key.
*/
int cca_genseckey(u16 cardnr, u16 domain,
- u32 keybitsize, u8 *seckey)
+ u32 keybitsize, u8 *seckey, u32 xflags)
{
int i, rc, keysize;
int seckeysize;
@@ -373,7 +373,6 @@ int cca_genseckey(u16 cardnr, u16 domain,
} keyblock;
} lv3;
} __packed * prepparm;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -478,7 +477,7 @@ EXPORT_SYMBOL(cca_genseckey);
* Generate an CCA AES DATA secure key with given key value.
*/
int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
- const u8 *clrkey, u8 *seckey)
+ const u8 *clrkey, u8 *seckey, u32 xflags)
{
int rc, keysize, seckeysize;
u8 *mem, *ptr;
@@ -516,7 +515,6 @@ int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
} keyblock;
} lv3;
} __packed * prepparm;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -620,7 +618,7 @@ EXPORT_SYMBOL(cca_clr2seckey);
*/
int cca_sec2protkey(u16 cardnr, u16 domain,
const u8 *seckey, u8 *protkey, u32 *protkeylen,
- u32 *protkeytype)
+ u32 *protkeytype, u32 xflags)
{
int rc;
u8 *mem, *ptr;
@@ -664,7 +662,6 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
} ckb;
} lv3;
} __packed * prepparm;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -786,7 +783,7 @@ static const u8 aes_cipher_key_skeleton[] = {
* Generate (random) CCA AES CIPHER secure key.
*/
int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
- u8 *keybuf, u32 *keybufsize)
+ u8 *keybuf, u32 *keybufsize, u32 xflags)
{
int rc;
u8 *mem, *ptr;
@@ -860,7 +857,6 @@ int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
} kb;
} __packed * prepparm;
struct cipherkeytoken *t;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -989,7 +985,8 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
const u8 *clr_key_value,
int clr_key_bit_size,
u8 *key_token,
- int *key_token_size)
+ int *key_token_size,
+ u32 xflags)
{
int rc, n;
u8 *mem, *ptr;
@@ -1038,7 +1035,6 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
} __packed * prepparm;
struct cipherkeytoken *t;
int complete = strncmp(rule_array_2, "COMPLETE", 8) ? 0 : 1;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -1138,14 +1134,13 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
* Build CCA AES CIPHER secure key with a given clear key value.
*/
int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags,
- const u8 *clrkey, u8 *keybuf, u32 *keybufsize)
+ const u8 *clrkey, u8 *keybuf, u32 *keybufsize, u32 xflags)
{
int rc;
void *mem;
int tokensize;
u8 *token, exorbuf[32];
struct cipherkeytoken *t;
- u32 xflags = 0;
/* fill exorbuf with random data */
get_random_bytes(exorbuf, sizeof(exorbuf));
@@ -1182,28 +1177,28 @@ int cca_clr2cipherkey(u16 card, u16 dom, u32 keybitsize, u32 keygenflags,
* 4/4 COMPLETE the secure cipher key import
*/
rc = _ip_cprb_helper(card, dom, "AES ", "FIRST ", "MIN3PART",
- exorbuf, keybitsize, token, &tokensize);
+ exorbuf, keybitsize, token, &tokensize, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s clear key import 1/4 with CSNBKPI2 failed, rc=%d\n",
__func__, rc);
goto out;
}
rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL,
- clrkey, keybitsize, token, &tokensize);
+ clrkey, keybitsize, token, &tokensize, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s clear key import 2/4 with CSNBKPI2 failed, rc=%d\n",
__func__, rc);
goto out;
}
rc = _ip_cprb_helper(card, dom, "AES ", "ADD-PART", NULL,
- exorbuf, keybitsize, token, &tokensize);
+ exorbuf, keybitsize, token, &tokensize, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s clear key import 3/4 with CSNBKPI2 failed, rc=%d\n",
__func__, rc);
goto out;
}
rc = _ip_cprb_helper(card, dom, "AES ", "COMPLETE", NULL,
- NULL, keybitsize, token, &tokensize);
+ NULL, keybitsize, token, &tokensize, xflags);
if (rc) {
ZCRYPT_DBF_ERR("%s clear key import 4/4 with CSNBKPI2 failed, rc=%d\n",
__func__, rc);
@@ -1229,7 +1224,8 @@ EXPORT_SYMBOL(cca_clr2cipherkey);
* Derive proteced key from CCA AES cipher secure key.
*/
int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
int rc;
u8 *mem, *ptr;
@@ -1279,7 +1275,6 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
} kb;
} __packed * prepparm;
int keytoklen = ((struct cipherkeytoken *)ckey)->len;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -1396,7 +1391,7 @@ EXPORT_SYMBOL(cca_cipher2protkey);
* Derive protected key from CCA ECC secure private key.
*/
int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype, u32 xflags)
{
int rc;
u8 *mem, *ptr;
@@ -1444,7 +1439,6 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
/* followed by a key block */
} __packed * prepparm;
int keylen = ((struct eccprivkeytoken *)key)->len;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(PARMBSIZE, &mem,
@@ -1547,7 +1541,8 @@ EXPORT_SYMBOL(cca_ecc2protkey);
int cca_query_crypto_facility(u16 cardnr, u16 domain,
const char *keyword,
u8 *rarray, size_t *rarraylen,
- u8 *varray, size_t *varraylen)
+ u8 *varray, size_t *varraylen,
+ u32 xflags)
{
int rc;
u16 len;
@@ -1569,7 +1564,6 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
u8 subfunc_code[2];
u8 lvdata[];
} __packed * prepparm;
- const u32 xflags = 0;
/* get already prepared memory for 2 cprbs with param block each */
rc = alloc_and_prep_cprbmem(parmbsize, &mem,
@@ -1758,7 +1752,7 @@ static int fetch_cca_info(u16 cardnr, u16 domain,
/* QF for this card/domain */
rc = cca_query_crypto_facility(cardnr, domain, "STATICSA",
- rarray, &rlen, varray, &vlen);
+ rarray, &rlen, varray, &vlen, xflags);
if (rc == 0 && rlen >= 10 * 8 && vlen >= 204) {
memcpy(ci->serial, rarray, 8);
ci->new_asym_mk_state = (char)rarray[4 * 8];
@@ -1785,7 +1779,7 @@ static int fetch_cca_info(u16 cardnr, u16 domain,
goto out;
rlen = vlen = PAGE_SIZE / 2;
rc = cca_query_crypto_facility(cardnr, domain, "STATICSB",
- rarray, &rlen, varray, &vlen);
+ rarray, &rlen, varray, &vlen, xflags);
if (rc == 0 && rlen >= 13 * 8 && vlen >= 240) {
ci->new_apka_mk_state = (char)rarray[10 * 8];
ci->cur_apka_mk_state = (char)rarray[11 * 8];
@@ -1827,13 +1821,12 @@ EXPORT_SYMBOL(cca_get_info);
* Master Key Verification Pattern given.
*/
static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
- int verify, int minhwtype)
+ int verify, int minhwtype, u32 xflg)
{
struct zcrypt_device_status_ext *device_status;
u16 card, dom;
struct cca_info ci;
int i, rc, oi = -1;
- u32 xflg = 0; /* xflags */
/* mkvp must not be zero, minhwtype needs to be >= 0 */
if (mkvp == 0 || minhwtype < 0)
@@ -1925,7 +1918,8 @@ static int findcard(u64 mkvp, u16 *pcardnr, u16 *pdomain,
* Search for a matching crypto card based on the Master Key
* Verification Pattern provided inside a secure key token.
*/
-int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify)
+int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain,
+ int verify, u32 xflags)
{
u64 mkvp;
int minhwtype = 0;
@@ -1946,19 +1940,18 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify)
return -EINVAL;
}
- return findcard(mkvp, pcardnr, pdomain, verify, minhwtype);
+ return findcard(mkvp, pcardnr, pdomain, verify, minhwtype, xflags);
}
EXPORT_SYMBOL(cca_findcard);
int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
- int verify)
+ int verify, u32 xflags)
{
struct zcrypt_device_status_ext *device_status;
int i, card, dom, curmatch, oldmatch, rc;
struct cca_info ci;
u32 _nr_apqns = 0;
- u32 xflags = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
diff --git a/drivers/s390/crypto/zcrypt_ccamisc.h b/drivers/s390/crypto/zcrypt_ccamisc.h
index 966f0eaf3c4c..0dd4c336abab 100644
--- a/drivers/s390/crypto/zcrypt_ccamisc.h
+++ b/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -160,44 +160,47 @@ int cca_check_sececckeytoken(debug_info_t *dbg, int dbflvl,
/*
* Generate (random) CCA AES DATA secure key.
*/
-int cca_genseckey(u16 cardnr, u16 domain, u32 keybitsize, u8 *seckey);
+int cca_genseckey(u16 cardnr, u16 domain, u32 keybitsize, u8 *seckey,
+ u32 xflags);
/*
* Generate CCA AES DATA secure key with given clear key value.
*/
int cca_clr2seckey(u16 cardnr, u16 domain, u32 keybitsize,
- const u8 *clrkey, u8 *seckey);
+ const u8 *clrkey, u8 *seckey, u32 xflags);
/*
* Derive proteced key from an CCA AES DATA secure key.
*/
int cca_sec2protkey(u16 cardnr, u16 domain,
const u8 *seckey, u8 *protkey, u32 *protkeylen,
- u32 *protkeytype);
+ u32 *protkeytype, u32 xflags);
/*
* Generate (random) CCA AES CIPHER secure key.
*/
int cca_gencipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
- u8 *keybuf, u32 *keybufsize);
+ u8 *keybuf, u32 *keybufsize, u32 xflags);
/*
* Derive proteced key from CCA AES cipher secure key.
*/
int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags);
/*
* Build CCA AES CIPHER secure key with a given clear key value.
*/
int cca_clr2cipherkey(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
- const u8 *clrkey, u8 *keybuf, u32 *keybufsize);
+ const u8 *clrkey, u8 *keybuf, u32 *keybufsize,
+ u32 xflags);
/*
* Derive proteced key from CCA ECC secure private key.
*/
int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype, u32 xflags);
/*
* Query cryptographic facility from CCA adapter
@@ -205,7 +208,8 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
int cca_query_crypto_facility(u16 cardnr, u16 domain,
const char *keyword,
u8 *rarray, size_t *rarraylen,
- u8 *varray, size_t *varraylen);
+ u8 *varray, size_t *varraylen,
+ u32 xflags);
/*
* Search for a matching crypto card based on the Master Key
@@ -214,7 +218,8 @@ int cca_query_crypto_facility(u16 cardnr, u16 domain,
* Returns < 0 on failure, 0 if CURRENT MKVP matches and
* 1 if OLD MKVP matches.
*/
-int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify);
+int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain,
+ int verify, u32 xflags);
/*
* Build a list of cca apqns meeting the following constrains:
@@ -236,7 +241,7 @@ int cca_findcard(const u8 *key, u16 *pcardnr, u16 *pdomain, int verify);
*/
int cca_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
- int verify);
+ int verify, u32 xflags);
#define AES_MK_SET 0
#define APKA_MK_SET 1
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
index a6ac0cac0c45..01e47708f7e9 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.c
+++ b/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -1454,13 +1454,12 @@ static int _ep11_wrapkey(u16 card, u16 domain,
int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
const u8 *clrkey, u8 *keybuf, u32 *keybufsize,
- u32 keytype)
+ u32 keytype, u32 xflags)
{
int rc;
void *mem;
u8 encbuf[64], *kek;
size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
- const u32 xflags = 0;
if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256) {
clrkeylen = keybitsize / 8;
@@ -1521,7 +1520,8 @@ EXPORT_SYMBOL(ep11_clr2keyblob);
int ep11_kblob2protkey(u16 card, u16 dom,
const u8 *keyblob, u32 keybloblen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags)
{
struct ep11kblob_header *hdr;
struct ep11keyblob *key;
@@ -1537,7 +1537,6 @@ int ep11_kblob2protkey(u16 card, u16 dom,
} __packed * wki;
u8 *wkbuf = NULL;
int rc = -EIO;
- const u32 xflags = 0;
if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen))
return -EINVAL;
@@ -1643,14 +1642,13 @@ int ep11_kblob2protkey(u16 card, u16 dom,
EXPORT_SYMBOL(ep11_kblob2protkey);
int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
- int minhwtype, int minapi, const u8 *wkvp)
+ int minhwtype, int minapi, const u8 *wkvp, u32 xflags)
{
struct zcrypt_device_status_ext *device_status;
int i, card, dom, rc;
struct ep11_domain_info edi;
struct ep11_card_info eci;
u32 _nr_apqns = 0;
- const u32 xflags = 0;
/* occupy the device status memory */
mutex_lock(&dev_status_mem_mutex);
diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h
index 7ef036759dc8..34b47522a893 100644
--- a/drivers/s390/crypto/zcrypt_ep11misc.h
+++ b/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -124,7 +124,7 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
*/
int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
const u8 *clrkey, u8 *keybuf, u32 *keybufsize,
- u32 keytype);
+ u32 keytype, u32 xflags);
/*
* Build a list of ep11 apqns meeting the following constrains:
@@ -144,13 +144,14 @@ int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
* If no apqn meeting the criteria is found, -ENODEV is returned.
*/
int ep11_findcard2(u32 *apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
- int minhwtype, int minapi, const u8 *wkvp);
+ int minhwtype, int minapi, const u8 *wkvp, u32 xflags);
/*
* Derive proteced key from EP11 key blob (AES and ECC keys).
*/
int ep11_kblob2protkey(u16 card, u16 dom, const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags);
int zcrypt_ep11misc_init(void);
void zcrypt_ep11misc_exit(void);
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH v1 20/20] s390/pkey/crypto: Introduce xflags param for pkey in-kernel API
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
` (18 preceding siblings ...)
2025-02-23 9:54 ` [PATCH v1 19/20] s390/zcrypt/pkey: Provide and pass xflags within pkey and zcrypt layers Harald Freudenberger
@ 2025-02-23 9:54 ` Harald Freudenberger
19 siblings, 0 replies; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-23 9:54 UTC (permalink / raw)
To: dengler, ifranzki, fcallies; +Cc: linux-s390, herbert
Add a new parameter xflags to the in-kernel API function
pkey_key2protkey(). Currently there is only one flag supported:
* PKEY_XFLAG_NOMEMALLOC - If this flag is given in the xflags
parameter, the pkey implementation is not allowed to allocate
memory but instead should fail with -ENOMEM. This flag is for
protected key derive within a cipher or similar which must not
allocate memory - see also the CRYPTO_ALG_ALLOCATES_MEMORY
flag in crypto.h.
The one and only user of this in-kernel API - the skcipher
implementations PAES in paes_s390.c set this flag upon request
to derive a protected key from the given raw key material.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
arch/s390/crypto/paes_s390.c | 2 +-
arch/s390/include/asm/pkey.h | 13 ++++++++++++-
drivers/s390/crypto/pkey_api.c | 3 +--
drivers/s390/crypto/zcrypt_api.h | 10 +++++++---
4 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c
index 511093713a6f..646cbbf0678d 100644
--- a/arch/s390/crypto/paes_s390.c
+++ b/arch/s390/crypto/paes_s390.c
@@ -189,7 +189,7 @@ static inline int __paes_keyblob2pkey(const u8 *key, unsigned int keylen,
return -EINTR;
}
rc = pkey_key2protkey(key, keylen, pk->protkey, &pk->len,
- &pk->type);
+ &pk->type, PKEY_XFLAG_NOMEMALLOC);
}
return rc;
diff --git a/arch/s390/include/asm/pkey.h b/arch/s390/include/asm/pkey.h
index 5dca1a46a9f6..2bd344cbc2ec 100644
--- a/arch/s390/include/asm/pkey.h
+++ b/arch/s390/include/asm/pkey.h
@@ -20,9 +20,20 @@
* @param key pointer to a buffer containing the key blob
* @param keylen size of the key blob in bytes
* @param protkey pointer to buffer receiving the protected key
+ * @param xflags additional execution flags (see PKEY_XFLAG_* definitions below)
* @return 0 on success, negative errno value on failure
*/
int pkey_key2protkey(const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype,
+ u32 xflags);
+
+/*
+ * If this flag is given in the xflags parameter, the pkey implementation
+ * is not allowed to allocate memory but instead should fail with -ENOMEM.
+ * This flag is for protected key derive within a cipher or similar
+ * which must not allocate memory - see also the CRYPTO_ALG_ALLOCATES_MEMORY
+ * flag in crypto.h.
+ */
+#define PKEY_XFLAG_NOMEMALLOC 0x0001
#endif /* _KAPI_PKEY_H */
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index 55a4e70b866b..cef60770f68b 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -53,10 +53,9 @@ static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
* In-Kernel function: Transform a key blob (of any type) into a protected key
*/
int pkey_key2protkey(const u8 *key, u32 keylen,
- u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+ u8 *protkey, u32 *protkeylen, u32 *protkeytype, u32 xflags)
{
int rc;
- const u32 xflags = 0;
rc = key2protkey(NULL, 0, key, keylen,
protkey, protkeylen, protkeytype, xflags);
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 92027304f0d8..f6d84751631f 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -16,6 +16,7 @@
#include <linux/atomic.h>
#include <asm/debug.h>
+#include <asm/pkey.h>
#include <asm/zcrypt.h>
#include "ap_bus.h"
@@ -79,10 +80,13 @@ struct zcrypt_track {
/*
* Do not allocate memory xflag. To be used with
* zcrypt_send_cprb() and zcrypt_send_ep11_cprb().
- * Currently only available and used for the in-kernel
- * zcrpyt api.
+ * But also used within the cca and ep11 misc functions
+ * and the pkey layer exposes this as a PKEY_XFLAG_
+ * via the in-kernel-api for protected key support.
+ * ZCRYPT_XFLAG_NOMEMALLOC and PKEY_XFLAG_NOMEMALLOC
+ * should have same value to avoid unnecessary conversions.
*/
-#define ZCRYPT_XFLAG_NOMEMALLOC 0x0001
+#define ZCRYPT_XFLAG_NOMEMALLOC PKEY_XFLAG_NOMEMALLOC
struct zcrypt_ops {
long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *,
--
2.43.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct
2025-02-23 9:54 ` [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct Harald Freudenberger
@ 2025-02-24 15:23 ` Holger Dengler
2025-02-25 7:39 ` Holger Dengler
2025-02-25 8:56 ` Harald Freudenberger
0 siblings, 2 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-24 15:23 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> Move the very small response_type struct into struct ap_msg.
> So there is no need to kmalloc this tiny struct with each
> ap message preparation.
I understand the intention for this patch, but in my opinion the layering concept between ap and zcrypt is violated by defining the response-type as part of the ap message struct. But I don't have any better solution, so for the moment you may leave it as is.
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/ap_bus.h | 12 ++-
> drivers/s390/crypto/zcrypt_msgtype50.c | 22 +++---
> drivers/s390/crypto/zcrypt_msgtype6.c | 101 ++++++++++---------------
> 3 files changed, 59 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
> index f4622ee4d894..a5d8f805625f 100644
> --- a/drivers/s390/crypto/ap_bus.h
> +++ b/drivers/s390/crypto/ap_bus.h
> @@ -214,6 +214,15 @@ struct ap_queue {
>
> typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
>
> +struct ap_response_type {
> + struct completion work;
> + int type;
> +};
> +
> +#define CEXXC_RESPONSE_TYPE_ICA 1
> +#define CEXXC_RESPONSE_TYPE_XCRB 2
> +#define CEXXC_RESPONSE_TYPE_EP11 3
> +
I would leave the type defines in the zcrypt_msgtype50.c.
> struct ap_message {
> struct list_head list; /* Request queueing. */
> unsigned long psmid; /* Message id. */
> @@ -222,7 +231,7 @@ struct ap_message {
> size_t bufsize; /* allocated msg buffer size */
> u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
> int rc; /* Return code for this message */
> - void *private; /* ap driver private pointer. */
> + struct ap_response_type response;
I don't like this change. The completion and the type are both message-type related. That means, this change pulls messate-type related data definitions into the ap-layer. On the other hand, I have currently no idea how this can be solved.
> /* receive is called from tasklet context */
> void (*receive)(struct ap_queue *, struct ap_message *,
> struct ap_message *);
> @@ -250,7 +259,6 @@ static inline void ap_init_message(struct ap_message *ap_msg)
> static inline void ap_release_message(struct ap_message *ap_msg)
> {
> kfree_sensitive(ap_msg->msg);
> - kfree_sensitive(ap_msg->private);
As far as I can see, the kfree_sensitive() was not really required, as this only contains the type and the completion, but no sensitive data, right?
If the assumption is true, the change is ok (if not, we should replace it with a memzero_explicit()).
> @@ -454,25 +454,24 @@ static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq,
> struct ica_rsa_modexpo *mex,
> struct ap_message *ap_msg)
> {
> - struct completion work;
> int rc;
>
> ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
> + if (!ap_msg->msg)
> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
This change will be removed by the next patch in the series. Please drop it. There are other occurances later in the code, see my further comments.
> if (!ap_msg->msg)
> return -ENOMEM;
> ap_msg->receive = zcrypt_msgtype50_receive;
> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
> atomic_inc_return(&zcrypt_step);
> - ap_msg->private = &work;
> rc = ICAMEX_msg_to_type50MEX_msg(zq, ap_msg, mex);
> if (rc)
> goto out;
> - init_completion(&work);
> + init_completion(&ap_msg->response.work);
> rc = ap_queue_message(zq->queue, ap_msg);
> if (rc)
> goto out;
> - rc = wait_for_completion_interruptible(&work);
> + rc = wait_for_completion_interruptible(&ap_msg->response.work);
> if (rc == 0) {
> rc = ap_msg->rc;
> if (rc == 0)
[...]
> @@ -504,25 +502,24 @@ static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq,
> struct ica_rsa_modexpo_crt *crt,
> struct ap_message *ap_msg)
> {
> - struct completion work;
> int rc;
>
> ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
> + if (!ap_msg->msg)
> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
Same here, please drop it.
> if (!ap_msg->msg)
> return -ENOMEM;
> ap_msg->receive = zcrypt_msgtype50_receive;
> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
> atomic_inc_return(&zcrypt_step);
> - ap_msg->private = &work;
> rc = ICACRT_msg_to_type50CRT_msg(zq, ap_msg, crt);
> if (rc)
> goto out;
> - init_completion(&work);
> + init_completion(&ap_msg->response.work);
> rc = ap_queue_message(zq->queue, ap_msg);
> if (rc)
> goto out;
> - rc = wait_for_completion_interruptible(&work);
> + rc = wait_for_completion_interruptible(&ap_msg->response.work);
> if (rc == 0) {
> rc = ap_msg->rc;
> if (rc == 0)
[...]
> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
> index b64c9d9fc613..21ee311cf33d 100644
> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
> @@ -31,15 +31,6 @@
>
> #define CEIL4(x) ((((x) + 3) / 4) * 4)
>
> -struct response_type {
> - struct completion work;
> - int type;
> -};
> -
> -#define CEXXC_RESPONSE_TYPE_ICA 0
> -#define CEXXC_RESPONSE_TYPE_XCRB 1
> -#define CEXXC_RESPONSE_TYPE_EP11 2
> -
Please define the message types here (see my previous comment).
> MODULE_AUTHOR("IBM Corporation");
> MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
> "Copyright IBM Corp. 2001, 2023");
[...]
> @@ -1061,28 +1046,26 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
> * Prepare a CCA AP msg: fetch the required data from userspace,
> * prepare the AP msg, fill some info into the ap_message struct,
> * extract some data from the CPRB and give back to the caller.
> - * This function allocates memory and needs an ap_msg prepared
> - * by the caller with ap_init_message(). Also the caller has to
> - * make sure ap_release_message() is always called even on failure.
> + * This function may allocate memory if the ap_msg msg buffer is
> + * not preallocated and needs an ap_msg prepared by the caller
> + * with ap_init_message(). Also the caller has to make sure
> + * ap_release_message() is always called even on failure.
Please move this change to the patch, which makes the allocation optional.
> */
> int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
> struct ap_message *ap_msg,
> unsigned int *func_code, unsigned short **dom)
> {
> - struct response_type resp_type = {
> - .type = CEXXC_RESPONSE_TYPE_XCRB,
> - };
> + struct ap_response_type *resp_type = &ap_msg->response;
>
> ap_msg->bufsize = atomic_read(&ap_max_msg_size);
> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
> + if (!ap_msg->msg)
> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
Please drop the kmalloc change.
> if (!ap_msg->msg)
> return -ENOMEM;
> ap_msg->receive = zcrypt_msgtype6_receive;
> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
> atomic_inc_return(&zcrypt_step);
> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
> - if (!ap_msg->private)
> - return -ENOMEM;
> + resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
> return xcrb_msg_to_type6cprb_msgx(userspace, ap_msg, xcrb, func_code, dom);
> }
>
[...]
> @@ -1158,28 +1141,26 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
> * Prepare an EP11 AP msg: fetch the required data from userspace,
> * prepare the AP msg, fill some info into the ap_message struct,
> * extract some data from the CPRB and give back to the caller.
> - * This function allocates memory and needs an ap_msg prepared
> - * by the caller with ap_init_message(). Also the caller has to
> - * make sure ap_release_message() is always called even on failure.
> + * This function may allocate memory if the ap_msg msg buffer is
> + * not preallocated and needs an ap_msg prepared by the caller
> + * with ap_init_message(). Also the caller has to make sure
> + * ap_release_message() is always called even on failure.
Please move this change to the patch, which makes the allocation optional.
> */
> int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
> struct ap_message *ap_msg,
> unsigned int *func_code, unsigned int *domain)
> {
> - struct response_type resp_type = {
> - .type = CEXXC_RESPONSE_TYPE_EP11,
> - };
> + struct ap_response_type *resp_type = &ap_msg->response;
>
> ap_msg->bufsize = atomic_read(&ap_max_msg_size);
> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
> + if (!ap_msg->msg)
> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
Please drop the kmalloc change.
> if (!ap_msg->msg)
> return -ENOMEM;
> ap_msg->receive = zcrypt_msgtype6_receive_ep11;
> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
> atomic_inc_return(&zcrypt_step);
> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
> - if (!ap_msg->private)
> - return -ENOMEM;
> + resp_type->type = CEXXC_RESPONSE_TYPE_EP11;
> return xcrb_msg_to_type6_ep11cprb_msgx(userspace, ap_msg, xcrb,
> func_code, domain);
> }
[...]
> @@ -1279,20 +1260,18 @@ static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
> int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
> unsigned int *domain)
> {
> - struct response_type resp_type = {
> - .type = CEXXC_RESPONSE_TYPE_XCRB,
> - };
> + struct ap_response_type *resp_type = &ap_msg->response;
>
> ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
> + if (!ap_msg->msg)
> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
Please drop the kmalloc change.
> if (!ap_msg->msg)
> return -ENOMEM;
> ap_msg->receive = zcrypt_msgtype6_receive;
> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
> atomic_inc_return(&zcrypt_step);
> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
> - if (!ap_msg->private)
> - return -ENOMEM;
> +
> + resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
>
> rng_type6cprb_msgx(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain);
>
[...]
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct
2025-02-24 15:23 ` Holger Dengler
@ 2025-02-25 7:39 ` Holger Dengler
2025-02-25 8:56 ` Harald Freudenberger
1 sibling, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-25 7:39 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 24/02/2025 16:23, Holger Dengler wrote:
> On 23/02/2025 10:54, Harald Freudenberger wrote:
>> Move the very small response_type struct into struct ap_msg.
>> So there is no need to kmalloc this tiny struct with each
>> ap message preparation.
>
> I understand the intention for this patch, but in my opinion the layering concept between ap and zcrypt is violated by defining the response-type as part of the ap message struct. But I don't have any better solution, so for the moment you may leave it as is.
>
>>
>> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
>> ---
>> drivers/s390/crypto/ap_bus.h | 12 ++-
>> drivers/s390/crypto/zcrypt_msgtype50.c | 22 +++---
>> drivers/s390/crypto/zcrypt_msgtype6.c | 101 ++++++++++---------------
>> 3 files changed, 59 insertions(+), 76 deletions(-)
>>
[...]
>> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c
>> index b64c9d9fc613..21ee311cf33d 100644
>> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
>> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
>> @@ -1061,28 +1046,26 @@ static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
>> * Prepare a CCA AP msg: fetch the required data from userspace,
>> * prepare the AP msg, fill some info into the ap_message struct,
>> * extract some data from the CPRB and give back to the caller.
>> - * This function allocates memory and needs an ap_msg prepared
>> - * by the caller with ap_init_message(). Also the caller has to
>> - * make sure ap_release_message() is always called even on failure.
>> + * This function may allocate memory if the ap_msg msg buffer is
>> + * not preallocated and needs an ap_msg prepared by the caller
>> + * with ap_init_message(). Also the caller has to make sure
>> + * ap_release_message() is always called even on failure.
>
> Please move this change to the patch, which makes the allocation optional.
This change will be reverted by the next patch in the series, so please dropt it here and make only the change in the next patch.
[...]
>> @@ -1158,28 +1141,26 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
>> * Prepare an EP11 AP msg: fetch the required data from userspace,
>> * prepare the AP msg, fill some info into the ap_message struct,
>> * extract some data from the CPRB and give back to the caller.
>> - * This function allocates memory and needs an ap_msg prepared
>> - * by the caller with ap_init_message(). Also the caller has to
>> - * make sure ap_release_message() is always called even on failure.
>> + * This function may allocate memory if the ap_msg msg buffer is
>> + * not preallocated and needs an ap_msg prepared by the caller
>> + * with ap_init_message(). Also the caller has to make sure
>> + * ap_release_message() is always called even on failure.
>
> Please move this change to the patch, which makes the allocation optional.
Same here.
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation
2025-02-23 9:54 ` [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation Harald Freudenberger
@ 2025-02-25 8:12 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-25 8:12 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> Slight rework on the way how AP message buffers are allocated.
> Instead of having multiple places with kmalloc() calls all
> the AP message buffers are now allocated and freed on exactyl
> one place ap_init_apmsg() allocates the current AP bus max
> limit of ap_max_msg_size (defaults to 12KB). The preparation
> functions only check for their payload to fit in. The AP
> message buffer is freed in ap_release_apmsg().
This patch reverts some non-neccessary changes from the previous one. Please clean this up.
Beside that,
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/ap_bus.c | 30 ++++++++++++++++
> drivers/s390/crypto/ap_bus.h | 21 ++---------
> drivers/s390/crypto/zcrypt_api.c | 49 +++++++++++++++-----------
> drivers/s390/crypto/zcrypt_msgtype50.c | 22 ++++++------
> drivers/s390/crypto/zcrypt_msgtype6.c | 46 ++++++++++++------------
> 5 files changed, 96 insertions(+), 72 deletions(-)
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct
2025-02-24 15:23 ` Holger Dengler
2025-02-25 7:39 ` Holger Dengler
@ 2025-02-25 8:56 ` Harald Freudenberger
2025-02-25 9:22 ` Holger Dengler
1 sibling, 1 reply; 31+ messages in thread
From: Harald Freudenberger @ 2025-02-25 8:56 UTC (permalink / raw)
To: Holger Dengler; +Cc: ifranzki, fcallies, linux-s390, herbert
On 2025-02-24 16:23, Holger Dengler wrote:
> On 23/02/2025 10:54, Harald Freudenberger wrote:
>> Move the very small response_type struct into struct ap_msg.
>> So there is no need to kmalloc this tiny struct with each
>> ap message preparation.
>
> I understand the intention for this patch, but in my opinion the
> layering concept between ap and zcrypt is violated by defining the
> response-type as part of the ap message struct. But I don't have any
> better solution, so for the moment you may leave it as is.
>
>>
>> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
>> ---
>> drivers/s390/crypto/ap_bus.h | 12 ++-
>> drivers/s390/crypto/zcrypt_msgtype50.c | 22 +++---
>> drivers/s390/crypto/zcrypt_msgtype6.c | 101
>> ++++++++++---------------
>> 3 files changed, 59 insertions(+), 76 deletions(-)
>>
>> diff --git a/drivers/s390/crypto/ap_bus.h
>> b/drivers/s390/crypto/ap_bus.h
>> index f4622ee4d894..a5d8f805625f 100644
>> --- a/drivers/s390/crypto/ap_bus.h
>> +++ b/drivers/s390/crypto/ap_bus.h
>> @@ -214,6 +214,15 @@ struct ap_queue {
>>
>> typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
>>
>> +struct ap_response_type {
>> + struct completion work;
>> + int type;
>> +};
>> +
>> +#define CEXXC_RESPONSE_TYPE_ICA 1
>> +#define CEXXC_RESPONSE_TYPE_XCRB 2
>> +#define CEXXC_RESPONSE_TYPE_EP11 3
>> +
>
> I would leave the type defines in the zcrypt_msgtype50.c.
Done -> v2
>
>> struct ap_message {
>> struct list_head list; /* Request queueing. */
>> unsigned long psmid; /* Message id. */
>> @@ -222,7 +231,7 @@ struct ap_message {
>> size_t bufsize; /* allocated msg buffer size */
>> u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
>> int rc; /* Return code for this message */
>> - void *private; /* ap driver private pointer. */
>> + struct ap_response_type response;
>
> I don't like this change. The completion and the type are both
> message-type related. That means, this change pulls messate-type
> related data definitions into the ap-layer. On the other hand, I have
> currently no idea how this can be solved.
>
Well, the "private" data could be opaque allocated in ap_init_apmsg
without
any knowledge about the data - just the size. And the msg type 50 and 6
implementations could just check for the right size and then overlay the
private data bytes with their own struct.
>> /* receive is called from tasklet context */
>> void (*receive)(struct ap_queue *, struct ap_message *,
>> struct ap_message *);
>> @@ -250,7 +259,6 @@ static inline void ap_init_message(struct
>> ap_message *ap_msg)
>> static inline void ap_release_message(struct ap_message *ap_msg)
>> {
>> kfree_sensitive(ap_msg->msg);
>> - kfree_sensitive(ap_msg->private);
>
> As far as I can see, the kfree_sensitive() was not really required, as
> this only contains the type and the completion, but no sensitive data,
> right?
> If the assumption is true, the change is ok (if not, we should replace
> it with a memzero_explicit()).
Your assumption is true - the private data only held a completion and
the type of the msg (type 50 or type 6) - all that is no sensitive info.
>
>> @@ -454,25 +454,24 @@ static long zcrypt_msgtype50_modexpo(struct
>> zcrypt_queue *zq,
>> struct ica_rsa_modexpo *mex,
>> struct ap_message *ap_msg)
>> {
>> - struct completion work;
>> int rc;
>>
>> ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
>> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>> + if (!ap_msg->msg)
>> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>
> This change will be removed by the next patch in the series. Please
> drop it. There are other occurances later in the code, see my further
> comments.
>
Done as you suggest -> v2
>> if (!ap_msg->msg)
>> return -ENOMEM;
>> ap_msg->receive = zcrypt_msgtype50_receive;
>> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
>> atomic_inc_return(&zcrypt_step);
>> - ap_msg->private = &work;
>> rc = ICAMEX_msg_to_type50MEX_msg(zq, ap_msg, mex);
>> if (rc)
>> goto out;
>> - init_completion(&work);
>> + init_completion(&ap_msg->response.work);
>> rc = ap_queue_message(zq->queue, ap_msg);
>> if (rc)
>> goto out;
>> - rc = wait_for_completion_interruptible(&work);
>> + rc = wait_for_completion_interruptible(&ap_msg->response.work);
>> if (rc == 0) {
>> rc = ap_msg->rc;
>> if (rc == 0)
> [...]
>> @@ -504,25 +502,24 @@ static long zcrypt_msgtype50_modexpo_crt(struct
>> zcrypt_queue *zq,
>> struct ica_rsa_modexpo_crt *crt,
>> struct ap_message *ap_msg)
>> {
>> - struct completion work;
>> int rc;
>>
>> ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE;
>> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>> + if (!ap_msg->msg)
>> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>
> Same here, please drop it.
-> v2
>
>> if (!ap_msg->msg)
>> return -ENOMEM;
>> ap_msg->receive = zcrypt_msgtype50_receive;
>> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
>> atomic_inc_return(&zcrypt_step);
>> - ap_msg->private = &work;
>> rc = ICACRT_msg_to_type50CRT_msg(zq, ap_msg, crt);
>> if (rc)
>> goto out;
>> - init_completion(&work);
>> + init_completion(&ap_msg->response.work);
>> rc = ap_queue_message(zq->queue, ap_msg);
>> if (rc)
>> goto out;
>> - rc = wait_for_completion_interruptible(&work);
>> + rc = wait_for_completion_interruptible(&ap_msg->response.work);
>> if (rc == 0) {
>> rc = ap_msg->rc;
>> if (rc == 0)
> [...]
>> diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c
>> b/drivers/s390/crypto/zcrypt_msgtype6.c
>> index b64c9d9fc613..21ee311cf33d 100644
>> --- a/drivers/s390/crypto/zcrypt_msgtype6.c
>> +++ b/drivers/s390/crypto/zcrypt_msgtype6.c
>> @@ -31,15 +31,6 @@
>>
>> #define CEIL4(x) ((((x) + 3) / 4) * 4)
>>
>> -struct response_type {
>> - struct completion work;
>> - int type;
>> -};
>> -
>> -#define CEXXC_RESPONSE_TYPE_ICA 0
>> -#define CEXXC_RESPONSE_TYPE_XCRB 1
>> -#define CEXXC_RESPONSE_TYPE_EP11 2
>> -
>
> Please define the message types here (see my previous comment).
>
done -> v2
>> MODULE_AUTHOR("IBM Corporation");
>> MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
>> "Copyright IBM Corp. 2001, 2023");
> [...]
>> @@ -1061,28 +1046,26 @@ static long zcrypt_msgtype6_modexpo_crt(struct
>> zcrypt_queue *zq,
>> * Prepare a CCA AP msg: fetch the required data from userspace,
>> * prepare the AP msg, fill some info into the ap_message struct,
>> * extract some data from the CPRB and give back to the caller.
>> - * This function allocates memory and needs an ap_msg prepared
>> - * by the caller with ap_init_message(). Also the caller has to
>> - * make sure ap_release_message() is always called even on failure.
>> + * This function may allocate memory if the ap_msg msg buffer is
>> + * not preallocated and needs an ap_msg prepared by the caller
>> + * with ap_init_message(). Also the caller has to make sure
>> + * ap_release_message() is always called even on failure.
>
> Please move this change to the patch, which makes the allocation
> optional.
done -> v2
>
>> */
>> int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
>> struct ap_message *ap_msg,
>> unsigned int *func_code, unsigned short **dom)
>> {
>> - struct response_type resp_type = {
>> - .type = CEXXC_RESPONSE_TYPE_XCRB,
>> - };
>> + struct ap_response_type *resp_type = &ap_msg->response;
>>
>> ap_msg->bufsize = atomic_read(&ap_max_msg_size);
>> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>> + if (!ap_msg->msg)
>> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>
> Please drop the kmalloc change.
done -> v2
>
>> if (!ap_msg->msg)
>> return -ENOMEM;
>> ap_msg->receive = zcrypt_msgtype6_receive;
>> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
>> atomic_inc_return(&zcrypt_step);
>> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type),
>> GFP_KERNEL);
>> - if (!ap_msg->private)
>> - return -ENOMEM;
>> + resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
>> return xcrb_msg_to_type6cprb_msgx(userspace, ap_msg, xcrb,
>> func_code, dom);
>> }
>>
> [...]
>> @@ -1158,28 +1141,26 @@ static long zcrypt_msgtype6_send_cprb(bool
>> userspace, struct zcrypt_queue *zq,
>> * Prepare an EP11 AP msg: fetch the required data from userspace,
>> * prepare the AP msg, fill some info into the ap_message struct,
>> * extract some data from the CPRB and give back to the caller.
>> - * This function allocates memory and needs an ap_msg prepared
>> - * by the caller with ap_init_message(). Also the caller has to
>> - * make sure ap_release_message() is always called even on failure.
>> + * This function may allocate memory if the ap_msg msg buffer is
>> + * not preallocated and needs an ap_msg prepared by the caller
>> + * with ap_init_message(). Also the caller has to make sure
>> + * ap_release_message() is always called even on failure.
>
> Please move this change to the patch, which makes the allocation
> optional.
done -> v2
>
>> */
>> int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
>> struct ap_message *ap_msg,
>> unsigned int *func_code, unsigned int *domain)
>> {
>> - struct response_type resp_type = {
>> - .type = CEXXC_RESPONSE_TYPE_EP11,
>> - };
>> + struct ap_response_type *resp_type = &ap_msg->response;
>>
>> ap_msg->bufsize = atomic_read(&ap_max_msg_size);
>> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>> + if (!ap_msg->msg)
>> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>
> Please drop the kmalloc change.
>
done -> v2
>> if (!ap_msg->msg)
>> return -ENOMEM;
>> ap_msg->receive = zcrypt_msgtype6_receive_ep11;
>> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
>> atomic_inc_return(&zcrypt_step);
>> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type),
>> GFP_KERNEL);
>> - if (!ap_msg->private)
>> - return -ENOMEM;
>> + resp_type->type = CEXXC_RESPONSE_TYPE_EP11;
>> return xcrb_msg_to_type6_ep11cprb_msgx(userspace, ap_msg, xcrb,
>> func_code, domain);
>> }
> [...]
>> @@ -1279,20 +1260,18 @@ static long
>> zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *
>> int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
>> unsigned int *domain)
>> {
>> - struct response_type resp_type = {
>> - .type = CEXXC_RESPONSE_TYPE_XCRB,
>> - };
>> + struct ap_response_type *resp_type = &ap_msg->response;
>>
>> ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
>> - ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>> + if (!ap_msg->msg)
>> + ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
>
> Please drop the kmalloc change.
>
done -> v2
>> if (!ap_msg->msg)
>> return -ENOMEM;
>> ap_msg->receive = zcrypt_msgtype6_receive;
>> ap_msg->psmid = (((unsigned long)current->pid) << 32) +
>> atomic_inc_return(&zcrypt_step);
>> - ap_msg->private = kmemdup(&resp_type, sizeof(resp_type),
>> GFP_KERNEL);
>> - if (!ap_msg->private)
>> - return -ENOMEM;
>> +
>> + resp_type->type = CEXXC_RESPONSE_TYPE_XCRB;
>>
>> rng_type6cprb_msgx(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain);
>>
> [...]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct
2025-02-25 8:56 ` Harald Freudenberger
@ 2025-02-25 9:22 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-25 9:22 UTC (permalink / raw)
To: freude; +Cc: ifranzki, fcallies, linux-s390, herbert
On 25/02/2025 09:56, Harald Freudenberger wrote:
> On 2025-02-24 16:23, Holger Dengler wrote:
>> On 23/02/2025 10:54, Harald Freudenberger wrote:
>>> Move the very small response_type struct into struct ap_msg.
>>> So there is no need to kmalloc this tiny struct with each
>>> ap message preparation.
>>
>> I understand the intention for this patch, but in my opinion the
>> layering concept between ap and zcrypt is violated by defining the
>> response-type as part of the ap message struct. But I don't have any
>> better solution, so for the moment you may leave it as is.
>>
>>>
>>> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
>>> ---
>>> drivers/s390/crypto/ap_bus.h | 12 ++-
>>> drivers/s390/crypto/zcrypt_msgtype50.c | 22 +++---
>>> drivers/s390/crypto/zcrypt_msgtype6.c | 101 ++++++++++---------------
>>> 3 files changed, 59 insertions(+), 76 deletions(-)
>>>
>>> diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
>>> index f4622ee4d894..a5d8f805625f 100644
>>> --- a/drivers/s390/crypto/ap_bus.h
>>> +++ b/drivers/s390/crypto/ap_bus.h
>>> struct ap_message {
>>> struct list_head list; /* Request queueing. */
>>> unsigned long psmid; /* Message id. */
>>> @@ -222,7 +231,7 @@ struct ap_message {
>>> size_t bufsize; /* allocated msg buffer size */
>>> u16 flags; /* Flags, see AP_MSG_FLAG_xxx */
>>> int rc; /* Return code for this message */
>>> - void *private; /* ap driver private pointer. */
>>> + struct ap_response_type response;
>>
>> I don't like this change. The completion and the type are both
>> message-type related. That means, this change pulls messate-type
>> related data definitions into the ap-layer. On the other hand, I have
>> currently no idea how this can be solved.
>>
>
> Well, the "private" data could be opaque allocated in ap_init_apmsg without
> any knowledge about the data - just the size. And the msg type 50 and 6
> implementations could just check for the right size and then overlay the
> private data bytes with their own struct.
The only "problem" is, that the lower layer (ap in this case) has no knowledge, how much memory is required for the private data.
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool
2025-02-23 9:54 ` [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool Harald Freudenberger
@ 2025-02-25 13:52 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-25 13:52 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> There is a need for a do-not-allocate-memory path through the
> ap bus layer. When ap_init_apmsg() with the AP_MSG_FLAG_MEMPOOL
> xflag is called, instead of kmalloc() the ap message buffer is
> allocated from the ap_msg_pool. This pool only holds a limited
> amount of buffers: AP_MSG_POOL_MIN_ITEMS with the item size
> AP_DEFAULT_MAX_MSG_SIZE and exactly one of these items (if available)
> is returned if ap_init_apmsg() with the MEMPOOL flag is called.
> When this pool is exhausted and the MEMPOOL flag is effective,
> ap_init_apmsg() returns -ENOMEM without any attempt to allocate
> memory.
>
> The zcrypt layer may use this flag to indicate to the ap bus
> that the processing path for this message should not allocate
> memory. This is to prevent deadlocks with crypto and io for
> example with encrypted swap volumes.
See my comments below.
The rest looks good to me.
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/ap_bus.c | 59 +++++++++++++++++++++++++++-----
> drivers/s390/crypto/ap_bus.h | 3 +-
> drivers/s390/crypto/zcrypt_api.c | 10 +++---
> 3 files changed, 57 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
> index 4940eaf538e9..b585b5d11074 100644
> --- a/drivers/s390/crypto/ap_bus.c
> +++ b/drivers/s390/crypto/ap_bus.c
[...]
> @@ -546,16 +562,27 @@ static void ap_poll_thread_stop(void)
> #define is_card_dev(x) ((x)->parent == ap_root_device)
> #define is_queue_dev(x) ((x)->parent != ap_root_device)
>
> -/**
> +/*
What is the reason for mixing coding styles?
> * ap_init_apmsg() - Initialize ap_message.
> - * Initialize a message before using. Otherwise this might result in
> - * unexpected behaviour.
> + * Initialize struct ap_message and allocate buffer to construct
> + * the ap message.
> */
> -int ap_init_apmsg(struct ap_message *ap_msg)
> +int ap_init_apmsg(struct ap_message *ap_msg, u32 xflags)
The xflags function parameter is very confusing (here and also in all other APIs too), because it allows to set some, but not all flags in ap_msg-flags. Why not using `bool alloc`? If you will keep the more flexible interface, please add another xflags element to struct ap_message. There is nothing in common between the ap_msg->flags and xflags, beside they're both named "flags".
> {
> - unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
> + unsigned int maxmsgsize;
>
> memset(ap_msg, 0, sizeof(*ap_msg));
> +
> + if (xflags & 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;
> + }
> +
> + maxmsgsize = atomic_read(&ap_max_msg_size);
> ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
> if (!ap_msg->msg)
> return -ENOMEM;
> @@ -565,14 +592,18 @@ int ap_init_apmsg(struct ap_message *ap_msg)
> }
> EXPORT_SYMBOL(ap_init_apmsg);
>
> -/**
> +/*
???
> * ap_release_apmsg() - Release ap_message.
> - * Releases all memory used internal within the ap_message struct
> - * Currently this is the message and private field.
> + * Cleanup struct ap_message and release all memory held.
> */
> void ap_release_apmsg(struct ap_message *ap_msg)
> {
> - kfree_sensitive(ap_msg->msg);
> + if (ap_msg->flags & AP_MSG_FLAG_MEMPOOL) {
> + memzero_explicit(ap_msg->msg, ap_msg->bufsize);
> + mempool_free(ap_msg->msg, ap_msg_pool);
> + } else {
> + kfree_sensitive(ap_msg->msg);
> + }
> }
> EXPORT_SYMBOL(ap_release_apmsg);
>
[...]
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC
2025-02-23 9:54 ` [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC Harald Freudenberger
@ 2025-02-27 8:21 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-27 8:21 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> 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.
See my comment below. Please evaluate, if the boolean `userspace` parameter can also be implemented as one of the xflags.
>
> One flag is implemented: The xflag ZCRYPT_XFLAG_NOMEMALLOC
> tells the zcrypt_send_*() functions to not allocate memory
> via kmalloc() and friends with the goal to not trigger any
> IO operations. If this xflag is given, it is also forwarded
> to the AP bus functions as AP_MSG_FLAG_MEMPOOL when the
> ap_init_apmsg() is invoked.
>
> If the ZCRYPT_XFLAG_NOMEMALLOC is given, the zcrypt layer
> does not allocate any memory but may fail to send a crypto
> load:
> - The number of EP11 targets if given must not exceed 16 APQNs.
> - As the flag is passed down to the AP bus functions the
> AP bus uses a limited mem pool (with limited item size)
> to construct the AP msg. The AP bus mem pool may be depleted
> and/or the message size may exceed the item size of the
> AP bus mem pool. Currently the AP bus mem pool is limited
> to 4 mem pool items of 12KB each. On not being able to process
> a crypto request without memory allocation the result will
> be -ENOMEM returned from the zcrypt_send_cprb_*() functions.
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
See my comments below. Beside that
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
> ---
> drivers/s390/crypto/zcrypt_api.c | 65 +++++++++++++++------------
> drivers/s390/crypto/zcrypt_api.h | 12 ++++-
> drivers/s390/crypto/zcrypt_ccamisc.c | 16 +++----
> drivers/s390/crypto/zcrypt_ep11misc.c | 10 ++---
> 4 files changed, 59 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
> index ce5f7cb974b9..f6deb10329e6 100644
> --- a/drivers/s390/crypto/zcrypt_api.c
> +++ b/drivers/s390/crypto/zcrypt_api.c
> @@ -846,7 +846,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
>
> static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
> struct zcrypt_track *tr,
> - struct ica_xcRB *xcrb)
> + struct ica_xcRB *xcrb, u32 xflags)
This is an internal only API, right? So please either use a bool for the NOMEMALLOC case or move the userspace boolean to the xflags.
> {
> struct zcrypt_card *zc, *pref_zc;
> struct zcrypt_queue *zq, *pref_zq;
> @@ -861,7 +861,8 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
>
> xcrb->status = 0;
>
> - rc = ap_init_apmsg(&ap_msg, 0);
> + rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
> + AP_MSG_FLAG_MEMPOOL : 0);
This is hard to read, because of the line break. I would prefer to have it in a separate line.
u32 ap_flags = flags & ZCRYPT_XFLAG_NOMEMALLOC ? AP_MSG_FLAG_MEMPOOL : 0;
[...]
rc = ap_init_apmsg(&ap_msg, ap_flags);
> if (rc)
> goto out;
>
> @@ -977,7 +978,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
> 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 +986,14 @@ 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(false, &ap_perms, &tr, xcrb, xflags);
> } 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(false, &ap_perms,
> + &tr, xcrb, xflags);
> } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
> if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
> rc = -EIO;
> @@ -1031,11 +1033,11 @@ static bool is_desired_ep11_queue(unsigned int dev_qid,
>
> static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
> struct zcrypt_track *tr,
> - struct ep11_urb *xcrb)
> + struct ep11_urb *xcrb, u32 xflags)
> {
> struct zcrypt_card *zc, *pref_zc;
> struct zcrypt_queue *zq, *pref_zq;
> - struct ep11_target_dev *targets;
> + struct ep11_target_dev targetbuf[16], *targets = NULL;
> unsigned short target_num;
> unsigned int wgt = 0, pref_wgt = 0;
> unsigned int func_code = 0, domain;
> @@ -1045,36 +1047,39 @@ 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, 0);
> + rc = ap_init_apmsg(&ap_msg, xflags & ZCRYPT_XFLAG_NOMEMALLOC ?
> + AP_MSG_FLAG_MEMPOOL : 0);
> if (rc)
> goto out;
>
> target_num = (unsigned short)xcrb->targets_num;
>
> /* empty list indicates autoselect (all available targets) */
> - targets = NULL;
> + rc = -ENOMEM;
> if (target_num != 0) {
> struct ep11_target_dev __user *uptr;
>
> - targets = kcalloc(target_num, sizeof(*targets), GFP_KERNEL);
> - if (!targets) {
> - func_code = 0;
> - rc = -ENOMEM;
> + if (target_num <= ARRAY_SIZE(targetbuf)) {
> + targets = targetbuf;
> + } else if (xflags & ZCRYPT_XFLAG_NOMEMALLOC) {
> goto out;
> + } else {
> + targets = kcalloc(target_num,
> + sizeof(*targets), GFP_KERNEL);
> + if (!targets)
> + goto out;
> }
> -
> uptr = (struct ep11_target_dev __force __user *)xcrb->targets;
> if (z_copy_from_user(userspace, targets, uptr,
> target_num * sizeof(*targets))) {
> - func_code = 0;
> rc = -EFAULT;
> - goto out_free;
> + goto out;
> }
> }
>
> rc = prep_ep11_ap_msg(userspace, xcrb, &ap_msg, &func_code, &domain);
> if (rc)
> - goto out_free;
> + goto out;
> print_hex_dump_debug("ep11req: ", DUMP_PREFIX_ADDRESS, 16, 1,
> ap_msg.msg, ap_msg.len, false);
>
> @@ -1082,11 +1087,11 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
> if (ap_msg.flags & AP_MSG_FLAG_ADMIN) {
> if (!test_bit_inv(domain, perms->adm)) {
> rc = -ENODEV;
> - goto out_free;
> + goto out;
> }
> } else if ((ap_msg.flags & AP_MSG_FLAG_USAGE) == 0) {
> rc = -EOPNOTSUPP;
> - goto out_free;
> + goto out;
> }
> }
>
> @@ -1154,7 +1159,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
> pr_debug("no match for address ff.ffff => ENODEV\n");
> }
> rc = -ENODEV;
> - goto out_free;
> + goto out;
> }
>
> qid = pref_zq->queue->qid;
> @@ -1168,9 +1173,9 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
> zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
> spin_unlock(&zcrypt_list_lock);
>
> -out_free:
> - kfree(targets);
> out:
> + if (targets && targets != targetbuf)
> + kfree(targets);
> ap_release_apmsg(&ap_msg);
> if (tr) {
> tr->last_rc = rc;
> @@ -1181,7 +1186,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
> 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;
> @@ -1189,13 +1194,15 @@ 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(false, &ap_perms,
> + &tr, xcrb, xflags);
> } 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(false, &ap_perms,
> + &tr, xcrb, xflags);
> } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
> if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
> rc = -EIO;
> @@ -1539,13 +1546,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(true, perms, &tr, &xcrb, 0);
> } 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(true, perms, &tr, &xcrb, 0);
> } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
> if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
> rc = -EIO;
> @@ -1569,13 +1576,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(true, perms, &tr, &xcrb, 0);
> } 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(true, perms, &tr, &xcrb, 0);
> } while (rc == -EAGAIN && ++tr.again_counter < TRACK_AGAIN_MAX);
> if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
> rc = -EIO;
> diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
> index 4ed481df57ca..06ff697d171c 100644
> --- a/drivers/s390/crypto/zcrypt_api.h
> +++ b/drivers/s390/crypto/zcrypt_api.h
> @@ -76,6 +76,14 @@ struct zcrypt_track {
> #define TRACK_AGAIN_CARD_WEIGHT_PENALTY 1000
> #define TRACK_AGAIN_QUEUE_WEIGHT_PENALTY 10000
>
> +/*
> + * Do not allocate memory xflag. To be used with
> + * zcrypt_send_cprb() and zcrypt_send_ep11_cprb().
> + * Currently only available and used for the in-kernel
> + * zcrpyt api.
> + */
> +#define ZCRYPT_XFLAG_NOMEMALLOC 0x0001
> +
> struct zcrypt_ops {
> long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *,
> struct ap_message *);
> @@ -161,8 +169,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);
> diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
> index 43a27cb3db84..521baaea06ff 100644
> --- a/drivers/s390/crypto/zcrypt_ccamisc.c
> +++ b/drivers/s390/crypto/zcrypt_ccamisc.c
> @@ -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);
> diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
> index cb7e6da43602..b60e262bcaa3 100644
> --- a/drivers/s390/crypto/zcrypt_ep11misc.c
> +++ b/drivers/s390/crypto/zcrypt_ep11misc.c
> @@ -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);
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2
2025-02-23 9:54 ` [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2 Harald Freudenberger
@ 2025-02-27 11:34 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-02-27 11:34 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> Introduce a new function zcrypt_device_status_mask_ext2().
> This function gives the possibility to provide upper limits
> for cards and queues. The current implementation of
> zcrypt_device_status_mask_ext() needs an array of
> 256 * 256 * 4 = 256 KB which is huge. The new function
> is more flexible in the sense that the caller can decide
> the upper limit for cards and domains to be stored into
> the status array. So for example a caller may decide to
> only query for cards 0...127 and queues 0...127 and thus
> only an array of size 128 * 128 * 4 = 64 KB is needed.
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/zcrypt_api.c | 26 ++++++++++++++++++++++++++
> drivers/s390/crypto/zcrypt_api.h | 2 ++
> 2 files changed, 28 insertions(+)
>
> diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
> index 3a521e65f3fe..fd9666ae1d26 100644
> --- a/drivers/s390/crypto/zcrypt_api.c
> +++ b/drivers/s390/crypto/zcrypt_api.c
> @@ -1330,6 +1330,32 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus)
> }
> EXPORT_SYMBOL(zcrypt_device_status_mask_ext);
>
> +void zcrypt_device_status_mask_ext2(struct zcrypt_device_status_ext *devstatus,
> + int maxcard, int maxqueue)
> +{
> + struct zcrypt_card *zc;
> + struct zcrypt_queue *zq;
> + struct zcrypt_device_status_ext *stat;
> + int card, queue;
> +
> + spin_lock(&zcrypt_list_lock);
> + for_each_zcrypt_card(zc) {
> + for_each_zcrypt_queue(zq, zc) {
> + card = AP_QID_CARD(zq->queue->qid);
> + queue = AP_QID_QUEUE(zq->queue->qid);
> + if (card >= maxcard || queue >= maxqueue)
> + continue;
What about doing a "break" here? Or are the the cards/queues iterated non-linear?
> + stat = &devstatus[card * maxqueue + queue];
> + stat->hwtype = zc->card->ap_dev.device_type;
> + stat->functions = zc->card->hwinfo.fac >> 26;
> + stat->qid = zq->queue->qid;
> + stat->online = zq->online ? 0x01 : 0x00;
> + }
> + }
> + spin_unlock(&zcrypt_list_lock);
> +}
> +EXPORT_SYMBOL(zcrypt_device_status_mask_ext2);
> +
In my opinion, this is a lot of code duplication for an early loop termination. Either extent the zcrypt_device_status_mask_ext() function with the two additional parameters and change all callers to
zcrypt_device_status_mask_ext(... , MAX_ZDEV_CARDIDS, MAX_ZDEV_DOMAINS);
or just implement zcrypt_device_status_mask_ext() as a wrapper to zcrypt_device_status_mask_ext2().
void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus)
{
zcrypt_device_status_ext2(devstatus, MAX_ZDEV_CARDIDS, MAX_ZDEV_DOMAINS);
}
EXPORT_SYMBOL(zcrypt_device_status_mask_ext);
> int zcrypt_device_status_ext(int card, int queue,
> struct zcrypt_device_status_ext *devstat)
> {
> diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
> index 06ff697d171c..92027304f0d8 100644
> --- a/drivers/s390/crypto/zcrypt_api.h
> +++ b/drivers/s390/crypto/zcrypt_api.h
> @@ -172,6 +172,8 @@ void zcrypt_api_exit(void);
> 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);
> +void zcrypt_device_status_mask_ext2(struct zcrypt_device_status_ext *devstatus,
> + int maxcard, int maxqueue);
> int zcrypt_device_status_ext(int card, int queue,
> struct zcrypt_device_status_ext *devstatus);
>
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions
2025-02-23 9:54 ` [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions Harald Freudenberger
@ 2025-03-03 8:07 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-03-03 8:07 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> Intruduce a cprb mempool for the zcrypt cca misc functions
typo: Introduce
> (zcrypt_ccamisc.*) do some preparation rework to support
> a do-not-allocate path through some zcrypt cca misc functions.
>
> This is only part of an rework to support a new xflag
> ZCRYPT_XFLAG_NOMEMALLOC but not jet complete.
typo: yet
See my comment below. Beside that and the typos, looks good to me.
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/zcrypt_api.c | 9 ++-
> drivers/s390/crypto/zcrypt_ccamisc.c | 115 ++++++++++++++++++++-------
> drivers/s390/crypto/zcrypt_ccamisc.h | 1 +
> 3 files changed, 94 insertions(+), 31 deletions(-)
>
[...]
> diff --git a/drivers/s390/crypto/zcrypt_ccamisc.c b/drivers/s390/crypto/zcrypt_ccamisc.c
> index 521baaea06ff..e604a69e40fc 100644
> --- a/drivers/s390/crypto/zcrypt_ccamisc.c
> +++ b/drivers/s390/crypto/zcrypt_ccamisc.c
[...]
> @@ -40,6 +41,17 @@ struct cca_info_list_entry {
> static LIST_HEAD(cca_info_list);
> static DEFINE_SPINLOCK(cca_info_list_lock);
>
> +/*
> + * Cprb memory pool held for urgend cases where no memory
typo: urgent
> + * can be allocated via kmalloc. This pool is only used
> + * when alloc_and_prep_cprbmem() is called with the xflag
> + * ZCRYPT_XFLAG_NOMEMALLOC. The cprb memory needs to hold
> + * space for request AND reply!
> + */
> +#define CPRB_MEMPOOL_MIN_ITEMS 4
4 slots might not be sufficient in setups with a large number of encrypted filesystems. In my opinion, this should be a module parameter (with default 4).
> +#define CPRB_MEMPOOL_ITEM_SIZE (16 * 1024)
> +static mempool_t *cprb_mempool;
> +
> /*
> * Simple check if the token is a valid CCA secure AES data key
> * token. If keybitsize is given, the bitsize of the key is
[...]
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 misc functions
2025-02-23 9:54 ` [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 " Harald Freudenberger
@ 2025-03-03 8:29 ` Holger Dengler
0 siblings, 0 replies; 31+ messages in thread
From: Holger Dengler @ 2025-03-03 8:29 UTC (permalink / raw)
To: Harald Freudenberger, ifranzki, fcallies; +Cc: linux-s390, herbert
On 23/02/2025 10:54, Harald Freudenberger wrote:
> Introduce a cprb mempool for zcrypt ep11 misc functions
> (zcrpyt_ep11misc.*) and do some preparation rework to
> support a do-not-allocate memory path through some
> zcrypt ep11 misc functions.
>
> This is only part one of a rework to support a new xflag
> ZCRYPT_XFLAG_NOMEMALLOC but not jet complete.
typo: yet
See my comment below. Beside that and the typos, it looks good to me.
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> ---
> drivers/s390/crypto/zcrypt_api.c | 6 +
> drivers/s390/crypto/zcrypt_ep11misc.c | 159 ++++++++++++++++----------
> drivers/s390/crypto/zcrypt_ep11misc.h | 1 +
> 3 files changed, 105 insertions(+), 61 deletions(-)
>
[...]
> diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c
> index b60e262bcaa3..3d96bd236c16 100644
> --- a/drivers/s390/crypto/zcrypt_ep11misc.c
> +++ b/drivers/s390/crypto/zcrypt_ep11misc.c
[...]
> @@ -30,6 +31,15 @@
> static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
> 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
>
> +/*
> + * Cprb memory pool held for urgend cases where no memory
typo: urgent
> + * can be allocated via kmalloc. This pool is only used when
> + * alloc_cprbmem() is called with the xflag ZCRYPT_XFLAG_NOMEMALLOC.
> + */
> +#define CPRB_MEMPOOL_MIN_ITEMS 8
Same here as in the previous patch: number of items as module parameter (with default 4).
> +#define CPRB_MEMPOOL_ITEM_SIZE (8 * 1024)
> +static mempool_t *cprb_mempool;
> +
> /* ep11 card info cache */
> struct card_list_entry {
> struct list_head list;
[...]
--
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2025-03-03 8:29 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-23 9:54 [PATCH v1 00/20] AP bus/zcrypt/pkey/paes no-mem-alloc patches Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 01/20] s390/ap: Move response_type struct into ap_msg struct Harald Freudenberger
2025-02-24 15:23 ` Holger Dengler
2025-02-25 7:39 ` Holger Dengler
2025-02-25 8:56 ` Harald Freudenberger
2025-02-25 9:22 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 02/20] s390/ap/zcrypt: Rework AP message buffer allocation Harald Freudenberger
2025-02-25 8:12 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 03/20] s390/ap: Introduce ap message buffer pool Harald Freudenberger
2025-02-25 13:52 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 04/20] s390/zcrypt: Rework zcrypt layer to support new flag NOMEMALLOC Harald Freudenberger
2025-02-27 8:21 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 05/20] s390/zcrypt: Introduce cprb mempool for cca misc functions Harald Freudenberger
2025-03-03 8:07 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 06/20] s390/zcrypt: Introduce cprb mempool for ep11 " Harald Freudenberger
2025-03-03 8:29 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 07/20] s390/zcrypt: New zcrypt function zcrypt_device_status_mask_ext2 Harald Freudenberger
2025-02-27 11:34 ` Holger Dengler
2025-02-23 9:54 ` [PATCH v1 08/20] s390/zcrypt: Introduce pre-allocated device status array for cca misc Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 09/20] s390/zcrypt: Introduce pre-allocated device status array for ep11 misc Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 10/20] s390/zcrypt/pkey: Rework cca findcard() implementation and callers Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 11/20] s390/zcrypt/pkey: Rework ep11 " Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 12/20] s390/zcrypt: Rework cca misc functions kmallocs to use the cprb mempool Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 13/20] s390/zcrypt: Add small mempool for cca info list entries Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 14/20] s390/zcrypt: Locate ep11_domain_query_info onto the stack instead of kmalloc Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 15/20] s390/zcrypt: Rework ep11 misc functions to use cprb mempool Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 16/20] s390/zcrypt: Add small mempool for ep11 card info list entries Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 17/20] s390/pkey: Rework CCA pkey handler to use stack for small memory allocs Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 18/20] s390/pkey: Rework EP11 " Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 19/20] s390/zcrypt/pkey: Provide and pass xflags within pkey and zcrypt layers Harald Freudenberger
2025-02-23 9:54 ` [PATCH v1 20/20] s390/pkey/crypto: Introduce xflags param for pkey in-kernel API Harald Freudenberger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox