From 2bf9e0ab08c64ac56067555911a1ae81ebff5f96 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 3 Aug 2015 11:42:57 +0200 Subject: [PATCH] locking/static_keys: Provide a selftest The 'jump label' self-test is in reality testing static keys - rename things accordingly. Also prettify the code in various places while at it. Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Jason Baron Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Shuah Khan Cc: Thomas Gleixner 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: 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 --- lib/Kconfig.debug | 6 +- lib/Makefile | 4 +- lib/test_jump_label.c | 225 ------------------ ...mp_label_base.c => test_static_key_base.c} | 10 +- lib/test_static_keys.c | 225 ++++++++++++++++++ .../selftests/jumplabel/test_jump_label.sh | 16 -- .../{jumplabel => static_keys}/Makefile | 4 +- .../selftests/static_keys/test_static_keys.sh | 16 ++ 8 files changed, 253 insertions(+), 253 deletions(-) delete mode 100644 lib/test_jump_label.c rename lib/{test_jump_label_base.c => test_static_key_base.c} (88%) create mode 100644 lib/test_static_keys.c delete mode 100644 tools/testing/selftests/jumplabel/test_jump_label.sh rename tools/testing/selftests/{jumplabel => static_keys}/Makefile (58%) create mode 100644 tools/testing/selftests/static_keys/test_static_keys.sh diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 304e75f832dc..0d859305c556 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1841,12 +1841,12 @@ config MEMTEST memtest=17, mean do 17 test patterns. If you are unsure how to answer this question, answer N. -config TEST_JUMP_LABEL - tristate "Test jump label" +config TEST_STATIC_KEYS + tristate "Test static keys" default n depends on m help - Test jump labels. + Test the static key interfaces. If unsure, say N. diff --git a/lib/Makefile b/lib/Makefile index 14f6e07e33a8..9f2fc71a14a3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,8 +39,8 @@ obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o obj-$(CONFIG_TEST_LKM) += test_module.o obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o -obj-$(CONFIG_TEST_JUMP_LABEL) += test_jump_label.o -obj-$(CONFIG_TEST_JUMP_LABEL) += test_jump_label_base.o +obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o +obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o ifeq ($(CONFIG_DEBUG_KOBJECT),y) CFLAGS_kobject.o += -DDEBUG diff --git a/lib/test_jump_label.c b/lib/test_jump_label.c deleted file mode 100644 index 2fe741329b0e..000000000000 --- a/lib/test_jump_label.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Kernel module for testing jump labels. - * - * Copyright 2015 Akamai Technologies Inc. All Rights Reserved - * - * Authors: - * Jason Baron - * - * 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 -#include - -/* 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 "); -MODULE_LICENSE("GPL"); diff --git a/lib/test_jump_label_base.c b/lib/test_static_key_base.c similarity index 88% rename from lib/test_jump_label_base.c rename to lib/test_static_key_base.c index 91aed8e8a7e8..729447aea02f 100644 --- a/lib/test_jump_label_base.c +++ b/lib/test_static_key_base.c @@ -1,5 +1,5 @@ /* - * Kernel module for testing jump labels. + * Kernel module for testing static keys. * * Copyright 2015 Akamai Technologies Inc. All Rights Reserved * @@ -47,7 +47,7 @@ static void invert_key(struct static_key *key) static_key_enable(key); } -static int __init test_jump_label_base_init(void) +static int __init test_static_key_base_init(void) { invert_key(&base_inv_old_true_key); invert_key(&base_inv_old_false_key); @@ -57,12 +57,12 @@ static int __init test_jump_label_base_init(void) return 0; } -static void __exit test_jump_label_base_exit(void) +static void __exit test_static_key_base_exit(void) { } -module_init(test_jump_label_base_init); -module_exit(test_jump_label_base_exit); +module_init(test_static_key_base_init); +module_exit(test_static_key_base_exit); MODULE_AUTHOR("Jason Baron "); MODULE_LICENSE("GPL"); diff --git a/lib/test_static_keys.c b/lib/test_static_keys.c new file mode 100644 index 000000000000..81d81052eb8d --- /dev/null +++ b/lib/test_static_keys.c @@ -0,0 +1,225 @@ +/* + * Kernel module for testing static keys. + * + * Copyright 2015 Akamai Technologies Inc. All Rights Reserved + * + * Authors: + * Jason Baron + * + * 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 +#include + +/* 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); +}; + +#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_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; + } + } +} + +int verify_keys(struct test_key *keys, int size, bool invert) +{ + 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; +} + +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, + .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(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 "); +MODULE_LICENSE("GPL"); diff --git a/tools/testing/selftests/jumplabel/test_jump_label.sh b/tools/testing/selftests/jumplabel/test_jump_label.sh deleted file mode 100644 index 3457e8a64e77..000000000000 --- a/tools/testing/selftests/jumplabel/test_jump_label.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/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 diff --git a/tools/testing/selftests/jumplabel/Makefile b/tools/testing/selftests/static_keys/Makefile similarity index 58% rename from tools/testing/selftests/jumplabel/Makefile rename to tools/testing/selftests/static_keys/Makefile index 7526aa59e005..9cdadf37f114 100644 --- a/tools/testing/selftests/jumplabel/Makefile +++ b/tools/testing/selftests/static_keys/Makefile @@ -1,8 +1,8 @@ -# Makefile for jump label selftests +# Makefile for static keys selftests # No binaries, but make sure arg-less "make" doesn't trigger "run_tests" all: -TEST_PROGS := test_jump_label.sh +TEST_PROGS := test_static_keys.sh include ../lib.mk diff --git a/tools/testing/selftests/static_keys/test_static_keys.sh b/tools/testing/selftests/static_keys/test_static_keys.sh new file mode 100644 index 000000000000..1261e3fa1e3a --- /dev/null +++ b/tools/testing/selftests/static_keys/test_static_keys.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Runs static keys kernel module tests + +if /sbin/modprobe -q test_static_key_base; then + if /sbin/modprobe -q test_static_keys; then + echo "static_key: ok" + /sbin/modprobe -q -r test_static_keys + /sbin/modprobe -q -r test_static_key_base + else + echo "static_keys: [FAIL]" + /sbin/modprobe -q -r test_static_key_base + fi +else + echo "static_key: [FAIL]" + exit 1 +fi