xref: /linux/lib/test_static_keys.c (revision 9c92ab61)
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