Skip to content

Commit dcc160b

Browse files
hfreudehcahca
authored andcommitted
s390/ap: Introduce ap message buffer pool
There is a need for a do-not-allocate-memory path through the AP bus layer. The pkey layer may be triggered via the in-kernel interface from a protected key crypto algorithm (namely PAES) to convert a secure key into a protected key. This happens in a workqueue context, so sleeping is allowed but memory allocations causing IO operations are not permitted. To accomplish this, an AP message memory pool with pre-allocated space is established. When ap_init_apmsg() with use_mempool set to true 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 use_mempool arg set to true is called. When this pool is exhausted and use_mempool is set true, ap_init_apmsg() returns -ENOMEM without any attempt to allocate memory and the caller has to deal with that. Default values for this mempool of ap messages is: * Each buffer is 12KB (that is the default AP bus size and all the urgent messages should fit into this space). * Minimum items held in the pool is 8. This value is adjustable via module parameter ap.msgpool_min_items. The zcrypt layer may use this flag to indicate to the ap bus that the processing path for this message should not allocate memory but should use pre-allocated memory buffer instead. This is to prevent deadlocks with crypto and io for example with encrypted swap volumes. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Link: https://lore.kernel.org/r/20250424133619.16495-4-freude@linux.ibm.com Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 57db62a commit dcc160b

3 files changed

Lines changed: 58 additions & 9 deletions

File tree

drivers/s390/crypto/ap_bus.c

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/module.h>
4242
#include <asm/uv.h>
4343
#include <asm/chsc.h>
44+
#include <linux/mempool.h>
4445

4546
#include "ap_bus.h"
4647
#include "ap_debug.h"
@@ -102,6 +103,27 @@ static struct ap_config_info *const ap_qci_info_old = &qci[1];
102103
*/
103104
debug_info_t *ap_dbf_info;
104105

106+
/*
107+
* There is a need for a do-not-allocate-memory path through the AP bus
108+
* layer. The pkey layer may be triggered via the in-kernel interface from
109+
* a protected key crypto algorithm (namely PAES) to convert a secure key
110+
* into a protected key. This happens in a workqueue context, so sleeping
111+
* is allowed but memory allocations causing IO operations are not permitted.
112+
* To accomplish this, an AP message memory pool with pre-allocated space
113+
* is established. When ap_init_apmsg() with use_mempool set to true is
114+
* called, instead of kmalloc() the ap message buffer is allocated from
115+
* the ap_msg_pool. This pool only holds a limited amount of buffers:
116+
* ap_msg_pool_min_items with the item size AP_DEFAULT_MAX_MSG_SIZE and
117+
* exactly one of these items (if available) is returned if ap_init_apmsg()
118+
* with the use_mempool arg set to true is called. When this pool is exhausted
119+
* and use_mempool is set true, ap_init_apmsg() returns -ENOMEM without
120+
* any attempt to allocate memory and the caller has to deal with that.
121+
*/
122+
static mempool_t *ap_msg_pool;
123+
static unsigned int ap_msg_pool_min_items = 8;
124+
module_param_named(msgpool_min_items, ap_msg_pool_min_items, uint, 0440);
125+
MODULE_PARM_DESC(msgpool_min_items, "AP message pool minimal items");
126+
105127
/*
106128
* AP bus rescan related things.
107129
*/
@@ -550,11 +572,22 @@ static void ap_poll_thread_stop(void)
550572
/*
551573
* ap_init_apmsg() - Initialize ap_message.
552574
*/
553-
int ap_init_apmsg(struct ap_message *ap_msg)
575+
int ap_init_apmsg(struct ap_message *ap_msg, bool use_mempool)
554576
{
555-
unsigned int maxmsgsize = atomic_read(&ap_max_msg_size);
577+
unsigned int maxmsgsize;
556578

557579
memset(ap_msg, 0, sizeof(*ap_msg));
580+
581+
if (use_mempool) {
582+
ap_msg->msg = mempool_alloc_preallocated(ap_msg_pool);
583+
if (!ap_msg->msg)
584+
return -ENOMEM;
585+
ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
586+
ap_msg->flags |= AP_MSG_FLAG_MEMPOOL;
587+
return 0;
588+
}
589+
590+
maxmsgsize = atomic_read(&ap_max_msg_size);
558591
ap_msg->msg = kmalloc(maxmsgsize, GFP_KERNEL);
559592
if (!ap_msg->msg)
560593
return -ENOMEM;
@@ -569,7 +602,12 @@ EXPORT_SYMBOL(ap_init_apmsg);
569602
*/
570603
void ap_release_apmsg(struct ap_message *ap_msg)
571604
{
572-
kfree_sensitive(ap_msg->msg);
605+
if (ap_msg->flags & AP_MSG_FLAG_MEMPOOL) {
606+
memzero_explicit(ap_msg->msg, ap_msg->bufsize);
607+
mempool_free(ap_msg->msg, ap_msg_pool);
608+
} else {
609+
kfree_sensitive(ap_msg->msg);
610+
}
573611
}
574612
EXPORT_SYMBOL(ap_release_apmsg);
575613

@@ -2457,6 +2495,14 @@ static int __init ap_module_init(void)
24572495
/* init ap_queue hashtable */
24582496
hash_init(ap_queues);
24592497

2498+
/* create ap msg buffer memory pool */
2499+
ap_msg_pool = mempool_create_kmalloc_pool(ap_msg_pool_min_items,
2500+
AP_DEFAULT_MAX_MSG_SIZE);
2501+
if (!ap_msg_pool) {
2502+
rc = -ENOMEM;
2503+
goto out;
2504+
}
2505+
24602506
/* set up the AP permissions (ioctls, ap and aq masks) */
24612507
ap_perms_init();
24622508

@@ -2503,6 +2549,7 @@ static int __init ap_module_init(void)
25032549
out_bus:
25042550
bus_unregister(&ap_bus_type);
25052551
out:
2552+
mempool_destroy(ap_msg_pool);
25062553
ap_debug_exit();
25072554
return rc;
25082555
}
@@ -2513,6 +2560,7 @@ static void __exit ap_module_exit(void)
25132560
ap_irq_exit();
25142561
root_device_unregister(ap_root_device);
25152562
bus_unregister(&ap_bus_type);
2563+
mempool_destroy(ap_msg_pool);
25162564
ap_debug_exit();
25172565
}
25182566

