Merge branch 'pci/microchip'
[platform/kernel/linux-rpi.git] / lib / test_static_keys.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Kernel module for testing static keys.
4  *
5  * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
6  *
7  * Authors:
8  *      Jason Baron       <jbaron@akamai.com>
9  */
10
11 #include <linux/module.h>
12 #include <linux/jump_label.h>
13
14 /* old keys */
15 struct static_key old_true_key  = STATIC_KEY_INIT_TRUE;
16 struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
17
18 /* new api */
19 DEFINE_STATIC_KEY_TRUE(true_key);
20 DEFINE_STATIC_KEY_FALSE(false_key);
21
22 /* external */
23 extern struct static_key base_old_true_key;
24 extern struct static_key base_inv_old_true_key;
25 extern struct static_key base_old_false_key;
26 extern struct static_key base_inv_old_false_key;
27
28 /* new api */
29 extern struct static_key_true base_true_key;
30 extern struct static_key_true base_inv_true_key;
31 extern struct static_key_false base_false_key;
32 extern struct static_key_false base_inv_false_key;
33
34
35 struct test_key {
36         bool                    init_state;
37         struct static_key       *key;
38         bool                    (*test_key)(void);
39 };
40
41 #define test_key_func(key, branch)      \
42 static bool key ## _ ## branch(void)    \
43 {                                       \
44         return branch(&key);            \
45 }
46
47 static void invert_key(struct static_key *key)
48 {
49         if (static_key_enabled(key))
50                 static_key_disable(key);
51         else
52                 static_key_enable(key);
53 }
54
55 static void invert_keys(struct test_key *keys, int size)
56 {
57         struct static_key *previous = NULL;
58         int i;
59
60         for (i = 0; i < size; i++) {
61                 if (previous != keys[i].key) {
62                         invert_key(keys[i].key);
63                         previous = keys[i].key;
64                 }
65         }
66 }
67
68 static int verify_keys(struct test_key *keys, int size, bool invert)
69 {
70         int i;
71         bool ret, init;
72
73         for (i = 0; i < size; i++) {
74                 ret = static_key_enabled(keys[i].key);
75                 init = keys[i].init_state;
76                 if (ret != (invert ? !init : init))
77                         return -EINVAL;
78                 ret = keys[i].test_key();
79                 if (static_key_enabled(keys[i].key)) {
80                         if (!ret)
81                                 return -EINVAL;
82                 } else {
83                         if (ret)
84                                 return -EINVAL;
85                 }
86         }
87         return 0;
88 }
89
90 test_key_func(old_true_key, static_key_true)
91 test_key_func(old_false_key, static_key_false)
92 test_key_func(true_key, static_branch_likely)
93 test_key_func(true_key, static_branch_unlikely)
94 test_key_func(false_key, static_branch_likely)
95 test_key_func(false_key, static_branch_unlikely)
96 test_key_func(base_old_true_key, static_key_true)
97 test_key_func(base_inv_old_true_key, static_key_true)
98 test_key_func(base_old_false_key, static_key_false)
99 test_key_func(base_inv_old_false_key, static_key_false)
100 test_key_func(base_true_key, static_branch_likely)
101 test_key_func(base_true_key, static_branch_unlikely)
102 test_key_func(base_inv_true_key, static_branch_likely)
103 test_key_func(base_inv_true_key, static_branch_unlikely)
104 test_key_func(base_false_key, static_branch_likely)
105 test_key_func(base_false_key, static_branch_unlikely)
106 test_key_func(base_inv_false_key, static_branch_likely)
107 test_key_func(base_inv_false_key, static_branch_unlikely)
108
109 static int __init test_static_key_init(void)
110 {
111         int ret;
112         int size;
113
114         struct test_key static_key_tests[] = {
115                 /* internal keys - old keys */
116                 {
117                         .init_state     = true,
118                         .key            = &old_true_key,
119                         .test_key       = &old_true_key_static_key_true,
120                 },
121                 {
122                         .init_state     = false,
123                         .key            = &old_false_key,
124                         .test_key       = &old_false_key_static_key_false,
125                 },
126                 /* internal keys - new keys */
127                 {
128                         .init_state     = true,
129                         .key            = &true_key.key,
130                         .test_key       = &true_key_static_branch_likely,
131                 },
132                 {
133                         .init_state     = true,
134                         .key            = &true_key.key,
135                         .test_key       = &true_key_static_branch_unlikely,
136                 },
137                 {
138                         .init_state     = false,
139                         .key            = &false_key.key,
140                         .test_key       = &false_key_static_branch_likely,
141                 },
142                 {
143                         .init_state     = false,
144                         .key            = &false_key.key,
145                         .test_key       = &false_key_static_branch_unlikely,
146                 },
147                 /* external keys - old keys */
148                 {
149                         .init_state     = true,
150                         .key            = &base_old_true_key,
151                         .test_key       = &base_old_true_key_static_key_true,
152                 },
153                 {
154                         .init_state     = false,
155                         .key            = &base_inv_old_true_key,
156                         .test_key       = &base_inv_old_true_key_static_key_true,
157                 },
158                 {
159                         .init_state     = false,
160                         .key            = &base_old_false_key,
161                         .test_key       = &base_old_false_key_static_key_false,
162                 },
163                 {
164                         .init_state     = true,
165                         .key            = &base_inv_old_false_key,
166                         .test_key       = &base_inv_old_false_key_static_key_false,
167                 },
168                 /* external keys - new keys */
169                 {
170                         .init_state     = true,
171                         .key            = &base_true_key.key,
172                         .test_key       = &base_true_key_static_branch_likely,
173                 },
174                 {
175                         .init_state     = true,
176                         .key            = &base_true_key.key,
177                         .test_key       = &base_true_key_static_branch_unlikely,
178                 },
179                 {
180                         .init_state     = false,
181                         .key            = &base_inv_true_key.key,
182                         .test_key       = &base_inv_true_key_static_branch_likely,
183                 },
184                 {
185                         .init_state     = false,
186                         .key            = &base_inv_true_key.key,
187                         .test_key       = &base_inv_true_key_static_branch_unlikely,
188                 },
189                 {
190                         .init_state     = false,
191                         .key            = &base_false_key.key,
192                         .test_key       = &base_false_key_static_branch_likely,
193                 },
194                 {
195                         .init_state     = false,
196                         .key            = &base_false_key.key,
197                         .test_key       = &base_false_key_static_branch_unlikely,
198                 },
199                 {
200                         .init_state     = true,
201                         .key            = &base_inv_false_key.key,
202                         .test_key       = &base_inv_false_key_static_branch_likely,
203                 },
204                 {
205                         .init_state     = true,
206                         .key            = &base_inv_false_key.key,
207                         .test_key       = &base_inv_false_key_static_branch_unlikely,
208                 },
209         };
210
211         size = ARRAY_SIZE(static_key_tests);
212
213         ret = verify_keys(static_key_tests, size, false);
214         if (ret)
215                 goto out;
216
217         invert_keys(static_key_tests, size);
218         ret = verify_keys(static_key_tests, size, true);
219         if (ret)
220                 goto out;
221
222         invert_keys(static_key_tests, size);
223         ret = verify_keys(static_key_tests, size, false);
224         if (ret)
225                 goto out;
226         return 0;
227 out:
228         return ret;
229 }
230
231 static void __exit test_static_key_exit(void)
232 {
233 }
234
235 module_init(test_static_key_init);
236 module_exit(test_static_key_exit);
237
238 MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
239 MODULE_LICENSE("GPL");