History

Merge branch 'for-mingo-kcsan' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into locking/core

Pull KCSAN changes from Paul E. McKenney: misc updates.

Ingo Molnar committed 5 years ago

Commit eedd6342 parents 9432bbd bd0ccc413 files · +111 −76Browse files

Unified · Split

13 files
  1. Documentation/dev-tools/kcsan.rst +3 −0
  2. include/linux/kcsan-checks.h +6 −0
  3. include/linux/kcsan.h +7 −0
  4. kernel/kcsan/Makefile +2 −2
  5. kernel/kcsan/atomic.h +5 −0
  6. kernel/kcsan/core.c +5 −2
  7. kernel/kcsan/debugfs.c +8 −1
  8. kernel/kcsan/encoding.h +5 −0
  9. kernel/kcsan/kcsan.h +2 −6
  10. kernel/kcsan/kcsan_test.c +55 −63
  11. kernel/kcsan/report.c +5 −0
  12. kernel/kcsan/selftest.c +5 −0
  13. lib/Kconfig.kcsan +3 −2
Documentation/dev-tools/kcsan.rst+3−0
@@ -1,3 +1,6 @@
1.. SPDX-License-Identifier: GPL-2.0
2.. Copyright (C) 2019, Google LLC.
3
1The Kernel Concurrency Sanitizer (KCSAN)4The Kernel Concurrency Sanitizer (KCSAN)
2========================================5========================================
3 6
include/linux/kcsan-checks.h+6−0
@@ -1,4 +1,10 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * KCSAN access checks and modifiers. These can be used to explicitly check
4 * uninstrumented accesses, or change KCSAN checking behaviour of accesses.
5 *
6 * Copyright (C) 2019, Google LLC.
7 */
2 8
3#ifndef _LINUX_KCSAN_CHECKS_H9#ifndef _LINUX_KCSAN_CHECKS_H
4#define _LINUX_KCSAN_CHECKS_H10#define _LINUX_KCSAN_CHECKS_H
include/linux/kcsan.h+7−0
@@ -1,4 +1,11 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * The Kernel Concurrency Sanitizer (KCSAN) infrastructure. Public interface and
4 * data structures to set up runtime. See kcsan-checks.h for explicit checks and
5 * modifiers. For more info please see Documentation/dev-tools/kcsan.rst.
6 *
7 * Copyright (C) 2019, Google LLC.
8 */
2 9
3#ifndef _LINUX_KCSAN_H10#ifndef _LINUX_KCSAN_H
4#define _LINUX_KCSAN_H11#define _LINUX_KCSAN_H
kernel/kcsan/Makefile+2−2
@@ -13,5 +13,5 @@ CFLAGS_core.o := $(call cc-option,-fno-conserve-stack) \ · 12 unmodified lines
13obj-y := core.o debugfs.o report.o13obj-y := core.o debugfs.o report.o
14obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o14obj-$(CONFIG_KCSAN_SELFTEST) += selftest.o
15 15
16CFLAGS_kcsan-test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer16CFLAGS_kcsan_test.o := $(CFLAGS_KCSAN) -g -fno-omit-frame-pointer
17obj-$(CONFIG_KCSAN_TEST) += kcsan-test.o17obj-$(CONFIG_KCSAN_KUNIT_TEST) += kcsan_test.o
kernel/kcsan/atomic.h+5−0
@@ -1,4 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Rules for implicitly atomic memory accesses.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#ifndef _KERNEL_KCSAN_ATOMIC_H8#ifndef _KERNEL_KCSAN_ATOMIC_H
4#define _KERNEL_KCSAN_ATOMIC_H9#define _KERNEL_KCSAN_ATOMIC_H
kernel/kcsan/core.c+5−2
@@ -1,4 +1,9 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/*
3 * KCSAN core runtime.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#define pr_fmt(fmt) "kcsan: " fmt8#define pr_fmt(fmt) "kcsan: " fmt
4 9
@@ -639,8 +644,6 @@ void __init kcsan_init(void) · 634 unmodified lines
639 644
640 BUG_ON(!in_task());645 BUG_ON(!in_task());
641 646
642 kcsan_debugfs_init();
643
644 for_each_possible_cpu(cpu)647 for_each_possible_cpu(cpu)
645 per_cpu(kcsan_rand_state, cpu) = (u32)get_cycles();648 per_cpu(kcsan_rand_state, cpu) = (u32)get_cycles();
646 649
kernel/kcsan/debugfs.c+8−1
@@ -1,4 +1,9 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/*
3 * KCSAN debugfs interface.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#define pr_fmt(fmt) "kcsan: " fmt8#define pr_fmt(fmt) "kcsan: " fmt
4 9
@@ -261,7 +266,9 @@ static const struct file_operations debugfs_ops = · 256 unmodified lines
261 .release = single_release266 .release = single_release
262};267};
263 268
264void __init kcsan_debugfs_init(void)269static void __init kcsan_debugfs_init(void)
265{270{
266 debugfs_create_file("kcsan", 0644, NULL, NULL, &debugfs_ops);271 debugfs_create_file("kcsan", 0644, NULL, NULL, &debugfs_ops);
267}272}
273
274late_initcall(kcsan_debugfs_init);
kernel/kcsan/encoding.h+5−0
@@ -1,4 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * KCSAN watchpoint encoding.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#ifndef _KERNEL_KCSAN_ENCODING_H8#ifndef _KERNEL_KCSAN_ENCODING_H
4#define _KERNEL_KCSAN_ENCODING_H9#define _KERNEL_KCSAN_ENCODING_H
kernel/kcsan/kcsan.h+2−6
@@ -1,8 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 */1/* SPDX-License-Identifier: GPL-2.0 */
2
3/*2/*
4 * The Kernel Concurrency Sanitizer (KCSAN) infrastructure. For more info please3 * The Kernel Concurrency Sanitizer (KCSAN) infrastructure. For more info please
5 * see Documentation/dev-tools/kcsan.rst.4 * see Documentation/dev-tools/kcsan.rst.
5 *
6 * Copyright (C) 2019, Google LLC.
6 */7 */
7 8
8#ifndef _KERNEL_KCSAN_KCSAN_H9#ifndef _KERNEL_KCSAN_KCSAN_H
@@ -30,11 +31,6 @@ extern bool kcsan_enabled; · 21 unmodified lines
30void kcsan_save_irqtrace(struct task_struct *task);31void kcsan_save_irqtrace(struct task_struct *task);
31void kcsan_restore_irqtrace(struct task_struct *task);32void kcsan_restore_irqtrace(struct task_struct *task);
32 33
33/*
34 * Initialize debugfs file.
35 */
36void kcsan_debugfs_init(void);
37
38/*34/*
39 * Statistics counters displayed via debugfs; should only be modified in35 * Statistics counters displayed via debugfs; should only be modified in
40 * slow-paths.36 * slow-paths.
kernel/kcsan/kcsan_test.crenamed from kernel/kcsan/kcsan-test.c+55−63
@@ -13,6 +13,8 @@ · 12 unmodified lines
13 * Author: Marco Elver <elver@google.com>13 * Author: Marco Elver <elver@google.com>
14 */14 */
15 15
16#define pr_fmt(fmt) "kcsan_test: " fmt
17
16#include <kunit/test.h>18#include <kunit/test.h>
17#include <linux/jiffies.h>19#include <linux/jiffies.h>
18#include <linux/kcsan-checks.h>20#include <linux/kcsan-checks.h>
@@ -951,22 +953,53 @@ static void test_atomic_builtins(struct kunit *test) · 932 unmodified lines
951}953}
952 954
953/*955/*
954 * Each test case is run with different numbers of threads. Until KUnit supports956 * Generate thread counts for all test cases. Values generated are in interval
955 * passing arguments for each test case, we encode #threads in the test case957 * [2, 5] followed by exponentially increasing thread counts from 8 to 32.
956 * name (read by get_num_threads()). [The '-' was chosen as a stylistic
957 * preference to separate test name and #threads.]
958 *958 *
959 * The thread counts are chosen to cover potentially interesting boundaries and959 * The thread counts are chosen to cover potentially interesting boundaries and
960 * corner cases (range 2-5), and then stress the system with larger counts.960 * corner cases (2 to 5), and then stress the system with larger counts.
961 */961 */
962#define KCSAN_KUNIT_CASE(test_name) \962static const void *nthreads_gen_params(const void *prev, char *desc)
963 { .run_case = test_name, .name = #test_name "-02" }, \963{
964 { .run_case = test_name, .name = #test_name "-03" }, \964 long nthreads = (long)prev;
965 { .run_case = test_name, .name = #test_name "-04" }, \965
966 { .run_case = test_name, .name = #test_name "-05" }, \966 if (nthreads < 0 || nthreads >= 32)
967 { .run_case = test_name, .name = #test_name "-08" }, \967 nthreads = 0; /* stop */
968 { .run_case = test_name, .name = #test_name "-16" }968 else if (!nthreads)
969 nthreads = 2; /* initial value */
970 else if (nthreads < 5)
971 nthreads++;
972 else if (nthreads == 5)
973 nthreads = 8;
974 else
975 nthreads *= 2;
969 976
977 if (!IS_ENABLED(CONFIG_PREEMPT) || !IS_ENABLED(CONFIG_KCSAN_INTERRUPT_WATCHER)) {
978 /*
979 * Without any preemption, keep 2 CPUs free for other tasks, one
980 * of which is the main test case function checking for
981 * completion or failure.
982 */
983 const long min_unused_cpus = IS_ENABLED(CONFIG_PREEMPT_NONE) ? 2 : 0;
984 const long min_required_cpus = 2 + min_unused_cpus;
985
986 if (num_online_cpus() < min_required_cpus) {
987 pr_err_once("Too few online CPUs (%u < %d) for test\n",
988 num_online_cpus(), min_required_cpus);
989 nthreads = 0;
990 } else if (nthreads >= num_online_cpus() - min_unused_cpus) {
991 /* Use negative value to indicate last param. */
992 nthreads = -(num_online_cpus() - min_unused_cpus);
993 pr_warn_once("Limiting number of threads to %ld (only %d online CPUs)\n",
994 -nthreads, num_online_cpus());
995 }
996 }
997
998 snprintf(desc, KUNIT_PARAM_DESC_SIZE, "threads=%ld", abs(nthreads));
999 return (void *)nthreads;
1000}
1001
1002#define KCSAN_KUNIT_CASE(test_name) KUNIT_CASE_PARAM(test_name, nthreads_gen_params)
970static struct kunit_case kcsan_test_cases[] = {1003static struct kunit_case kcsan_test_cases[] = {
971 KCSAN_KUNIT_CASE(test_basic),1004 KCSAN_KUNIT_CASE(test_basic),
972 KCSAN_KUNIT_CASE(test_concurrent_races),1005 KCSAN_KUNIT_CASE(test_concurrent_races),
@@ -996,24 +1029,6 @@ static struct kunit_case kcsan_test_cases[] = { · 23 unmodified lines
996 1029
997/* ===== End test cases ===== */1030/* ===== End test cases ===== */
998 1031
999/* Get number of threads encoded in test name. */
1000static bool __no_kcsan
1001get_num_threads(const char *test, int *nthreads)
1002{
1003 int len = strlen(test);
1004
1005 if (WARN_ON(len < 3))
1006 return false;
1007
1008 *nthreads = test[len - 1] - '0';
1009 *nthreads += (test[len - 2] - '0') * 10;
1010
1011 if (WARN_ON(*nthreads < 0))
1012 return false;
1013
1014 return true;
1015}
1016
1017/* Concurrent accesses from interrupts. */1032/* Concurrent accesses from interrupts. */
1018__no_kcsan1033__no_kcsan
1019static void access_thread_timer(struct timer_list *timer)1034static void access_thread_timer(struct timer_list *timer)
@@ -1076,9 +1091,6 @@ static int test_init(struct kunit *test) · 56 unmodified lines
1076 if (!torture_init_begin((char *)test->name, 1))1091 if (!torture_init_begin((char *)test->name, 1))
1077 return -EBUSY;1092 return -EBUSY;
1078 1093
1079 if (!get_num_threads(test->name, &nthreads))
1080 goto err;
1081
1082 if (WARN_ON(threads))1094 if (WARN_ON(threads))
1083 goto err;1095 goto err;
1084 1096
@@ -1087,38 +1099,18 @@ static int test_init(struct kunit *test) · 2 unmodified lines
1087 goto err;1099 goto err;
1088 }1100 }
1089 1101
1090 if (!IS_ENABLED(CONFIG_PREEMPT) || !IS_ENABLED(CONFIG_KCSAN_INTERRUPT_WATCHER)) {1102 nthreads = abs((long)test->param_value);
1091 /*1103 if (WARN_ON(!nthreads))
1092 * Without any preemption, keep 2 CPUs free for other tasks, one1104 goto err;
1093 * of which is the main test case function checking for
1094 * completion or failure.
1095 */
1096 const int min_unused_cpus = IS_ENABLED(CONFIG_PREEMPT_NONE) ? 2 : 0;
1097 const int min_required_cpus = 2 + min_unused_cpus;
1098 1105
1099 if (num_online_cpus() < min_required_cpus) {1106 threads = kcalloc(nthreads + 1, sizeof(struct task_struct *), GFP_KERNEL);
1100 pr_err("%s: too few online CPUs (%u < %d) for test",1107 if (WARN_ON(!threads))
1101 test->name, num_online_cpus(), min_required_cpus);1108 goto err;
1102 goto err;
1103 } else if (nthreads > num_online_cpus() - min_unused_cpus) {
1104 nthreads = num_online_cpus() - min_unused_cpus;
1105 pr_warn("%s: limiting number of threads to %d\n",
1106 test->name, nthreads);
1107 }
1108 }
1109 1109
1110 if (nthreads) {1110 threads[nthreads] = NULL;
1111 threads = kcalloc(nthreads + 1, sizeof(struct task_struct *),1111 for (i = 0; i < nthreads; ++i) {
1112 GFP_KERNEL);1112 if (torture_create_kthread(access_thread, NULL, threads[i]))
1113 if (WARN_ON(!threads))
1114 goto err;1113 goto err;
1115
1116 threads[nthreads] = NULL;
1117 for (i = 0; i < nthreads; ++i) {
1118 if (torture_create_kthread(access_thread, NULL,
1119 threads[i]))
1120 goto err;
1121 }
1122 }1114 }
1123 1115
1124 torture_init_end();1116 torture_init_end();
@@ -1156,7 +1148,7 @@ static void test_exit(struct kunit *test) · 31 unmodified lines
1156}1148}
1157 1149
1158static struct kunit_suite kcsan_test_suite = {1150static struct kunit_suite kcsan_test_suite = {
1159 .name = "kcsan-test",1151 .name = "kcsan",
1160 .test_cases = kcsan_test_cases,1152 .test_cases = kcsan_test_cases,
1161 .init = test_init,1153 .init = test_init,
1162 .exit = test_exit,1154 .exit = test_exit,
kernel/kcsan/report.c+5−0
@@ -1,4 +1,9 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/*
3 * KCSAN reporting.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#include <linux/debug_locks.h>8#include <linux/debug_locks.h>
4#include <linux/delay.h>9#include <linux/delay.h>
kernel/kcsan/selftest.c+5−0
@@ -1,4 +1,9 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/*
3 * KCSAN short boot-time selftests.
4 *
5 * Copyright (C) 2019, Google LLC.
6 */
2 7
3#define pr_fmt(fmt) "kcsan: " fmt8#define pr_fmt(fmt) "kcsan: " fmt
4 9
lib/Kconfig.kcsan+3−2
@@ -69,8 +69,9 @@ config KCSAN_SELFTEST · 68 unmodified lines
69 panic. Recommended to be enabled, ensuring critical functionality69 panic. Recommended to be enabled, ensuring critical functionality
70 works as intended.70 works as intended.
71 71
72config KCSAN_TEST72config KCSAN_KUNIT_TEST
73 tristate "KCSAN test for integrated runtime behaviour"73 tristate "KCSAN test for integrated runtime behaviour" if !KUNIT_ALL_TESTS
74 default KUNIT_ALL_TESTS
74 depends on TRACEPOINTS && KUNIT75 depends on TRACEPOINTS && KUNIT
75 select TORTURE_TEST76 select TORTURE_TEST
76 help77 help

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t