]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - lib/test_static_keys.c
Merge tag 'for-f2fs-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[mirror_ubuntu-artful-kernel.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 static bool key ## _ ## branch(void) \
51 { \
52 return branch(&key); \
53 }
54
55 static void invert_key(struct static_key *key)
56 {
57 if (static_key_enabled(key))
58 static_key_disable(key);
59 else
60 static_key_enable(key);
61 }
62
63 static void invert_keys(struct test_key *keys, int size)
64 {
65 struct static_key *previous = NULL;
66 int i;
67
68 for (i = 0; i < size; i++) {
69 if (previous != keys[i].key) {
70 invert_key(keys[i].key);
71 previous = keys[i].key;
72 }
73 }
74 }
75
76 static int verify_keys(struct test_key *keys, int size, bool invert)
77 {
78 int i;
79 bool ret, init;
80
81 for (i = 0; i < size; i++) {
82 ret = static_key_enabled(keys[i].key);
83 init = keys[i].init_state;
84 if (ret != (invert ? !init : init))
85 return -EINVAL;
86 ret = keys[i].test_key();
87 if (static_key_enabled(keys[i].key)) {
88 if (!ret)
89 return -EINVAL;
90 } else {
91 if (ret)
92 return -EINVAL;
93 }
94 }
95 return 0;
96 }
97
98 test_key_func(old_true_key, static_key_true)
99 test_key_func(old_false_key, static_key_false)
100 test_key_func(true_key, static_branch_likely)
101 test_key_func(true_key, static_branch_unlikely)
102 test_key_func(false_key, static_branch_likely)
103 test_key_func(false_key, static_branch_unlikely)
104 test_key_func(base_old_true_key, static_key_true)
105 test_key_func(base_inv_old_true_key, static_key_true)
106 test_key_func(base_old_false_key, static_key_false)
107 test_key_func(base_inv_old_false_key, static_key_false)
108 test_key_func(base_true_key, static_branch_likely)
109 test_key_func(base_true_key, static_branch_unlikely)
110 test_key_func(base_inv_true_key, static_branch_likely)
111 test_key_func(base_inv_true_key, static_branch_unlikely)
112 test_key_func(base_false_key, static_branch_likely)
113 test_key_func(base_false_key, static_branch_unlikely)
114 test_key_func(base_inv_false_key, static_branch_likely)
115 test_key_func(base_inv_false_key, static_branch_unlikely)
116
117 static int __init test_static_key_init(void)
118 {
119 int ret;
120 int size;
121
122 struct test_key static_key_tests[] = {
123 /* internal keys - old keys */
124 {
125 .init_state = true,
126 .key = &old_true_key,
127 .test_key = &old_true_key_static_key_true,
128 },
129 {
130 .init_state = false,
131 .key = &old_false_key,
132 .test_key = &old_false_key_static_key_false,
133 },
134 /* internal keys - new keys */
135 {
136 .init_state = true,
137 .key = &true_key.key,
138 .test_key = &true_key_static_branch_likely,
139 },
140 {
141 .init_state = true,
142 .key = &true_key.key,
143 .test_key = &true_key_static_branch_unlikely,
144 },
145 {
146 .init_state = false,
147 .key = &false_key.key,
148 .test_key = &false_key_static_branch_likely,
149 },
150 {
151 .init_state = false,
152 .key = &false_key.key,
153 .test_key = &false_key_static_branch_unlikely,
154 },
155 /* external keys - old keys */
156 {
157 .init_state = true,
158 .key = &base_old_true_key,
159 .test_key = &base_old_true_key_static_key_true,
160 },
161 {
162 .init_state = false,
163 .key = &base_inv_old_true_key,
164 .test_key = &base_inv_old_true_key_static_key_true,
165 },
166 {
167 .init_state = false,
168 .key = &base_old_false_key,
169 .test_key = &base_old_false_key_static_key_false,
170 },
171 {
172 .init_state = true,
173 .key = &base_inv_old_false_key,
174 .test_key = &base_inv_old_false_key_static_key_false,
175 },
176 /* external keys - new keys */
177 {
178 .init_state = true,
179 .key = &base_true_key.key,
180 .test_key = &base_true_key_static_branch_likely,
181 },
182 {
183 .init_state = true,
184 .key = &base_true_key.key,
185 .test_key = &base_true_key_static_branch_unlikely,
186 },
187 {
188 .init_state = false,
189 .key = &base_inv_true_key.key,
190 .test_key = &base_inv_true_key_static_branch_likely,
191 },
192 {
193 .init_state = false,
194 .key = &base_inv_true_key.key,
195 .test_key = &base_inv_true_key_static_branch_unlikely,
196 },
197 {
198 .init_state = false,
199 .key = &base_false_key.key,
200 .test_key = &base_false_key_static_branch_likely,
201 },
202 {
203 .init_state = false,
204 .key = &base_false_key.key,
205 .test_key = &base_false_key_static_branch_unlikely,
206 },
207 {
208 .init_state = true,
209 .key = &base_inv_false_key.key,
210 .test_key = &base_inv_false_key_static_branch_likely,
211 },
212 {
213 .init_state = true,
214 .key = &base_inv_false_key.key,
215 .test_key = &base_inv_false_key_static_branch_unlikely,
216 },
217 };
218
219 size = ARRAY_SIZE(static_key_tests);
220
221 ret = verify_keys(static_key_tests, size, false);
222 if (ret)
223 goto out;
224
225 invert_keys(static_key_tests, size);
226 ret = verify_keys(static_key_tests, size, true);
227 if (ret)
228 goto out;
229
230 invert_keys(static_key_tests, size);
231 ret = verify_keys(static_key_tests, size, false);
232 if (ret)
233 goto out;
234 return 0;
235 out:
236 return ret;
237 }
238
239 static void __exit test_static_key_exit(void)
240 {
241 }
242
243 module_init(test_static_key_init);
244 module_exit(test_static_key_exit);
245
246 MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>");
247 MODULE_LICENSE("GPL");