Skip to content

Commit 579e1ac

Browse files
almostivanIngo Molnar
authored andcommitted
1 parent ed79e94 commit 579e1ac

File tree

7 files changed

+329
-0
lines changed

7 files changed

+329
-0
lines changed

lib/Kconfig.debug

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,15 @@ config MEMTEST
18411841
memtest=17, mean do 17 test patterns.
18421842
If you are unsure how to answer this question, answer N.
18431843

1844+
config TEST_JUMP_LABEL
1845+
tristate "Test jump label"
1846+
default n
1847+
depends on m
1848+
help
1849+
Test jump labels.
1850+
1851+
If unsure, say N.
1852+
18441853
source "samples/Kconfig"
18451854

18461855
source "lib/Kconfig.kgdb"

lib/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
3939
obj-$(CONFIG_TEST_LKM) += test_module.o
4040
obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
4141
obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
42+
obj-$(CONFIG_TEST_JUMP_LABEL) += test_jump_label.o
43+
obj-$(CONFIG_TEST_JUMP_LABEL) += test_jump_label_base.o
4244

4345
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
4446
CFLAGS_kobject.o += -DDEBUG

lib/test_jump_label.c

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Kernel module for testing jump labels.
3+
*
4+
* Copyright 2015 Akamai Technologies Inc. All Rights Reserved
5+
*
6+
* Authors:
7+
* Jason Baron <[email protected]>
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_branch {
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_branch *branches, int size)
61+
{
62+
struct static_key *previous = NULL;
63+
int i;
64+
65+
for (i = 0; i < size; i++) {
66+
if (previous != branches[i].key) {
67+
invert_key(branches[i].key);
68+
previous = branches[i].key;
69+
}
70+
}
71+
}
72+
73+
int verify_branches(struct test_branch *branches, 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(branches[i].key);
80+
init = branches[i].init_state;
81+
if (ret != (invert ? !init : init))
82+
return -EINVAL;
83+
ret = branches[i].test_key();
84+
if (static_key_enabled(branches[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_jump_label_init(void)
96+
{
97+
int ret;
98+
int size;
99+
100+
struct test_branch jump_label_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(jump_label_tests);
198+
199+
ret = verify_branches(jump_label_tests, size, false);
200+
if (ret)
201+
goto out;
202+
203+
invert_keys(jump_label_tests, size);
204+
ret = verify_branches(jump_label_tests, size, true);
205+
if (ret)
206+
goto out;
207+
208+
invert_keys(jump_label_tests, size);
209+
ret = verify_branches(jump_label_tests, size, false);
210+
if (ret)
211+
goto out;
212+
return 0;
213+
out:
214+
return ret;
215+
}
216+
217+
static void __exit test_jump_label_exit(void)
218+
{
219+
}
220+
221+
module_init(test_jump_label_init);
222+
module_exit(test_jump_label_exit);
223+
224+
MODULE_AUTHOR("Jason Baron <[email protected]>");
225+
MODULE_LICENSE("GPL");

lib/test_jump_label_base.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Kernel module for testing jump labels.
3+
*
4+
* Copyright 2015 Akamai Technologies Inc. All Rights Reserved
5+
*
6+
* Authors:
7+
* Jason Baron <[email protected]>
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 base_old_true_key = STATIC_KEY_INIT_TRUE;
24+
EXPORT_SYMBOL_GPL(base_old_true_key);
25+
struct static_key base_inv_old_true_key = STATIC_KEY_INIT_TRUE;
26+
EXPORT_SYMBOL_GPL(base_inv_old_true_key);
27+
struct static_key base_old_false_key = STATIC_KEY_INIT_FALSE;
28+
EXPORT_SYMBOL_GPL(base_old_false_key);
29+
struct static_key base_inv_old_false_key = STATIC_KEY_INIT_FALSE;
30+
EXPORT_SYMBOL_GPL(base_inv_old_false_key);
31+
32+
/* new keys */
33+
DEFINE_STATIC_KEY_TRUE(base_true_key);
34+
EXPORT_SYMBOL_GPL(base_true_key);
35+
DEFINE_STATIC_KEY_TRUE(base_inv_true_key);
36+
EXPORT_SYMBOL_GPL(base_inv_true_key);
37+
DEFINE_STATIC_KEY_FALSE(base_false_key);
38+
EXPORT_SYMBOL_GPL(base_false_key);
39+
DEFINE_STATIC_KEY_FALSE(base_inv_false_key);
40+
EXPORT_SYMBOL_GPL(base_inv_false_key);
41+
42+
static void invert_key(struct static_key *key)
43+
{
44+
if (static_key_enabled(key))
45+
static_key_disable(key);
46+
else
47+
static_key_enable(key);
48+
}
49+
50+
static int __init test_jump_label_base_init(void)
51+
{
52+
invert_key(&base_inv_old_true_key);
53+
invert_key(&base_inv_old_false_key);
54+
invert_key(&base_inv_true_key.key);
55+
invert_key(&base_inv_false_key.key);
56+
57+
return 0;
58+
}
59+
60+
static void __exit test_jump_label_base_exit(void)
61+
{
62+
}
63+
64+
module_init(test_jump_label_base_init);
65+
module_exit(test_jump_label_base_exit);
66+
67+
MODULE_AUTHOR("Jason Baron <[email protected]>");
68+
MODULE_LICENSE("GPL");

tools/testing/selftests/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ifneq (1, $(quicktest))
2020
TARGETS += timers
2121
endif
2222
TARGETS += user
23+
TARGETS += jumplabel
2324
TARGETS += vm
2425
TARGETS += x86
2526
#Please keep the TARGETS list alphabetically sorted
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Makefile for jump label selftests
2+
3+
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests"
4+
all:
5+
6+
TEST_PROGS := test_jump_label.sh
7+
8+
include ../lib.mk
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
# Runs jump label kernel module tests
3+
4+
if /sbin/modprobe -q test_jump_label_base; then
5+
if /sbin/modprobe -q test_jump_label; then
6+
echo "jump_label: ok"
7+
/sbin/modprobe -q -r test_jump_label
8+
/sbin/modprobe -q -r test_jump_label_base
9+
else
10+
echo "jump_label: [FAIL]"
11+
/sbin/modprobe -q -r test_jump_label_base
12+
fi
13+
else
14+
echo "jump_label: [FAIL]"
15+
exit 1
16+
fi

0 commit comments

Comments
 (0)