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