aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-20 14:21:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-20 14:21:17 -0500
commitf7458a5d631df2ecdbfe4a606053aba19913cc41 (patch)
tree26df2860fe3a750ed3b0359178d2b4c4fe8798d2 /tools
parent575260e3f8f8ac72dc0c41a4a20190d1a5f2b887 (diff)
parenta8709fa4a06d4af5f86e3660839531cbe0f2a19b (diff)
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull RCU updates from Ingo Molnar: "The RCU changes in this cycle are: - Dynticks updates, consolidating open-coded counter accesses into a well-defined API - SRCU updates: Simplify algorithm, add formal verification - Documentation updates - Miscellaneous fixes - Torture-test updates Most of the diffstat comes from the relatively large documentation update" * 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (42 commits) srcu: Reduce probability of SRCU ->unlock_count[] counter overflow rcutorture: Add CBMC-based formal verification for SRCU srcu: Force full grace-period ordering srcu: Implement more-efficient reader counts rcu: Adjust FQS offline checks for exact online-CPU detection rcu: Check cond_resched_rcu_qs() state less often to reduce GP overhead rcu: Abstract extended quiescent state determination rcu: Abstract dynticks extended quiescent state enter/exit operations rcu: Add lockdep checks to synchronous expedited primitives rcu: Eliminate unused expedited_normal counter llist: Clarify comments about when locking is needed rcu: Fix comment in rcu_organize_nocb_kthreads() rcu: Enable RCU tracepoints by default to aid in debugging rcu: Make rcu_cpu_starting() use its "cpu" argument rcu: Add comment headers to expedited-grace-period counter functions rcu: Don't wake rcuc/X kthreads on NOCB CPUs rcu: Re-enable TASKS_RCU for User Mode Linux rcu: Once again use NMI-based stack traces in stall warnings rcu: Remove short-term CPU kicking rcu: Add long-term CPU kicking ...
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/CFcommon3
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY011
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TINY023
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE013
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE024
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE033
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE044
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE053
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE063
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE073
-rw-r--r--tools/testing/selftests/rcutorture/configs/rcu/TREE084
-rw-r--r--tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt33
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile16
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h155
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk375
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h16
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h41
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h13
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c13
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h27
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c31
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h33
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h220
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c11
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h58
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h92
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c78
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h58
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c50
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h102
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile11
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail1
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass0
-rw-r--r--tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c72
-rwxr-xr-xtools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh102
52 files changed, 1641 insertions, 8 deletions
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
index f824b4c9d9d9..d2d2a86139db 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
+++ b/tools/testing/selftests/rcutorture/configs/rcu/CFcommon
@@ -1,5 +1,2 @@
1CONFIG_RCU_TORTURE_TEST=y 1CONFIG_RCU_TORTURE_TEST=y
2CONFIG_PRINTK_TIME=y 2CONFIG_PRINTK_TIME=y
3CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
4CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
5CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY01 b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
index 0a63e073a00c..6db705e55487 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY01
@@ -7,6 +7,7 @@ CONFIG_HZ_PERIODIC=n
7CONFIG_NO_HZ_IDLE=y 7CONFIG_NO_HZ_IDLE=y
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=n 9CONFIG_RCU_TRACE=n
10#CHECK#CONFIG_RCU_STALL_COMMON=n
10CONFIG_DEBUG_LOCK_ALLOC=n 11CONFIG_DEBUG_LOCK_ALLOC=n
11CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 12CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
12CONFIG_PREEMPT_COUNT=n 13CONFIG_PREEMPT_COUNT=n
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TINY02 b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
index f1892e0371c9..a59f7686e219 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TINY02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TINY02
@@ -8,7 +8,8 @@ CONFIG_NO_HZ_IDLE=n
8CONFIG_NO_HZ_FULL=n 8CONFIG_NO_HZ_FULL=n
9CONFIG_RCU_TRACE=y 9CONFIG_RCU_TRACE=y
10CONFIG_PROVE_LOCKING=y 10CONFIG_PROVE_LOCKING=y
11CONFIG_PROVE_RCU_REPEATEDLY=y
11#CHECK#CONFIG_PROVE_RCU=y 12#CHECK#CONFIG_PROVE_RCU=y
12CONFIG_DEBUG_LOCK_ALLOC=y 13CONFIG_DEBUG_LOCK_ALLOC=y
13CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 14CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
14CONFIG_PREEMPT_COUNT=y 15CONFIG_PREEMPT_COUNT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
index f572b873c620..359cb258f639 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01
@@ -16,3 +16,6 @@ CONFIG_DEBUG_LOCK_ALLOC=n
16CONFIG_RCU_BOOST=n 16CONFIG_RCU_BOOST=n
17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 17CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
18CONFIG_RCU_EXPERT=y 18CONFIG_RCU_EXPERT=y
19CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
20CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
21CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE02 b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
index ef6a22c44dea..c1ab5926568b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE02
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE02
@@ -20,3 +20,7 @@ CONFIG_PROVE_LOCKING=n
20CONFIG_RCU_BOOST=n 20CONFIG_RCU_BOOST=n
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 21CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
22CONFIG_RCU_EXPERT=y 22CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
24CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
25CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
26CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE03 b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
index 7a17c503b382..3b93ee544e70 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE03
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE03
@@ -17,3 +17,6 @@ CONFIG_RCU_BOOST=y
17CONFIG_RCU_KTHREAD_PRIO=2 17CONFIG_RCU_KTHREAD_PRIO=2
18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 18CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
19CONFIG_RCU_EXPERT=y 19CONFIG_RCU_EXPERT=y
20CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
21CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
index 17cbe098b115..5af758e783c7 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04
@@ -19,3 +19,7 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
25CONFIG_RCU_EQS_DEBUG=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE05 b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
index 1257d3227b1e..d4cdc0d74e16 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE05
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE05
@@ -19,3 +19,6 @@ CONFIG_PROVE_LOCKING=y
19#CHECK#CONFIG_PROVE_RCU=y 19#CHECK#CONFIG_PROVE_RCU=y
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE06 b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
index d3e456b74cbe..4cb02bd28f08 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE06
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE06
@@ -20,3 +20,6 @@ CONFIG_PROVE_LOCKING=y
20#CHECK#CONFIG_PROVE_RCU=y 20#CHECK#CONFIG_PROVE_RCU=y
21CONFIG_DEBUG_OBJECTS_RCU_HEAD=y 21CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
22CONFIG_RCU_EXPERT=y 22CONFIG_RCU_EXPERT=y
23CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
24CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
25CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE07 b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
index 3956b4131f72..b12a3ea1867e 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE07
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE07
@@ -19,3 +19,6 @@ CONFIG_RCU_NOCB_CPU=n
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 20CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
21CONFIG_RCU_EXPERT=y 21CONFIG_RCU_EXPERT=y
22CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP=y
23CONFIG_RCU_TORTURE_TEST_SLOW_INIT=y
24CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT=y
diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE08 b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
index bb9b0c1a23c2..099cc63c6a3b 100644
--- a/tools/testing/selftests/rcutorture/configs/rcu/TREE08
+++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE08
@@ -17,8 +17,8 @@ CONFIG_RCU_FANOUT_LEAF=2
17CONFIG_RCU_NOCB_CPU=y 17CONFIG_RCU_NOCB_CPU=y
18CONFIG_RCU_NOCB_CPU_ALL=y 18CONFIG_RCU_NOCB_CPU_ALL=y
19CONFIG_DEBUG_LOCK_ALLOC=n 19CONFIG_DEBUG_LOCK_ALLOC=n
20CONFIG_PROVE_LOCKING=y 20CONFIG_PROVE_LOCKING=n
21#CHECK#CONFIG_PROVE_RCU=y
22CONFIG_RCU_BOOST=n 21CONFIG_RCU_BOOST=n
23CONFIG_DEBUG_OBJECTS_RCU_HEAD=n 22CONFIG_DEBUG_OBJECTS_RCU_HEAD=n
24CONFIG_RCU_EXPERT=y 23CONFIG_RCU_EXPERT=y
24CONFIG_RCU_EQS_DEBUG=y
diff --git a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
index 4e2b1893d40d..364801b1a230 100644
--- a/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
+++ b/tools/testing/selftests/rcutorture/doc/TREE_RCU-kconfig.txt
@@ -14,6 +14,7 @@ CONFIG_NO_HZ_FULL_SYSIDLE -- Do one.
14CONFIG_PREEMPT -- Do half. (First three and #8.) 14CONFIG_PREEMPT -- Do half. (First three and #8.)
15CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not. 15CONFIG_PROVE_LOCKING -- Do several, covering CONFIG_DEBUG_LOCK_ALLOC=y and not.
16CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING. 16CONFIG_PROVE_RCU -- Hardwired to CONFIG_PROVE_LOCKING.
17CONFIG_PROVE_RCU_REPEATEDLY -- Do one.
17CONFIG_RCU_BOOST -- one of PREEMPT_RCU. 18CONFIG_RCU_BOOST -- one of PREEMPT_RCU.
18CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing. 19CONFIG_RCU_KTHREAD_PRIO -- set to 2 for _BOOST testing.
19CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others. 20CONFIG_RCU_FANOUT -- Cover hierarchy, but overlap with others.
@@ -25,7 +26,12 @@ CONFIG_RCU_NOCB_CPU_NONE -- Do one.
25CONFIG_RCU_NOCB_CPU_ZERO -- Do one. 26CONFIG_RCU_NOCB_CPU_ZERO -- Do one.
26CONFIG_RCU_TRACE -- Do half. 27CONFIG_RCU_TRACE -- Do half.
27CONFIG_SMP -- Need one !SMP for PREEMPT_RCU. 28CONFIG_SMP -- Need one !SMP for PREEMPT_RCU.
28!RCU_EXPERT -- Do a few, but these have to be vanilla configurations. 29CONFIG_RCU_EXPERT=n -- Do a few, but these have to be vanilla configurations.
30CONFIG_RCU_EQS_DEBUG -- Do at least one for CONFIG_NO_HZ_FULL and not.
31CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP -- Do for all but a couple TREE scenarios.
32CONFIG_RCU_TORTURE_TEST_SLOW_INIT -- Do for all but a couple TREE scenarios.
33CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT -- Do for all but a couple TREE scenarios.
34
29RCU-bh: Do one with PREEMPT and one with !PREEMPT. 35RCU-bh: Do one with PREEMPT and one with !PREEMPT.
30RCU-sched: Do one with PREEMPT but not BOOST. 36RCU-sched: Do one with PREEMPT but not BOOST.
31 37
@@ -72,7 +78,30 @@ CONFIG_RCU_TORTURE_TEST_RUNNABLE
72 78
73 Always used in KVM testing. 79 Always used in KVM testing.
74 80
81CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT_DELAY
82CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
83CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP_DELAY
84
85 Inspection suffices, ignore.
86
75CONFIG_PREEMPT_RCU 87CONFIG_PREEMPT_RCU
76CONFIG_TREE_RCU 88CONFIG_TREE_RCU
89CONFIG_TINY_RCU
90
91 These are controlled by CONFIG_PREEMPT and/or CONFIG_SMP.
92
93CONFIG_SPARSE_RCU_POINTER
94
95 Makes sense only for sparse runs, not for kernel builds.
96
97CONFIG_SRCU
98CONFIG_TASKS_RCU
99
100 Selected by CONFIG_RCU_TORTURE_TEST, so cannot disable.
101
102CONFIG_RCU_TRACE
103
104 Implied by CONFIG_RCU_TRACE for Tree RCU.
105
77 106
78 These are controlled by CONFIG_PREEMPT. 107boot parameters ignored: TBD
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore
new file mode 100644
index 000000000000..712a3d41a325
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/.gitignore
@@ -0,0 +1 @@
srcu.c
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
new file mode 100644
index 000000000000..16b01559fa55
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/Makefile
@@ -0,0 +1,16 @@
1all: srcu.c store_buffering
2
3LINUX_SOURCE = ../../../../../..
4
5modified_srcu_input = $(LINUX_SOURCE)/include/linux/srcu.h \
6 $(LINUX_SOURCE)/kernel/rcu/srcu.c
7
8modified_srcu_output = include/linux/srcu.h srcu.c
9
10include/linux/srcu.h: srcu.c
11
12srcu.c: modify_srcu.awk Makefile $(modified_srcu_input)
13 awk -f modify_srcu.awk $(modified_srcu_input) $(modified_srcu_output)
14
15store_buffering:
16 @cd tests/store_buffering; make
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/delay.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/export.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/mutex.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/percpu.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/preempt.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/rcupdate.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/sched.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/smp.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/linux/workqueue.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/empty_includes/uapi/linux/types.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore
new file mode 100644
index 000000000000..1d016e66980a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/.gitignore
@@ -0,0 +1 @@
srcu.h
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h
new file mode 100644
index 000000000000..f2860dd1b407
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/kconfig.h
@@ -0,0 +1 @@
#include <LINUX_SOURCE/linux/kconfig.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
new file mode 100644
index 000000000000..4a3d538fef12
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/include/linux/types.h
@@ -0,0 +1,155 @@
1/*
2 * This header has been modifies to remove definitions of types that
3 * are defined in standard userspace headers or are problematic for some
4 * other reason.
5 */
6
7#ifndef _LINUX_TYPES_H
8#define _LINUX_TYPES_H
9
10#define __EXPORTED_HEADERS__
11#include <uapi/linux/types.h>
12
13#ifndef __ASSEMBLY__
14
15#define DECLARE_BITMAP(name, bits) \
16 unsigned long name[BITS_TO_LONGS(bits)]
17
18typedef __u32 __kernel_dev_t;
19
20/* bsd */
21typedef unsigned char u_char;
22typedef unsigned short u_short;
23typedef unsigned int u_int;
24typedef unsigned long u_long;
25
26/* sysv */
27typedef unsigned char unchar;
28typedef unsigned short ushort;
29typedef unsigned int uint;
30typedef unsigned long ulong;
31
32#ifndef __BIT_TYPES_DEFINED__
33#define __BIT_TYPES_DEFINED__
34
35typedef __u8 u_int8_t;
36typedef __s8 int8_t;
37typedef __u16 u_int16_t;
38typedef __s16 int16_t;
39typedef __u32 u_int32_t;
40typedef __s32 int32_t;
41
42#endif /* !(__BIT_TYPES_DEFINED__) */
43
44typedef __u8 uint8_t;
45typedef __u16 uint16_t;
46typedef __u32 uint32_t;
47
48/* this is a special 64bit data type that is 8-byte aligned */
49#define aligned_u64 __u64 __attribute__((aligned(8)))
50#define aligned_be64 __be64 __attribute__((aligned(8)))
51#define aligned_le64 __le64 __attribute__((aligned(8)))
52
53/**
54 * The type used for indexing onto a disc or disc partition.
55 *
56 * Linux always considers sectors to be 512 bytes long independently
57 * of the devices real block size.
58 *
59 * blkcnt_t is the type of the inode's block count.
60 */
61#ifdef CONFIG_LBDAF
62typedef u64 sector_t;
63#else
64typedef unsigned long sector_t;
65#endif
66
67/*
68 * The type of an index into the pagecache.
69 */
70#define pgoff_t unsigned long
71
72/*
73 * A dma_addr_t can hold any valid DMA address, i.e., any address returned
74 * by the DMA API.
75 *
76 * If the DMA API only uses 32-bit addresses, dma_addr_t need only be 32
77 * bits wide. Bus addresses, e.g., PCI BARs, may be wider than 32 bits,
78 * but drivers do memory-mapped I/O to ioremapped kernel virtual addresses,
79 * so they don't care about the size of the actual bus addresses.
80 */
81#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
82typedef u64 dma_addr_t;
83#else
84typedef u32 dma_addr_t;
85#endif
86
87#ifdef CONFIG_PHYS_ADDR_T_64BIT
88typedef u64 phys_addr_t;
89#else
90typedef u32 phys_addr_t;
91#endif
92
93typedef phys_addr_t resource_size_t;
94
95/*
96 * This type is the placeholder for a hardware interrupt number. It has to be
97 * big enough to enclose whatever representation is used by a given platform.
98 */
99typedef unsigned long irq_hw_number_t;
100
101typedef struct {
102 int counter;
103} atomic_t;
104
105#ifdef CONFIG_64BIT
106typedef struct {
107 long counter;
108} atomic64_t;
109#endif
110
111struct list_head {
112 struct list_head *next, *prev;
113};
114
115struct hlist_head {
116 struct hlist_node *first;
117};
118
119struct hlist_node {
120 struct hlist_node *next, **pprev;
121};
122
123/**
124 * struct callback_head - callback structure for use with RCU and task_work
125 * @next: next update requests in a list
126 * @func: actual update function to call after the grace period.
127 *
128 * The struct is aligned to size of pointer. On most architectures it happens
129 * naturally due ABI requirements, but some architectures (like CRIS) have
130 * weird ABI and we need to ask it explicitly.
131 *
132 * The alignment is required to guarantee that bits 0 and 1 of @next will be
133 * clear under normal conditions -- as long as we use call_rcu(),
134 * call_rcu_bh(), call_rcu_sched(), or call_srcu() to queue callback.
135 *
136 * This guarantee is important for few reasons:
137 * - future call_rcu_lazy() will make use of lower bits in the pointer;
138 * - the structure shares storage spacer in struct page with @compound_head,
139 * which encode PageTail() in bit 0. The guarantee is needed to avoid
140 * false-positive PageTail().
141 */
142struct callback_head {
143 struct callback_head *next;
144 void (*func)(struct callback_head *head);
145} __attribute__((aligned(sizeof(void *))));
146#define rcu_head callback_head
147
148typedef void (*rcu_callback_t)(struct rcu_head *head);
149typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
150
151/* clocksource cycle base type */
152typedef u64 cycle_t;
153
154#endif /* __ASSEMBLY__ */
155#endif /* _LINUX_TYPES_H */
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
new file mode 100755
index 000000000000..8ff89043d0a9
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/modify_srcu.awk
@@ -0,0 +1,375 @@
1#!/bin/awk -f
2
3# Modify SRCU for formal verification. The first argument should be srcu.h and
4# the second should be srcu.c. Outputs modified srcu.h and srcu.c into the
5# current directory.
6
7BEGIN {
8 if (ARGC != 5) {
9 print "Usange: input.h input.c output.h output.c" > "/dev/stderr";
10 exit 1;
11 }
12 h_output = ARGV[3];
13 c_output = ARGV[4];
14 ARGC = 3;
15
16 # Tokenize using FS and not RS as FS supports regular expressions. Each
17 # record is one line of source, except that backslashed lines are
18 # combined. Comments are treated as field separators, as are quotes.
19 quote_regexp="\"([^\\\\\"]|\\\\.)*\"";
20 comment_regexp="\\/\\*([^*]|\\*+[^*/])*\\*\\/|\\/\\/.*(\n|$)";
21 FS="([ \\\\\t\n\v\f;,.=(){}+*/<>&|^-]|\\[|\\]|" comment_regexp "|" quote_regexp ")+";
22
23 inside_srcu_struct = 0;
24 inside_srcu_init_def = 0;
25 srcu_init_param_name = "";
26 in_macro = 0;
27 brace_nesting = 0;
28 paren_nesting = 0;
29
30 # Allow the manipulation of the last field separator after has been
31 # seen.
32 last_fs = "";
33 # Whether the last field separator was intended to be output.
34 last_fs_print = 0;
35
36 # rcu_batches stores the initialization for each instance of struct
37 # rcu_batch
38
39 in_comment = 0;
40
41 outputfile = "";
42}
43
44{
45 prev_outputfile = outputfile;
46 if (FILENAME ~ /\.h$/) {
47 outputfile = h_output;
48 if (FNR != NR) {
49 print "Incorrect file order" > "/dev/stderr";
50 exit 1;
51 }
52 }
53 else
54 outputfile = c_output;
55
56 if (prev_outputfile && outputfile != prev_outputfile) {
57 new_outputfile = outputfile;
58 outputfile = prev_outputfile;
59 update_fieldsep("", 0);
60 outputfile = new_outputfile;
61 }
62}
63
64# Combine the next line into $0.
65function combine_line() {
66 ret = getline next_line;
67 if (ret == 0) {
68 # Don't allow two consecutive getlines at the end of the file
69 if (eof_found) {
70 print "Error: expected more input." > "/dev/stderr";
71 exit 1;
72 } else {
73 eof_found = 1;
74 }
75 } else if (ret == -1) {
76 print "Error reading next line of file" FILENAME > "/dev/stderr";
77 exit 1;
78 }
79 $0 = $0 "\n" next_line;
80}
81
82# Combine backslashed lines and multiline comments.
83function combine_backslashes() {
84 while (/\\$|\/\*([^*]|\*+[^*\/])*\**$/) {
85 combine_line();
86 }
87}
88
89function read_line() {
90 combine_line();
91 combine_backslashes();
92}
93
94# Print out field separators and update variables that depend on them. Only
95# print if p is true. Call with sep="" and p=0 to print out the last field
96# separator.
97function update_fieldsep(sep, p) {
98 # Count braces
99 sep_tmp = sep;
100 gsub(quote_regexp "|" comment_regexp, "", sep_tmp);
101 while (1)
102 {
103 if (sub("[^{}()]*\\{", "", sep_tmp)) {
104 brace_nesting++;
105 continue;
106 }
107 if (sub("[^{}()]*\\}", "", sep_tmp)) {
108 brace_nesting--;
109 if (brace_nesting < 0) {
110 print "Unbalanced braces!" > "/dev/stderr";
111 exit 1;
112 }
113 continue;
114 }
115 if (sub("[^{}()]*\\(", "", sep_tmp)) {
116 paren_nesting++;
117 continue;
118 }
119 if (sub("[^{}()]*\\)", "", sep_tmp)) {
120 paren_nesting--;
121 if (paren_nesting < 0) {
122 print "Unbalanced parenthesis!" > "/dev/stderr";
123 exit 1;
124 }
125 continue;
126 }
127
128 break;
129 }
130
131 if (last_fs_print)
132 printf("%s", last_fs) > outputfile;
133 last_fs = sep;
134 last_fs_print = p;
135}
136
137# Shifts the fields down by n positions. Calls next if there are no more. If p
138# is true then print out field separators.
139function shift_fields(n, p) {
140 do {
141 if (match($0, FS) > 0) {
142 update_fieldsep(substr($0, RSTART, RLENGTH), p);
143 if (RSTART + RLENGTH <= length())
144 $0 = substr($0, RSTART + RLENGTH);
145 else
146 $0 = "";
147 } else {
148 update_fieldsep("", 0);
149 print "" > outputfile;
150 next;
151 }
152 } while (--n > 0);
153}
154
155# Shifts and prints the first n fields.
156function print_fields(n) {
157 do {
158 update_fieldsep("", 0);
159 printf("%s", $1) > outputfile;
160 shift_fields(1, 1);
161 } while (--n > 0);
162}
163
164{
165 combine_backslashes();
166}
167
168# Print leading FS
169{
170 if (match($0, "^(" FS ")+") > 0) {
171 update_fieldsep(substr($0, RSTART, RLENGTH), 1);
172 if (RSTART + RLENGTH <= length())
173 $0 = substr($0, RSTART + RLENGTH);
174 else
175 $0 = "";
176 }
177}
178
179# Parse the line.
180{
181 while (NF > 0) {
182 if ($1 == "struct" && NF < 3) {
183 read_line();
184 continue;
185 }
186
187 if (FILENAME ~ /\.h$/ && !inside_srcu_struct &&
188 brace_nesting == 0 && paren_nesting == 0 &&
189 $1 == "struct" && $2 == "srcu_struct" &&
190 $0 ~ "^struct(" FS ")+srcu_struct(" FS ")+\\{") {
191 inside_srcu_struct = 1;
192 print_fields(2);
193 continue;
194 }
195 if (inside_srcu_struct && brace_nesting == 0 &&
196 paren_nesting == 0) {
197 inside_srcu_struct = 0;
198 update_fieldsep("", 0);
199 for (name in rcu_batches)
200 print "extern struct rcu_batch " name ";" > outputfile;
201 }
202
203 if (inside_srcu_struct && $1 == "struct" && $2 == "rcu_batch") {
204 # Move rcu_batches outside of the struct.
205 rcu_batches[$3] = "";
206 shift_fields(3, 1);
207 sub(/;[[:space:]]*$/, "", last_fs);
208 continue;
209 }
210
211 if (FILENAME ~ /\.h$/ && !inside_srcu_init_def &&
212 $1 == "#define" && $2 == "__SRCU_STRUCT_INIT") {
213 inside_srcu_init_def = 1;
214 srcu_init_param_name = $3;
215 in_macro = 1;
216 print_fields(3);
217 continue;
218 }
219 if (inside_srcu_init_def && brace_nesting == 0 &&
220 paren_nesting == 0) {
221 inside_srcu_init_def = 0;
222 in_macro = 0;
223 continue;
224 }
225
226 if (inside_srcu_init_def && brace_nesting == 1 &&
227 paren_nesting == 0 && last_fs ~ /\.[[:space:]]*$/ &&
228 $1 ~ /^[[:alnum:]_]+$/) {
229 name = $1;
230 if (name in rcu_batches) {
231 # Remove the dot.
232 sub(/\.[[:space:]]*$/, "", last_fs);
233
234 old_record = $0;
235 do
236 shift_fields(1, 0);
237 while (last_fs !~ /,/ || paren_nesting > 0);
238 end_loc = length(old_record) - length($0);
239 end_loc += index(last_fs, ",") - length(last_fs);
240
241 last_fs = substr(last_fs, index(last_fs, ",") + 1);
242 last_fs_print = 1;
243
244 match(old_record, "^"name"("FS")+=");
245 start_loc = RSTART + RLENGTH;
246
247 len = end_loc - start_loc;
248 initializer = substr(old_record, start_loc, len);
249 gsub(srcu_init_param_name "\\.", "", initializer);
250 rcu_batches[name] = initializer;
251 continue;
252 }
253 }
254
255 # Don't include a nonexistent file
256 if (!in_macro && $1 == "#include" && /^#include[[:space:]]+"rcu\.h"/) {
257 update_fieldsep("", 0);
258 next;
259 }
260
261 # Ignore most preprocessor stuff.
262 if (!in_macro && $1 ~ /#/) {
263 break;
264 }
265
266 if (brace_nesting > 0 && $1 ~ "^[[:alnum:]_]+$" && NF < 2) {
267 read_line();
268 continue;
269 }
270 if (brace_nesting > 0 &&
271 $0 ~ "^[[:alnum:]_]+[[:space:]]*(\\.|->)[[:space:]]*[[:alnum:]_]+" &&
272 $2 in rcu_batches) {
273 # Make uses of rcu_batches global. Somewhat unreliable.
274 shift_fields(1, 0);
275 print_fields(1);
276 continue;
277 }
278
279 if ($1 == "static" && NF < 3) {
280 read_line();
281 continue;
282 }
283 if ($1 == "static" && ($2 == "bool" && $3 == "try_check_zero" ||
284 $2 == "void" && $3 == "srcu_flip")) {
285 shift_fields(1, 1);
286 print_fields(2);
287 continue;
288 }
289
290 # Distinguish between read-side and write-side memory barriers.
291 if ($1 == "smp_mb" && NF < 2) {
292 read_line();
293 continue;
294 }
295 if (match($0, /^smp_mb[[:space:]();\/*]*[[:alnum:]]/)) {
296 barrier_letter = substr($0, RLENGTH, 1);
297 if (barrier_letter ~ /A|D/)
298 new_barrier_name = "sync_smp_mb";
299 else if (barrier_letter ~ /B|C/)
300 new_barrier_name = "rs_smp_mb";
301 else {
302 print "Unrecognized memory barrier." > "/dev/null";
303 exit 1;
304 }
305
306 shift_fields(1, 1);
307 printf("%s", new_barrier_name) > outputfile;
308 continue;
309 }
310
311 # Skip definition of rcu_synchronize, since it is already
312 # defined in misc.h. Only present in old versions of srcu.
313 if (brace_nesting == 0 && paren_nesting == 0 &&
314 $1 == "struct" && $2 == "rcu_synchronize" &&
315 $0 ~ "^struct(" FS ")+rcu_synchronize(" FS ")+\\{") {
316 shift_fields(2, 0);
317 while (brace_nesting) {
318 if (NF < 2)
319 read_line();
320 shift_fields(1, 0);
321 }
322 }
323
324 # Skip definition of wakeme_after_rcu for the same reason
325 if (brace_nesting == 0 && $1 == "static" && $2 == "void" &&
326 $3 == "wakeme_after_rcu") {
327 while (NF < 5)
328 read_line();
329 shift_fields(3, 0);
330 do {
331 while (NF < 3)
332 read_line();
333 shift_fields(1, 0);
334 } while (paren_nesting || brace_nesting);
335 }
336
337 if ($1 ~ /^(unsigned|long)$/ && NF < 3) {
338 read_line();
339 continue;
340 }
341
342 # Give srcu_batches_completed the correct type for old SRCU.
343 if (brace_nesting == 0 && $1 == "long" &&
344 $2 == "srcu_batches_completed") {
345 update_fieldsep("", 0);
346 printf("unsigned ") > outputfile;
347 print_fields(2);
348 continue;
349 }
350 if (brace_nesting == 0 && $1 == "unsigned" && $2 == "long" &&
351 $3 == "srcu_batches_completed") {
352 print_fields(3);
353 continue;
354 }
355
356 # Just print out the input code by default.
357 print_fields(1);
358 }
359 update_fieldsep("", 0);
360 print > outputfile;
361 next;
362}
363
364END {
365 update_fieldsep("", 0);
366
367 if (brace_nesting != 0) {
368 print "Unbalanced braces!" > "/dev/stderr";
369 exit 1;
370 }
371
372 # Define the rcu_batches
373 for (name in rcu_batches)
374 print "struct rcu_batch " name " = " rcu_batches[name] ";" > c_output;
375}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
new file mode 100644
index 000000000000..a64955447995
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/assume.h
@@ -0,0 +1,16 @@
1#ifndef ASSUME_H
2#define ASSUME_H
3
4/* Provide an assumption macro that can be disabled for gcc. */
5#ifdef RUN
6#define assume(x) \
7 do { \
8 /* Evaluate x to suppress warnings. */ \
9 (void) (x); \
10 } while (0)
11
12#else
13#define assume(x) __CPROVER_assume(x)
14#endif
15
16#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
new file mode 100644
index 000000000000..6687acc08e6d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/barriers.h
@@ -0,0 +1,41 @@
1#ifndef BARRIERS_H
2#define BARRIERS_H
3
4#define barrier() __asm__ __volatile__("" : : : "memory")
5
6#ifdef RUN
7#define smp_mb() __sync_synchronize()
8#define smp_mb__after_unlock_lock() __sync_synchronize()
9#else
10/*
11 * Copied from CBMC's implementation of __sync_synchronize(), which
12 * seems to be disabled by default.
13 */
14#define smp_mb() __CPROVER_fence("WWfence", "RRfence", "RWfence", "WRfence", \
15 "WWcumul", "RRcumul", "RWcumul", "WRcumul")
16#define smp_mb__after_unlock_lock() __CPROVER_fence("WWfence", "RRfence", "RWfence", "WRfence", \
17 "WWcumul", "RRcumul", "RWcumul", "WRcumul")
18#endif
19
20/*
21 * Allow memory barriers to be disabled in either the read or write side
22 * of SRCU individually.
23 */
24
25#ifndef NO_SYNC_SMP_MB
26#define sync_smp_mb() smp_mb()
27#else
28#define sync_smp_mb() do {} while (0)
29#endif
30
31#ifndef NO_READ_SIDE_SMP_MB
32#define rs_smp_mb() smp_mb()
33#else
34#define rs_smp_mb() do {} while (0)
35#endif
36
37#define ACCESS_ONCE(x) (*(volatile typeof(x) *) &(x))
38#define READ_ONCE(x) ACCESS_ONCE(x)
39#define WRITE_ONCE(x, val) (ACCESS_ONCE(x) = (val))
40
41#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
new file mode 100644
index 000000000000..2a80e91f78e7
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/bug_on.h
@@ -0,0 +1,13 @@
1#ifndef BUG_ON_H
2#define BUG_ON_H
3
4#include <assert.h>
5
6#define BUG() assert(0)
7#define BUG_ON(x) assert(!(x))
8
9/* Does it make sense to treat warnings as errors? */
10#define WARN() BUG()
11#define WARN_ON(x) (BUG_ON(x), false)
12
13#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
new file mode 100644
index 000000000000..29eb5d2697ed
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/combined_source.c
@@ -0,0 +1,13 @@
1#include <config.h>
2
3/* Include all source files. */
4
5#include "include_srcu.c"
6
7#include "preempt.c"
8#include "misc.c"
9
10/* Used by test.c files */
11#include <pthread.h>
12#include <stdlib.h>
13#include <linux/srcu.h>
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
new file mode 100644
index 000000000000..a60038aeea7a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/config.h
@@ -0,0 +1,27 @@
1/* "Cheater" definitions based on restricted Kconfig choices. */
2
3#undef CONFIG_TINY_RCU
4#undef __CHECKER__
5#undef CONFIG_DEBUG_LOCK_ALLOC
6#undef CONFIG_DEBUG_OBJECTS_RCU_HEAD
7#undef CONFIG_HOTPLUG_CPU
8#undef CONFIG_MODULES
9#undef CONFIG_NO_HZ_FULL_SYSIDLE
10#undef CONFIG_PREEMPT_COUNT
11#undef CONFIG_PREEMPT_RCU
12#undef CONFIG_PROVE_RCU
13#undef CONFIG_RCU_NOCB_CPU
14#undef CONFIG_RCU_NOCB_CPU_ALL
15#undef CONFIG_RCU_STALL_COMMON
16#undef CONFIG_RCU_TRACE
17#undef CONFIG_RCU_USER_QS
18#undef CONFIG_TASKS_RCU
19#define CONFIG_TREE_RCU
20
21#define CONFIG_GENERIC_ATOMIC64
22
23#if NR_CPUS > 1
24#define CONFIG_SMP
25#else
26#undef CONFIG_SMP
27#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
new file mode 100644
index 000000000000..5ec582a53018
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/include_srcu.c
@@ -0,0 +1,31 @@
1#include <config.h>
2
3#include <assert.h>
4#include <errno.h>
5#include <inttypes.h>
6#include <pthread.h>
7#include <stddef.h>
8#include <string.h>
9#include <sys/types.h>
10
11#include "int_typedefs.h"
12
13#include "barriers.h"
14#include "bug_on.h"
15#include "locks.h"
16#include "misc.h"
17#include "preempt.h"
18#include "percpu.h"
19#include "workqueues.h"
20
21#ifdef USE_SIMPLE_SYNC_SRCU
22#define synchronize_srcu(sp) synchronize_srcu_original(sp)
23#endif
24
25#include <srcu.c>
26
27#ifdef USE_SIMPLE_SYNC_SRCU
28#undef synchronize_srcu
29
30#include "simple_sync_srcu.c"
31#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
new file mode 100644
index 000000000000..3aad63917858
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/int_typedefs.h
@@ -0,0 +1,33 @@
1#ifndef INT_TYPEDEFS_H
2#define INT_TYPEDEFS_H
3
4#include <inttypes.h>
5
6typedef int8_t s8;
7typedef uint8_t u8;
8typedef int16_t s16;
9typedef uint16_t u16;
10typedef int32_t s32;
11typedef uint32_t u32;
12typedef int64_t s64;
13typedef uint64_t u64;
14
15typedef int8_t __s8;
16typedef uint8_t __u8;
17typedef int16_t __s16;
18typedef uint16_t __u16;
19typedef int32_t __s32;
20typedef uint32_t __u32;
21typedef int64_t __s64;
22typedef uint64_t __u64;
23
24#define S8_C(x) INT8_C(x)
25#define U8_C(x) UINT8_C(x)
26#define S16_C(x) INT16_C(x)
27#define U16_C(x) UINT16_C(x)
28#define S32_C(x) INT32_C(x)
29#define U32_C(x) UINT32_C(x)
30#define S64_C(x) INT64_C(x)
31#define U64_C(x) UINT64_C(x)
32
33#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
new file mode 100644
index 000000000000..356004665576
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/locks.h
@@ -0,0 +1,220 @@
1#ifndef LOCKS_H
2#define LOCKS_H
3
4#include <limits.h>
5#include <pthread.h>
6#include <stdbool.h>
7
8#include "assume.h"
9#include "bug_on.h"
10#include "preempt.h"
11
12int nondet_int(void);
13
14#define __acquire(x)
15#define __acquires(x)
16#define __release(x)
17#define __releases(x)
18
19/* Only use one lock mechanism. Select which one. */
20#ifdef PTHREAD_LOCK
21struct lock_impl {
22 pthread_mutex_t mutex;
23};
24
25static inline void lock_impl_lock(struct lock_impl *lock)
26{
27 BUG_ON(pthread_mutex_lock(&lock->mutex));
28}
29
30static inline void lock_impl_unlock(struct lock_impl *lock)
31{
32 BUG_ON(pthread_mutex_unlock(&lock->mutex));
33}
34
35static inline bool lock_impl_trylock(struct lock_impl *lock)
36{
37 int err = pthread_mutex_trylock(&lock->mutex);
38
39 if (!err)
40 return true;
41 else if (err == EBUSY)
42 return false;
43 BUG();
44}
45
46static inline void lock_impl_init(struct lock_impl *lock)
47{
48 pthread_mutex_init(&lock->mutex, NULL);
49}
50
51#define LOCK_IMPL_INITIALIZER {.mutex = PTHREAD_MUTEX_INITIALIZER}
52
53#else /* !defined(PTHREAD_LOCK) */
54/* Spinlock that assumes that it always gets the lock immediately. */
55
56struct lock_impl {
57 bool locked;
58};
59
60static inline bool lock_impl_trylock(struct lock_impl *lock)
61{
62#ifdef RUN
63 /* TODO: Should this be a test and set? */
64 return __sync_bool_compare_and_swap(&lock->locked, false, true);
65#else
66 __CPROVER_atomic_begin();
67 bool old_locked = lock->locked;
68 lock->locked = true;
69 __CPROVER_atomic_end();
70
71 /* Minimal barrier to prevent accesses leaking out of lock. */
72 __CPROVER_fence("RRfence", "RWfence");
73
74 return !old_locked;
75#endif
76}
77
78static inline void lock_impl_lock(struct lock_impl *lock)
79{
80 /*
81 * CBMC doesn't support busy waiting, so just assume that the
82 * lock is available.
83 */
84 assume(lock_impl_trylock(lock));
85
86 /*
87 * If the lock was already held by this thread then the assumption
88 * is unsatisfiable (deadlock).
89 */
90}
91
92static inline void lock_impl_unlock(struct lock_impl *lock)
93{
94#ifdef RUN
95 BUG_ON(!__sync_bool_compare_and_swap(&lock->locked, true, false));
96#else
97 /* Minimal barrier to prevent accesses leaking out of lock. */
98 __CPROVER_fence("RWfence", "WWfence");
99
100 __CPROVER_atomic_begin();
101 bool old_locked = lock->locked;
102 lock->locked = false;
103 __CPROVER_atomic_end();
104
105 BUG_ON(!old_locked);
106#endif
107}
108
109static inline void lock_impl_init(struct lock_impl *lock)
110{
111 lock->locked = false;
112}
113
114#define LOCK_IMPL_INITIALIZER {.locked = false}
115
116#endif /* !defined(PTHREAD_LOCK) */
117
118/*
119 * Implement spinlocks using the lock mechanism. Wrap the lock to prevent mixing
120 * locks of different types.
121 */
122typedef struct {
123 struct lock_impl internal_lock;
124} spinlock_t;
125
126#define SPIN_LOCK_UNLOCKED {.internal_lock = LOCK_IMPL_INITIALIZER}
127#define __SPIN_LOCK_UNLOCKED(x) SPIN_LOCK_UNLOCKED
128#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
129
130static inline void spin_lock_init(spinlock_t *lock)
131{
132 lock_impl_init(&lock->internal_lock);
133}
134
135static inline void spin_lock(spinlock_t *lock)
136{
137 /*
138 * Spin locks also need to be removed in order to eliminate all
139 * memory barriers. They are only used by the write side anyway.
140 */
141#ifndef NO_SYNC_SMP_MB
142 preempt_disable();
143 lock_impl_lock(&lock->internal_lock);
144#endif
145}
146
147static inline void spin_unlock(spinlock_t *lock)
148{
149#ifndef NO_SYNC_SMP_MB
150 lock_impl_unlock(&lock->internal_lock);
151 preempt_enable();
152#endif
153}
154
155/* Don't bother with interrupts */
156#define spin_lock_irq(lock) spin_lock(lock)
157#define spin_unlock_irq(lock) spin_unlock(lock)
158#define spin_lock_irqsave(lock, flags) spin_lock(lock)
159#define spin_unlock_irqrestore(lock, flags) spin_unlock(lock)
160
161/*
162 * This is supposed to return an int, but I think that a bool should work as
163 * well.
164 */
165static inline bool spin_trylock(spinlock_t *lock)
166{
167#ifndef NO_SYNC_SMP_MB
168 preempt_disable();
169 return lock_impl_trylock(&lock->internal_lock);
170#else
171 return true;
172#endif
173}
174
175struct completion {
176 /* Hopefuly this won't overflow. */
177 unsigned int count;
178};
179
180#define COMPLETION_INITIALIZER(x) {.count = 0}
181#define DECLARE_COMPLETION(x) struct completion x = COMPLETION_INITIALIZER(x)
182#define DECLARE_COMPLETION_ONSTACK(x) DECLARE_COMPLETION(x)
183
184static inline void init_completion(struct completion *c)
185{
186 c->count = 0;
187}
188
189static inline void wait_for_completion(struct completion *c)
190{
191 unsigned int prev_count = __sync_fetch_and_sub(&c->count, 1);
192
193 assume(prev_count);
194}
195
196static inline void complete(struct completion *c)
197{
198 unsigned int prev_count = __sync_fetch_and_add(&c->count, 1);
199
200 BUG_ON(prev_count == UINT_MAX);
201}
202
203/* This function probably isn't very useful for CBMC. */
204static inline bool try_wait_for_completion(struct completion *c)
205{
206 BUG();
207}
208
209static inline bool completion_done(struct completion *c)
210{
211 return c->count;
212}
213
214/* TODO: Implement complete_all */
215static inline void complete_all(struct completion *c)
216{
217 BUG();
218}
219
220#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
new file mode 100644
index 000000000000..ca892e3b2351
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.c
@@ -0,0 +1,11 @@
1#include <config.h>
2
3#include "misc.h"
4#include "bug_on.h"
5
6struct rcu_head;
7
8void wakeme_after_rcu(struct rcu_head *head)
9{
10 BUG();
11}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h
new file mode 100644
index 000000000000..aca50030f954
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/misc.h
@@ -0,0 +1,58 @@
1#ifndef MISC_H
2#define MISC_H
3
4#include "assume.h"
5#include "int_typedefs.h"
6#include "locks.h"
7
8#include <linux/types.h>
9
10/* Probably won't need to deal with bottom halves. */
11static inline void local_bh_disable(void) {}
12static inline void local_bh_enable(void) {}
13
14#define MODULE_ALIAS(X)
15#define module_param(...)
16#define EXPORT_SYMBOL_GPL(x)
17
18#define container_of(ptr, type, member) ({ \
19 const typeof(((type *)0)->member) *__mptr = (ptr); \
20 (type *)((char *)__mptr - offsetof(type, member)); \
21})
22
23#ifndef USE_SIMPLE_SYNC_SRCU
24/* Abuse udelay to make sure that busy loops terminate. */
25#define udelay(x) assume(0)
26
27#else
28
29/* The simple custom synchronize_srcu is ok with try_check_zero failing. */
30#define udelay(x) do { } while (0)
31#endif
32
33#define trace_rcu_torture_read(rcutorturename, rhp, secs, c_old, c) \
34 do { } while (0)
35
36#define notrace
37
38/* Avoid including rcupdate.h */
39struct rcu_synchronize {
40 struct rcu_head head;
41 struct completion completion;
42};
43
44void wakeme_after_rcu(struct rcu_head *head);
45
46#define rcu_lock_acquire(a) do { } while (0)
47#define rcu_lock_release(a) do { } while (0)
48#define rcu_lockdep_assert(c, s) do { } while (0)
49#define RCU_LOCKDEP_WARN(c, s) do { } while (0)
50
51/* Let CBMC non-deterministically choose switch between normal and expedited. */
52bool rcu_gp_is_normal(void);
53bool rcu_gp_is_expedited(void);
54
55/* Do the same for old versions of rcu. */
56#define rcu_expedited (rcu_gp_is_expedited())
57
58#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
new file mode 100644
index 000000000000..3de5a49de49b
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/percpu.h
@@ -0,0 +1,92 @@
1#ifndef PERCPU_H
2#define PERCPU_H
3
4#include <stddef.h>
5#include "bug_on.h"
6#include "preempt.h"
7
8#define __percpu
9
10/* Maximum size of any percpu data. */
11#define PERCPU_OFFSET (4 * sizeof(long))
12
13/* Ignore alignment, as CBMC doesn't care about false sharing. */
14#define alloc_percpu(type) __alloc_percpu(sizeof(type), 1)
15
16static inline void *__alloc_percpu(size_t size, size_t align)
17{
18 BUG();
19 return NULL;
20}
21
22static inline void free_percpu(void *ptr)
23{
24 BUG();
25}
26
27#define per_cpu_ptr(ptr, cpu) \
28 ((typeof(ptr)) ((char *) (ptr) + PERCPU_OFFSET * cpu))
29
30#define __this_cpu_inc(pcp) __this_cpu_add(pcp, 1)
31#define __this_cpu_dec(pcp) __this_cpu_sub(pcp, 1)
32#define __this_cpu_sub(pcp, n) __this_cpu_add(pcp, -(typeof(pcp)) (n))
33
34#define this_cpu_inc(pcp) this_cpu_add(pcp, 1)
35#define this_cpu_dec(pcp) this_cpu_sub(pcp, 1)
36#define this_cpu_sub(pcp, n) this_cpu_add(pcp, -(typeof(pcp)) (n))
37
38/* Make CBMC use atomics to work around bug. */
39#ifdef RUN
40#define THIS_CPU_ADD_HELPER(ptr, x) (*(ptr) += (x))
41#else
42/*
43 * Split the atomic into a read and a write so that it has the least
44 * possible ordering.
45 */
46#define THIS_CPU_ADD_HELPER(ptr, x) \
47 do { \
48 typeof(ptr) this_cpu_add_helper_ptr = (ptr); \
49 typeof(ptr) this_cpu_add_helper_x = (x); \
50 typeof(*ptr) this_cpu_add_helper_temp; \
51 __CPROVER_atomic_begin(); \
52 this_cpu_add_helper_temp = *(this_cpu_add_helper_ptr); \
53 __CPROVER_atomic_end(); \
54 this_cpu_add_helper_temp += this_cpu_add_helper_x; \
55 __CPROVER_atomic_begin(); \
56 *(this_cpu_add_helper_ptr) = this_cpu_add_helper_temp; \
57 __CPROVER_atomic_end(); \
58 } while (0)
59#endif
60
61/*
62 * For some reason CBMC needs an atomic operation even though this is percpu
63 * data.
64 */
65#define __this_cpu_add(pcp, n) \
66 do { \
67 BUG_ON(preemptible()); \
68 THIS_CPU_ADD_HELPER(per_cpu_ptr(&(pcp), thread_cpu_id), \
69 (typeof(pcp)) (n)); \
70 } while (0)
71
72#define this_cpu_add(pcp, n) \
73 do { \
74 int this_cpu_add_impl_cpu = get_cpu(); \
75 THIS_CPU_ADD_HELPER(per_cpu_ptr(&(pcp), this_cpu_add_impl_cpu), \
76 (typeof(pcp)) (n)); \
77 put_cpu(); \
78 } while (0)
79
80/*
81 * This will cause a compiler warning because of the cast from char[][] to
82 * type*. This will cause a compile time error if type is too big.
83 */
84#define DEFINE_PER_CPU(type, name) \
85 char name[NR_CPUS][PERCPU_OFFSET]; \
86 typedef char percpu_too_big_##name \
87 [sizeof(type) > PERCPU_OFFSET ? -1 : 1]
88
89#define for_each_possible_cpu(cpu) \
90 for ((cpu) = 0; (cpu) < NR_CPUS; ++(cpu))
91
92#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
new file mode 100644
index 000000000000..4f1b068e9b7a
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.c
@@ -0,0 +1,78 @@
1#include <config.h>
2
3#include "preempt.h"
4
5#include "assume.h"
6#include "locks.h"
7
8/* Support NR_CPUS of at most 64 */
9#define CPU_PREEMPTION_LOCKS_INIT0 LOCK_IMPL_INITIALIZER
10#define CPU_PREEMPTION_LOCKS_INIT1 \
11 CPU_PREEMPTION_LOCKS_INIT0, CPU_PREEMPTION_LOCKS_INIT0
12#define CPU_PREEMPTION_LOCKS_INIT2 \
13 CPU_PREEMPTION_LOCKS_INIT1, CPU_PREEMPTION_LOCKS_INIT1
14#define CPU_PREEMPTION_LOCKS_INIT3 \
15 CPU_PREEMPTION_LOCKS_INIT2, CPU_PREEMPTION_LOCKS_INIT2
16#define CPU_PREEMPTION_LOCKS_INIT4 \
17 CPU_PREEMPTION_LOCKS_INIT3, CPU_PREEMPTION_LOCKS_INIT3
18#define CPU_PREEMPTION_LOCKS_INIT5 \
19 CPU_PREEMPTION_LOCKS_INIT4, CPU_PREEMPTION_LOCKS_INIT4
20
21/*
22 * Simulate disabling preemption by locking a particular cpu. NR_CPUS
23 * should be the actual number of cpus, not just the maximum.
24 */
25struct lock_impl cpu_preemption_locks[NR_CPUS] = {
26 CPU_PREEMPTION_LOCKS_INIT0
27#if (NR_CPUS - 1) & 1
28 , CPU_PREEMPTION_LOCKS_INIT0
29#endif
30#if (NR_CPUS - 1) & 2
31 , CPU_PREEMPTION_LOCKS_INIT1
32#endif
33#if (NR_CPUS - 1) & 4
34 , CPU_PREEMPTION_LOCKS_INIT2
35#endif
36#if (NR_CPUS - 1) & 8
37 , CPU_PREEMPTION_LOCKS_INIT3
38#endif
39#if (NR_CPUS - 1) & 16
40 , CPU_PREEMPTION_LOCKS_INIT4
41#endif
42#if (NR_CPUS - 1) & 32
43 , CPU_PREEMPTION_LOCKS_INIT5
44#endif
45};
46
47#undef CPU_PREEMPTION_LOCKS_INIT0
48#undef CPU_PREEMPTION_LOCKS_INIT1
49#undef CPU_PREEMPTION_LOCKS_INIT2
50#undef CPU_PREEMPTION_LOCKS_INIT3
51#undef CPU_PREEMPTION_LOCKS_INIT4
52#undef CPU_PREEMPTION_LOCKS_INIT5
53
54__thread int thread_cpu_id;
55__thread int preempt_disable_count;
56
57void preempt_disable(void)
58{
59 BUG_ON(preempt_disable_count < 0 || preempt_disable_count == INT_MAX);
60
61 if (preempt_disable_count++)
62 return;
63
64 thread_cpu_id = nondet_int();
65 assume(thread_cpu_id >= 0);
66 assume(thread_cpu_id < NR_CPUS);
67 lock_impl_lock(&cpu_preemption_locks[thread_cpu_id]);
68}
69
70void preempt_enable(void)
71{
72 BUG_ON(preempt_disable_count < 1);
73
74 if (--preempt_disable_count)
75 return;
76
77 lock_impl_unlock(&cpu_preemption_locks[thread_cpu_id]);
78}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
new file mode 100644
index 000000000000..2f95ee0e4dd5
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/preempt.h
@@ -0,0 +1,58 @@
1#ifndef PREEMPT_H
2#define PREEMPT_H
3
4#include <stdbool.h>
5
6#include "bug_on.h"
7
8/* This flag contains garbage if preempt_disable_count is 0. */
9extern __thread int thread_cpu_id;
10
11/* Support recursive preemption disabling. */
12extern __thread int preempt_disable_count;
13
14void preempt_disable(void);
15void preempt_enable(void);
16
17static inline void preempt_disable_notrace(void)
18{
19 preempt_disable();
20}
21
22static inline void preempt_enable_no_resched(void)
23{
24 preempt_enable();
25}
26
27static inline void preempt_enable_notrace(void)
28{
29 preempt_enable();
30}
31
32static inline int preempt_count(void)
33{
34 return preempt_disable_count;
35}
36
37static inline bool preemptible(void)
38{
39 return !preempt_count();
40}
41
42static inline int get_cpu(void)
43{
44 preempt_disable();
45 return thread_cpu_id;
46}
47
48static inline void put_cpu(void)
49{
50 preempt_enable();
51}
52
53static inline void might_sleep(void)
54{
55 BUG_ON(preempt_disable_count);
56}
57
58#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
new file mode 100644
index 000000000000..ac9cbc62b411
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/simple_sync_srcu.c
@@ -0,0 +1,50 @@
1#include <config.h>
2
3#include <assert.h>
4#include <errno.h>
5#include <inttypes.h>
6#include <pthread.h>
7#include <stddef.h>
8#include <string.h>
9#include <sys/types.h>
10
11#include "int_typedefs.h"
12
13#include "barriers.h"
14#include "bug_on.h"
15#include "locks.h"
16#include "misc.h"
17#include "preempt.h"
18#include "percpu.h"
19#include "workqueues.h"
20
21#include <linux/srcu.h>
22
23/* Functions needed from modify_srcu.c */
24bool try_check_zero(struct srcu_struct *sp, int idx, int trycount);
25void srcu_flip(struct srcu_struct *sp);
26
27/* Simpler implementation of synchronize_srcu that ignores batching. */
28void synchronize_srcu(struct srcu_struct *sp)
29{
30 int idx;
31 /*
32 * This code assumes that try_check_zero will succeed anyway,
33 * so there is no point in multiple tries.
34 */
35 const int trycount = 1;
36
37 might_sleep();
38
39 /* Ignore the lock, as multiple writers aren't working yet anyway. */
40
41 idx = 1 ^ (sp->completed & 1);
42
43 /* For comments see srcu_advance_batches. */
44
45 assume(try_check_zero(sp, idx, trycount));
46
47 srcu_flip(sp);
48
49 assume(try_check_zero(sp, idx^1, trycount));
50}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
new file mode 100644
index 000000000000..e58c8dfd3e90
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/src/workqueues.h
@@ -0,0 +1,102 @@
1#ifndef WORKQUEUES_H
2#define WORKQUEUES_H
3
4#include <stdbool.h>
5
6#include "barriers.h"
7#include "bug_on.h"
8#include "int_typedefs.h"
9
10#include <linux/types.h>
11
12/* Stub workqueue implementation. */
13
14struct work_struct;
15typedef void (*work_func_t)(struct work_struct *work);
16void delayed_work_timer_fn(unsigned long __data);
17
18struct work_struct {
19/* atomic_long_t data; */
20 unsigned long data;
21
22 struct list_head entry;
23 work_func_t func;
24#ifdef CONFIG_LOCKDEP
25 struct lockdep_map lockdep_map;
26#endif
27};
28
29struct timer_list {
30 struct hlist_node entry;
31 unsigned long expires;
32 void (*function)(unsigned long);
33 unsigned long data;
34 u32 flags;
35 int slack;
36};
37
38struct delayed_work {
39 struct work_struct work;
40 struct timer_list timer;
41
42 /* target workqueue and CPU ->timer uses to queue ->work */
43 struct workqueue_struct *wq;
44 int cpu;
45};
46
47
48static inline bool schedule_work(struct work_struct *work)
49{
50 BUG();
51 return true;
52}
53
54static inline bool schedule_work_on(int cpu, struct work_struct *work)
55{
56 BUG();
57 return true;
58}
59
60static inline bool queue_work(struct workqueue_struct *wq,
61 struct work_struct *work)
62{
63 BUG();
64 return true;
65}
66
67static inline bool queue_delayed_work(struct workqueue_struct *wq,
68 struct delayed_work *dwork,
69 unsigned long delay)
70{
71 BUG();
72 return true;
73}
74
75#define INIT_WORK(w, f) \
76 do { \
77 (w)->data = 0; \
78 (w)->func = (f); \
79 } while (0)
80
81#define INIT_DELAYED_WORK(w, f) INIT_WORK(&(w)->work, (f))
82
83#define __WORK_INITIALIZER(n, f) { \
84 .data = 0, \
85 .entry = { &(n).entry, &(n).entry }, \
86 .func = f \
87 }
88
89/* Don't bother initializing timer. */
90#define __DELAYED_WORK_INITIALIZER(n, f, tflags) { \
91 .work = __WORK_INITIALIZER((n).work, (f)), \
92 }
93
94#define DECLARE_WORK(n, f) \
95 struct workqueue_struct n = __WORK_INITIALIZER
96
97#define DECLARE_DELAYED_WORK(n, f) \
98 struct delayed_work n = __DELAYED_WORK_INITIALIZER(n, f, 0)
99
100#define system_power_efficient_wq ((struct workqueue_struct *) NULL)
101
102#endif
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore
new file mode 100644
index 000000000000..f47cb2045f13
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/.gitignore
@@ -0,0 +1 @@
*.out
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
new file mode 100644
index 000000000000..3a3aee149225
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/Makefile
@@ -0,0 +1,11 @@
1CBMC_FLAGS = -I../.. -I../../src -I../../include -I../../empty_includes -32 -pointer-check -mm pso
2
3all:
4 for i in ./*.pass; do \
5 echo $$i ; \
6 CBMC_FLAGS="$(CBMC_FLAGS)" sh ../test_script.sh --should-pass $$i > $$i.out 2>&1 ; \
7 done
8 for i in ./*.fail; do \
9 echo $$i ; \
10 CBMC_FLAGS="$(CBMC_FLAGS)" sh ../test_script.sh --should-fail $$i > $$i.out 2>&1 ; \
11 done
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail
new file mode 100644
index 000000000000..40c8075919d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/assert_end.fail
@@ -0,0 +1 @@
test_cbmc_options="-DASSERT_END"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail
new file mode 100644
index 000000000000..ada5baf0b60d
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail
new file mode 100644
index 000000000000..8fe00c8db466
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force2.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE_2"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail
new file mode 100644
index 000000000000..612ed6772844
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/force3.fail
@@ -0,0 +1 @@
test_cbmc_options="-DFORCE_FAILURE_3"
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/main.pass
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
new file mode 100644
index 000000000000..470b1105a112
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/store_buffering/test.c
@@ -0,0 +1,72 @@
1#include <src/combined_source.c>
2
3int x;
4int y;
5
6int __unbuffered_tpr_x;
7int __unbuffered_tpr_y;
8
9DEFINE_SRCU(ss);
10
11void rcu_reader(void)
12{
13 int idx;
14
15#ifndef FORCE_FAILURE_3
16 idx = srcu_read_lock(&ss);
17#endif
18 might_sleep();
19
20 __unbuffered_tpr_y = READ_ONCE(y);
21#ifdef FORCE_FAILURE
22 srcu_read_unlock(&ss, idx);
23 idx = srcu_read_lock(&ss);
24#endif
25 WRITE_ONCE(x, 1);
26
27#ifndef FORCE_FAILURE_3
28 srcu_read_unlock(&ss, idx);
29#endif
30 might_sleep();
31}
32
33void *thread_update(void *arg)
34{
35 WRITE_ONCE(y, 1);
36#ifndef FORCE_FAILURE_2
37 synchronize_srcu(&ss);
38#endif
39 might_sleep();
40 __unbuffered_tpr_x = READ_ONCE(x);
41
42 return NULL;
43}
44
45void *thread_process_reader(void *arg)
46{
47 rcu_reader();
48
49 return NULL;
50}
51
52int main(int argc, char *argv[])
53{
54 pthread_t tu;
55 pthread_t tpr;
56
57 if (pthread_create(&tu, NULL, thread_update, NULL))
58 abort();
59 if (pthread_create(&tpr, NULL, thread_process_reader, NULL))
60 abort();
61 if (pthread_join(tu, NULL))
62 abort();
63 if (pthread_join(tpr, NULL))
64 abort();
65 assert(__unbuffered_tpr_y != 0 || __unbuffered_tpr_x != 0);
66
67#ifdef ASSERT_END
68 assert(0);
69#endif
70
71 return 0;
72}
diff --git a/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
new file mode 100755
index 000000000000..d1545972a0fa
--- /dev/null
+++ b/tools/testing/selftests/rcutorture/formal/srcu-cbmc/tests/test_script.sh
@@ -0,0 +1,102 @@
1#!/bin/sh
2
3# This script expects a mode (either --should-pass or --should-fail) followed by
4# an input file. The script uses the following environment variables. The test C
5# source file is expected to be named test.c in the directory containing the
6# input file.
7#
8# CBMC: The command to run CBMC. Default: cbmc
9# CBMC_FLAGS: Additional flags to pass to CBMC
10# NR_CPUS: Number of cpus to run tests with. Default specified by the test
11# SYNC_SRCU_MODE: Choose implementation of synchronize_srcu. Defaults to simple.
12# kernel: Version included in the linux kernel source.
13# simple: Use try_check_zero directly.
14#
15# The input file is a script that is sourced by this file. It can define any of
16# the following variables to configure the test.
17#
18# test_cbmc_options: Extra options to pass to CBMC.
19# min_cpus_fail: Minimum number of CPUs (NR_CPUS) for verification to fail.
20# The test is expected to pass if it is run with fewer. (Only
21# useful for .fail files)
22# default_cpus: Quantity of CPUs to use for the test, if not specified on the
23# command line. Default: Larger of 2 and MIN_CPUS_FAIL.
24
25set -e
26
27if test "$#" -ne 2; then
28 echo "Expected one option followed by an input file" 1>&2
29 exit 99
30fi
31
32if test "x$1" = "x--should-pass"; then
33 should_pass="yes"
34elif test "x$1" = "x--should-fail"; then
35 should_pass="no"
36else
37 echo "Unrecognized argument '$1'" 1>&2
38
39 # Exit code 99 indicates a hard error.
40 exit 99
41fi
42
43CBMC=${CBMC:-cbmc}
44
45SYNC_SRCU_MODE=${SYNC_SRCU_MODE:-simple}
46
47case ${SYNC_SRCU_MODE} in
48kernel) sync_srcu_mode_flags="" ;;
49simple) sync_srcu_mode_flags="-DUSE_SIMPLE_SYNC_SRCU" ;;
50
51*)
52 echo "Unrecognized argument '${SYNC_SRCU_MODE}'" 1>&2
53 exit 99
54 ;;
55esac
56
57min_cpus_fail=1
58
59c_file=`dirname "$2"`/test.c
60
61# Source the input file.
62. $2
63
64if test ${min_cpus_fail} -gt 2; then
65 default_default_cpus=${min_cpus_fail}
66else
67 default_default_cpus=2
68fi
69default_cpus=${default_cpus:-${default_default_cpus}}
70cpus=${NR_CPUS:-${default_cpus}}
71
72# Check if there are two few cpus to make the test fail.
73if test $cpus -lt ${min_cpus_fail:-0}; then
74 should_pass="yes"
75fi
76
77cbmc_opts="-DNR_CPUS=${cpus} ${sync_srcu_mode_flags} ${test_cbmc_options} ${CBMC_FLAGS}"
78
79echo "Running CBMC: ${CBMC} ${cbmc_opts} ${c_file}"
80if ${CBMC} ${cbmc_opts} "${c_file}"; then
81 # Verification successful. Make sure that it was supposed to verify.
82 test "x${should_pass}" = xyes
83else
84 cbmc_exit_status=$?
85
86 # An exit status of 10 indicates a failed verification.
87 # (see cbmc_parse_optionst::do_bmc in the CBMC source code)
88 if test ${cbmc_exit_status} -eq 10 && test "x${should_pass}" = xno; then
89 :
90 else
91 echo "CBMC returned ${cbmc_exit_status} exit status" 1>&2
92
93 # Parse errors have exit status 6. Any other type of error
94 # should be considered a hard error.
95 if test ${cbmc_exit_status} -ne 6 && \
96 test ${cbmc_exit_status} -ne 10; then
97 exit 99
98 else
99 exit 1
100 fi
101 fi
102fi