1*9c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22bf9e0abSIngo Molnar /*
32bf9e0abSIngo Molnar * Kernel module for testing static keys.
42bf9e0abSIngo Molnar *
52bf9e0abSIngo Molnar * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
62bf9e0abSIngo Molnar *
72bf9e0abSIngo Molnar * Authors:
82bf9e0abSIngo Molnar * Jason Baron <jbaron@akamai.com>
92bf9e0abSIngo Molnar */
102bf9e0abSIngo Molnar
112bf9e0abSIngo Molnar #include <linux/module.h>
122bf9e0abSIngo Molnar #include <linux/jump_label.h>
132bf9e0abSIngo Molnar
142bf9e0abSIngo Molnar /* old keys */
152bf9e0abSIngo Molnar struct static_key old_true_key = STATIC_KEY_INIT_TRUE;
162bf9e0abSIngo Molnar struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
172bf9e0abSIngo Molnar
182bf9e0abSIngo Molnar /* new api */
192bf9e0abSIngo Molnar DEFINE_STATIC_KEY_TRUE(true_key);
202bf9e0abSIngo Molnar DEFINE_STATIC_KEY_FALSE(false_key);
212bf9e0abSIngo Molnar
222bf9e0abSIngo Molnar /* external */
232bf9e0abSIngo Molnar extern struct static_key base_old_true_key;
242bf9e0abSIngo Molnar extern struct static_key base_inv_old_true_key;
252bf9e0abSIngo Molnar extern struct static_key base_old_false_key;
262bf9e0abSIngo Molnar extern struct static_key base_inv_old_false_key;
272bf9e0abSIngo Molnar
282bf9e0abSIngo Molnar /* new api */
292bf9e0abSIngo Molnar extern struct static_key_true base_true_key;
302bf9e0abSIngo Molnar extern struct static_key_true base_inv_true_key;
312bf9e0abSIngo Molnar extern struct static_key_false base_false_key;
322bf9e0abSIngo Molnar extern struct static_key_false base_inv_false_key;
332bf9e0abSIngo Molnar
342bf9e0abSIngo Molnar
352bf9e0abSIngo Molnar struct test_key {
362bf9e0abSIngo Molnar bool init_state;
372bf9e0abSIngo Molnar struct static_key *key;
382bf9e0abSIngo Molnar bool (*test_key)(void);
392bf9e0abSIngo Molnar };
402bf9e0abSIngo Molnar
412bf9e0abSIngo Molnar #define test_key_func(key, branch) \
42975db45eSArnd Bergmann static bool key ## _ ## branch(void) \
43975db45eSArnd Bergmann { \
44975db45eSArnd Bergmann return branch(&key); \
45975db45eSArnd Bergmann }
462bf9e0abSIngo Molnar
invert_key(struct static_key * key)472bf9e0abSIngo Molnar static void invert_key(struct static_key *key)
482bf9e0abSIngo Molnar {
492bf9e0abSIngo Molnar if (static_key_enabled(key))
502bf9e0abSIngo Molnar static_key_disable(key);
512bf9e0abSIngo Molnar else
522bf9e0abSIngo Molnar static_key_enable(key);
532bf9e0abSIngo Molnar }
542bf9e0abSIngo Molnar
invert_keys(struct test_key * keys,int size)552bf9e0abSIngo Molnar static void invert_keys(struct test_key *keys, int size)
562bf9e0abSIngo Molnar {
572bf9e0abSIngo Molnar struct static_key *previous = NULL;
582bf9e0abSIngo Molnar int i;
592bf9e0abSIngo Molnar
602bf9e0abSIngo Molnar for (i = 0; i < size; i++) {
612bf9e0abSIngo Molnar if (previous != keys[i].key) {
622bf9e0abSIngo Molnar invert_key(keys[i].key);
632bf9e0abSIngo Molnar previous = keys[i].key;
642bf9e0abSIngo Molnar }
652bf9e0abSIngo Molnar }
662bf9e0abSIngo Molnar }
672bf9e0abSIngo Molnar
verify_keys(struct test_key * keys,int size,bool invert)6820f9ed15Skbuild test robot static int verify_keys(struct test_key *keys, int size, bool invert)
692bf9e0abSIngo Molnar {
702bf9e0abSIngo Molnar int i;
712bf9e0abSIngo Molnar bool ret, init;
722bf9e0abSIngo Molnar
732bf9e0abSIngo Molnar for (i = 0; i < size; i++) {
742bf9e0abSIngo Molnar ret = static_key_enabled(keys[i].key);
752bf9e0abSIngo Molnar init = keys[i].init_state;
762bf9e0abSIngo Molnar if (ret != (invert ? !init : init))
772bf9e0abSIngo Molnar return -EINVAL;
782bf9e0abSIngo Molnar ret = keys[i].test_key();
792bf9e0abSIngo Molnar if (static_key_enabled(keys[i].key)) {
802bf9e0abSIngo Molnar if (!ret)
812bf9e0abSIngo Molnar return -EINVAL;
822bf9e0abSIngo Molnar } else {
832bf9e0abSIngo Molnar if (ret)
842bf9e0abSIngo Molnar return -EINVAL;
852bf9e0abSIngo Molnar }
862bf9e0abSIngo Molnar }
872bf9e0abSIngo Molnar return 0;
882bf9e0abSIngo Molnar }
892bf9e0abSIngo Molnar
test_key_func(old_true_key,static_key_true)90975db45eSArnd Bergmann test_key_func(old_true_key, static_key_true)
91975db45eSArnd Bergmann test_key_func(old_false_key, static_key_false)
92975db45eSArnd Bergmann test_key_func(true_key, static_branch_likely)
93975db45eSArnd Bergmann test_key_func(true_key, static_branch_unlikely)
94975db45eSArnd Bergmann test_key_func(false_key, static_branch_likely)
95975db45eSArnd Bergmann test_key_func(false_key, static_branch_unlikely)
96975db45eSArnd Bergmann test_key_func(base_old_true_key, static_key_true)
97975db45eSArnd Bergmann test_key_func(base_inv_old_true_key, static_key_true)
98975db45eSArnd Bergmann test_key_func(base_old_false_key, static_key_false)
99975db45eSArnd Bergmann test_key_func(base_inv_old_false_key, static_key_false)
100975db45eSArnd Bergmann test_key_func(base_true_key, static_branch_likely)
101975db45eSArnd Bergmann test_key_func(base_true_key, static_branch_unlikely)
102975db45eSArnd Bergmann test_key_func(base_inv_true_key, static_branch_likely)
103975db45eSArnd Bergmann test_key_func(base_inv_true_key, static_branch_unlikely)
104975db45eSArnd Bergmann test_key_func(base_false_key, static_branch_likely)
105975db45eSArnd Bergmann test_key_func(base_false_key, static_branch_unlikely)
106975db45eSArnd Bergmann test_key_func(base_inv_false_key, static_branch_likely)
107975db45eSArnd Bergmann test_key_func(base_inv_false_key, static_branch_unlikely)
108975db45eSArnd Bergmann
1092bf9e0abSIngo Molnar static int __init test_static_key_init(void)
1102bf9e0abSIngo Molnar {
1112bf9e0abSIngo Molnar int ret;
1122bf9e0abSIngo Molnar int size;
1132bf9e0abSIngo Molnar
1142bf9e0abSIngo Molnar struct test_key static_key_tests[] = {
1152bf9e0abSIngo Molnar /* internal keys - old keys */
1162bf9e0abSIngo Molnar {
1172bf9e0abSIngo Molnar .init_state = true,
1182bf9e0abSIngo Molnar .key = &old_true_key,
119975db45eSArnd Bergmann .test_key = &old_true_key_static_key_true,
1202bf9e0abSIngo Molnar },
1212bf9e0abSIngo Molnar {
1222bf9e0abSIngo Molnar .init_state = false,
1232bf9e0abSIngo Molnar .key = &old_false_key,
124975db45eSArnd Bergmann .test_key = &old_false_key_static_key_false,
1252bf9e0abSIngo Molnar },
1262bf9e0abSIngo Molnar /* internal keys - new keys */
1272bf9e0abSIngo Molnar {
1282bf9e0abSIngo Molnar .init_state = true,
1292bf9e0abSIngo Molnar .key = &true_key.key,
130975db45eSArnd Bergmann .test_key = &true_key_static_branch_likely,
1312bf9e0abSIngo Molnar },
1322bf9e0abSIngo Molnar {
1332bf9e0abSIngo Molnar .init_state = true,
1342bf9e0abSIngo Molnar .key = &true_key.key,
135975db45eSArnd Bergmann .test_key = &true_key_static_branch_unlikely,
1362bf9e0abSIngo Molnar },
1372bf9e0abSIngo Molnar {
1382bf9e0abSIngo Molnar .init_state = false,
1392bf9e0abSIngo Molnar .key = &false_key.key,
140975db45eSArnd Bergmann .test_key = &false_key_static_branch_likely,
1412bf9e0abSIngo Molnar },
1422bf9e0abSIngo Molnar {
1432bf9e0abSIngo Molnar .init_state = false,
1442bf9e0abSIngo Molnar .key = &false_key.key,
145975db45eSArnd Bergmann .test_key = &false_key_static_branch_unlikely,
1462bf9e0abSIngo Molnar },
1472bf9e0abSIngo Molnar /* external keys - old keys */
1482bf9e0abSIngo Molnar {
1492bf9e0abSIngo Molnar .init_state = true,
1502bf9e0abSIngo Molnar .key = &base_old_true_key,
151975db45eSArnd Bergmann .test_key = &base_old_true_key_static_key_true,
1522bf9e0abSIngo Molnar },
1532bf9e0abSIngo Molnar {
1542bf9e0abSIngo Molnar .init_state = false,
1552bf9e0abSIngo Molnar .key = &base_inv_old_true_key,
156975db45eSArnd Bergmann .test_key = &base_inv_old_true_key_static_key_true,
1572bf9e0abSIngo Molnar },
1582bf9e0abSIngo Molnar {
1592bf9e0abSIngo Molnar .init_state = false,
1602bf9e0abSIngo Molnar .key = &base_old_false_key,
161975db45eSArnd Bergmann .test_key = &base_old_false_key_static_key_false,
1622bf9e0abSIngo Molnar },
1632bf9e0abSIngo Molnar {
1642bf9e0abSIngo Molnar .init_state = true,
1652bf9e0abSIngo Molnar .key = &base_inv_old_false_key,
166975db45eSArnd Bergmann .test_key = &base_inv_old_false_key_static_key_false,
1672bf9e0abSIngo Molnar },
1682bf9e0abSIngo Molnar /* external keys - new keys */
1692bf9e0abSIngo Molnar {
1702bf9e0abSIngo Molnar .init_state = true,
1712bf9e0abSIngo Molnar .key = &base_true_key.key,
172975db45eSArnd Bergmann .test_key = &base_true_key_static_branch_likely,
1732bf9e0abSIngo Molnar },
1742bf9e0abSIngo Molnar {
1752bf9e0abSIngo Molnar .init_state = true,
1762bf9e0abSIngo Molnar .key = &base_true_key.key,
177975db45eSArnd Bergmann .test_key = &base_true_key_static_branch_unlikely,
1782bf9e0abSIngo Molnar },
1792bf9e0abSIngo Molnar {
1802bf9e0abSIngo Molnar .init_state = false,
1812bf9e0abSIngo Molnar .key = &base_inv_true_key.key,
182975db45eSArnd Bergmann .test_key = &base_inv_true_key_static_branch_likely,
1832bf9e0abSIngo Molnar },
1842bf9e0abSIngo Molnar {
1852bf9e0abSIngo Molnar .init_state = false,
1862bf9e0abSIngo Molnar .key = &base_inv_true_key.key,
187975db45eSArnd Bergmann .test_key = &base_inv_true_key_static_branch_unlikely,
1882bf9e0abSIngo Molnar },
1892bf9e0abSIngo Molnar {
1902bf9e0abSIngo Molnar .init_state = false,
1912bf9e0abSIngo Molnar .key = &base_false_key.key,
192975db45eSArnd Bergmann .test_key = &base_false_key_static_branch_likely,
1932bf9e0abSIngo Molnar },
1942bf9e0abSIngo Molnar {
1952bf9e0abSIngo Molnar .init_state = false,
1962bf9e0abSIngo Molnar .key = &base_false_key.key,
197975db45eSArnd Bergmann .test_key = &base_false_key_static_branch_unlikely,
1982bf9e0abSIngo Molnar },
1992bf9e0abSIngo Molnar {
2002bf9e0abSIngo Molnar .init_state = true,
2012bf9e0abSIngo Molnar .key = &base_inv_false_key.key,
202975db45eSArnd Bergmann .test_key = &base_inv_false_key_static_branch_likely,
2032bf9e0abSIngo Molnar },
2042bf9e0abSIngo Molnar {
2052bf9e0abSIngo Molnar .init_state = true,
2062bf9e0abSIngo Molnar .key = &base_inv_false_key.key,
207975db45eSArnd Bergmann .test_key = &base_inv_false_key_static_branch_unlikely,
2082bf9e0abSIngo Molnar },
2092bf9e0abSIngo Molnar };
2102bf9e0abSIngo Molnar
2112bf9e0abSIngo Molnar size = ARRAY_SIZE(static_key_tests);
2122bf9e0abSIngo Molnar
2132bf9e0abSIngo Molnar ret = verify_keys(static_key_tests, size, false);
2142bf9e0abSIngo Molnar if (ret)
2152bf9e0abSIngo Molnar goto out;
2162bf9e0abSIngo Molnar
2172bf9e0abSIngo Molnar invert_keys(static_key_tests, size);
2182bf9e0abSIngo Molnar ret = verify_keys(static_key_tests, size, true);
2192bf9e0abSIngo Molnar if (ret)
2202bf9e0abSIngo Molnar goto out;
2212bf9e0abSIngo Molnar
2222bf9e0abSIngo Molnar invert_keys(static_key_tests, size);
2232bf9e0abSIngo Molnar ret = verify_keys(static_key_tests, size, false);
2242bf9e0abSIngo Molnar if (ret)
2252bf9e0abSIngo Molnar goto out;
2262bf9e0abSIngo Molnar return 0;
2272bf9e0abSIngo Molnar out:
2282bf9e0abSIngo Molnar return ret;
2292bf9e0abSIngo Molnar }
2302bf9e0abSIngo Molnar
test_static_key_exit(void)2312bf9e0abSIngo Molnar static void __exit test_static_key_exit(void)
2322bf9e0abSIngo Molnar {
2332bf9e0abSIngo Molnar }
2342bf9e0abSIngo Molnar
2352bf9e0abSIngo Molnar module_init(test_static_key_init);
2362bf9e0abSIngo Molnar module_exit(test_static_key_exit);
2372bf9e0abSIngo Molnar
2382bf9e0abSIngo Molnar MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
2392bf9e0abSIngo Molnar MODULE_LICENSE("GPL");
240