Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rv/monitor: Add the wwnr monitor

Per task wakeup while not running (wwnr) monitor.

This model is broken, the reason is that a task can be running in the
processor without being set as RUNNABLE. Think about a task about to
sleep:

1: set_current_state(TASK_UNINTERRUPTIBLE);
2: schedule();

And then imagine an IRQ happening in between the lines one and two,
waking the task up. BOOM, the wakeup will happen while the task is
running.

Q: Why do we need this model, so?
A: To test the reactors.

Link: https://lkml.kernel.org/r/473c0fc39967250fdebcff8b620311c11dccad30.1659052063.git.bristot@kernel.org

Cc: Wim Van Sebroeck <wim@linux-watchdog.org>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marco Elver <elver@google.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Shuah Khan <skhan@linuxfoundation.org>
Cc: Gabriele Paoloni <gpaoloni@redhat.com>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: Tao Zhou <tao.zhou@linux.dev>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-trace-devel@vger.kernel.org
Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Daniel Bristot de Oliveira and committed by
Steven Rostedt (Google)
ccc319dc 10bde81c

+220
+1
Documentation/trace/rv/index.rst
··· 11 11 da_monitor_synthesis.rst 12 12 da_monitor_instrumentation.rst 13 13 monitor_wip.rst 14 + monitor_wwnr.rst
+45
Documentation/trace/rv/monitor_wwnr.rst
··· 1 + Monitor wwnr 2 + ============ 3 + 4 + - Name: wwrn - wakeup while not running 5 + - Type: per-task deterministic automaton 6 + - Author: Daniel Bristot de Oliveira <bristot@kernel.org> 7 + 8 + Description 9 + ----------- 10 + 11 + This is a per-task sample monitor, with the following 12 + definition:: 13 + 14 + | 15 + | 16 + v 17 + wakeup +-------------+ 18 + +--------- | | 19 + | | not_running | 20 + +--------> | | <+ 21 + +-------------+ | 22 + | | 23 + | switch_in | switch_out 24 + v | 25 + +-------------+ | 26 + | running | -+ 27 + +-------------+ 28 + 29 + This model is borken, the reason is that a task can be running 30 + in the processor without being set as RUNNABLE. Think about a 31 + task about to sleep:: 32 + 33 + 1: set_current_state(TASK_UNINTERRUPTIBLE); 34 + 2: schedule(); 35 + 36 + And then imagine an IRQ happening in between the lines one and two, 37 + waking the task up. BOOM, the wakeup will happen while the task is 38 + running. 39 + 40 + - Why do we need this model, so? 41 + - To test the reactors. 42 + 43 + Specification 44 + ------------- 45 + Grapviz Dot file in tools/verification/models/wwnr.dot
+12
include/trace/events/rv.h
··· 122 122 __entry->event, 123 123 __entry->state) 124 124 ); 125 + 126 + #ifdef CONFIG_RV_MON_WWNR 127 + /* id is the pid of the task */ 128 + DEFINE_EVENT(event_da_monitor_id, event_wwnr, 129 + TP_PROTO(int id, char *state, char *event, char *next_state, bool final_state), 130 + TP_ARGS(id, state, event, next_state, final_state)); 131 + 132 + DEFINE_EVENT(error_da_monitor_id, error_wwnr, 133 + TP_PROTO(int id, char *state, char *event), 134 + TP_ARGS(id, state, event)); 135 + #endif /* CONFIG_RV_MON_WWNR */ 136 + 125 137 #endif /* CONFIG_DA_MON_EVENTS_ID */ 126 138 #endif /* _TRACE_RV_H */ 127 139
+12
kernel/trace/rv/Kconfig
··· 38 38 For further information, see: 39 39 Documentation/trace/rv/monitor_wip.rst 40 40 41 + config RV_MON_WWNR 42 + depends on RV 43 + select DA_MON_EVENTS_ID 44 + bool "wwnr monitor" 45 + help 46 + Enable wwnr (wakeup while not running) sample monitor, this is a 47 + sample monitor that illustrates the usage of per-task monitor. 48 + The model is borken on purpose: it serves to test reactors. 49 + 50 + For further information, see: 51 + Documentation/trace/rv/monitor_wwnr.rst 52 + 41 53 config RV_REACTORS 42 54 bool "Runtime verification reactors" 43 55 default y
+1
kernel/trace/rv/Makefile
··· 3 3 obj-$(CONFIG_RV) += rv.o 4 4 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o 5 5 obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o 6 + obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
+87
kernel/trace/rv/monitors/wwnr/wwnr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/ftrace.h> 3 + #include <linux/tracepoint.h> 4 + #include <linux/kernel.h> 5 + #include <linux/module.h> 6 + #include <linux/init.h> 7 + #include <linux/rv.h> 8 + #include <rv/instrumentation.h> 9 + #include <rv/da_monitor.h> 10 + 11 + #define MODULE_NAME "wwnr" 12 + 13 + #include <trace/events/rv.h> 14 + #include <trace/events/sched.h> 15 + 16 + #include "wwnr.h" 17 + 18 + struct rv_monitor rv_wwnr; 19 + DECLARE_DA_MON_PER_TASK(wwnr, unsigned char); 20 + 21 + static void handle_switch(void *data, bool preempt, struct task_struct *p, 22 + struct task_struct *n, unsigned int prev_state) 23 + { 24 + /* start monitoring only after the first suspension */ 25 + if (prev_state == TASK_INTERRUPTIBLE) 26 + da_handle_start_event_wwnr(p, switch_out_wwnr); 27 + else 28 + da_handle_event_wwnr(p, switch_out_wwnr); 29 + 30 + da_handle_event_wwnr(n, switch_in_wwnr); 31 + } 32 + 33 + static void handle_wakeup(void *data, struct task_struct *p) 34 + { 35 + da_handle_event_wwnr(p, wakeup_wwnr); 36 + } 37 + 38 + static int enable_wwnr(void) 39 + { 40 + int retval; 41 + 42 + retval = da_monitor_init_wwnr(); 43 + if (retval) 44 + return retval; 45 + 46 + rv_attach_trace_probe("wwnr", sched_switch, handle_switch); 47 + rv_attach_trace_probe("wwnr", sched_wakeup, handle_wakeup); 48 + 49 + return 0; 50 + } 51 + 52 + static void disable_wwnr(void) 53 + { 54 + rv_wwnr.enabled = 0; 55 + 56 + rv_detach_trace_probe("wwnr", sched_switch, handle_switch); 57 + rv_detach_trace_probe("wwnr", sched_wakeup, handle_wakeup); 58 + 59 + da_monitor_destroy_wwnr(); 60 + } 61 + 62 + struct rv_monitor rv_wwnr = { 63 + .name = "wwnr", 64 + .description = "wakeup while not running per-task testing model.", 65 + .enable = enable_wwnr, 66 + .disable = disable_wwnr, 67 + .reset = da_monitor_reset_all_wwnr, 68 + .enabled = 0, 69 + }; 70 + 71 + static int register_wwnr(void) 72 + { 73 + rv_register_monitor(&rv_wwnr); 74 + return 0; 75 + } 76 + 77 + static void unregister_wwnr(void) 78 + { 79 + rv_unregister_monitor(&rv_wwnr); 80 + } 81 + 82 + module_init(register_wwnr); 83 + module_exit(unregister_wwnr); 84 + 85 + MODULE_LICENSE("GPL"); 86 + MODULE_AUTHOR("Daniel Bristot de Oliveira <bristot@kernel.org>"); 87 + MODULE_DESCRIPTION("wwnr: wakeup while not running monitor");
+46
kernel/trace/rv/monitors/wwnr/wwnr.h
··· 1 + /* 2 + * Automatically generated C representation of wwnr automaton 3 + * For further information about this format, see kernel documentation: 4 + * Documentation/trace/rv/deterministic_automata.rst 5 + */ 6 + 7 + enum states_wwnr { 8 + not_running_wwnr = 0, 9 + running_wwnr, 10 + state_max_wwnr 11 + }; 12 + 13 + #define INVALID_STATE state_max_wwnr 14 + 15 + enum events_wwnr { 16 + switch_in_wwnr = 0, 17 + switch_out_wwnr, 18 + wakeup_wwnr, 19 + event_max_wwnr 20 + }; 21 + 22 + struct automaton_wwnr { 23 + char *state_names[state_max_wwnr]; 24 + char *event_names[event_max_wwnr]; 25 + unsigned char function[state_max_wwnr][event_max_wwnr]; 26 + unsigned char initial_state; 27 + bool final_states[state_max_wwnr]; 28 + }; 29 + 30 + struct automaton_wwnr automaton_wwnr = { 31 + .state_names = { 32 + "not_running", 33 + "running" 34 + }, 35 + .event_names = { 36 + "switch_in", 37 + "switch_out", 38 + "wakeup" 39 + }, 40 + .function = { 41 + { running_wwnr, INVALID_STATE, not_running_wwnr }, 42 + { INVALID_STATE, not_running_wwnr, INVALID_STATE }, 43 + }, 44 + .initial_state = not_running_wwnr, 45 + .final_states = { 1, 0 }, 46 + };
+16
tools/verification/models/wwnr.dot
··· 1 + digraph state_automaton { 2 + {node [shape = plaintext, style=invis, label=""] "__init_not_running"}; 3 + {node [shape = ellipse] "not_running"}; 4 + {node [shape = plaintext] "not_running"}; 5 + {node [shape = plaintext] "running"}; 6 + "__init_not_running" -> "not_running"; 7 + "not_running" [label = "not_running", color = green3]; 8 + "not_running" -> "not_running" [ label = "wakeup" ]; 9 + "not_running" -> "running" [ label = "switch_in" ]; 10 + "running" [label = "running"]; 11 + "running" -> "not_running" [ label = "switch_out" ]; 12 + { rank = min ; 13 + "__init_not_running"; 14 + "not_running"; 15 + } 16 + }