]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - lib/test_static_keys.c
Merge remote-tracking branch 'remotes/stable/linux-4.4.y' into karo-tx6-mainline
[karo-tx-linux.git] / lib / test_static_keys.c
1 /*
2  * Kernel module for testing static keys.
3  *
4  * Copyright 2015 Akamai Technologies Inc. All Rights Reserved
5  *
6  * Authors:
7  *      Jason Baron       <jbaron@akamai.com>
8  *
9  * This software is licensed under the terms of the GNU General Public
10  * License version 2, as published by the Free Software Foundation, and
11  * may be copied, distributed, and modified under those terms.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  */
18
19 #include <linux/module.h>
20 #include <linux/jump_label.h>
21
22 /* old keys */
23 struct static_key old_true_key  = STATIC_KEY_INIT_TRUE;
24 struct static_key old_false_key = STATIC_KEY_INIT_FALSE;
25
26 /* new api */
27 DEFINE_STATIC_KEY_TRUE(true_key);
28 DEFINE_STATIC_KEY_FALSE(false_key);
29
30 /* external */
31 extern struct static_key base_old_true_key;
32 extern struct static_key base_inv_old_true_key;
33 extern struct static_key base_old_false_key;
34 extern struct static_key base_inv_old_false_key;
35
36 /* new api */
37 extern struct static_key_true base_true_key;
38 extern struct static_key_true base_inv_true_key;
39 extern struct static_key_false base_false_key;
40 extern struct static_key_false base_inv_false_key;
41
42
43 struct test_key {
44         bool                    init_state;
45         struct static_key       *key;
46         bool                    (*test_key)(void);
47 };
48
49 #define test_key_func(key, branch) \
50         ({bool func(void) { return branch(key); } func; })
51
52 static void invert_key(struct static_key *key)
53 {
54         if (static_key_enabled(key))
55                 static_key_disable(key);
56         else
57                 static_key_enable(key);
58 }
59
60 static void invert_keys(struct test_key *keys, int size)
61 {
62         struct static_key *previous = NULL;
63         int i;
64
65         for (i = 0; i < size; i++) {
66                 if (previous != keys[i].key) {
67                         invert_key(keys[i].key);
68                         previous = keys[i].key;
69                 }
70         }
71 }
72
73 static int verify_keys(struct test_key *keys, int size, bool invert)
74 {
75         int i;
76         bool ret, init;
77
78         for (i = 0; i < size; i++) {
79                 ret = static_key_enabled(keys[i].key);
80                 init = keys[i].init_state;
81                 if (ret != (invert ? !init : init))
82                         return -EINVAL;
83                 ret = keys[i].test_key();
84                 if (static_key_enabled(keys[i].key)) {
85                         if (!ret)
86                                 return -EINVAL;
87                 } else {
88                         if (ret)
89                                 return -EINVAL;
90                 }
91         }
92         return 0;
93 }
94
95 static int __init test_static_key_init(void)
96 {
97         int ret;
98         int size;
99
100         struct test_key static_key_tests[] = {
101                 /* internal keys - old keys */
102                 {
103                         .init_state     = true,
104                         .key            = &old_true_key,
105                         .test_key       = test_key_func(&old_true_key, static_key_true),
106                 },
107                 {
108                         .init_state     = false,
109                         .key            = &old_false_key,
110                         .test_key       = test_key_func(&old_false_key, static_key_false),
111                 },
112                 /* internal keys - new keys */
113                 {
114                         .init_state     = true,
115                         .key            = &true_key.key,
116                         .test_key       = test_key_func(&true_key, static_branch_likely),
117                 },
118                 {
119                         .init_state     = true,
120                         .key            = &true_key.key,
121                         .test_key       = test_key_func(&true_key, static_branch_unlikely),
122                 },
123                 {
124                         .init_state     = false,
125                         .key            = &false_key.key,
126                         .test_key       = test_key_func(&false_key, static_branch_likely),
127                 },
128                 {
129                         .init_state     = false,
130                         .key            = &false_key.key,
131                         .test_key       = test_key_func(&false_key, static_branch_unlikely),
132                 },
133                 /* external keys - old keys */
134                 {
135                         .init_state     = true,
136                         .key            = &base_old_true_key,
137                         .test_key       = test_key_func(&base_old_true_key, static_key_true),
138                 },
139                 {
140                         .init_state     = false,
141                         .key            = &base_inv_old_true_key,
142                         .test_key       = test_key_func(&base_inv_old_true_key, static_key_true),
143                 },
144                 {
145                         .init_state     = false,
146                         .key            = &base_old_false_key,
147                         .test_key       = test_key_func(&base_old_false_key, static_key_false),
148                 },
149                 {
150                         .init_state     = true,
151                         .key            = &base_inv_old_false_key,
152                         .test_key       = test_key_func(&base_inv_old_false_key, static_key_false),
153                 },
154                 /* external keys - new keys */
155                 {
156                         .init_state     = true,
157                         .key            = &base_true_key.key,
158                         .test_key       = test_key_func(&base_true_key, static_branch_likely),
159                 },
160                 {
161                         .init_state     = true,
162                         .key            = &base_true_key.key,
163                         .test_key       = test_key_func(&base_true_key, static_branch_unlikely),
164                 },
165                 {
166                         .init_state     = false,
167                         .key            = &base_inv_true_key.key,
168                         .test_key       = test_key_func(&base_inv_true_key, static_branch_likely),
169                 },
170                 {
171                         .init_state     = false,
172                         .key            = &base_inv_true_key.key,
173                         .test_key       = test_key_func(&base_inv_true_key, static_branch_unlikely),
174                 },
175                 {
176                         .init_state     = false,
177                         .key            = &base_false_key.key,
178                         .test_key       = test_key_func(&base_false_key, static_branch_likely),
179                 },
180                 {
181                         .init_state     = false,
182                         .key            = &base_false_key.key,
183                         .test_key       = test_key_func(&base_false_key, static_branch_unlikely),
184                 },
185                 {
186                         .init_state     = true,
187                         .key            = &base_inv_false_key.key,
188                         .test_key       = test_key_func(&base_inv_false_key, static_branch_likely),
189                 },
190                 {
191                         .init_state     = true,
192                         .key            = &base_inv_false_key.key,
193                         .test_key       = test_key_func(&base_inv_false_key, static_branch_unlikely),
194                 },
195         };
196
197         size = ARRAY_SIZE(static_key_tests);
198
199         ret = verify_keys(static_key_tests, size, false);
200         if (ret)
201                 goto out;
202
203         invert_keys(static_key_tests, size);
204         ret = verify_keys(static_key_tests, size, true);
205         if (ret)
206                 goto out;
207
208         invert_keys(static_key_tests, size);
209         ret = verify_keys(static_key_tests, size, false);
210         if (ret)
211                 goto out;
212         return 0;
213 out:
214         return ret;
215 }
216
217 static void __exit test_static_key_exit(void)
218 {
219 }
220
221 module_init(test_static_key_init);
222 module_exit(test_static_key_exit);
223
224 MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
225 MODULE_LICENSE("GPL");