|
@@ -690,3 +690,87 @@ static void rcu_spawn_tasks_kthread(void)
|
|
|
}
|
|
|
|
|
|
#endif /* #ifdef CONFIG_TASKS_RCU */
|
|
|
+
|
|
|
+#ifdef CONFIG_PROVE_RCU
|
|
|
+
|
|
|
+/*
|
|
|
+ * Early boot self test parameters, one for each flavor
|
|
|
+ */
|
|
|
+static bool rcu_self_test;
|
|
|
+static bool rcu_self_test_bh;
|
|
|
+static bool rcu_self_test_sched;
|
|
|
+
|
|
|
+module_param(rcu_self_test, bool, 0444);
|
|
|
+module_param(rcu_self_test_bh, bool, 0444);
|
|
|
+module_param(rcu_self_test_sched, bool, 0444);
|
|
|
+
|
|
|
+static int rcu_self_test_counter;
|
|
|
+
|
|
|
+static void test_callback(struct rcu_head *r)
|
|
|
+{
|
|
|
+ rcu_self_test_counter++;
|
|
|
+ pr_info("RCU test callback executed %d\n", rcu_self_test_counter);
|
|
|
+}
|
|
|
+
|
|
|
+static void early_boot_test_call_rcu(void)
|
|
|
+{
|
|
|
+ static struct rcu_head head;
|
|
|
+
|
|
|
+ call_rcu(&head, test_callback);
|
|
|
+}
|
|
|
+
|
|
|
+static void early_boot_test_call_rcu_bh(void)
|
|
|
+{
|
|
|
+ static struct rcu_head head;
|
|
|
+
|
|
|
+ call_rcu_bh(&head, test_callback);
|
|
|
+}
|
|
|
+
|
|
|
+static void early_boot_test_call_rcu_sched(void)
|
|
|
+{
|
|
|
+ static struct rcu_head head;
|
|
|
+
|
|
|
+ call_rcu_sched(&head, test_callback);
|
|
|
+}
|
|
|
+
|
|
|
+void rcu_early_boot_tests(void)
|
|
|
+{
|
|
|
+ pr_info("Running RCU self tests\n");
|
|
|
+
|
|
|
+ if (rcu_self_test)
|
|
|
+ early_boot_test_call_rcu();
|
|
|
+ if (rcu_self_test_bh)
|
|
|
+ early_boot_test_call_rcu_bh();
|
|
|
+ if (rcu_self_test_sched)
|
|
|
+ early_boot_test_call_rcu_sched();
|
|
|
+}
|
|
|
+
|
|
|
+static int rcu_verify_early_boot_tests(void)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ int early_boot_test_counter = 0;
|
|
|
+
|
|
|
+ if (rcu_self_test) {
|
|
|
+ early_boot_test_counter++;
|
|
|
+ rcu_barrier();
|
|
|
+ }
|
|
|
+ if (rcu_self_test_bh) {
|
|
|
+ early_boot_test_counter++;
|
|
|
+ rcu_barrier_bh();
|
|
|
+ }
|
|
|
+ if (rcu_self_test_sched) {
|
|
|
+ early_boot_test_counter++;
|
|
|
+ rcu_barrier_sched();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rcu_self_test_counter != early_boot_test_counter) {
|
|
|
+ WARN_ON(1);
|
|
|
+ ret = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+late_initcall(rcu_verify_early_boot_tests);
|
|
|
+#else
|
|
|
+void rcu_early_boot_tests(void) {}
|
|
|
+#endif /* CONFIG_PROVE_RCU */
|