Blame view

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