xref: /linux/drivers/s390/crypto/pkey_base.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
18fcc231cSHarald Freudenberger // SPDX-License-Identifier: GPL-2.0
28fcc231cSHarald Freudenberger /*
38fcc231cSHarald Freudenberger  *  pkey base: debug feature, pkey handler registry
48fcc231cSHarald Freudenberger  *
58fcc231cSHarald Freudenberger  *  Copyright IBM Corp. 2024
68fcc231cSHarald Freudenberger  */
78fcc231cSHarald Freudenberger 
88fcc231cSHarald Freudenberger #define KMSG_COMPONENT "pkey"
98fcc231cSHarald Freudenberger #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
108fcc231cSHarald Freudenberger 
118fcc231cSHarald Freudenberger #include <linux/cpufeature.h>
128fcc231cSHarald Freudenberger #include <linux/init.h>
138fcc231cSHarald Freudenberger #include <linux/list.h>
148fcc231cSHarald Freudenberger #include <linux/module.h>
158fcc231cSHarald Freudenberger #include <linux/rculist.h>
168fcc231cSHarald Freudenberger 
178fcc231cSHarald Freudenberger #include "pkey_base.h"
188fcc231cSHarald Freudenberger 
198fcc231cSHarald Freudenberger MODULE_LICENSE("GPL");
208fcc231cSHarald Freudenberger MODULE_AUTHOR("IBM Corporation");
218fcc231cSHarald Freudenberger MODULE_DESCRIPTION("s390 protected key base and api");
228fcc231cSHarald Freudenberger 
238fcc231cSHarald Freudenberger /*
248fcc231cSHarald Freudenberger  * pkey debug feature
258fcc231cSHarald Freudenberger  */
268fcc231cSHarald Freudenberger debug_info_t *pkey_dbf_info;
278fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_dbf_info);
288fcc231cSHarald Freudenberger 
298fcc231cSHarald Freudenberger /*
308fcc231cSHarald Freudenberger  * pkey handler registry
318fcc231cSHarald Freudenberger  */
328fcc231cSHarald Freudenberger 
338fcc231cSHarald Freudenberger static DEFINE_SPINLOCK(handler_list_write_lock);
348fcc231cSHarald Freudenberger static LIST_HEAD(handler_list);
358fcc231cSHarald Freudenberger 
pkey_handler_register(struct pkey_handler * handler)368fcc231cSHarald Freudenberger int pkey_handler_register(struct pkey_handler *handler)
378fcc231cSHarald Freudenberger {
388fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
398fcc231cSHarald Freudenberger 
408fcc231cSHarald Freudenberger 	if (!handler ||
418fcc231cSHarald Freudenberger 	    !handler->is_supported_key ||
428fcc231cSHarald Freudenberger 	    !handler->is_supported_keytype)
438fcc231cSHarald Freudenberger 		return -EINVAL;
448fcc231cSHarald Freudenberger 
458fcc231cSHarald Freudenberger 	if (!try_module_get(handler->module))
468fcc231cSHarald Freudenberger 		return -ENXIO;
478fcc231cSHarald Freudenberger 
488fcc231cSHarald Freudenberger 	spin_lock(&handler_list_write_lock);
498fcc231cSHarald Freudenberger 
508fcc231cSHarald Freudenberger 	rcu_read_lock();
518fcc231cSHarald Freudenberger 	list_for_each_entry_rcu(h, &handler_list, list) {
528fcc231cSHarald Freudenberger 		if (h == handler) {
538fcc231cSHarald Freudenberger 			rcu_read_unlock();
548fcc231cSHarald Freudenberger 			spin_unlock(&handler_list_write_lock);
558fcc231cSHarald Freudenberger 			module_put(handler->module);
568fcc231cSHarald Freudenberger 			return -EEXIST;
578fcc231cSHarald Freudenberger 		}
588fcc231cSHarald Freudenberger 	}
598fcc231cSHarald Freudenberger 	rcu_read_unlock();
608fcc231cSHarald Freudenberger 
618fcc231cSHarald Freudenberger 	list_add_rcu(&handler->list, &handler_list);
628fcc231cSHarald Freudenberger 	spin_unlock(&handler_list_write_lock);
638fcc231cSHarald Freudenberger 	synchronize_rcu();
648fcc231cSHarald Freudenberger 
658fcc231cSHarald Freudenberger 	module_put(handler->module);
668fcc231cSHarald Freudenberger 
678fcc231cSHarald Freudenberger 	PKEY_DBF_INFO("%s pkey handler '%s' registered\n", __func__,
688fcc231cSHarald Freudenberger 		      handler->name ?: "<no name>");
698fcc231cSHarald Freudenberger 
708fcc231cSHarald Freudenberger 	return 0;
718fcc231cSHarald Freudenberger }
728fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_register);
738fcc231cSHarald Freudenberger 
pkey_handler_unregister(struct pkey_handler * handler)748fcc231cSHarald Freudenberger int pkey_handler_unregister(struct pkey_handler *handler)
758fcc231cSHarald Freudenberger {
768fcc231cSHarald Freudenberger 	spin_lock(&handler_list_write_lock);
778fcc231cSHarald Freudenberger 	list_del_rcu(&handler->list);
788fcc231cSHarald Freudenberger 	INIT_LIST_HEAD_RCU(&handler->list);
798fcc231cSHarald Freudenberger 	spin_unlock(&handler_list_write_lock);
808fcc231cSHarald Freudenberger 	synchronize_rcu();
818fcc231cSHarald Freudenberger 
828fcc231cSHarald Freudenberger 	PKEY_DBF_INFO("%s pkey handler '%s' unregistered\n", __func__,
838fcc231cSHarald Freudenberger 		      handler->name ?: "<no name>");
848fcc231cSHarald Freudenberger 
858fcc231cSHarald Freudenberger 	return 0;
868fcc231cSHarald Freudenberger }
878fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_unregister);
888fcc231cSHarald Freudenberger 
898fcc231cSHarald Freudenberger /*
908fcc231cSHarald Freudenberger  * Handler invocation functions.
918fcc231cSHarald Freudenberger  */
928fcc231cSHarald Freudenberger 
pkey_handler_get_keybased(const u8 * key,u32 keylen)938fcc231cSHarald Freudenberger const struct pkey_handler *pkey_handler_get_keybased(const u8 *key, u32 keylen)
948fcc231cSHarald Freudenberger {
958fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
968fcc231cSHarald Freudenberger 
978fcc231cSHarald Freudenberger 	rcu_read_lock();
988fcc231cSHarald Freudenberger 	list_for_each_entry_rcu(h, &handler_list, list) {
998fcc231cSHarald Freudenberger 		if (!try_module_get(h->module))
1008fcc231cSHarald Freudenberger 			continue;
1018fcc231cSHarald Freudenberger 		if (h->is_supported_key(key, keylen)) {
1028fcc231cSHarald Freudenberger 			rcu_read_unlock();
1038fcc231cSHarald Freudenberger 			return h;
1048fcc231cSHarald Freudenberger 		}
1058fcc231cSHarald Freudenberger 		module_put(h->module);
1068fcc231cSHarald Freudenberger 	}
1078fcc231cSHarald Freudenberger 	rcu_read_unlock();
1088fcc231cSHarald Freudenberger 
1098fcc231cSHarald Freudenberger 	return NULL;
1108fcc231cSHarald Freudenberger }
1118fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_get_keybased);
1128fcc231cSHarald Freudenberger 
pkey_handler_get_keytypebased(enum pkey_key_type kt)1138fcc231cSHarald Freudenberger const struct pkey_handler *pkey_handler_get_keytypebased(enum pkey_key_type kt)
1148fcc231cSHarald Freudenberger {
1158fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
1168fcc231cSHarald Freudenberger 
1178fcc231cSHarald Freudenberger 	rcu_read_lock();
1188fcc231cSHarald Freudenberger 	list_for_each_entry_rcu(h, &handler_list, list) {
1198fcc231cSHarald Freudenberger 		if (!try_module_get(h->module))
1208fcc231cSHarald Freudenberger 			continue;
1218fcc231cSHarald Freudenberger 		if (h->is_supported_keytype(kt)) {
1228fcc231cSHarald Freudenberger 			rcu_read_unlock();
1238fcc231cSHarald Freudenberger 			return h;
1248fcc231cSHarald Freudenberger 		}
1258fcc231cSHarald Freudenberger 		module_put(h->module);
1268fcc231cSHarald Freudenberger 	}
1278fcc231cSHarald Freudenberger 	rcu_read_unlock();
1288fcc231cSHarald Freudenberger 
1298fcc231cSHarald Freudenberger 	return NULL;
1308fcc231cSHarald Freudenberger }
1318fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_get_keytypebased);
1328fcc231cSHarald Freudenberger 
pkey_handler_put(const struct pkey_handler * handler)1338fcc231cSHarald Freudenberger void pkey_handler_put(const struct pkey_handler *handler)
1348fcc231cSHarald Freudenberger {
1358fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
1368fcc231cSHarald Freudenberger 
1378fcc231cSHarald Freudenberger 	if (!handler)
1388fcc231cSHarald Freudenberger 		return;
1398fcc231cSHarald Freudenberger 
1408fcc231cSHarald Freudenberger 	rcu_read_lock();
1418fcc231cSHarald Freudenberger 	list_for_each_entry_rcu(h, &handler_list, list) {
1428fcc231cSHarald Freudenberger 		if (h == handler) {
1438fcc231cSHarald Freudenberger 			module_put(h->module);
1448fcc231cSHarald Freudenberger 			break;
1458fcc231cSHarald Freudenberger 		}
1468fcc231cSHarald Freudenberger 	}
1478fcc231cSHarald Freudenberger 	rcu_read_unlock();
1488fcc231cSHarald Freudenberger }
1498fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_put);
1508fcc231cSHarald Freudenberger 
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)1518fcc231cSHarald Freudenberger int pkey_handler_key_to_protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
1528fcc231cSHarald Freudenberger 				const u8 *key, u32 keylen,
1538fcc231cSHarald Freudenberger 				u8 *protkey, u32 *protkeylen, u32 *protkeytype)
1548fcc231cSHarald Freudenberger {
1558fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
1568fcc231cSHarald Freudenberger 	int rc = -ENODEV;
1578fcc231cSHarald Freudenberger 
1588fcc231cSHarald Freudenberger 	h = pkey_handler_get_keybased(key, keylen);
1598fcc231cSHarald Freudenberger 	if (h && h->key_to_protkey) {
1608fcc231cSHarald Freudenberger 		rc = h->key_to_protkey(apqns, nr_apqns, key, keylen,
1618fcc231cSHarald Freudenberger 				       protkey, protkeylen,
1628fcc231cSHarald Freudenberger 				       protkeytype);
1638fcc231cSHarald Freudenberger 	}
1648fcc231cSHarald Freudenberger 	pkey_handler_put(h);
1658fcc231cSHarald Freudenberger 
1668fcc231cSHarald Freudenberger 	return rc;
1678fcc231cSHarald Freudenberger }
1688fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_key_to_protkey);
1698fcc231cSHarald Freudenberger 
1702fc401b9SHarald Freudenberger /*
1712fc401b9SHarald Freudenberger  * This handler invocation is special as there may be more than
1722fc401b9SHarald Freudenberger  * one handler providing support for the very same key (type).
1732fc401b9SHarald Freudenberger  * And the handler may not respond true on is_supported_key(),
1742fc401b9SHarald Freudenberger  * so simple try and check return value here.
1752fc401b9SHarald Freudenberger  */
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)1762fc401b9SHarald Freudenberger int pkey_handler_slowpath_key_to_protkey(const struct pkey_apqn *apqns,
1772fc401b9SHarald Freudenberger 					 size_t nr_apqns,
1782fc401b9SHarald Freudenberger 					 const u8 *key, u32 keylen,
1792fc401b9SHarald Freudenberger 					 u8 *protkey, u32 *protkeylen,
1802fc401b9SHarald Freudenberger 					 u32 *protkeytype)
1812fc401b9SHarald Freudenberger {
1822fc401b9SHarald Freudenberger 	const struct pkey_handler *h, *htmp[10];
1832fc401b9SHarald Freudenberger 	int i, n = 0, rc = -ENODEV;
1842fc401b9SHarald Freudenberger 
1852fc401b9SHarald Freudenberger 	rcu_read_lock();
1862fc401b9SHarald Freudenberger 	list_for_each_entry_rcu(h, &handler_list, list) {
1872fc401b9SHarald Freudenberger 		if (!try_module_get(h->module))
1882fc401b9SHarald Freudenberger 			continue;
1892fc401b9SHarald Freudenberger 		if (h->slowpath_key_to_protkey && n < ARRAY_SIZE(htmp))
1902fc401b9SHarald Freudenberger 			htmp[n++] = h;
1912fc401b9SHarald Freudenberger 		else
1922fc401b9SHarald Freudenberger 			module_put(h->module);
1932fc401b9SHarald Freudenberger 	}
1942fc401b9SHarald Freudenberger 	rcu_read_unlock();
1952fc401b9SHarald Freudenberger 
1962fc401b9SHarald Freudenberger 	for (i = 0; i < n; i++) {
1972fc401b9SHarald Freudenberger 		h = htmp[i];
1982fc401b9SHarald Freudenberger 		if (rc)
1992fc401b9SHarald Freudenberger 			rc = h->slowpath_key_to_protkey(apqns, nr_apqns,
2002fc401b9SHarald Freudenberger 							key, keylen,
2012fc401b9SHarald Freudenberger 							protkey, protkeylen,
2022fc401b9SHarald Freudenberger 							protkeytype);
2032fc401b9SHarald Freudenberger 		module_put(h->module);
2042fc401b9SHarald Freudenberger 	}
2052fc401b9SHarald Freudenberger 
2062fc401b9SHarald Freudenberger 	return rc;
2072fc401b9SHarald Freudenberger }
2082fc401b9SHarald Freudenberger EXPORT_SYMBOL(pkey_handler_slowpath_key_to_protkey);
2092fc401b9SHarald Freudenberger 
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)2108fcc231cSHarald Freudenberger int pkey_handler_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
2118fcc231cSHarald Freudenberger 			 u32 keytype, u32 keysubtype,
2128fcc231cSHarald Freudenberger 			 u32 keybitsize, u32 flags,
2138fcc231cSHarald Freudenberger 			 u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
2148fcc231cSHarald Freudenberger {
2158fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
2168fcc231cSHarald Freudenberger 	int rc = -ENODEV;
2178fcc231cSHarald Freudenberger 
2188fcc231cSHarald Freudenberger 	h = pkey_handler_get_keytypebased(keysubtype);
2198fcc231cSHarald Freudenberger 	if (h && h->gen_key) {
2208fcc231cSHarald Freudenberger 		rc = h->gen_key(apqns, nr_apqns, keytype, keysubtype,
2218fcc231cSHarald Freudenberger 				keybitsize, flags,
2228fcc231cSHarald Freudenberger 				keybuf, keybuflen, keyinfo);
2238fcc231cSHarald Freudenberger 	}
2248fcc231cSHarald Freudenberger 	pkey_handler_put(h);
2258fcc231cSHarald Freudenberger 
2268fcc231cSHarald Freudenberger 	return rc;
2278fcc231cSHarald Freudenberger }
2288fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_gen_key);
2298fcc231cSHarald Freudenberger 
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)2308fcc231cSHarald Freudenberger int pkey_handler_clr_to_key(const struct pkey_apqn *apqns, size_t nr_apqns,
2318fcc231cSHarald Freudenberger 			    u32 keytype, u32 keysubtype,
2328fcc231cSHarald Freudenberger 			    u32 keybitsize, u32 flags,
2338fcc231cSHarald Freudenberger 			    const u8 *clrkey, u32 clrkeylen,
2348fcc231cSHarald Freudenberger 			    u8 *keybuf, u32 *keybuflen, u32 *keyinfo)
2358fcc231cSHarald Freudenberger {
2368fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
2378fcc231cSHarald Freudenberger 	int rc = -ENODEV;
2388fcc231cSHarald Freudenberger 
2398fcc231cSHarald Freudenberger 	h = pkey_handler_get_keytypebased(keysubtype);
2408fcc231cSHarald Freudenberger 	if (h && h->clr_to_key) {
2418fcc231cSHarald Freudenberger 		rc = h->clr_to_key(apqns, nr_apqns, keytype, keysubtype,
2428fcc231cSHarald Freudenberger 				   keybitsize, flags, clrkey, clrkeylen,
2438fcc231cSHarald Freudenberger 				   keybuf, keybuflen, keyinfo);
2448fcc231cSHarald Freudenberger 	}
2458fcc231cSHarald Freudenberger 	pkey_handler_put(h);
2468fcc231cSHarald Freudenberger 
2478fcc231cSHarald Freudenberger 	return rc;
2488fcc231cSHarald Freudenberger }
2498fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_clr_to_key);
2508fcc231cSHarald Freudenberger 
pkey_handler_verify_key(const u8 * key,u32 keylen,u16 * card,u16 * dom,u32 * keytype,u32 * keybitsize,u32 * flags)2518fcc231cSHarald Freudenberger int pkey_handler_verify_key(const u8 *key, u32 keylen,
2528fcc231cSHarald Freudenberger 			    u16 *card, u16 *dom,
2538fcc231cSHarald Freudenberger 			    u32 *keytype, u32 *keybitsize, u32 *flags)
2548fcc231cSHarald Freudenberger {
2558fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
2568fcc231cSHarald Freudenberger 	int rc = -ENODEV;
2578fcc231cSHarald Freudenberger 
2588fcc231cSHarald Freudenberger 	h = pkey_handler_get_keybased(key, keylen);
2598fcc231cSHarald Freudenberger 	if (h && h->verify_key) {
2608fcc231cSHarald Freudenberger 		rc = h->verify_key(key, keylen, card, dom,
2618fcc231cSHarald Freudenberger 				   keytype, keybitsize, flags);
2628fcc231cSHarald Freudenberger 	}
2638fcc231cSHarald Freudenberger 	pkey_handler_put(h);
2648fcc231cSHarald Freudenberger 
2658fcc231cSHarald Freudenberger 	return rc;
2668fcc231cSHarald Freudenberger }
2678fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_verify_key);
2688fcc231cSHarald Freudenberger 
pkey_handler_apqns_for_key(const u8 * key,u32 keylen,u32 flags,struct pkey_apqn * apqns,size_t * nr_apqns)2698fcc231cSHarald Freudenberger int pkey_handler_apqns_for_key(const u8 *key, u32 keylen, u32 flags,
2708fcc231cSHarald Freudenberger 			       struct pkey_apqn *apqns, size_t *nr_apqns)
2718fcc231cSHarald Freudenberger {
2728fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
2738fcc231cSHarald Freudenberger 	int rc = -ENODEV;
2748fcc231cSHarald Freudenberger 
2758fcc231cSHarald Freudenberger 	h = pkey_handler_get_keybased(key, keylen);
2768fcc231cSHarald Freudenberger 	if (h && h->apqns_for_key)
2778fcc231cSHarald Freudenberger 		rc = h->apqns_for_key(key, keylen, flags, apqns, nr_apqns);
2788fcc231cSHarald Freudenberger 	pkey_handler_put(h);
2798fcc231cSHarald Freudenberger 
2808fcc231cSHarald Freudenberger 	return rc;
2818fcc231cSHarald Freudenberger }
2828fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_apqns_for_key);
2838fcc231cSHarald Freudenberger 
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)2848fcc231cSHarald Freudenberger int pkey_handler_apqns_for_keytype(enum pkey_key_type keysubtype,
2858fcc231cSHarald Freudenberger 				   u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
2868fcc231cSHarald Freudenberger 				   struct pkey_apqn *apqns, size_t *nr_apqns)
2878fcc231cSHarald Freudenberger {
2888fcc231cSHarald Freudenberger 	const struct pkey_handler *h;
2898fcc231cSHarald Freudenberger 	int rc = -ENODEV;
2908fcc231cSHarald Freudenberger 
2918fcc231cSHarald Freudenberger 	h = pkey_handler_get_keytypebased(keysubtype);
2928fcc231cSHarald Freudenberger 	if (h && h->apqns_for_keytype) {
2938fcc231cSHarald Freudenberger 		rc = h->apqns_for_keytype(keysubtype,
2948fcc231cSHarald Freudenberger 					  cur_mkvp, alt_mkvp, flags,
2958fcc231cSHarald Freudenberger 					  apqns, nr_apqns);
2968fcc231cSHarald Freudenberger 	}
2978fcc231cSHarald Freudenberger 	pkey_handler_put(h);
2988fcc231cSHarald Freudenberger 
2998fcc231cSHarald Freudenberger 	return rc;
3008fcc231cSHarald Freudenberger }
3018fcc231cSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_apqns_for_keytype);
3028fcc231cSHarald Freudenberger 
pkey_handler_request_modules(void)303*177b621bSHarald Freudenberger void pkey_handler_request_modules(void)
304*177b621bSHarald Freudenberger {
305*177b621bSHarald Freudenberger #ifdef CONFIG_MODULES
306*177b621bSHarald Freudenberger 	static const char * const pkey_handler_modules[] = {
307*177b621bSHarald Freudenberger 		"pkey_cca", "pkey_ep11", "pkey_pckmo" };
308*177b621bSHarald Freudenberger 	int i;
309*177b621bSHarald Freudenberger 
310*177b621bSHarald Freudenberger 	for (i = 0; i < ARRAY_SIZE(pkey_handler_modules); i++) {
311*177b621bSHarald Freudenberger 		const struct pkey_handler *h;
312*177b621bSHarald Freudenberger 		bool found = false;
313*177b621bSHarald Freudenberger 
314*177b621bSHarald Freudenberger 		rcu_read_lock();
315*177b621bSHarald Freudenberger 		list_for_each_entry_rcu(h, &handler_list, list) {
316*177b621bSHarald Freudenberger 			if (h->module &&
317*177b621bSHarald Freudenberger 			    !strcmp(h->module->name, pkey_handler_modules[i])) {
318*177b621bSHarald Freudenberger 				found = true;
319*177b621bSHarald Freudenberger 				break;
320*177b621bSHarald Freudenberger 			}
321*177b621bSHarald Freudenberger 		}
322*177b621bSHarald Freudenberger 		rcu_read_unlock();
323*177b621bSHarald Freudenberger 		if (!found) {
324*177b621bSHarald Freudenberger 			pr_debug("request_module(%s)\n", pkey_handler_modules[i]);
325*177b621bSHarald Freudenberger 			request_module(pkey_handler_modules[i]);
326*177b621bSHarald Freudenberger 		}
327*177b621bSHarald Freudenberger 	}
328*177b621bSHarald Freudenberger #endif
329*177b621bSHarald Freudenberger }
330*177b621bSHarald Freudenberger EXPORT_SYMBOL(pkey_handler_request_modules);
331*177b621bSHarald Freudenberger 
3328fcc231cSHarald Freudenberger /*
3338fcc231cSHarald Freudenberger  * Module init
3348fcc231cSHarald Freudenberger  */
pkey_init(void)3358fcc231cSHarald Freudenberger static int __init pkey_init(void)
3368fcc231cSHarald Freudenberger {
3378fcc231cSHarald Freudenberger 	int rc;
3388fcc231cSHarald Freudenberger 
3398fcc231cSHarald Freudenberger 	/* init debug feature */
3408fcc231cSHarald Freudenberger 	pkey_dbf_info = debug_register("pkey", 1, 1, 5 * sizeof(long));
3418fcc231cSHarald Freudenberger 	debug_register_view(pkey_dbf_info, &debug_sprintf_view);
3428fcc231cSHarald Freudenberger 	debug_set_level(pkey_dbf_info, 4);
3438fcc231cSHarald Freudenberger 
3448fcc231cSHarald Freudenberger 	/* the handler registry does not need any init */
3458fcc231cSHarald Freudenberger 
3468fcc231cSHarald Freudenberger 	rc = pkey_api_init();
3478fcc231cSHarald Freudenberger 	if (rc)
3488fcc231cSHarald Freudenberger 		debug_unregister(pkey_dbf_info);
3498fcc231cSHarald Freudenberger 
3508fcc231cSHarald Freudenberger 	return rc;
3518fcc231cSHarald Freudenberger }
3528fcc231cSHarald Freudenberger 
3538fcc231cSHarald Freudenberger /*
3548fcc231cSHarald Freudenberger  * Module exit
3558fcc231cSHarald Freudenberger  */
pkey_exit(void)3568fcc231cSHarald Freudenberger static void __exit pkey_exit(void)
3578fcc231cSHarald Freudenberger {
3588fcc231cSHarald Freudenberger 	pkey_api_exit();
3598fcc231cSHarald Freudenberger }
3608fcc231cSHarald Freudenberger 
3618fcc231cSHarald Freudenberger module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init);
3628fcc231cSHarald Freudenberger module_exit(pkey_exit);
363