-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Jason Baron <jbaron@akamai.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: benh@kernel.crashing.org Cc: bp@alien8.de Cc: davem@davemloft.net Cc: ddaney@caviumnetworks.com Cc: heiko.carstens@de.ibm.com Cc: linux-kernel@vger.kernel.org Cc: liuj97@gmail.com Cc: luto@amacapital.net Cc: michael@ellerman.id.au Cc: rabin@rab.in Cc: ralf@linux-mips.org Cc: rostedt@goodmis.org Cc: shuahkh@osg.samsung.com Cc: vbabka@suse.cz Cc: will.deacon@arm.com Link: http://lkml.kernel.org/r/0c091ecebd78a879ed8a71835d205a691a75ab4e.1438227999.git.jbaron@akamai.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
- Loading branch information
Jason Baron
authored and
Ingo Molnar
committed
Aug 3, 2015
1 parent
ed79e94
commit 579e1ac
Showing
7 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
/* | ||
* Kernel module for testing jump labels. | ||
* | ||
* 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_branch { | ||
bool init_state; | ||
struct static_key *key; | ||
bool (*test_key)(void); | ||
}; | ||
|
||
#define test_key_func(key, branch) \ | ||
({bool func(void) { return branch(key); } func; }) | ||
|
||
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_branch *branches, int size) | ||
{ | ||
struct static_key *previous = NULL; | ||
int i; | ||
|
||
for (i = 0; i < size; i++) { | ||
if (previous != branches[i].key) { | ||
invert_key(branches[i].key); | ||
previous = branches[i].key; | ||
} | ||
} | ||
} | ||
|
||
int verify_branches(struct test_branch *branches, int size, bool invert) | ||
{ | ||
int i; | ||
bool ret, init; | ||
|
||
for (i = 0; i < size; i++) { | ||
ret = static_key_enabled(branches[i].key); | ||
init = branches[i].init_state; | ||
if (ret != (invert ? !init : init)) | ||
return -EINVAL; | ||
ret = branches[i].test_key(); | ||
if (static_key_enabled(branches[i].key)) { | ||
if (!ret) | ||
return -EINVAL; | ||
} else { | ||
if (ret) | ||
return -EINVAL; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
static int __init test_jump_label_init(void) | ||
{ | ||
int ret; | ||
int size; | ||
|
||
struct test_branch jump_label_tests[] = { | ||
/* internal keys - old keys */ | ||
{ | ||
.init_state = true, | ||
.key = &old_true_key, | ||
.test_key = test_key_func(&old_true_key, static_key_true), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &old_false_key, | ||
.test_key = test_key_func(&old_false_key, static_key_false), | ||
}, | ||
/* internal keys - new keys */ | ||
{ | ||
.init_state = true, | ||
.key = &true_key.key, | ||
.test_key = test_key_func(&true_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = true, | ||
.key = &true_key.key, | ||
.test_key = test_key_func(&true_key, static_branch_unlikely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &false_key.key, | ||
.test_key = test_key_func(&false_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &false_key.key, | ||
.test_key = test_key_func(&false_key, static_branch_unlikely), | ||
}, | ||
/* external keys - old keys */ | ||
{ | ||
.init_state = true, | ||
.key = &base_old_true_key, | ||
.test_key = test_key_func(&base_old_true_key, static_key_true), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_inv_old_true_key, | ||
.test_key = test_key_func(&base_inv_old_true_key, static_key_true), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_old_false_key, | ||
.test_key = test_key_func(&base_old_false_key, static_key_false), | ||
}, | ||
{ | ||
.init_state = true, | ||
.key = &base_inv_old_false_key, | ||
.test_key = test_key_func(&base_inv_old_false_key, static_key_false), | ||
}, | ||
/* external keys - new keys */ | ||
{ | ||
.init_state = true, | ||
.key = &base_true_key.key, | ||
.test_key = test_key_func(&base_true_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = true, | ||
.key = &base_true_key.key, | ||
.test_key = test_key_func(&base_true_key, static_branch_unlikely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_inv_true_key.key, | ||
.test_key = test_key_func(&base_inv_true_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_inv_true_key.key, | ||
.test_key = test_key_func(&base_inv_true_key, static_branch_unlikely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_false_key.key, | ||
.test_key = test_key_func(&base_false_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = false, | ||
.key = &base_false_key.key, | ||
.test_key = test_key_func(&base_false_key, static_branch_unlikely), | ||
}, | ||
{ | ||
.init_state = true, | ||
.key = &base_inv_false_key.key, | ||
.test_key = test_key_func(&base_inv_false_key, static_branch_likely), | ||
}, | ||
{ | ||
.init_state = true, | ||
.key = &base_inv_false_key.key, | ||
.test_key = test_key_func(&base_inv_false_key, static_branch_unlikely), | ||
}, | ||
}; | ||
|
||
size = ARRAY_SIZE(jump_label_tests); | ||
|
||
ret = verify_branches(jump_label_tests, size, false); | ||
if (ret) | ||
goto out; | ||
|
||
invert_keys(jump_label_tests, size); | ||
ret = verify_branches(jump_label_tests, size, true); | ||
if (ret) | ||
goto out; | ||
|
||
invert_keys(jump_label_tests, size); | ||
ret = verify_branches(jump_label_tests, size, false); | ||
if (ret) | ||
goto out; | ||
return 0; | ||
out: | ||
return ret; | ||
} | ||
|
||
static void __exit test_jump_label_exit(void) | ||
{ | ||
} | ||
|
||
module_init(test_jump_label_init); | ||
module_exit(test_jump_label_exit); | ||
|
||
MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Kernel module for testing jump labels. | ||
* | ||
* 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 base_old_true_key = STATIC_KEY_INIT_TRUE; | ||
EXPORT_SYMBOL_GPL(base_old_true_key); | ||
struct static_key base_inv_old_true_key = STATIC_KEY_INIT_TRUE; | ||
EXPORT_SYMBOL_GPL(base_inv_old_true_key); | ||
struct static_key base_old_false_key = STATIC_KEY_INIT_FALSE; | ||
EXPORT_SYMBOL_GPL(base_old_false_key); | ||
struct static_key base_inv_old_false_key = STATIC_KEY_INIT_FALSE; | ||
EXPORT_SYMBOL_GPL(base_inv_old_false_key); | ||
|
||
/* new keys */ | ||
DEFINE_STATIC_KEY_TRUE(base_true_key); | ||
EXPORT_SYMBOL_GPL(base_true_key); | ||
DEFINE_STATIC_KEY_TRUE(base_inv_true_key); | ||
EXPORT_SYMBOL_GPL(base_inv_true_key); | ||
DEFINE_STATIC_KEY_FALSE(base_false_key); | ||
EXPORT_SYMBOL_GPL(base_false_key); | ||
DEFINE_STATIC_KEY_FALSE(base_inv_false_key); | ||
EXPORT_SYMBOL_GPL(base_inv_false_key); | ||
|
||
static void invert_key(struct static_key *key) | ||
{ | ||
if (static_key_enabled(key)) | ||
static_key_disable(key); | ||
else | ||
static_key_enable(key); | ||
} | ||
|
||
static int __init test_jump_label_base_init(void) | ||
{ | ||
invert_key(&base_inv_old_true_key); | ||
invert_key(&base_inv_old_false_key); | ||
invert_key(&base_inv_true_key.key); | ||
invert_key(&base_inv_false_key.key); | ||
|
||
return 0; | ||
} | ||
|
||
static void __exit test_jump_label_base_exit(void) | ||
{ | ||
} | ||
|
||
module_init(test_jump_label_base_init); | ||
module_exit(test_jump_label_base_exit); | ||
|
||
MODULE_AUTHOR("Jason Baron <jbaron@akamai.com>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Makefile for jump label selftests | ||
|
||
# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" | ||
all: | ||
|
||
TEST_PROGS := test_jump_label.sh | ||
|
||
include ../lib.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/bin/sh | ||
# Runs jump label kernel module tests | ||
|
||
if /sbin/modprobe -q test_jump_label_base; then | ||
if /sbin/modprobe -q test_jump_label; then | ||
echo "jump_label: ok" | ||
/sbin/modprobe -q -r test_jump_label | ||
/sbin/modprobe -q -r test_jump_label_base | ||
else | ||
echo "jump_label: [FAIL]" | ||
/sbin/modprobe -q -r test_jump_label_base | ||
fi | ||
else | ||
echo "jump_label: [FAIL]" | ||
exit 1 | ||
fi |