drivers/s390/crypto/ap_bus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ struct ap_message {
236236
#define AP_MSG_FLAG_SPECIAL 0x0001 /* flag msg as 'special' with NQAP */
237237
#define AP_MSG_FLAG_USAGE 0x0002 /* CCA, EP11: usage (no admin) msg */
238238
#define AP_MSG_FLAG_ADMIN 0x0004 /* CCA, EP11: admin (=control) msg */
239+
#define AP_MSG_FLAG_MEMPOOL 0x0008 /* ap msg buffer allocated via mempool */
239240

240-
int ap_init_apmsg(struct ap_message *ap_msg);
241+
int ap_init_apmsg(struct ap_message *ap_msg, bool use_mempool);
241242
void ap_release_apmsg(struct ap_message *ap_msg);
242243

243244
enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);

drivers/s390/crypto/zcrypt_api.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,7 @@ static long zcrypt_rsa_modexpo(struct ap_perms *perms,
648648

649649
trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO);
650650

651-
rc = ap_init_apmsg(&ap_msg);
651+
rc = ap_init_apmsg(&ap_msg, false);
652652
if (rc)
653653
goto out;
654654

@@ -753,7 +753,7 @@ static long zcrypt_rsa_crt(struct ap_perms *perms,
753753

754754
trace_s390_zcrypt_req(crt, TP_ICARSACRT);
755755

756-
rc = ap_init_apmsg(&ap_msg);
756+
rc = ap_init_apmsg(&ap_msg, false);
757757
if (rc)
758758
goto out;
759759

@@ -861,7 +861,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
861861

862862
xcrb->status = 0;
863863

864-
rc = ap_init_apmsg(&ap_msg);
864+
rc = ap_init_apmsg(&ap_msg, false);
865865
if (rc)
866866
goto out;
867867

@@ -1045,7 +1045,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
10451045

10461046
trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);
10471047

1048-
rc = ap_init_apmsg(&ap_msg);
1048+
rc = ap_init_apmsg(&ap_msg, false);
10491049
if (rc)
10501050
goto out;
10511051

@@ -1219,7 +1219,7 @@ static long zcrypt_rng(char *buffer)
12191219

12201220
trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
12211221

1222-
rc = ap_init_apmsg(&ap_msg);
1222+
rc = ap_init_apmsg(&ap_msg, false);
12231223
if (rc)
12241224
goto out;
12251225
rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);

0 commit comments

Comments
 (0)