Skip to contentSkip to conversation

The Runtime Verification (RV) interface

PATCH Superseded Daniel Bristot de Oliveira 3 participants 30 messages Jul 13, 2022 – Jul 18, 2022

Subsystems (6)

v5 of 9 Superseded Latest is v9 →

lore
Share & tools
lore
#0 lore raw

v5 cover The Runtime Verification (RV) interface

Over the last years, I've been exploring the possibility of verifying the Linux kernel behavior using Runtime Verification.

Runtime Verification (RV) is a lightweight (yet rigorous) method that complements classical exhaustive verification techniques (such as model checking and theorem proving) with a more practical approach for complex systems.

Instead of relying on a fine-grained model of a system (e.g., a re-implementation a instruction level), RV works by analyzing the trace of the system's actual execution, comparing it against a formal specification of the system behavior.

The usage of deterministic automaton for RV is a well-established approach. In the specific case of the Linux kernel, you can check how to model complex behavior of the Linux kernel with this paper:

De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo Silva. *Efficient formal verification for the Linux kernel.* In: International Conference on Software Engineering and Formal Methods. Springer, Cham, 2019. p. 315-332.

And how efficient is this approach here:

De Oliveira, Daniel B.; De Oliveira, Romulo S.; Cucinotta, Tommaso. *A thread synchronization model for the PREEMPT_RT Linux kernel.* Journal of Systems Architecture, 2020, 107: 101729.

tlrd: it is possible to model complex behaviors in a modular way, with an acceptable overhead (even for production systems). See this presentation at 2019's ELCE: https://www.youtube.com/watch?v=BfTuEHafNgg

Here I am proposing a more practical approach for the usage of deterministic automata for runtime verification, and it includes:

- An interface for controlling the verification;
- A tool and set of headers that enables the automatic code generation of the RV monitor (Monitor Synthesis);
- Sample monitors to evaluate the interface;

Given that RV is a tracing consumer, the code is being placed inside the tracing subsystem (Steven and I have been talking about it for a while).

Features to be added after this patchset:
- safe_wtd monitor (requires further discussion with watchdog maintainers)
- Export symbols for external modules
- dot2bpf
- Add a reactor that enables the visualization of the visited states via KCOV (Marco Elver & Dmitry Vyukov)
- Add a CRC method to check from user-space if the values exported by the monitor were not corrupted by any other kernel task (Gabriele Paoloni)

Changes from v4:
- The watchdog monitor will be discussed on another thread (Daniel)
- s/safe/final/ in the tracepoint definition (Daniel)
- Improved error handling at __init functions (Daniel)
- Remove the hostname from example of commands in a shell (Bagas Sanjaya)
- Added documentation about automata representation in C/DOT/Formal and this documentation is cited in a comment on all model.h (Steven)
- Make wwnr a single patch (Daniel/Steven)
- Add the .dot file for each monitor (Daniel)
- Add a document for each monitor (Daniel)
- Add an order for documentation in the index.rst (Daniel)
- Add wip/wwnr/... long description (Steven/Randy)
- Add comments for helper functions (Steven)
- Improve checks in da_monitor.h (Tao Zhou)
- Change final states set to bool (Tao/Daniel)
- Adjust indentation on enabling monitor/reactor (Steven)
- Use strim on buffers from user-space (Steven)
- Remove ifdefs inside functions (Steven)
- Adjust depends on RV in Kconfig (Steven)
- Check empty enabled monitor list (Tao Zhou)
- Fixed Copyright (Steven)
- Adjusted structures' indentation (Steven)
- Fix rv/monitors/$monitor/enabled return value (Song Liu)
- Typos (Punit Agrawal/Randy)
- Improved python scripts w.r.t. consistency (Steve)
- Blamed myself for so many problems :-) (Daniel's mind)
Changes from v3:
- Rebased on 5.19
(rostedt's request were made on 1x1 meetings)
- Moved monitors to monitors/$name/ (Rostedt)
- Consolidate the tracepoints into a single include file in the default directory (trace/events/rv.h) (Rostedt)
- The tracepoints now record the entire string to the buffer.
- Change the enable_monitors to disable monitors with ! (instead of -). (Rostedt)
- Add a suffix to the state/events enums, to avoid conflict in the vmlinux.h used by eBPF.
- The models are now placed in the $name.h (it used to store the tracepoints, but they are now consolidated in a single file)
- dot2c and dot2k updated to the changes
- models re-generated with these new standards.
- user-space tools moved to an directory outside of tools/tracing as other methods of verification/log sources are planned.
Changes from v2:
- Tons of checkpatch and kernel test robot
- Moved files to better places
- Adjusted watchdog tracepoints patch (Guenter Roeck)
- Added pretimeout watchdog events (Peter Enderborg)
- Used task struct to store per-task monitors (Peter Zijlstra)
- Changed the instrumentation to use internal definition of tracepoint and check the callback signature (Steven Rostedt)
- Used printk_deferred() and removed the comment about deadlocks (Shuah Khan/John Ogness)
- Some simplifications:
- Removed the safe watchdog nowayout for now (myself)
- Removed export symbols for now (myself)
Changes from V1:
- rebased to the latest kernel;
- code cleanup;
- the watchdog dev monitor;
- safety app;

Daniel Bristot de Oliveira (16):
rv: Add Runtime Verification (RV) interface
rv: Add runtime reactors interface
rv/include: Add helper functions for deterministic automata rv/include: Add deterministic automata monitor definition via C macros rv/include: Add instrumentation helper functions Documentation/rv: Add a basic documentation
tools/rv: Add dot2c
Documentation/rv: Add deterministic automaton documentation tools/rv: Add dot2k
Documentation/rv: Add deterministic automata monitor synthesis
documentation
Documentation/rv: Add deterministic automata instrumentation
documentation
rv/monitor: Add the wip monitor skeleton created by dot2k rv/monitor: Add the wip monitor
rv/monitor: Add the wwnr monitor
rv/reactor: Add the printk reactor
rv/reactor: Add the panic reactor

 Documentation/trace/index.rst                 |   1 +
 .../trace/rv/da_monitor_instrumentation.rst   | 169 ++++
 .../trace/rv/da_monitor_synthesis.rst         | 147 ++++
 .../trace/rv/deterministic_automata.rst       | 184 +++++
 Documentation/trace/rv/index.rst              |  14 +
 Documentation/trace/rv/monitor_wip.rst        |  55 ++
 Documentation/trace/rv/monitor_wwnr.rst       |  45 ++
 .../trace/rv/runtime-verification.rst         | 233 ++++++
 include/linux/rv.h                            |  35 +
 include/linux/sched.h                         |  11 +
 include/rv/automata.h                         |  75 ++
 include/rv/da_monitor.h                       | 524 +++++++++++++
 include/rv/instrumentation.h                  |  29 +
 include/rv/rv.h                               |  32 +
 include/trace/events/rv.h                     | 142 ++++
 kernel/fork.c                                 |  14 +
 kernel/trace/Kconfig                          |   2 +
 kernel/trace/Makefile                         |   1 +
 kernel/trace/rv/Kconfig                       |  81 ++
 kernel/trace/rv/Makefile                      |   8 +
 kernel/trace/rv/monitors/wip/wip.c            |  91 +++
 kernel/trace/rv/monitors/wip/wip.h            |  46 ++
 kernel/trace/rv/monitors/wwnr/wwnr.c          |  90 +++
 kernel/trace/rv/monitors/wwnr/wwnr.h          |  46 ++
 kernel/trace/rv/reactor_panic.c               |  43 +
 kernel/trace/rv/reactor_printk.c              |  42 +
 kernel/trace/rv/rv.c                          | 739 ++++++++++++++++++
 kernel/trace/rv/rv.h                          |  65 ++
 kernel/trace/rv/rv_reactors.c                 | 488 ++++++++++++
 kernel/trace/trace.c                          |   2 +
 kernel/trace/trace.h                          |   9 +
 tools/verification/dot2/Makefile              |  26 +
 tools/verification/dot2/automata.py           | 174 +++++
 tools/verification/dot2/dot2c                 |  26 +
 tools/verification/dot2/dot2c.py              | 254 ++++++
 tools/verification/dot2/dot2k                 |  47 ++
 tools/verification/dot2/dot2k.py              | 177 +++++
 .../dot2/dot2k_templates/main_global.c        |  94 +++
 .../dot2/dot2k_templates/main_per_cpu.c       |  94 +++
 .../dot2/dot2k_templates/main_per_task.c      |  94 +++
 tools/verification/models/wip.dot             |  16 +
 tools/verification/models/wwnr.dot            |  16 +
 42 files changed, 4481 insertions(+)
 create mode 100644 Documentation/trace/rv/da_monitor_instrumentation.rst
 create mode 100644 Documentation/trace/rv/da_monitor_synthesis.rst
 create mode 100644 Documentation/trace/rv/deterministic_automata.rst
 create mode 100644 Documentation/trace/rv/index.rst
 create mode 100644 Documentation/trace/rv/monitor_wip.rst
 create mode 100644 Documentation/trace/rv/monitor_wwnr.rst
 create mode 100644 Documentation/trace/rv/runtime-verification.rst
 create mode 100644 include/linux/rv.h
 create mode 100644 include/rv/automata.h
 create mode 100644 include/rv/da_monitor.h
 create mode 100644 include/rv/instrumentation.h
 create mode 100644 include/rv/rv.h
 create mode 100644 include/trace/events/rv.h
 create mode 100644 kernel/trace/rv/Kconfig
 create mode 100644 kernel/trace/rv/Makefile
 create mode 100644 kernel/trace/rv/monitors/wip/wip.c
 create mode 100644 kernel/trace/rv/monitors/wip/wip.h
 create mode 100644 kernel/trace/rv/monitors/wwnr/wwnr.c
 create mode 100644 kernel/trace/rv/monitors/wwnr/wwnr.h
 create mode 100644 kernel/trace/rv/reactor_panic.c
 create mode 100644 kernel/trace/rv/reactor_printk.c
 create mode 100644 kernel/trace/rv/rv.c
 create mode 100644 kernel/trace/rv/rv.h
 create mode 100644 kernel/trace/rv/rv_reactors.c
 create mode 100644 tools/verification/dot2/Makefile
 create mode 100644 tools/verification/dot2/automata.py
 create mode 100644 tools/verification/dot2/dot2c
 create mode 100644 tools/verification/dot2/dot2c.py
 create mode 100644 tools/verification/dot2/dot2k
 create mode 100644 tools/verification/dot2/dot2k.py
 create mode 100644 tools/verification/dot2/dot2k_templates/main_global.c
 create mode 100644 tools/verification/dot2/dot2k_templates/main_per_cpu.c
 create mode 100644 tools/verification/dot2/dot2k_templates/main_per_task.c
 create mode 100644 tools/verification/models/wip.dot
 create mode 100644 tools/verification/models/wwnr.dot
Signature · 1 line
2.35.1
#1 lore raw

PATCH v5 1/16 Add Runtime Verification (RV) interface

RV is a lightweight (yet rigorous) method that complements classical exhaustive verification techniques (such as model checking and theorem proving) with a more practical approach to complex systems.

RV works by analyzing the trace of the system's actual execution, comparing it against a formal specification of the system behavior. RV can give precise information on the runtime behavior of the monitored system while enabling the reaction for unexpected events, avoiding, for example, the propagation of a failure on safety-critical systems.

The development of this interface roots in the development of the paper:

De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo Silva. Efficient formal verification for the Linux kernel. In:
International Conference on Software Engineering and Formal Methods. Springer, Cham, 2019. p. 315-332.

And:

De Oliveira, Daniel Bristot. Automata-based formal analysis and verification of the real-time Linux kernel. PhD Thesis, 2020.

The RV interface resembles the tracing/ interface on purpose. The current path for the RV interface is /sys/kernel/tracing/rv/.

It presents these files:

"available_monitors"
- List the available monitors, one per line.

For example:

     # cat available_monitors
     wip
     wwnr

"enabled_monitors"
- Lists the enabled monitors, one per line;
- Writing to it enables a given monitor;
- Writing a monitor name with a '!' prefix disables it;
- Truncating the file disables all enabled monitors.

For example:

     # cat enabled_monitors
     # echo wip > enabled_monitors
     # echo wwnr >> enabled_monitors
     # cat enabled_monitors
     wip
     wwnr
     # echo '!wip' >> enabled_monitors
     # cat enabled_monitors
     wwnr
     # echo > enabled_monitors
     # cat enabled_monitors
     #

Note that more than one monitor can be enabled concurrently.

"monitoring_on"
- It is an on/off general switcher for monitoring. Note that it does not disable enabled monitors or detach events, but stop the per-entity monitors of monitoring the events received from the system. It resembles the "tracing_on" switcher.

"monitors/"
Each monitor will have its one directory inside "monitors/". There the monitor specific files will be presented.
The "monitors/" directory resembles the "events" directory on tracefs.

For example:

     # cd monitors/wip/
     # ls
     desc  enable
     # cat desc
     wakeup in preemptive per-cpu testing monitor.
     # cat enable
     0

For further information, see the comments in the header of kernel/trace/rv/rv.c from this patch.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/linux/rv.h       |  22 ++
 include/linux/sched.h    |  11 +
 include/rv/rv.h          |  23 ++
 kernel/trace/Kconfig     |   2 +
 kernel/trace/Makefile    |   1 +
 kernel/trace/rv/Kconfig  |  12 +
 kernel/trace/rv/Makefile |   3 +
 kernel/trace/rv/rv.c     | 722 +++++++++++++++++++++++++++++++++++++++
 kernel/trace/rv/rv.h     |  36 ++
 kernel/trace/trace.c     |   2 +
 kernel/trace/trace.h     |   9 +
 11 files changed, 843 insertions(+)
 create mode 100644 include/linux/rv.h
 create mode 100644 include/rv/rv.h
 create mode 100644 kernel/trace/rv/Kconfig
 create mode 100644 kernel/trace/rv/Makefile
 create mode 100644 kernel/trace/rv/rv.c
 create mode 100644 kernel/trace/rv/rv.h
include/linux/rv.h new file +22 -0
new file mode 100644
index 000000000000..0f7a1f9413a8
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Runtime Verification.
+ *
+ * For futher information, see: kernel/trace/rv/rv.c.
+ */
+#ifndef _LINUX_RV_H
+#define _LINUX_RV_H
+
+struct rv_monitor {
+	const char		*name;
+	const char		*description;
+	bool			enabled;
+	int			(*start)(void);
+	void			(*stop)(void);
+	void			(*reset)(void);
+};
+
+extern bool monitoring_on;
+int rv_unregister_monitor(struct rv_monitor *monitor);
+int rv_register_monitor(struct rv_monitor *monitor);
+#endif /* _LINUX_RV_H */
include/linux/sched.h +11 -0
index c46f3a63b758..b037f364efdc 100644
@@ -35,6 +35,7 @@
 #include <linux/seqlock.h>
 #include <linux/kcsan.h>
 #include <asm/kmap_size.h>
+#include <rv/rv.h>
 
 /* task_struct member predeclarations (sorted alphabetically): */
 struct audit_context;
@@ -1500,6 +1501,16 @@ struct task_struct {
 	struct callback_head		l1d_flush_kill;
 #endif
 
+#ifdef CONFIG_RV
+	/*
+	 * Per-task RV monitor. Nowadays fixed in RV_PER_TASK_MONITORS.
+	 * If we find justification for more monitors, we can think
+	 * about adding more or developing a dynamic method. So far,
+	 * none of these are justified.
+	 */
+	union rv_task_monitor		rv[RV_PER_TASK_MONITORS];
+#endif
+
 	/*
 	 * New fields for task_struct should be added above here, so that
 	 * they are included in the randomized portion of task_struct.
include/rv/rv.h new file +23 -0
new file mode 100644
index 000000000000..27a108881d35
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _RV_RV_H
+#define _RV_RV_H
+
+/*
+ * Per-task RV monitors count. Nowadays fixed in RV_PER_TASK_MONITORS.
+ * If we find justification for more monitors, we can think about
+ * adding more or developing a dynamic method. So far, none of
+ * these are justified.
+ */
+#define RV_PER_TASK_MONITORS		1
+#define RV_PER_TASK_MONITOR_INIT	(RV_PER_TASK_MONITORS)
+
+/*
+ * Futher monitor types are expected, so make this a union.
+ */
+union rv_task_monitor {
+};
+
+int get_task_monitor_slot(void);
+void put_task_monitor_slot(int slot);
+#endif /* _RV_RV_H */
kernel/trace/Kconfig +2 -0
index ccd6a5ade3e9..1052126bdca2 100644
@@ -1106,4 +1106,6 @@ config HIST_TRIGGERS_DEBUG
 
           If unsure, say N.
 
+source "kernel/trace/rv/Kconfig"
+
 endif # FTRACE
kernel/trace/Makefile +1 -0
index 0d261774d6f3..c6651e16b557 100644
@@ -106,5 +106,6 @@ obj-$(CONFIG_FPROBE) += fprobe.o
 obj-$(CONFIG_RETHOOK) += rethook.o
 
 obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o
+obj-$(CONFIG_RV) += rv/
 
 libftrace-y := ftrace.o
kernel/trace/rv/Kconfig new file +12 -0
new file mode 100644
index 000000000000..6d127cdb00dd
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+menuconfig RV
+	bool "Runtime Verification"
+	depends on TRACING
+	help
+	  Enable the kernel runtime verification infrastructure. RV is a
+	  lightweight (yet rigorous) method that complements classical
+	  exhaustive verification techniques (such as model checking and
+	  theorem proving). RV works by analyzing the trace of the system's
+	  actual execution, comparing it against a formal specification of
+	  the system behavior.
kernel/trace/rv/Makefile new file +3 -0
new file mode 100644
index 000000000000..fd995379df67
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_RV) += rv.o
kernel/trace/rv/rv.c new file +722 -0

722 lines not on this page · raw message

kernel/trace/rv/rv.h new file +36 -0
new file mode 100644
index 000000000000..6b8eff6725d9
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/mutex.h>
+
+struct rv_interface {
+	struct dentry		*root_dir;
+	struct dentry		*monitors_dir;
+};
+
+#include "../trace.h"
+#include <linux/tracefs.h>
+#include <linux/rv.h>
+
+#define RV_MODE_WRITE			TRACE_MODE_WRITE
+#define RV_MODE_READ			TRACE_MODE_READ
+
+#define rv_create_dir			tracefs_create_dir
+#define rv_create_file			tracefs_create_file
+#define rv_remove			tracefs_remove
+
+#define MAX_RV_MONITOR_NAME_SIZE	32
+
+extern struct mutex rv_interface_lock;
+
+struct rv_monitor_def {
+	struct list_head	list;
+	struct rv_monitor	*monitor;
+	struct dentry		*root_d;
+	bool			task_monitor;
+};
+
+extern bool monitoring_on;
+struct dentry *get_monitors_root(void);
+void reset_all_monitors(void);
+int init_rv_monitors(struct dentry *root_dir);
+int get_task_monitor_slot(void);
+void put_task_monitor_slot(int slot);
kernel/trace/trace.c +2 -0
index b8dd54627075..062423371741 100644
@@ -9772,6 +9772,8 @@ static __init int tracer_init_tracefs(void)
 		tracer_init_tracefs_work_func(NULL);
 	}
 
+	rv_init_interface();
+
 	return 0;
 }
 
kernel/trace/trace.h +9 -0
index ff816fb41e48..900e75d96c84 100644
@@ -2005,4 +2005,13 @@ struct trace_min_max_param {
 
 extern const struct file_operations trace_min_max_fops;
 
+#ifdef CONFIG_RV
+extern int rv_init_interface(void);
+#else
+static inline int rv_init_interface(void)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_KERNEL_TRACE_H */
Signature · 1 line
2.35.1
#2 lore raw

Re: [PATCH V5 01/16] rv: Add Runtime Verification (RV) interface

On Wed, Jul 13, 2022 at 11:17:17PM +0200, Daniel Bristot de Oliveira <[email protected]> wrote:

[...]

kernel/trace/rv/rv.c line 194

Quoted 5 lines
kernel/trace/rv/rv.c new file +5 -0
+void put_task_monitor_slot(int slot)
+{
+	lockdep_assert_held(&rv_interface_lock);
+
+	if (slot < 0 || slot > RV_PER_TASK_MONITORS) {

slot is the array index that should be 0 here. The up bound is not bigger than 0 because the element of array now is RV_PER_TASK_MONITORS.

So up bound check is 'slot > RV_PER_TASK_MONITORS-1'.

[...]

Quoted 16 lines
kernel/trace/rv/rv.c new file +16 -0
+/*
+ * interface for enabling/disabling a monitor.
+ */
+static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct rv_monitor_def *mdef = filp->private_data;
+	int retval;
+	bool val;
+
+	retval = kstrtobool_from_user(user_buf, count, &val);
+	if (retval)
+		return retval;
+
+	retval = count;
+

kernel/trace/rv/rv.c line 283

Quoted 10 lines
kernel/trace/rv/rv.c new file +10 -0
+	mutex_lock(&rv_interface_lock);
+
+	if (val)
+		retval = enable_monitor(mdef);
+	else
+		retval = disable_monitor(mdef);
+
+	mutex_unlock(&rv_interface_lock);
+
+	return retval ? retval : count;

Feel that this can be written return retval ? : count;

[...]

Quoted 6 lines
kernel/trace/rv/rv.c new file +6 -0
+static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
+{
+	struct rv_monitor_def *m_def;
+	loff_t l;
+
+	mutex_lock(&rv_interface_lock);

kernel/trace/rv/rv.c line 420

Quoted 10 lines
kernel/trace/rv/rv.c new file +10 -0
+
+	if (list_empty(&rv_monitors_list))
+		return NULL;
+
+	m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
+
+	for (l = 0; l <= *pos; ) {
+		m_def = enabled_monitors_next(m, m_def, &l);
+		if (!m_def)
+			break;

Is this check is inversed. enabled_monitors_start() will stop at first enabled monitor, then enabled_monitors_next() do loop to next. Check like the above, enabled_monitors_start() will loop to the last monitor. But I doubt myself I do not mention/see it. Sorry for these.

the check is:

if (m_def)

     break;

[...]

kernel/trace/rv/rv.c line 488

Quoted 12 lines
kernel/trace/rv/rv.c new file +12 -0
+static ssize_t
+enabled_monitors_write(struct file *filp, const char __user *user_buf,
+		      size_t count, loff_t *ppos)
+{
+	char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
+	struct rv_monitor_def *mdef;
+	int retval = -EINVAL;
+	bool enable = true;
+	char *ptr = buff;
+	int len;
+
+	if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 2)

@count would not include '\0'. That the max val of @count is MAX_RV_MONITOR_NAME_SIZE+1. So the up bound check of @count is count > MAX_RV_MONITOR_NAME_SIZE + 1.

Thanks,
Tao

Quoted 44 lines
kernel/trace/rv/rv.c new file +44 -0
+		return -EINVAL;
+
+	memset(buff, 0, sizeof(buff));
+
+	retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf, count);
+	if (!retval)
+		return -EFAULT;
+
+	ptr = strim(buff);
+
+	if (ptr[0] == '!') {
+		enable = false;
+		ptr++;
+	}
+
+	len = strlen(ptr);
+	if (!len)
+		return count;
+
+	mutex_lock(&rv_interface_lock);
+
+	retval = -EINVAL;
+
+	list_for_each_entry(mdef, &rv_monitors_list, list) {
+		if (strcmp(ptr, mdef->monitor->name) != 0)
+			continue;
+
+		/*
+		 * Monitor found!
+		 */
+		if (enable)
+			retval = enable_monitor(mdef);
+		else
+			retval = disable_monitor(mdef);
+
+		if (!retval)
+			retval = count;
+
+		break;
+	}
+
+	mutex_unlock(&rv_interface_lock);
+	return retval;
+}
#3 lore raw

Re: [PATCH V5 01/16] rv: Add Runtime Verification (RV) interface

Quoted 14 lines · Tao Zhou

On Wed, Jul 13, 2022 at 11:17:17PM +0200, Daniel Bristot de Oliveira <[email protected]> wrote:

[...]

kernel/trace/rv/rv.c line 194

Quoted 5 lines
kernel/trace/rv/rv.c new file +5 -0
+void put_task_monitor_slot(int slot)
+{
+	lockdep_assert_held(&rv_interface_lock);
+
+	if (slot < 0 || slot > RV_PER_TASK_MONITORS) {

slot is the array index that should be 0 here. The up bound is not bigger than 0 because the element of array now is RV_PER_TASK_MONITORS.

Quoted 1 line

So up bound check is 'slot > RV_PER_TASK_MONITORS-1'.

fixed! (slot >= RV...)

Quoted 22 lines

[...]

Quoted 20 lines
kernel/trace/rv/rv.c new file +20 -0
+/*
+ * interface for enabling/disabling a monitor.
+ */
+static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct rv_monitor_def *mdef = filp->private_data;
+	int retval;
+	bool val;
+
+	retval = kstrtobool_from_user(user_buf, count, &val);
+	if (retval)
+		return retval;
+
+	retval = count;
+
+	mutex_lock(&rv_interface_lock);
+
+	if (val)
+		retval = enable_monitor(mdef);
Quoted 8 lines

kernel/trace/rv/rv.c line 283

Quoted 6 lines
kernel/trace/rv/rv.c new file +6 -0
+	else
+		retval = disable_monitor(mdef);
+
+	mutex_unlock(&rv_interface_lock);
+
+	return retval ? retval : count;

Feel that this can be written return retval ? : count;

why not...

Quoted 24 lines

[...]

Quoted 6 lines
kernel/trace/rv/rv.c new file +6 -0
+static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
+{
+	struct rv_monitor_def *m_def;
+	loff_t l;
+
+	mutex_lock(&rv_interface_lock);

kernel/trace/rv/rv.c line 420

Quoted 10 lines
kernel/trace/rv/rv.c new file +10 -0
+
+	if (list_empty(&rv_monitors_list))
+		return NULL;
+
+	m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
+
+	for (l = 0; l <= *pos; ) {
+		m_def = enabled_monitors_next(m, m_def, &l);
+		if (!m_def)
+			break;

Is this check is inversed. enabled_monitors_start() will stop at first enabled monitor, then enabled_monitors_next() do loop to next. Check like the above, enabled_monitors_start() will loop to the last monitor. But I doubt myself I do not mention/see it. Sorry for these.

Quoted 6 lines

the check is:

if (m_def)

     break;

[...]

see kernel/trace/trace_events.c:s_start...

Quoted 8 lines
Quoted 8 lines
kernel/trace/rv/rv.c new file +8 -0
+static ssize_t
+enabled_monitors_write(struct file *filp, const char __user *user_buf,
+		      size_t count, loff_t *ppos)
+{
+	char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
+	struct rv_monitor_def *mdef;
+	int retval = -EINVAL;
+	bool enable = true;
Quoted 8 lines

kernel/trace/rv/rv.c line 488

Quoted 4 lines
kernel/trace/rv/rv.c new file +4 -0
+	char *ptr = buff;
+	int len;
+
+	if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 2)

@count would not include '\0'. That the max val of @count is MAX_RV_MONITOR_NAME_SIZE+1. So the up bound check of @count is count > MAX_RV_MONITOR_NAME_SIZE + 1.

Fixed for v6...

-- Daniel

#4 lore raw

Re: [PATCH V5 01/16] rv: Add Runtime Verification (RV) interface

Quoted 79 lines · Daniel Bristot de Oliveira
Quoted 14 lines · Tao Zhou

On Wed, Jul 13, 2022 at 11:17:17PM +0200, Daniel Bristot de Oliveira <[email protected]> wrote:

[...]

kernel/trace/rv/rv.c line 194

Quoted 5 lines
kernel/trace/rv/rv.c new file +5 -0
+void put_task_monitor_slot(int slot)
+{
+	lockdep_assert_held(&rv_interface_lock);
+
+	if (slot < 0 || slot > RV_PER_TASK_MONITORS) {

slot is the array index that should be 0 here. The up bound is not bigger than 0 because the element of array now is RV_PER_TASK_MONITORS.

Quoted 1 line

So up bound check is 'slot > RV_PER_TASK_MONITORS-1'.

fixed! (slot >= RV...)

Quoted 22 lines

[...]

Quoted 20 lines
kernel/trace/rv/rv.c new file +20 -0
+/*
+ * interface for enabling/disabling a monitor.
+ */
+static ssize_t monitor_enable_write_data(struct file *filp, const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct rv_monitor_def *mdef = filp->private_data;
+	int retval;
+	bool val;
+
+	retval = kstrtobool_from_user(user_buf, count, &val);
+	if (retval)
+		return retval;
+
+	retval = count;
+
+	mutex_lock(&rv_interface_lock);
+
+	if (val)
+		retval = enable_monitor(mdef);
Quoted 8 lines

kernel/trace/rv/rv.c line 283

Quoted 6 lines
kernel/trace/rv/rv.c new file +6 -0
+	else
+		retval = disable_monitor(mdef);
+
+	mutex_unlock(&rv_interface_lock);
+
+	return retval ? retval : count;

Feel that this can be written return retval ? : count;

why not...

Quoted 26 lines

[...]

Quoted 6 lines
kernel/trace/rv/rv.c new file +6 -0
+static void *enabled_monitors_start(struct seq_file *m, loff_t *pos)
+{
+	struct rv_monitor_def *m_def;
+	loff_t l;
+
+	mutex_lock(&rv_interface_lock);

kernel/trace/rv/rv.c line 420

Quoted 10 lines
kernel/trace/rv/rv.c new file +10 -0
+
+	if (list_empty(&rv_monitors_list))
+		return NULL;
+
+	m_def = list_entry(&rv_monitors_list, struct rv_monitor_def, list);
+
+	for (l = 0; l <= *pos; ) {
+		m_def = enabled_monitors_next(m, m_def, &l);
+		if (!m_def)
+			break;

Is this check is inversed. enabled_monitors_start() will stop at first enabled monitor, then enabled_monitors_next() do loop to next. Check like the above, enabled_monitors_start() will loop to the last monitor. But I doubt myself I do not mention/see it. Sorry for these.

the check is:

Quoted 7 lines
Quoted 4 lines

if (m_def)

     break;

[...]

see kernel/trace/trace_events.c:s_start...

I presumed @l changed in function enabled_monitors_next() will impack on the @*pos of enabled_monitors_start(). But it's not. @l is increased by 1 in enabled_monitors_next() and is used to check with @*pos passed as parameter argument of enabled_monitors_start(). Absolutely I lost here.. Thanks.

Quoted 20 lines
Quoted 8 lines
Quoted 8 lines
kernel/trace/rv/rv.c new file +8 -0
+static ssize_t
+enabled_monitors_write(struct file *filp, const char __user *user_buf,
+		      size_t count, loff_t *ppos)
+{
+	char buff[MAX_RV_MONITOR_NAME_SIZE + 2];
+	struct rv_monitor_def *mdef;
+	int retval = -EINVAL;
+	bool enable = true;
Quoted 8 lines

kernel/trace/rv/rv.c line 488

Quoted 4 lines
kernel/trace/rv/rv.c new file +4 -0
+	char *ptr = buff;
+	int len;
+
+	if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 2)

@count would not include '\0'. That the max val of @count is MAX_RV_MONITOR_NAME_SIZE+1. So the up bound check of @count is count > MAX_RV_MONITOR_NAME_SIZE + 1.

Fixed for v6...

-- Daniel

#5 lore raw

PATCH v5 2/16 Add runtime reactors interface

In reply to Daniel Bristot de Oliveira

A runtime monitor can cause a reaction to the detection of an exception on the model's execution. By default, the monitors have tracing reactions, printing the monitor output via tracepoints. But other reactions can be added (on-demand) via this interface.

The user interface resembles the kernel tracing interface and presents these files:

"available_reactors"
- Reading shows the available reactors, one per line.

For example:

     # cat available_reactors
     nop
     panic
     printk

"reacting_on"
- It is an on/off general switch for reactors, disabling all reactions.

"monitors/MONITOR/reactors"
- List available reactors, with the select reaction for the given MONITOR inside []. The default one is the nop (no operation) reactor.
- Writing the name of a reactor enables it to the given MONITOR.

For example:

     # cat monitors/wip/reactors
     [nop]
     panic
     printk
     # echo panic > monitors/wip/reactors
     # cat monitors/wip/reactors
     nop
     [panic]
     printk
Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/linux/rv.h            |  11 +
 kernel/trace/rv/Kconfig       |  11 +
 kernel/trace/rv/Makefile      |   1 +
 kernel/trace/rv/rv.c          |   9 +
 kernel/trace/rv/rv.h          |  29 ++
 kernel/trace/rv/rv_reactors.c | 488 ++++++++++++++++++++++++++++++++++
 6 files changed, 549 insertions(+)
 create mode 100644 kernel/trace/rv/rv_reactors.c
include/linux/rv.h +11 -0
index 0f7a1f9413a8..88d28d207f3a 100644
@@ -7,6 +7,12 @@
 #ifndef _LINUX_RV_H
 #define _LINUX_RV_H
 
+struct rv_reactor {
+	char			*name;
+	char			*description;
+	void			(*react)(char *msg);
+};
+
 struct rv_monitor {
 	const char		*name;
 	const char		*description;
@@ -14,9 +20,14 @@ struct rv_monitor {
 	int			(*start)(void);
 	void			(*stop)(void);
 	void			(*reset)(void);
+	void			(*react)(char *msg);
 };
 
 extern bool monitoring_on;
 int rv_unregister_monitor(struct rv_monitor *monitor);
 int rv_register_monitor(struct rv_monitor *monitor);
+
+extern bool reacting_on;
+int rv_unregister_reactor(struct rv_reactor *reactor);
+int rv_register_reactor(struct rv_reactor *reactor);
 #endif /* _LINUX_RV_H */
kernel/trace/rv/Kconfig +11 -0
index 6d127cdb00dd..3eb5d48ab4f6 100644
@@ -10,3 +10,14 @@ menuconfig RV
 	  theorem proving). RV works by analyzing the trace of the system's
 	  actual execution, comparing it against a formal specification of
 	  the system behavior.
+
+config RV_REACTORS
+	bool "Runtime verification reactors"
+	default y
+	depends on RV
+	help
+	  Enables the online runtime verification reactors. A runtime
+	  monitor can cause a reaction to the detection of an exception
+	  on the model's execution. By default, the monitors have
+	  tracing reactions, printing the monitor output via tracepoints,
+	  but other reactions can be added (on-demand) via this interface.
kernel/trace/rv/Makefile +1 -0
index fd995379df67..8944274d9b41 100644
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_RV) += rv.o
+obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
kernel/trace/rv/rv.c +9 -0
index d9199d1873bb..d988e2b1b9d2 100644
@@ -343,6 +343,10 @@ static int create_monitor_dir(struct rv_monitor_def *mdef)
 		goto out_remove_root;
 	}
 
+	retval = reactor_create_monitor_files(mdef);
+	if (retval)
+		goto out_remove_root;
+
 	return 0;
 
 out_remove_root:
@@ -687,6 +691,7 @@ void reset_all_monitors(void)
 int __init rv_init_interface(void)
 {
 	struct dentry *tmp;
+	int retval;
 
 	rv_root.root_dir = rv_create_dir("rv", NULL);
 	if (!rv_root.root_dir)
@@ -711,6 +716,10 @@ int __init rv_init_interface(void)
 	if (!tmp)
 		goto out_err;
 
+	retval = init_rv_reactors(rv_root.root_dir);
+	if (retval)
+		goto out_err;
+
 	monitoring_on = true;
 
 	return 0;
kernel/trace/rv/rv.h +29 -0
index 6b8eff6725d9..5dd2f56ff953 100644
@@ -18,13 +18,27 @@ struct rv_interface {
 #define rv_remove			tracefs_remove
 
 #define MAX_RV_MONITOR_NAME_SIZE	32
+#define MAX_RV_REACTOR_NAME_SIZE	32
 
 extern struct mutex rv_interface_lock;
 
+#ifdef CONFIG_RV_REACTORS
+struct rv_reactor_def {
+	struct list_head	list;
+	struct rv_reactor	*reactor;
+	/* protected by the monitor interface lock */
+	int			counter;
+};
+#endif
+
 struct rv_monitor_def {
 	struct list_head	list;
 	struct rv_monitor	*monitor;
 	struct dentry		*root_d;
+#ifdef CONFIG_RV_REACTORS
+	struct rv_reactor_def	*rdef;
+	bool			reacting;
+#endif
 	bool			task_monitor;
 };
 
@@ -34,3 +48,18 @@ void reset_all_monitors(void);
 int init_rv_monitors(struct dentry *root_dir);
 int get_task_monitor_slot(void);
 void put_task_monitor_slot(int slot);
+
+#ifdef CONFIG_RV_REACTORS
+extern bool reacting_on;
+int reactor_create_monitor_files(struct rv_monitor_def *mdef);
+int init_rv_reactors(struct dentry *root_dir);
+#else
+static inline int reactor_create_monitor_files(struct rv_monitor_def *mdef)
+{
+	return 0;
+}
+static inline int init_rv_reactors(struct dentry *root_dir)
+{
+	return 0;
+}
+#endif
kernel/trace/rv/rv_reactors.c new file +488 -0

488 lines not on this page · raw message

Signature · 1 line
2.35.1
#6 lore raw

Re: [PATCH V5 02/16] rv: Add runtime reactors interface

Quoted 70 lines · Daniel Bristot de Oliveira

A runtime monitor can cause a reaction to the detection of an exception on the model's execution. By default, the monitors have tracing reactions, printing the monitor output via tracepoints. But other reactions can be added (on-demand) via this interface.

The user interface resembles the kernel tracing interface and presents these files:

"available_reactors"
- Reading shows the available reactors, one per line.

For example:

     # cat available_reactors
     nop
     panic
     printk

"reacting_on"
- It is an on/off general switch for reactors, disabling all reactions.

"monitors/MONITOR/reactors"
- List available reactors, with the select reaction for the given MONITOR inside []. The default one is the nop (no operation) reactor.
- Writing the name of a reactor enables it to the given MONITOR.

For example:

     # cat monitors/wip/reactors
     [nop]
     panic
     printk
     # echo panic > monitors/wip/reactors
     # cat monitors/wip/reactors
     nop
     [panic]
     printk
Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/linux/rv.h            |  11 +
 kernel/trace/rv/Kconfig       |  11 +
 kernel/trace/rv/Makefile      |   1 +
 kernel/trace/rv/rv.c          |   9 +
 kernel/trace/rv/rv.h          |  29 ++
 kernel/trace/rv/rv_reactors.c | 488 ++++++++++++++++++++++++++++++++++
 6 files changed, 549 insertions(+)
 create mode 100644 kernel/trace/rv/rv_reactors.c

[snip]

Quoted 172 lines

new file mode 100644
index 000000000000..27f48fec5a51

kernel/trace/rv/rv_reactors.c new file +167 -0
@@ -0,0 +1,488 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
+ *
+ * Runtime reactor interface.
+ *
+ * A runtime monitor can cause a reaction to the detection of an
+ * exception on the model's execution. By default, the monitors have
+ * tracing reactions, printing the monitor output via tracepoints.
+ * But other reactions can be added (on-demand) via this interface.
+ *
+ * == Registering reactors ==
+ *
+ * The struct rv_reactor defines a callback function to be executed
+ * in case of a model exception happens. The callback function
+ * receives a message to be (optionally) printed before executing
+ * the reaction.
+ *
+ * A RV reactor is registered via:
+ *   int rv_register_reactor(struct rv_reactor *reactor)
+ * And unregistered via:
+ *   int rv_unregister_reactor(struct rv_reactor *reactor)
+ *
+ * These functions are exported to modules, enabling reactors to be
+ * dynamically loaded.
+ *
+ * == User interface ==
+ *
+ * The user interface resembles the kernel tracing interface and
+ * presents these files:
+ *
+ *  "available_reactors"
+ *    - List the available reactors, one per line.
+ *
+ *    For example:
+ *      # cat available_reactors
+ *      nop
+ *      panic
+ *      printk
+ *
+ *  "reacting_on"
+ *    - It is an on/off general switch for reactors, disabling
+ *    all reactions.
+ *
+ *  "monitors/MONITOR/reactors"
+ *    - List available reactors, with the select reaction for the given
+ *    MONITOR inside []. The default one is the nop (no operation)
+ *    reactor.
+ *    - Writing the name of an reactor enables it to the given
+ *    MONITOR.
+ *
+ *    For example:
+ *      # cat monitors/wip/reactors
+ *      [nop]
+ *      panic
+ *      printk
+ *      # echo panic > monitors/wip/reactors
+ *      # cat monitors/wip/reactors
+ *      nop
+ *      [panic]
+ *      printk
+ */
+
+#include <linux/slab.h>
+
+#include "rv.h"
+
+bool __read_mostly reacting_on;
+
+/*
+ * Interface for the reactor register.
+ */
+LIST_HEAD(rv_reactors_list);
+
+static struct rv_reactor_def *get_reactor_rdef_by_name(char *name)
+{
+	struct rv_reactor_def *r;
+
+	list_for_each_entry(r, &rv_reactors_list, list) {
+		if (strcmp(name, r->reactor->name) == 0)
+			return r;
+	}
+	return NULL;
+}
+
+/*
+ * Available reactors seq functions.
+ */
+static int reactors_show(struct seq_file *m, void *p)
+{
+	struct rv_reactor_def *rea_def = p;
+
+	seq_printf(m, "%s\n", rea_def->reactor->name);
+	return 0;
+}
+
+static void reactors_stop(struct seq_file *m, void *p)
+{
+	mutex_unlock(&rv_interface_lock);
+}
+
+static void *reactors_start(struct seq_file *m, loff_t *pos)
+{
+	mutex_lock(&rv_interface_lock);
+	return seq_list_start(&rv_reactors_list, *pos);
+}
+
+static void *reactors_next(struct seq_file *m, void *p, loff_t *pos)
+{
+	return seq_list_next(p, &rv_reactors_list, pos);
+}
+
+/*
+ * available reactors seq definition.
+ */
+static const struct seq_operations available_reactors_seq_ops = {
+	.start	= reactors_start,
+	.next	= reactors_next,
+	.stop	= reactors_stop,
+	.show	= reactors_show
+};
+
+/*
+ * available_reactors interface.
+ */
+static int available_reactors_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &available_reactors_seq_ops);
+};
+
+static const struct file_operations available_reactors_ops = {
+	.open    = available_reactors_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release
+};
+
+/*
+ * Monitor reactor file.
+ */
+static int monitor_reactor_show(struct seq_file *m, void *p)
+{
+	struct rv_monitor_def *mdef = m->private;
+	struct rv_reactor_def *rdef = p;
+
+	if (mdef->rdef == rdef)
+		seq_printf(m, "[%s]\n", rdef->reactor->name);
+	else
+		seq_printf(m, "%s\n", rdef->reactor->name);
+	return 0;
+}
+
+/*
+ * available reactors seq definition.
+ */
+static const struct seq_operations monitor_reactors_seq_ops = {
+	.start	= reactors_start,
+	.next	= reactors_next,
+	.stop	= reactors_stop,
+	.show	= monitor_reactor_show
+};
+
+static ssize_t
+monitor_reactors_write(struct file *file, const char __user *user_buf,
+		      size_t count, loff_t *ppos)
+{
+	char buff[MAX_RV_REACTOR_NAME_SIZE + 2];

kernel/trace/rv/rv_reactors.c line 177

Quoted 10 lines
kernel/trace/rv/rv_reactors.c new file +10 -0
+	struct rv_monitor_def *mdef;
+	struct rv_reactor_def *rdef;
+	struct seq_file *seq_f;
+	int retval = -EINVAL;
+	bool enabled;
+	char *ptr;
+	int len;
+
+	if (count < 1 || count > MAX_RV_REACTOR_NAME_SIZE + 2)
+		return -EINVAL;

The same case as patch1. The up bound check need to be changed.

kernel/trace/rv/rv_reactors.c line 184

Quoted 7 lines
kernel/trace/rv/rv_reactors.c new file +7 -0
+
+	memset(buff, 0, sizeof(buff));
+
+	retval = simple_write_to_buffer(buff, sizeof(buff) - 1, ppos, user_buf,
+					count);
+	if (!retval)
+		return -EFAULT;

If simple_write_to_buffer() is error(return value < 0), no return here. If the return value is 0, no write has happened. For this case, the code want to return -EFAULT.

Quoted 245 lines
kernel/trace/rv/rv_reactors.c new file +245 -0
+
+	ptr = strim(buff);
+
+	len = strlen(ptr);
+	if (!len)
+		return count;
+
+	/*
+	 * See monitor_reactors_open()
+	 */
+	seq_f = file->private_data;
+	mdef = seq_f->private;
+
+	mutex_lock(&rv_interface_lock);
+
+	retval = -EINVAL;
+
+	/*
+	 * nop special case: disable reacting.
+	 */
+	if (strcmp(ptr, "nop") == 0) {
+
+		enabled = mdef->monitor->enabled;
+		if (enabled)
+			mdef->monitor->stop();
+
+		mdef->rdef = get_reactor_rdef_by_name("nop");
+		mdef->reacting = false;
+		mdef->monitor->react = NULL;
+
+		if (enabled) {
+			mdef->monitor->start();
+			mdef->monitor->enabled = 1;
+		}
+
+		retval = count;
+		goto unlock;
+	}
+
+	list_for_each_entry(rdef, &rv_reactors_list, list) {
+		if (strcmp(ptr, rdef->reactor->name) != 0)
+			continue;
+
+		/*
+		 * found!
+		 */
+		enabled = mdef->monitor->enabled;
+		if (enabled)
+			mdef->monitor->stop();
+
+		mdef->rdef = rdef;
+		mdef->reacting = true;
+		mdef->monitor->react = rdef->reactor->react;
+
+		if (enabled) {
+			mdef->monitor->start();
+			mdef->monitor->enabled = 1;
+		}
+
+		retval = count;
+		break;
+	}
+
+unlock:
+	mutex_unlock(&rv_interface_lock);
+
+	return retval;
+}
+
+/*
+ * available_reactors interface.
+ */
+static int monitor_reactors_open(struct inode *inode, struct file *file)
+{
+	/*
+	 * create file "private" info is stored in the inode->i_private
+	 */
+	struct rv_monitor_def *mdef = inode->i_private;
+	struct seq_file *seq_f;
+	int ret;
+
+	ret = seq_open(file, &monitor_reactors_seq_ops);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * seq_open stores the seq_file on the file->private data.
+	 */
+	seq_f = file->private_data;
+
+	/*
+	 * Copy the create file "private" data to the seq_file
+	 * private data.
+	 */
+	seq_f->private = mdef;
+
+	return 0;
+};
+
+static const struct file_operations monitor_reactors_ops = {
+	.open    = monitor_reactors_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+	.write = monitor_reactors_write
+};
+
+static int __rv_register_reactor(struct rv_reactor *reactor)
+{
+	struct rv_reactor_def *r;
+
+	list_for_each_entry(r, &rv_reactors_list, list) {
+		if (strcmp(reactor->name, r->reactor->name) == 0) {
+			pr_info("Reactor %s is already registered\n",
+				reactor->name);
+			return -EINVAL;
+		}
+	}
+
+	r = kzalloc(sizeof(struct rv_reactor_def), GFP_KERNEL);
+	if (!r)
+		return -ENOMEM;
+
+	r->reactor = reactor;
+	r->counter = 0;
+
+	list_add_tail(&r->list, &rv_reactors_list);
+
+	return 0;
+}
+
+/**
+ * rv_register_reactor - register a rv reactor.
+ * @reactor:    The rv_reactor to be registered.
+ *
+ * Returns 0 if successful, error otherwise.
+ */
+int rv_register_reactor(struct rv_reactor *reactor)
+{
+	int retval = 0;
+
+	if (strlen(reactor->name) >= MAX_RV_REACTOR_NAME_SIZE) {
+		pr_info("Reactor %s has a name longer than %d\n",
+			reactor->name, MAX_RV_MONITOR_NAME_SIZE);
+		return -EINVAL;
+	}
+
+	mutex_lock(&rv_interface_lock);
+	retval = __rv_register_reactor(reactor);
+	mutex_unlock(&rv_interface_lock);
+	return retval;
+}
+
+/**
+ * rv_unregister_reactor - unregister a rv reactor.
+ * @reactor:    The rv_reactor to be unregistered.
+ *
+ * Returns 0 if successful, error otherwise.
+ */
+int rv_unregister_reactor(struct rv_reactor *reactor)
+{
+	struct rv_reactor_def *ptr, *next;
+
+	mutex_lock(&rv_interface_lock);
+
+	list_for_each_entry_safe(ptr, next, &rv_reactors_list, list) {
+		if (strcmp(reactor->name, ptr->reactor->name) == 0) {
+
+			if (!ptr->counter) {
+				list_del(&ptr->list);
+			} else {
+				printk(KERN_WARNING
+				       "rv: the rv_reactor %s is in use by %d monitor(s)\n",
+				       ptr->reactor->name, ptr->counter);
+				printk(KERN_WARNING "rv: the rv_reactor %s cannot be removed\n",
+				       ptr->reactor->name);
+				return -EBUSY;
+			}
+
+		}
+	}
+
+	mutex_unlock(&rv_interface_lock);
+	return 0;
+}
+
+/*
+ * reacting_on interface.
+ */
+static ssize_t reacting_on_read_data(struct file *filp,
+				     char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	char *buff;
+
+	mutex_lock(&rv_interface_lock);
+	buff = reacting_on ? "1\n" : "0\n";
+	mutex_unlock(&rv_interface_lock);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buff, strlen(buff)+1);
+}
+
+static void turn_reacting_off(void)
+{
+	reacting_on = false;
+}
+
+static void turn_reacting_on(void)
+{
+	reacting_on = true;
+}
+
+static ssize_t
+reacting_on_write_data(struct file *filp, const char __user *user_buf,
+		       size_t count, loff_t *ppos)
+{
+	int retval;
+	bool val;
+
+	retval = kstrtobool_from_user(user_buf, count, &val);
+	if (retval)
+		return retval;
+
+	mutex_lock(&rv_interface_lock);
+
+	if (val)
+		turn_reacting_on();
+	else
+		turn_reacting_off();
+
+	mutex_unlock(&rv_interface_lock);
+
+	return count;
+}
+
+static const struct file_operations reacting_on_fops = {
+	.open   = simple_open,
+	.llseek = no_llseek,
+	.write  = reacting_on_write_data,
+	.read   = reacting_on_read_data,
+};
+
+int reactor_create_monitor_files(struct rv_monitor_def *mdef)
+{
+	struct dentry *tmp;

kernel/trace/rv/rv_reactors.c line 439

Quoted 10 lines
kernel/trace/rv/rv_reactors.c new file +10 -0
+
+	tmp = rv_create_file("reactors", RV_MODE_WRITE, mdef->root_d, mdef, &monitor_reactors_ops);
+	if (!tmp)
+		return -ENOMEM;
+
+	/*
+	 * Configure as the rv_nop reactor.
+	 */
+	mdef->rdef = get_reactor_rdef_by_name("nop");
+	mdef->reacting = false;

Not need mdef->monitor->react = NULL;. The monitor->react is not set to others that means it is set to NULL, When initializing the specific rv_monitor structure. Note to myself. Thanks.

Quoted 51 lines
kernel/trace/rv/rv_reactors.c new file +49 -0
+
+	return 0;
+}
+
+/*
+ * None reactor register
+ */
+static void rv_nop_reaction(char *msg)
+{
+}
+
+struct rv_reactor rv_nop = {
+	.name = "nop",
+	.description = "no-operation reactor: do nothing.",
+	.react = rv_nop_reaction
+};
+
+/*
+ * This section collects the rv/ root dir files and folders.
+ */
+int init_rv_reactors(struct dentry *root_dir)
+{
+	struct dentry *available, *reacting;
+	int retval;
+
+	available = rv_create_file("available_reactors", RV_MODE_READ, root_dir, NULL,
+				   &available_reactors_ops);
+	if (!available)
+		goto out_err;
+
+	reacting = rv_create_file("reacting_on", RV_MODE_WRITE, root_dir, NULL, &reacting_on_fops);
+	if (!reacting)
+		goto rm_available;
+
+	retval = __rv_register_reactor(&rv_nop);
+	if (retval)
+		goto rm_reacting;
+
+	reacting_on = 1;
+
+	return 0;
+
+rm_reacting:
+	rv_remove(reacting);
+rm_available:
+	rv_remove(available);
+out_err:
+	return -ENOMEM;
+}
Signature · 1 line
2.35.1
#7 lore raw

Re: [PATCH V5 02/16] rv: Add runtime reactors interface

In reply to Daniel Bristot de Oliveira
I love your patch! Perhaps something to improve:

Hi Daniel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rostedt-trace/for-next]
[also build test WARNING on tip/sched/core]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220718/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/aa2ae8ed1dd28e5df7022e89ed27a9a5283647d9
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
        git checkout aa2ae8ed1dd28e5df7022e89ed27a9a5283647d9
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/misc/lkdtm/ kernel/trace/rv/

If you fix the issue, kindly add following tag where applicable

sparse warnings: (new ones prefixed by >>)

>> kernel/trace/rv/rv_reactors.c:73:1: sparse: sparse: symbol 'rv_reactors_list' was not declared. Should it be static?
>> kernel/trace/rv/rv_reactors.c:451:19: sparse: sparse: symbol 'rv_nop' was not declared. Should it be static?
Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp
#8 lore raw

PATCH v5 3/16 rv/include: Add helper functions for deterministic automata

In reply to Daniel Bristot de Oliveira

Formally, a deterministic automaton, denoted by G, is defined as a quintuple:

G = { X, E, f, x_0, X_m }

where:
- X is the set of states;
- E is the finite set of events;
- x_0 is the initial state;
- X_m (subset of X) is the set of marked states.
- f : X x E -> X $ is the transition function. It defines the state transition in the occurrence of a event from E in the state X. In the special case of deterministic automata, the occurrence of the event in E in a state in X has a deterministic next state from X.

An automaton can also be represented using a graphical format of vertices (nodes) and edges. The open-source tool Graphviz can produce this graphic format using the (textual) DOT language as the source code.

The dot2c tool presented in this paper:

DE OLIVEIRA, Daniel Bristot; CUCINOTTA, Tommaso; DE OLIVEIRA, Romulo Silva. Efficient formal verification for the Linux kernel. In:
International Conference on Software Engineering and Formal Methods. Springer, Cham, 2019. p. 315-332.

Translates a deterministic automaton in the DOT format into a C source code representation that to be used for monitoring.

This header file implements helper functions to facilitate the usage of the C output from dot2c/k for monitoring.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/rv/automata.h | 75 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 include/rv/automata.h
include/rv/automata.h new file +75 -0
new file mode 100644
index 000000000000..7125c91df607
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira  <[email protected]>
+ *
+ * Deterministic automata helper functions, to be used with the automata
+ * models in C generated by the dot2k tool.
+ */
+
+/*
+ * DECLARE_AUTOMATA_HELPERS - define a set of helper functions for automata
+ *
+ * Define a set of helper functions for automata. The 'name' argument is used
+ * as suffix for the functions and data. These functions will handle automaton
+ * with data type 'type'.
+ */
+#define DECLARE_AUTOMATA_HELPERS(name, type)					\
+										\
+/*										\
+ * model_get_state_name_##name - return the (string) name of the given state	\
+ */ 										\
+static char *model_get_state_name_##name(enum states_##name state)		\
+{										\
+	if ((state < 0) || (state >= state_max_##name))				\
+		return "INVALID";						\
+										\
+	return automaton_##name.state_names[state];				\
+}										\
+										\
+/*										\
+ * model_get_event_name_##name - return the (string) name of the given event	\
+ */										\
+static char *model_get_event_name_##name(enum events_##name event)		\
+{										\
+	if ((event < 0) || (event >= event_max_##name))				\
+		return "INVALID";						\
+										\
+	return automaton_##name.event_names[event];				\
+}										\
+										\
+/*										\
+ * model_get_init_state_##name - return the automaton's initial state		\
+ */										\
+static inline type model_get_init_state_##name(void)				\
+{										\
+	return automaton_##name.initial_state;					\
+}										\
+										\
+/*										\
+ * model_get_next_state_##name - process an automaton event occurrence		\
+ *										\
+ * Given the current state (curr_state) and the event (event), returns		\
+ * the next state, or INVALID_STATE in case of error.				\
+ */										\
+static inline type model_get_next_state_##name(enum states_##name curr_state,	\
+					       enum events_##name event)	\
+{										\
+	if ((curr_state < 0) || (curr_state >= state_max_##name))		\
+		return INVALID_STATE;						\
+										\
+	if ((event < 0) || (event >= event_max_##name))				\
+		return INVALID_STATE;						\
+										\
+	return automaton_##name.function[curr_state][event];			\
+}										\
+										\
+/*										\
+ * model_is_final_state_##name - check if the given state is a final state	\
+ */										\
+static inline bool model_is_final_state_##name(enum states_##name state)	\
+{										\
+	if ((state < 0) || (state >= state_max_##name))				\
+		return 0;							\
+										\
+	return automaton_##name.final_states[state];				\
+}
Signature · 1 line
2.35.1
#9 lore raw

PATCH v5 4/16 rv/include: Add deterministic automata monitor definition via C macros

In reply to Daniel Bristot de Oliveira

In Linux terms, the runtime verification monitors are encapsulated inside the "RV monitor" abstraction. The "RV monitor" includes a set of instances of the monitor (per-cpu monitor, per-task monitor, and so on), the helper functions that glue the monitor to the system reference model, and the trace output as a reaction for event parsing and exceptions, as depicted below:

Linux +----- RV Monitor ----------------------------------+ Formal
Realm | | Realm

 +-------------------+     +----------------+     +-----------------+
 |   Linux kernel    |     |     Monitor    |     |     Reference   |
 |     Tracing       |  -> |   Instance(s)  | <-  |       Model     |
 | (instrumentation) |     | (verification) |     | (specification) |
 +-------------------+     +----------------+     +-----------------+
        |                          |                       |
        |                          V                       |
        |                     +----------+                 |
        |                     | Reaction |                 |
        |                     +--+--+--+-+                 |
        |                        |  |  |                   |
        |                        |  |  +-> trace output ?  |
        +------------------------|--|----------------------+
                                 |  +----> panic ?
                                 +-------> <user-specified>

Add the rv/da_monitor.h, enabling automatic code generation for the *Monitor Instance(s)* using C macros, and code to support it.

The benefits of the usage of macro for monitor synthesis are 3-fold as it:

- Reduces the code duplication;
- Facilitates the bug fix/improvement;
- Avoids the case of developers changing the core of the monitor code to manipulate the model in a (let's say) non-standard way.

This initial implementation presents three different types of monitor instances:

- DECLARE_DA_MON_GLOBAL(name, type)
- DECLARE_DA_MON_PER_CPU(name, type)
- DECLARE_DA_MON_PER_TASK(name, type)

The first declares the functions for a global deterministic automata monitor, the second for monitors with per-cpu instances, and the third with per-task instances.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/linux/rv.h        |   2 +
 include/rv/da_monitor.h   | 521 ++++++++++++++++++++++++++++++++++++++
 include/rv/rv.h           |   9 +
 include/trace/events/rv.h | 120 +++++++++
 kernel/fork.c             |  14 +
 kernel/trace/rv/Kconfig   |  14 +
 kernel/trace/rv/rv.c      |   5 +
 7 files changed, 685 insertions(+)
 create mode 100644 include/rv/da_monitor.h
 create mode 100644 include/trace/events/rv.h
include/linux/rv.h +2 -0
index 88d28d207f3a..bdefdff12a1f 100644
@@ -7,6 +7,8 @@
 #ifndef _LINUX_RV_H
 #define _LINUX_RV_H
 
+#define MAX_DA_NAME_LEN         24
+
 struct rv_reactor {
 	char			*name;
 	char			*description;
include/rv/da_monitor.h new file +521 -0

521 lines not on this page · raw message

include/rv/rv.h +9 -0
index 27a108881d35..b0658cdc53d9 100644
@@ -3,6 +3,14 @@
 #ifndef _RV_RV_H
 #define _RV_RV_H
 
+/*
+ * Deterministic automaton per-object variables.
+ */
+struct da_monitor {
+	bool	monitoring;
+	int	curr_state;
+};
+
 /*
  * Per-task RV monitors count. Nowadays fixed in RV_PER_TASK_MONITORS.
  * If we find justification for more monitors, we can think about
@@ -16,6 +24,7 @@
  * Futher monitor types are expected, so make this a union.
  */
 union rv_task_monitor {
+	struct da_monitor da_mon;
 };
 
 int get_task_monitor_slot(void);
include/trace/events/rv.h new file +120 -0

120 lines not on this page · raw message

kernel/fork.c +14 -0
index 9d44f2d46c69..6f1f82ccd5f2 100644
@@ -1964,6 +1964,18 @@ static void copy_oom_score_adj(u64 clone_flags, struct task_struct *tsk)
 	mutex_unlock(&oom_adj_mutex);
 }
 
+#ifdef CONFIG_RV
+static void rv_task_fork(struct task_struct *p)
+{
+	int i;
+
+	for (i = 0; i < RV_PER_TASK_MONITORS; i++)
+		p->rv[i].da_mon.monitoring = false;
+}
+#else
+#define rv_task_fork(p) do {} while (0)
+#endif
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -2399,6 +2411,8 @@ static __latent_entropy struct task_struct *copy_process(
 	 */
 	copy_seccomp(p);
 
+	rv_task_fork(p);
+
 	rseq_fork(p, clone_flags);
 
 	/* Don't start children in a dying pid namespace */
kernel/trace/rv/Kconfig +14 -0
index 3eb5d48ab4f6..0123bdf7052a 100644
@@ -1,5 +1,19 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
+config DA_MON_EVENTS
+	default n
+	bool
+
+config DA_MON_EVENTS_IMPLICIT
+	select DA_MON_EVENTS
+	default n
+	bool
+
+config DA_MON_EVENTS_ID
+	select DA_MON_EVENTS
+	default n
+	bool
+
 menuconfig RV
 	bool "Runtime Verification"
 	depends on TRACING
kernel/trace/rv/rv.c +5 -0
index d988e2b1b9d2..00f1ffc49a7b 100644
@@ -141,6 +141,11 @@
 #include <linux/slab.h>
 #include <rv/rv.h>
 
+#ifdef CONFIG_DA_MON_EVENTS
+#define CREATE_TRACE_POINTS
+#include <trace/events/rv.h>
+#endif
+
 #include "rv.h"
 
 DEFINE_MUTEX(rv_interface_lock);
Signature · 1 line
2.35.1
#10 lore raw

Re: [PATCH V5 04/16] rv/include: Add deterministic automata monitor definition via C macros

Quoted 344 lines · Daniel Bristot de Oliveira

In Linux terms, the runtime verification monitors are encapsulated inside the "RV monitor" abstraction. The "RV monitor" includes a set of instances of the monitor (per-cpu monitor, per-task monitor, and so on), the helper functions that glue the monitor to the system reference model, and the trace output as a reaction for event parsing and exceptions, as depicted below:

Linux +----- RV Monitor ----------------------------------+ Formal
Realm | | Realm

 +-------------------+     +----------------+     +-----------------+
 |   Linux kernel    |     |     Monitor    |     |     Reference   |
 |     Tracing       |  -> |   Instance(s)  | <-  |       Model     |
 | (instrumentation) |     | (verification) |     | (specification) |
 +-------------------+     +----------------+     +-----------------+
        |                          |                       |
        |                          V                       |
        |                     +----------+                 |
        |                     | Reaction |                 |
        |                     +--+--+--+-+                 |
        |                        |  |  |                   |
        |                        |  |  +-> trace output ?  |
        +------------------------|--|----------------------+
                                 |  +----> panic ?
                                 +-------> <user-specified>

Add the rv/da_monitor.h, enabling automatic code generation for the *Monitor Instance(s)* using C macros, and code to support it.

The benefits of the usage of macro for monitor synthesis are 3-fold as it:

- Reduces the code duplication;
- Facilitates the bug fix/improvement;
- Avoids the case of developers changing the core of the monitor code to manipulate the model in a (let's say) non-standard way.

This initial implementation presents three different types of monitor instances:

- DECLARE_DA_MON_GLOBAL(name, type)
- DECLARE_DA_MON_PER_CPU(name, type)
- DECLARE_DA_MON_PER_TASK(name, type)

The first declares the functions for a global deterministic automata monitor, the second for monitors with per-cpu instances, and the third with per-task instances.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/linux/rv.h        |   2 +
 include/rv/da_monitor.h   | 521 ++++++++++++++++++++++++++++++++++++++
 include/rv/rv.h           |   9 +
 include/trace/events/rv.h | 120 +++++++++
 kernel/fork.c             |  14 +
 kernel/trace/rv/Kconfig   |  14 +
 kernel/trace/rv/rv.c      |   5 +
 7 files changed, 685 insertions(+)
 create mode 100644 include/rv/da_monitor.h
 create mode 100644 include/trace/events/rv.h
include/linux/rv.h +2 -0
index 88d28d207f3a..bdefdff12a1f 100644
@@ -7,6 +7,8 @@
 #ifndef _LINUX_RV_H
 #define _LINUX_RV_H
 
+#define MAX_DA_NAME_LEN         24
+
 struct rv_reactor {
 	char			*name;
 	char			*description;
include/rv/da_monitor.h new file +245 -0
new file mode 100644
index 000000000000..d21045e6c5fc
@@ -0,0 +1,521 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
+ *
+ * Deterministic automata (DA) monitor functions, to be used together
+ * with automata models in C generated by the dot2k tool.
+ *
+ * The dot2k tool is available at tools/verification/dot2k/
+ */
+
+#include <rv/automata.h>
+#include <linux/rv.h>
+
+/*
+ * Generic helpers for all types of deterministic automata monitors.
+ */
+#define DECLARE_DA_MON_GENERIC_HELPERS(name, type)				\
+static char REACT_MSG[1024];							\
+										\
+static inline char *format_react_msg(type curr_state, type event)		\
+{										\
+	snprintf(REACT_MSG, 1024,						\
+		 "rv: monitor %s does not allow event %s on state %s\n",	\
+		 #name,								\
+		 model_get_event_name_##name(event),				\
+		 model_get_state_name_##name(curr_state));			\
+	return REACT_MSG;							\
+}										\
+										\
+static void cond_react(char *msg)						\
+{										\
+	if (rv_##name.react)							\
+		rv_##name.react(msg);						\
+}										\
+										\
+/*										\
+ * da_monitor_reset_##name - reset a monitor and setting it to init state	\
+ */										\
+static inline void da_monitor_reset_##name(struct da_monitor *da_mon)		\
+{										\
+	da_mon->monitoring = 0;							\
+	da_mon->curr_state = model_get_init_state_##name();			\
+}										\
+										\
+/*										\
+ * da_monitor_curr_state_##name - return the current state			\
+ */										\
+static inline type da_monitor_curr_state_##name(struct da_monitor *da_mon)	\
+{										\
+	return da_mon->curr_state;						\
+}										\
+										\
+/*										\
+ * da_monitor_set_state_##name - set the new current state			\
+ */										\
+static inline void								\
+da_monitor_set_state_##name(struct da_monitor *da_mon, enum states_##name state)\
+{										\
+	da_mon->curr_state = state;						\
+}										\
+										\
+/*										\
+ * da_monitor_start_##name - start monitoring					\
+ *										\
+ * The monitor will ignore all events until monitoring is set to true. This	\
+ * function needs to be called to tell the monitor to start monitoring.		\
+ */										\
+static inline void da_monitor_start_##name(struct da_monitor *da_mon)		\
+{										\
+	da_mon->monitoring = 1;							\
+}										\
+										\
+/*										\
+ * da_monitoring_##name - returns true if the monitor is processing events	\
+ */										\
+static inline bool da_monitoring_##name(struct da_monitor *da_mon)		\
+{										\
+	return da_mon->monitoring;						\
+}
+
+
+/*
+ * Event handler for implicit monitors. Implicit monitor is the one which the
+ * handler does not need to specify which da_monitor to manipulate. Examples
+ * of implicit monitor are the per_cpu or the global ones.
+ */
+#define DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type)			\
+static inline bool								\
+da_event_##name(struct da_monitor *da_mon, enum events_##name event)		\
+{										\
+	type curr_state = da_monitor_curr_state_##name(da_mon);			\
+	type next_state = model_get_next_state_##name(curr_state, event);	\
+										\
+	if (next_state != INVALID_STATE) {					\
+		da_monitor_set_state_##name(da_mon, next_state);		\
+										\
+		trace_event_##name(model_get_state_name_##name(curr_state),	\
+				model_get_event_name_##name(event),		\
+				model_get_state_name_##name(next_state),	\
+				model_is_final_state_##name(next_state));	\
+										\
+		return true;							\
+	}									\
+										\
+	if (reacting_on)							\
+		cond_react(format_react_msg(curr_state, event));		\
+										\
+	trace_error_##name(model_get_state_name_##name(curr_state),		\
+			   model_get_event_name_##name(event));			\
+										\
+	return false;								\
+}										\
+
+/*
+ * Event handler for per_task monitors.
+ */
+#define DECLARE_DA_MON_MODEL_HANDLER_PER_TASK(name, type)			\
+static inline type								\
+da_event_##name(struct da_monitor *da_mon, struct task_struct *tsk,		\
+		enum events_##name event)					\
+{										\
+	type curr_state = da_monitor_curr_state_##name(da_mon);			\
+	type next_state = model_get_next_state_##name(curr_state, event);	\
+										\
+	if (next_state != INVALID_STATE) {					\
+		da_monitor_set_state_##name(da_mon, next_state);		\
+										\
+		trace_event_##name(tsk->pid,					\
+				   model_get_state_name_##name(curr_state),	\
+				   model_get_event_name_##name(event),		\
+				   model_get_state_name_##name(next_state),	\
+				   model_is_final_state_##name(next_state));	\
+										\
+		return true;							\
+	}									\
+										\
+	if (reacting_on)							\
+		cond_react(format_react_msg(curr_state, event));		\
+										\
+	trace_error_##name(tsk->pid,						\
+			   model_get_state_name_##name(curr_state),		\
+			   model_get_event_name_##name(event));			\
+										\
+	return false;								\
+}
+
+/*
+ * Functions to define, init and get a global monitor.
+ */
+#define DECLARE_DA_MON_INIT_GLOBAL(name, type)					\
+										\
+/*										\
+ * global monitor (a single variable)						\
+ */										\
+static struct da_monitor da_mon_##name;						\
+										\
+/*										\
+ * da_get_monitor_##name - return the global monitor address			\
+ */										\
+static struct da_monitor *da_get_monitor_##name(void)				\
+{										\
+	return &da_mon_##name;							\
+}										\
+										\
+/*										\
+ * da_monitor_reset_all_##name - reset the single monitor			\
+ */										\
+static void da_monitor_reset_all_##name(void)					\
+{										\
+	da_monitor_reset_##name(&da_mon_##name);				\
+}										\
+										\
+/*										\
+ * da_monitor_init_##name - initialize a monitor				\
+ */										\
+static inline int da_monitor_init_##name(void)					\
+{										\
+	struct da_monitor *da_mon = &da_mon_##name;				\
+	da_mon->curr_state = model_get_init_state_##name();			\
+	da_mon->monitoring = 0;							\
+	return 0;								\
+}										\
+										\
+/*										\
+ * da_monitor_destroy_##name - destroy the monitor				\
+ */										\
+static inline void da_monitor_destroy_##name(void)				\
+{										\
+	return;									\
+}
+
+/*
+ * Functions to define, init and get a per-cpu monitor.
+ */
+#define DECLARE_DA_MON_INIT_PER_CPU(name, type)					\
+										\
+/*										\
+ * per-cpu monitor variables							\
+ */										\
+DEFINE_PER_CPU(struct da_monitor, da_mon_##name);				\
+										\
+/*										\
+ * da_get_monitor_##name - return current CPU monitor address			\
+ */										\
+static struct da_monitor *da_get_monitor_##name(void)				\
+{										\
+	return this_cpu_ptr(&da_mon_##name);					\
+}										\
+										\
+/*										\
+ * da_monitor_reset_all_##name - reset all CPUs' monitor			\
+ */										\
+static void da_monitor_reset_all_##name(void)					\
+{										\
+	struct da_monitor *da_mon;						\
+	int cpu;								\
+	for_each_cpu(cpu, cpu_online_mask) {					\
+		da_mon = per_cpu_ptr(&da_mon_##name, cpu);			\
+		da_monitor_reset_##name(da_mon);				\
+	}									\
+}										\
+										\
+/*										\
+ * da_monitor_init_##name - initialize all CPUs' monitor			\
+ */										\
+static inline int da_monitor_init_##name(void)					\
+{										\
+	struct da_monitor *da_mon;						\
+	int cpu;								\
+	for_each_cpu(cpu, cpu_online_mask) {					\
+		da_mon = per_cpu_ptr(&da_mon_##name, cpu);			\
+		da_mon->curr_state = model_get_init_state_##name();		\
+		da_mon->monitoring = 0;						\
+	}									\
+	return 0;								\
+}										\
+										\
+/*										\
+ * da_monitor_destroy_##name - destroy the monitor				\
+ */										\
+static inline void da_monitor_destroy_##name(void)				\
+{										\
+	return;									\
+}
+

include/rv/da_monitor.h line 255

Quoted 10 lines
include/rv/da_monitor.h new file +10 -0
+/*
+ * Functions to define, init and get a per-task monitor.
+ */
+#define DECLARE_DA_MON_INIT_PER_TASK(name, type)				\
+										\
+/*										\
+ * The per-task monitor is stored a vector in the task struct. This variable	\
+ * stores the position on the vector reserved for this monitor.			\
+ */										\
+static int task_mon_slot_##name = RV_PER_TASK_MONITOR_INIT;			\

In patch1, RV_PER_TASK_MONITOR_INIT is defined as:

#define RV_PER_TASK_MONITORS 1
#define RV_PER_TASK_MONITOR_INIT (RV_PER_TASK_MONITORS)

RV_PER_TASK_MONITOR_INIT is 1 now, seems not the index of the first only element in vector. Now no map here, one task has one monitor though if I am not wrong.
So task_mon_slot_##name must be defined to the index of first element. Modify the macro definition of RV_PER_TASK_MONITOR_INIT to the index of first element in vector.

#define RV_PER_TASK_MONITOR_INIT (RV_PER_TASK_MONITORS) - 1

If there are more monitors per task in the furture, like you say, dynamic allocation and mapping should be used. But I don't know.

#11 lore raw

Re: [PATCH V5 04/16] rv/include: Add deterministic automata monitor definition via C macros

Quoted 6 lines · Tao Zhou
Quoted 1 line

+static int task_mon_slot_##name = RV_PER_TASK_MONITOR_INIT; \

In patch1, RV_PER_TASK_MONITOR_INIT is defined as:

#define RV_PER_TASK_MONITORS 1
#define RV_PER_TASK_MONITOR_INIT (RV_PER_TASK_MONITORS)

Quoted 8 lines

RV_PER_TASK_MONITOR_INIT is 1 now, seems not the index of the first only element in vector. Now no map here, one task has one monitor though if I am not wrong.
So task_mon_slot_##name must be defined to the index of first element. Modify the macro definition of RV_PER_TASK_MONITOR_INIT to the index of first element in vector.

#define RV_PER_TASK_MONITOR_INIT (RV_PER_TASK_MONITORS) - 1

nop, (RV_PER_TASK_MONITORS) is an invalid vector value, so we can detect things like:
disabling a disabled monitor.

(I forgot to reset it when disabling a monitor... added)

-- Daniel

#12 lore raw

PATCH v5 5/16 rv/include: Add instrumentation helper functions

In reply to Daniel Bristot de Oliveira

Instrumentation helper functions to facilitate the instrumentation of auto-generated RV monitors create by dot2k.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 include/rv/instrumentation.h | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 include/rv/instrumentation.h
include/rv/instrumentation.h new file +29 -0
new file mode 100644
index 000000000000..d4e7a02ede1a
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
+ *
+ * Helper functions to facilitate the instrumentation of auto-generated
+ * RV monitors create by dot2k.
+ *
+ * The dot2k tool is available at tools/verification/dot2/
+ */
+
+#include <linux/ftrace.h>
+
+/*
+ * rv_attach_trace_probe - check and attach a handler function to a tracepoint
+ */
+#define rv_attach_trace_probe(monitor, tp, rv_handler)					\
+	do {										\
+		check_trace_callback_type_##tp(rv_handler);				\
+		WARN_ONCE(register_trace_##tp(rv_handler, NULL),			\
+				"fail attaching " #monitor " " #tp "handler");		\
+	} while (0)
+
+/*
+ * rv_detach_trace_probe - detach a handler function to a tracepoint
+ */
+#define rv_detach_trace_probe(monitor, tp, rv_handler)					\
+	do {										\
+		unregister_trace_##tp(rv_handler, NULL);				\
+	} while (0)
Signature · 1 line
2.35.1
#13 lore raw

PATCH v5 6/16 Documentation/rv: Add a basic documentation

In reply to Daniel Bristot de Oliveira

Add the runtime-verification.rst document, explaining the basics of RV and how to use the interface.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 Documentation/trace/index.rst                 |   1 +
 Documentation/trace/rv/index.rst              |   9 +
 .../trace/rv/runtime-verification.rst         | 233 ++++++++++++++++++
 kernel/trace/rv/Kconfig                       |   3 +
 kernel/trace/rv/rv.c                          |   3 +
 5 files changed, 249 insertions(+)
 create mode 100644 Documentation/trace/rv/index.rst
 create mode 100644 Documentation/trace/rv/runtime-verification.rst
Documentation/trace/index.rst +1 -0
index f9b7bcb5a630..2d73e8697523 100644
@@ -32,3 +32,4 @@ Linux Tracing Technologies
    sys-t
    coresight/index
    user_events
+   rv/index
Documentation/trace/rv/index.rst new file +9 -0
new file mode 100644
index 000000000000..b54e49b1d0de
@@ -0,0 +1,9 @@
+====================
+Runtime Verification
+====================
+
+.. toctree::
+   :maxdepth: 2
+   :glob:
+
+   runtime-verification.rst
Documentation/trace/rv/runtime-verification.rst new file +233 -0

233 lines not on this page · raw message

kernel/trace/rv/Kconfig +3 -0
index 0123bdf7052a..7ad6c93cda64 100644
@@ -25,6 +25,9 @@ menuconfig RV
 	  actual execution, comparing it against a formal specification of
 	  the system behavior.
 
+	  For further information, see:
+	    Documentation/trace/rv/runtime-verification.rst
+
 config RV_REACTORS
 	bool "Runtime verification reactors"
 	default y
kernel/trace/rv/rv.c +3 -0
index 00f1ffc49a7b..b2f963a54e3d 100644
@@ -133,6 +133,9 @@
  *      auto-generated wakeup in preemptive monitor.
  *      # cat enable
  *      0
+ *
+ *  For further information, see:
+ *   Documentation/trace/rv/runtime-verification.rst
  */
 
 #include <linux/kernel.h>
Signature · 1 line
2.35.1
#14 lore raw

Re: [PATCH V5 06/16] Documentation/rv: Add a basic documentation

Quoted 35 lines · Daniel Bristot de Oliveira

Add the runtime-verification.rst document, explaining the basics of RV and how to use the interface.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 Documentation/trace/index.rst                 |   1 +
 Documentation/trace/rv/index.rst              |   9 +
 .../trace/rv/runtime-verification.rst         | 233 ++++++++++++++++++
 kernel/trace/rv/Kconfig                       |   3 +
 kernel/trace/rv/rv.c                          |   3 +
 5 files changed, 249 insertions(+)
 create mode 100644 Documentation/trace/rv/index.rst
 create mode 100644 Documentation/trace/rv/runtime-verification.rst

+ runtime-verification.rst

[snip]

Quoted 24 lines
Documentation/trace/rv/runtime-verification.rst new file +24 -0
+The user interface
+==================
+
+The user interface resembles the tracing interface (on purpose). It is
+currently at "/sys/kernel/tracing/rv/".
+
+The following files/folders are currently available:
+
+**available_monitors**
+
+- Reading list the available monitors, one per line
+
+For example::
+
+   # cat available_monitors
+   wip
+   wwnr
+
+**available_reactors**
+
+- Reading shows the available reactors, one per line.
+
+For example::
+

Documentation/trace/rv/runtime-verification.rst line 152

Quoted 10 lines
Documentation/trace/rv/runtime-verification.rst new file +10 -0
+   # cat available_reactors
+   nop
+   panic
+   printk
+
+**enabled_monitors**:
+
+- Reading lists the enabled monitors, one per line
+- Writing to it enables a given monitor
+- Writing a monitor name with a '-' prefix disables it

s/-/!/

Quoted 27 lines

+- Truncating the file disables all enabled monitors

Documentation/trace/rv/runtime-verification.rst new file +26 -0
+
+For example::
+
+   # cat enabled_monitors
+   # echo wip > enabled_monitors
+   # echo wwnr >> enabled_monitors
+   # cat enabled_monitors
+   wip
+   wwnr
+   # echo '!wip' >> enabled_monitors
+   # cat enabled_monitors
+   wwnr
+   # echo > enabled_monitors
+   # cat enabled_monitors
+   #
+
+Note that it is possible to enable more than one monitor concurrently.
+
+
+**monitoring_on**
+
+This is an on/off general switcher for monitoring. It resembles the
+"tracing_on" switcher in the trace interface.
+
+- Writing "0" stops the monitoring
+- Writing "1" continues the monitoring

Documentation/trace/rv/runtime-verification.rst line 189

Quoted 10 lines
Documentation/trace/rv/runtime-verification.rst new file +10 -0
+- Reading returns the current status of the monitoring
+
+Note that it does not disable enabled monitors but stop the per-entity
+monitors monitoring the events received from the system.
+
+**reacting_on**
+
+- Writing "0" prevents reactions for happening
+- Writing "1" enable reactions
+- Reading returns the current status of the monitoring

s/monitoring/reaction/

#15 lore raw

PATCH v5 7/16 tools/rv: Add dot2c

In reply to Daniel Bristot de Oliveira

dot2c is a tool that transforms an automata in the graphiviz .dot file into an C representation of the automata.

usage: dot2c [-h] dot_file

dot2c: converts a .dot file into a C structure

positional arguments:
dot_file The dot file to be converted

optional arguments:
-h, --help show this help message and exit

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 tools/verification/dot2/Makefile    |  21 +++
 tools/verification/dot2/automata.py | 171 +++++++++++++++++++
 tools/verification/dot2/dot2c       |  23 +++
 tools/verification/dot2/dot2c.py    | 251 ++++++++++++++++++++++++++++
 4 files changed, 466 insertions(+)
 create mode 100644 tools/verification/dot2/Makefile
 create mode 100644 tools/verification/dot2/automata.py
 create mode 100644 tools/verification/dot2/dot2c
 create mode 100644 tools/verification/dot2/dot2c.py
tools/verification/dot2/Makefile new file +21 -0
new file mode 100644
index 000000000000..235d182f6b2c
@@ -0,0 +1,21 @@
+INSTALL=install
+
+prefix  ?= /usr
+bindir  ?= $(prefix)/bin
+mandir  ?= $(prefix)/share/man
+miscdir ?= $(prefix)/share/dot2
+srcdir  ?= $(prefix)/src
+
+PYLIB  ?= $(shell python3 -c 'import sysconfig;  print (sysconfig.get_path("purelib"))')
+
+.PHONY: all
+all:
+
+.PHONY: clean
+clean:
+
+.PHONY: install
+install:
+	$(INSTALL) automata.py -D -m 644 $(DESTDIR)$(PYLIB)/dot2/automata.py
+	$(INSTALL) dot2c.py -D -m 644 $(DESTDIR)$(PYLIB)/dot2/dot2c.py
+	$(INSTALL) dot2c -D -m 755 $(DESTDIR)$(bindir)/
tools/verification/dot2/automata.py new file +171 -0

171 lines not on this page · raw message

tools/verification/dot2/dot2c new file +23 -0
new file mode 100644
index 000000000000..8a8cd84bdfcf
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
+#
+# dot2c: parse an automata in dot file digraph format into a C
+#
+# This program was written in the development of this paper:
+#  de Oliveira, D. B. and Cucinotta, T. and de Oliveira, R. S.
+#  "Efficient Formal Verification for the Linux Kernel." International
+#  Conference on Software Engineering and Formal Methods. Springer, Cham, 2019.
+
+if __name__ == '__main__':
+    from dot2 import dot2c
+    import argparse
+    import sys
+
+    parser = argparse.ArgumentParser(description='dot2c: converts a .dot file into a C structure')
+    parser.add_argument('dot_file',  help='The dot file to be converted')
+
+    args = parser.parse_args()
+    d = dot2c.Dot2c(args.dot_file)
+    d.print_model_classic()
tools/verification/dot2/dot2c.py new file +251 -0

251 lines not on this page · raw message

Signature · 1 line
2.35.1
#16 lore raw

PATCH v5 8/16 Documentation/rv: Add deterministic automaton documentation

In reply to Daniel Bristot de Oliveira

Add documentation about deterministic automaton and its possible representations (formal, graphic, .dot and C).

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 .../trace/rv/deterministic_automata.rst       | 184 ++++++++++++++++++
 Documentation/trace/rv/index.rst              |   1 +
 tools/verification/dot2/automata.py           |   3 +
 tools/verification/dot2/dot2c                 |   3 +
 tools/verification/dot2/dot2c.py              |   3 +
 5 files changed, 194 insertions(+)
 create mode 100644 Documentation/trace/rv/deterministic_automata.rst
Documentation/trace/rv/deterministic_automata.rst new file +184 -0
new file mode 100644
index 000000000000..8599cc01759d
@@ -0,0 +1,184 @@
+Deterministic Automata
+======================
+
+Formally, a deterministic automaton, denoted by G, is defined as a quintuple:
+
+        *G* = { *X*, *E*, *f*, x\ :subscript:`0`, X\ :subscript:`m` }
+
+where:
+
+- *X* is the set of states;
+- *E* is the finite set of events;
+- x\ :subscript:`0` is the initial state;
+- X\ :subscript:`m` (subset of *X*) is the set of marked (or final) states.
+- *f* : *X* x *E* -> *X* $ is the transition function. It defines the state
+  transition in the occurrence of an event from *E* in the state *X*. In the
+  special case of deterministic automata, the occurrence of the event in *E*
+  in a state in *X* has a deterministic next state from *X*.
+
+For example, a given automaton named 'wip' (wakeup in preemptive) can
+be defined as:
+
+- *X* = { ``preemptive``, ``non_preemptive``}
+- *E* = { ``preempt_enable``, ``preempt_disable``, ``sched_waking``}
+- x\ :subscript:`0` = ``preemptive``
+- X\ :subscript:`m` = {``preemptive``}
+- *f* =
+   - *f*\ (``preemptive``, ``preempt_disable``) = ``non_preemptive``
+   - *f*\ (``non_preemptive``, ``sched_waking``) = ``non_preemptive``
+   - *f*\ (``non_preemptive``, ``preempt_enable``) = ``preemptive``
+
+One of the benefits of this formal definition is that it can be presented
+in multiple formats. For example, using a *graphical representation*, using
+vertices (nodes) and edges, which is very intuitive for *operating system*
+practitioners, without any loss.
+
+The previous 'wip' automaton can also be represented as::
+
+                       preempt_enable
+          +---------------------------------+
+          v                                 |
+        #============#  preempt_disable   +------------------+
+    --> H preemptive H -----------------> |  non_preemptive  |
+        #============#                    +------------------+
+                                            ^              |
+                                            | sched_waking |
+                                            +--------------+
+
+Deterministic Automaton in C
+----------------------------
+
+In the paper "Efficient formal verification for the Linux kernel",
+the authors present a simple way to represent an automaton in C that can
+be used as regular code in the Linux kernel.
+
+For example, the 'wip' automata can be presented as (augmented with comments)::
+
+  /* enum representation of X (set of states) to be used as index */
+  enum states {
+	preemptive = 0,
+	non_preemptive,
+	state_max
+  };
+
+  #define INVALID_STATE state_max
+
+  /* enum representation of E (set of events) to be used as index */
+  enum events {
+	preempt_disable = 0,
+	preempt_enable,
+	sched_waking,
+	event_max
+  };
+
+  struct automaton {
+	char *state_names[state_max];                   // X: the set of states
+	char *event_names[event_max];                   // E: the finite set of events
+	unsigned char function[state_max][event_max];   // f: transition function
+	unsigned char initial_state;                    // x_0: the initial state
+	bool final_states[state_max];                   // X_m: the set of marked states
+  };
+
+  struct automaton aut = {
+	.state_names = {
+		"preemptive",
+		"non_preemptive"
+	},
+	.event_names = {
+		"preempt_disable",
+		"preempt_enable",
+		"sched_waking"
+	},
+	.function = {
+		{ non_preemptive,  INVALID_STATE,  INVALID_STATE },
+		{  INVALID_STATE,     preemptive, non_preemptive },
+	},
+	.initial_state = preemptive,
+	.final_states = { 1, 0 },
+  };
+
+The *transition function* is represented as a matrix of states (lines) and
+events (columns), and so the function *f* : *X* x *E* -> *X* can be solved
+in O(1). For example::
+
+  next_state = automaton_wip.function[curr_state][event];
+
+Graphviz .dot format
+--------------------
+
+The Graphviz open-source tool can produce the graphical representation
+of an automaton using the (textual) DOT language as the source code.
+The DOT format is widely used and can be converted to many other formats.
+
+For example, this is the 'wip' model in DOT::
+
+  digraph state_automaton {
+        {node [shape = circle] "non_preemptive"};
+        {node [shape = plaintext, style=invis, label=""] "__init_preemptive"};
+        {node [shape = doublecircle] "preemptive"};
+        {node [shape = circle] "preemptive"};
+        "__init_preemptive" -> "preemptive";
+        "non_preemptive" [label = "non_preemptive"];
+        "non_preemptive" -> "non_preemptive" [ label = "sched_waking" ];
+        "non_preemptive" -> "preemptive" [ label = "preempt_enable" ];
+        "preemptive" [label = "preemptive"];
+        "preemptive" -> "non_preemptive" [ label = "preempt_disable" ];
+        { rank = min ;
+                "__init_preemptive";
+                "preemptive";
+        }
+  }
+
+This DOT format can be transformed into a bitmap or vectorial image
+using the dot utility, or into an ASCII art using graph-easy. For
+instance::
+
+  $ dot -Tsvg -o wip.svg wip.dot
+  $ graph-easy wip.dot > wip.txt
+
+dot2c
+-----
+
+dot2c is a utility that can parse a .dot file containing an automaton as
+in the example above and automatically convert it to the C representation
+presented in [3].
+
+For example, having the previous 'wip' model into a file named 'wip.dot',
+the following command will transform the .dot file into the C
+representation (previously shown) in the 'wip.h' file::
+
+  $ dot2c wip.dot > wip.h
+
+The 'wip.h' content is the code sample in section 'Deterministic Automaton
+in C'.
+
+Remarks
+-------
+
+The automata formalism allows modeling discrete event systems (DES) in
+multiple formats, suitable for different applications/users.
+
+For example, the formal description using set theory is better suitable
+for automata operations, while the graphical format for human interpretation;
+and computer languages for machine execution.
+
+References
+----------
+
+Many textbooks cover automata formalism. For a brief introduction see::
+
+  O'Regan, Gerard. Concise guide to software engineering. Springer,
+  Cham, 2017.
+
+For a detailed description, including operations, and application on Discrete
+Event Systems (DES), see::
+
+  Cassandras, Christos G., and Stephane Lafortune, eds. Introduction to discrete
+  event systems. Boston, MA: Springer US, 2008.
+
+For the C representation in kernel, see::
+
+  De Oliveira, Daniel Bristot; Cucinotta, Tommaso; De Oliveira, Romulo
+  Silva. Efficient formal verification for the Linux kernel. In:
+  International Conference on Software Engineering and Formal Methods.
+  Springer, Cham, 2019. p. 315-332.
Documentation/trace/rv/index.rst +1 -0
index b54e49b1d0de..013a41a410cf 100644
@@ -7,3 +7,4 @@ Runtime Verification
    :glob:
 
    runtime-verification.rst
+   deterministic_automata.rst
tools/verification/dot2/automata.py +3 -0
index f22e1dff19ce..baffeb960ff0 100644
@@ -4,6 +4,9 @@
 # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
 #
 # Automata object: parse an automata in dot file digraph format into a python object
+#
+# For further information, see:
+#   Documentation/trace/rv/deterministic_automata.rst
 
 import ntpath
 
tools/verification/dot2/dot2c +3 -0
index 8a8cd84bdfcf..3fe89ab88b65 100644
@@ -9,6 +9,9 @@
 #  de Oliveira, D. B. and Cucinotta, T. and de Oliveira, R. S.
 #  "Efficient Formal Verification for the Linux Kernel." International
 #  Conference on Software Engineering and Formal Methods. Springer, Cham, 2019.
+#
+# For further information, see:
+#   Documentation/trace/rv/deterministic_automata.rst
 
 if __name__ == '__main__':
     from dot2 import dot2c
tools/verification/dot2/dot2c.py +3 -0
index bca902eec483..fa73353f7e56 100644
@@ -9,6 +9,9 @@
 #  de Oliveira, D. B. and Cucinotta, T. and de Oliveira, R. S.
 #  "Efficient Formal Verification for the Linux Kernel." International
 #  Conference on Software Engineering and Formal Methods. Springer, Cham, 2019.
+#
+# For further information, see:
+#   Documentation/trace/rv/deterministic_automata.rst
 
 from dot2.automata import Automata
 
Signature · 1 line
2.35.1
#17 lore raw

PATCH v5 9/16 tools/rv: Add dot2k

In reply to Daniel Bristot de Oliveira

transform .dot file into kernel rv monitor

usage: dot2k [-h] -d DOT_FILE -t MONITOR_TYPE [-n MODEL_NAME] [-D DESCRIPTION]

optional arguments:
-h, --help show this help message and exit
-d DOT_FILE, --dot DOT_FILE
-t MONITOR_TYPE, --monitor_type MONITOR_TYPE
-n MODEL_NAME, --model_name MODEL_NAME
-D DESCRIPTION, --description DESCRIPTION

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 tools/verification/dot2/Makefile              |   5 +
 tools/verification/dot2/dot2k                 |  44 +++++
 tools/verification/dot2/dot2k.py              | 174 ++++++++++++++++++
 .../dot2/dot2k_templates/main_global.c        |  94 ++++++++++
 .../dot2/dot2k_templates/main_per_cpu.c       |  94 ++++++++++
 .../dot2/dot2k_templates/main_per_task.c      |  94 ++++++++++
 6 files changed, 505 insertions(+)
 create mode 100644 tools/verification/dot2/dot2k
 create mode 100644 tools/verification/dot2/dot2k.py
 create mode 100644 tools/verification/dot2/dot2k_templates/main_global.c
 create mode 100644 tools/verification/dot2/dot2k_templates/main_per_cpu.c
 create mode 100644 tools/verification/dot2/dot2k_templates/main_per_task.c
tools/verification/dot2/Makefile +5 -0
index 235d182f6b2c..021beb07a521 100644
@@ -19,3 +19,8 @@ install:
 	$(INSTALL) automata.py -D -m 644 $(DESTDIR)$(PYLIB)/dot2/automata.py
 	$(INSTALL) dot2c.py -D -m 644 $(DESTDIR)$(PYLIB)/dot2/dot2c.py
 	$(INSTALL) dot2c -D -m 755 $(DESTDIR)$(bindir)/
+	$(INSTALL) dot2k.py -D -m 644 $(DESTDIR)$(PYLIB)/dot2/dot2k.py
+	$(INSTALL) dot2k -D -m 755 $(DESTDIR)$(bindir)/
+
+	mkdir -p ${miscdir}/
+	cp -rp dot2k_templates $(DESTDIR)$(miscdir)/
tools/verification/dot2/dot2k new file +44 -0

44 lines not on this page · raw message

tools/verification/dot2/dot2k.py new file +174 -0

174 lines not on this page · raw message

tools/verification/dot2/dot2k_templates/main_global.c new file +94 -0

94 lines not on this page · raw message

tools/verification/dot2/dot2k_templates/main_per_cpu.c new file +94 -0

94 lines not on this page · raw message

tools/verification/dot2/dot2k_templates/main_per_task.c new file +94 -0

94 lines not on this page · raw message

Signature · 1 line
2.35.1
#18 lore raw

PATCH v5 10/16 Documentation/rv: Add deterministic automata monitor synthesis documentation

In reply to Daniel Bristot de Oliveira

Add the da_monitor_synthesis.rst introduces some concepts behind the Deterministic Automata (DA) monitor synthesis and interface.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 .../trace/rv/da_monitor_synthesis.rst         | 147 ++++++++++++++++++
 Documentation/trace/rv/index.rst              |   1 +
 include/rv/da_monitor.h                       |   3 +
 tools/verification/dot2/dot2k                 |   3 +
 tools/verification/dot2/dot2k.py              |   3 +
 5 files changed, 157 insertions(+)
 create mode 100644 Documentation/trace/rv/da_monitor_synthesis.rst
Documentation/trace/rv/da_monitor_synthesis.rst new file +147 -0
new file mode 100644
index 000000000000..427ed4f4729b
@@ -0,0 +1,147 @@
+Deterministic Automata Monitor Synthesis
+========================================
+
+The starting point for the application of runtime verification (RV) technics
+is the *specification* or *modeling* of the desired (or undesired) behavior
+of the system under scrutiny.
+
+The formal representation needs to be then *synthesized* into a *monitor*
+that can then be used in the analysis of the trace of the system. The
+*monitor* connects to the system via an *instrumentation* that converts
+the events from the *system* to the events of the *specification*.
+
+
+In Linux terms, the runtime verification monitors are encapsulated inside
+the *RV monitor* abstraction. The RV monitor includes a set of instances
+of the monitor (per-cpu monitor, per-task monitor, and so on), the helper
+functions that glue the monitor to the system reference model, and the
+trace output as a reaction to event parsing and exceptions, as depicted
+below::
+
+ Linux  +----- RV Monitor ----------------------------------+ Formal
+  Realm |                                                   |  Realm
+  +-------------------+     +----------------+     +-----------------+
+  |   Linux kernel    |     |     Monitor    |     |     Reference   |
+  |     Tracing       |  -> |   Instance(s)  | <-  |       Model     |
+  | (instrumentation) |     | (verification) |     | (specification) |
+  +-------------------+     +----------------+     +-----------------+
+         |                          |                       |
+         |                          V                       |
+         |                     +----------+                 |
+         |                     | Reaction |                 |
+         |                     +--+--+--+-+                 |
+         |                        |  |  |                   |
+         |                        |  |  +-> trace output ?  |
+         +------------------------|--|----------------------+
+                                  |  +----> panic ?
+                                  +-------> <user-specified>
+
+DA monitor synthesis
+--------------------
+
+The synthesis of automata-based models into the Linux *RV monitor* abstraction
+is automated by the dot2k tool and the rv/da_monitor.h header file that
+contains a set of macros that automatically generate the monitor's code.
+
+dot2k
+-----
+
+The dot2k utility leverages dot2c by converting an automaton model in
+the DOT format into the C representation [1] and creating the skeleton of
+a kernel monitor in C.
+
+For example, it is possible to transform the wip.dot model present in
+[1] into a per-cpu monitor with the following command::
+
+  $ dot2k -d wip.dot -t per_cpu
+
+This will create a directory named wip/ with the following files:
+
+- wip.h: the wip model in C
+- wip.c: the RV monitor
+
+The wip.c file contains the monitor declaration and the starting point for
+the system instrumentation.
+
+Monitor macros
+--------------
+
+The rv/da_monitor.h enables automatic code generation for the *Monitor
+Instance(s)* using C macros.
+
+The benefits of the usage of macro for monitor synthesis are 3-fold as it:
+
+- Reduces the code duplication;
+- Facilitates the bug fix/improvement;
+- Avoids the case of developers changing the core of the monitor code
+  to manipulate the model in a (let's say) non-standard way.
+
+This initial implementation presents three different types of monitor instances:
+
+- ``#define DECLARE_DA_MON_GLOBAL(name, type)``
+- ``#define DECLARE_DA_MON_PER_CPU(name, type)``
+- ``#define DECLARE_DA_MON_PER_TASK(name, type)``
+
+The first declares the functions for a global deterministic automata monitor,
+the second for monitors with per-cpu instances, and the third with per-task
+instances.
+
+In all cases, the 'name' argument is a string that identifies the monitor, and
+the 'type' argument is the data type used by dot2k on the representation of
+the model in C.
+
+For example, the wip model with two states and three events can be
+stored in an 'unsigned char' type. Considering that the preemption control
+is a per-cpu behavior, the monitor declaration in the 'wip.c' file is::
+
+  DECLARE_DA_MON_PER_CPU(wip, unsigned char);
+
+The monitor is executed by sending events to be processed via the functions
+presented below::
+
+  da_handle_event_$(MONITOR_NAME)($(event from event enum));
+  da_handle_init_event_$(MONITOR_NAME)($(event from event enum));
+  da_handle_init_run_event_$(MONITOR_NAME)($(event from event enum));
+
+The function ``da_handle_event_$(MONITOR_NAME)()`` is the regular case where
+the event will be processed if the monitor is processing events.
+
+When a monitor is enabled, it is placed in the initial state of the automata.
+However, the monitor does not know if the system is in the *initial state*.
+
+The ``da_handle_init_event_$(MONITOR_NAME)()`` function is used to notify the
+monitor that the system is returning to the initial state, so the monitor can
+start monitoring the next event.
+
+The ``da_handle_init_run_event_$(MONITOR_NAME)()`` function is used to notify
+the monitor that the system is known to be in the initial state, so the
+monitor can start monitoring and monitor the current event.
+
+Using the wip model as example, the events "preempt_disable" and
+"sched_waking" should be sent to monitor, respectively, via [2]::
+
+  da_handle_event_wip(preempt_disable_wip);
+  da_handle_event_wip(sched_waking_wip);
+
+While the event "preempt_enabled" will use::
+
+  da_handle_init_event_wip(preempt_enable_wip);
+
+To notify the monitor that the system will be returning to the initial state,
+so the system and the monitor should be in sync.
+
+Final remarks
+-------------
+
+With the monitor synthesis in place using the rv/da_monitor.h and
+dot2k, the developer's work should be limited to the instrumentation
+of the system, increasing the confidence in the overall approach.
+
+[1] For details about deterministic automata format and the translation
+from one representation to another, see::
+
+  Documentation/trace/rv/deterministic_automata.rst
+
+[2] dot2k appends the monitor's name suffix to the events enums to
+avoid conflicting variables when exporting the global vmlinux.h
+use by BPF programs.
Documentation/trace/rv/index.rst +1 -0
index 013a41a410cf..46d47f33052c 100644
@@ -8,3 +8,4 @@ Runtime Verification
 
    runtime-verification.rst
    deterministic_automata.rst
+   da_monitor_synthesis.rst
include/rv/da_monitor.h +3 -0
index d21045e6c5fc..7a1e6fcd642e 100644
@@ -6,6 +6,9 @@
  * with automata models in C generated by the dot2k tool.
  *
  * The dot2k tool is available at tools/verification/dot2k/
+ *
+ * For further information, see:
+ *   Documentation/trace/rv/da_monitor_synthesis.rst
  */
 
 #include <rv/automata.h>
tools/verification/dot2/dot2k +3 -0
index 69106f4b7682..9dcd38abe20a 100644
@@ -4,6 +4,9 @@
 # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
 #
 # dot2k: transform dot files into a monitor for the Linux kernel.
+#
+# For further information, see:
+#   Documentation/trace/rv/da_monitor_synthesis.rst
 
 if __name__ == '__main__':
     from dot2.dot2k import dot2k
tools/verification/dot2/dot2k.py +3 -0
index 4eecd69c2568..2856e1ce1259 100644
@@ -4,6 +4,9 @@
 # Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <[email protected]>
 #
 # dot2k: transform dot files into a monitor for the Linux kernel.
+#
+# For further information, see:
+#   Documentation/trace/rv/da_monitor_synthesis.rst
 
 from dot2.dot2c import Dot2c
 import platform
Signature · 1 line
2.35.1
#19 lore raw

PATCH v5 11/16 Documentation/rv: Add deterministic automata instrumentation documentation

In reply to Daniel Bristot de Oliveira

Add the da_monitor_instrumentation.rst. It describes the basics of RV monitor instrumentation.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 .../trace/rv/da_monitor_instrumentation.rst   | 169 ++++++++++++++++++
 Documentation/trace/rv/index.rst              |   1 +
 2 files changed, 170 insertions(+)
 create mode 100644 Documentation/trace/rv/da_monitor_instrumentation.rst
Documentation/trace/rv/da_monitor_instrumentation.rst new file +169 -0
new file mode 100644
index 000000000000..7b83d6c7dbed
@@ -0,0 +1,169 @@
+Deterministic Automata Instrumentation
+========================================
+
+The RV monitor file created by dot2k, with the name "$MODEL_NAME.c"
+includes a section dedicated to instrumentation.
+
+In the example of the wip.dot monitor created on [1], it will look like::
+
+  /*
+   * This is the instrumentation part of the monitor.
+   *
+   * This is the section where manual work is required. Here the kernel events
+   * are translated into model's event.
+   *
+   */
+  static void handle_preempt_disable(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(preempt_disable_wip);
+  }
+
+  static void handle_preempt_enable(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(preempt_enable_wip);
+  }
+
+  static void handle_sched_waking(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(sched_waking_wip);
+  }
+
+  static int start_wip(void)
+  {
+	int retval;
+
+	retval = da_monitor_init_wip();
+	if (retval)
+		return retval;
+
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking);
+
+	return 0;
+  }
+
+The comment at the top of the section explains the general idea: the
+instrumentation section translates *kernel events* into the *model's
+event*.
+
+Tracing callback functions
+-----------------------------
+
+The first three functions are the starting point of the callback *handler
+functions* for each of the three events from the wip model. The developer
+does not necessarily need to use them: they are just starting points.
+
+Using the example of::
+
+ void handle_preempt_disable(void *data, /* XXX: fill header */)
+ {
+        da_handle_event_wip(preempt_disable_wip);
+ }
+
+The preempt_disable event from the model connects directly to the
+preemptirq:preempt_disable. The preemptirq:preempt_disable event
+has the following signature, from include/trace/events/preemptirq.h::
+
+  TP_PROTO(unsigned long ip, unsigned long parent_ip)
+
+Hence, the handle_preempt_disable() function will look like::
+
+  void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip)
+
+In this case, the kernel event translates one to one with the automata
+event, and indeed, no other change is required for this function.
+
+The next handler function, handle_preempt_enable() has the same argument
+list from the handle_preempt_disable(). The difference is that the
+preempt_enable event will be used to synchronize the system to the model.
+
+Initially, the *model* is placed in the initial state. However, the *system*
+might or might not be in the initial state. The monitor cannot start
+processing events until it knows that the system has reached the initial state.
+Otherwise, the monitor and the system could be out-of-sync.
+
+Looking at the automata definition, it is possible to see that the system
+and the model are expected to return to the initial state after the
+preempt_enable execution. Hence, it can be used to synchronize the
+system and the model at the initialization of the monitoring section.
+
+The initialization is informed via a special handle function, the
+"da_handle_init_event_$(MONITOR)(event)", in this case::
+
+  da_handle_event_wip(preempt_disable_wip);
+
+So, the callback function will look like::
+
+  void handle_preempt_enable(void *data, unsigned long ip, unsigned long parent_ip)
+  {
+        da_handle_init_event_wip(preempt_enable_wip);
+  }
+
+Finally, the "handle_sched_waking()" will look like::
+
+  void handle_sched_waking(void *data, struct task_struct *task)
+  {
+        da_handle_event_wip(sched_waking_wip);
+  }
+
+And the explanation is left for the reader as an exercise.
+
+Start and Stop functions
+------------------------
+
+dot2k automatically creates two special functions::
+
+  start_$MODELNAME()
+  stop_$MODELNAME()
+
+These functions are called when the monitor is enabled and disabled,
+respectively.
+
+They should be used to *attach* and *detach* the instrumentation to the running
+system. The developer must add to the relative function all that is needed to
+*attach* and *detach* its monitor to the system.
+
+For the wip case, these functions were named::
+
+ start_wip()
+ stop_wip()
+
+But no change was required because: by default, these functions *attach* and
+*detach* the tracepoints_to_attach, which was enough for this case.
+
+Instrumentation helpers
+--------------------------
+
+To complete the instrumentation, the *handler functions* need to be attached to a
+kernel event, at the monitoring start phase.
+
+The RV interface also facilitates this step. For example, the macro "rv_attach_trace_probe()"
+is used to connect the wip model events to the relative kernel event. dot2k automatically
+adds "rv_attach_trace_probe()" function call for each model event in the start phase, as
+a suggestion.
+
+For example, from the wip sample model::
+
+  static int start_wip(void)
+  {
+        int retval;
+
+        retval = da_monitor_init_wip();
+        if (retval)
+                return retval;
+
+        rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable);
+        rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable);
+        rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking);
+
+        return 0;
+  }
+
+The probes then need to be detached at the stop phase.
+
+[1] The wip model is presented in:
+      Documentation/trace/rv/deterministic_automata.rst
+
+    The wip monitor is presented in:
+      Documentation/trace/rv/da_monitor_synthesis.rst
Documentation/trace/rv/index.rst +1 -0
index 46d47f33052c..db2ae3f90b90 100644
@@ -9,3 +9,4 @@ Runtime Verification
    runtime-verification.rst
    deterministic_automata.rst
    da_monitor_synthesis.rst
+   da_monitor_instrumentation.rst
Signature · 1 line
2.35.1
#20 lore raw

Re: [PATCH V5 11/16] Documentation/rv: Add deterministic automata instrumentation documentation

Quoted 121 lines · Daniel Bristot de Oliveira

Add the da_monitor_instrumentation.rst. It describes the basics of RV monitor instrumentation.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 .../trace/rv/da_monitor_instrumentation.rst   | 169 ++++++++++++++++++
 Documentation/trace/rv/index.rst              |   1 +
 2 files changed, 170 insertions(+)
 create mode 100644 Documentation/trace/rv/da_monitor_instrumentation.rst
Documentation/trace/rv/da_monitor_instrumentation.rst new file +84 -0
new file mode 100644
index 000000000000..7b83d6c7dbed
@@ -0,0 +1,169 @@
+Deterministic Automata Instrumentation
+========================================
+
+The RV monitor file created by dot2k, with the name "$MODEL_NAME.c"
+includes a section dedicated to instrumentation.
+
+In the example of the wip.dot monitor created on [1], it will look like::
+
+  /*
+   * This is the instrumentation part of the monitor.
+   *
+   * This is the section where manual work is required. Here the kernel events
+   * are translated into model's event.
+   *
+   */
+  static void handle_preempt_disable(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(preempt_disable_wip);
+  }
+
+  static void handle_preempt_enable(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(preempt_enable_wip);
+  }
+
+  static void handle_sched_waking(void *data, /* XXX: fill header */)
+  {
+	da_handle_event_wip(sched_waking_wip);
+  }
+
+  static int start_wip(void)
+  {
+	int retval;
+
+	retval = da_monitor_init_wip();
+	if (retval)
+		return retval;
+
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking);
+
+	return 0;
+  }
+
+The comment at the top of the section explains the general idea: the
+instrumentation section translates *kernel events* into the *model's
+event*.
+
+Tracing callback functions
+-----------------------------
+
+The first three functions are the starting point of the callback *handler
+functions* for each of the three events from the wip model. The developer
+does not necessarily need to use them: they are just starting points.
+
+Using the example of::
+
+ void handle_preempt_disable(void *data, /* XXX: fill header */)
+ {
+        da_handle_event_wip(preempt_disable_wip);
+ }
+
+The preempt_disable event from the model connects directly to the
+preemptirq:preempt_disable. The preemptirq:preempt_disable event
+has the following signature, from include/trace/events/preemptirq.h::
+
+  TP_PROTO(unsigned long ip, unsigned long parent_ip)
+
+Hence, the handle_preempt_disable() function will look like::
+
+  void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip)
+
+In this case, the kernel event translates one to one with the automata
+event, and indeed, no other change is required for this function.
+
+The next handler function, handle_preempt_enable() has the same argument
+list from the handle_preempt_disable(). The difference is that the
+preempt_enable event will be used to synchronize the system to the model.
+
+Initially, the *model* is placed in the initial state. However, the *system*
+might or might not be in the initial state. The monitor cannot start
+processing events until it knows that the system has reached the initial state.
+Otherwise, the monitor and the system could be out-of-sync.

Documentation/trace/rv/da_monitor_instrumentation.rst line 94

Quoted 10 lines
Documentation/trace/rv/da_monitor_instrumentation.rst new file +10 -0
+
+Looking at the automata definition, it is possible to see that the system
+and the model are expected to return to the initial state after the
+preempt_enable execution. Hence, it can be used to synchronize the
+system and the model at the initialization of the monitoring section.
+
+The initialization is informed via a special handle function, the
+"da_handle_init_event_$(MONITOR)(event)", in this case::
+
+  da_handle_event_wip(preempt_disable_wip);

In this case, it is da_handle_init_event_wip(preempt_disable_wip). Thanks.

#21 lore raw

PATCH v5 12/16 rv/monitor: Add the wip monitor skeleton created by dot2k

In reply to Daniel Bristot de Oliveira

THIS CODE IS NOT LINKED TO THE MAKEFILE.

This model does not compile because it lacks the instrumentation part, which will be added next. In the typical case, there will be only one patch, but it was split into two patches for educational purposes.

This is the direct output this command line:

  $ dot2k -d tools/verification/models/wip.dot -t per_cpu
Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 kernel/trace/rv/monitors/wip/wip.c | 112 +++++++++++++++++++++++++++++
 kernel/trace/rv/monitors/wip/wip.h |  46 ++++++++++++
 2 files changed, 158 insertions(+)
 create mode 100644 kernel/trace/rv/monitors/wip/wip.c
 create mode 100644 kernel/trace/rv/monitors/wip/wip.h
kernel/trace/rv/monitors/wip/wip.c new file +112 -0
new file mode 100644
index 000000000000..9ac5dc9618a3
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/ftrace.h>
+#include <linux/tracepoint.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rv.h>
+#include <rv/instrumentation.h>
+#include <rv/da_monitor.h>
+
+#define MODULE_NAME "wip"
+
+/*
+ * XXX: include required tracepoint headers, e.g.,
+ * #include <linux/trace/events/sched.h>
+ */
+#include <trace/events/rv.h>
+
+/*
+ * This is the self-generated part of the monitor. Generally, there is no need
+ * to touch this section.
+ */
+#include "wip.h"
+
+/*
+ * Declare the deterministic automata monitor.
+ *
+ * The rv monitor reference is needed for the monitor declaration.
+ */
+struct rv_monitor rv_wip;
+DECLARE_DA_MON_PER_CPU(wip, unsigned char);
+
+/*
+ * This is the instrumentation part of the monitor.
+ *
+ * This is the section where manual work is required. Here the kernel events
+ * are translated into model's event.
+ *
+ */
+static void handle_preempt_disable(void *data, /* XXX: fill header */)
+{
+	da_handle_event_wip(preempt_disable_wip);
+}
+
+static void handle_preempt_enable(void *data, /* XXX: fill header */)
+{
+	da_handle_event_wip(preempt_enable_wip);
+}
+
+static void handle_sched_waking(void *data, /* XXX: fill header */)
+{
+	da_handle_event_wip(sched_waking_wip);
+}
+
+static int start_wip(void)
+{
+	int retval;
+
+	retval = da_monitor_init_wip();
+	if (retval)
+		return retval;
+
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable);
+	rv_attach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking);
+
+	return 0;
+}
+
+static void stop_wip(void)
+{
+	rv_wip.enabled = 0;
+
+	rv_detach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_disable);
+	rv_detach_trace_probe("wip", /* XXX: tracepoint */, handle_preempt_enable);
+	rv_detach_trace_probe("wip", /* XXX: tracepoint */, handle_sched_waking);
+
+	da_monitor_destroy_wip();
+}
+
+/*
+ * This is the monitor register section.
+ */
+struct rv_monitor rv_wip = {
+	.name = "wip",
+	.description = "auto-generated wip",
+	.start = start_wip,
+	.stop = stop_wip,
+	.reset = da_monitor_reset_all_wip,
+	.enabled = 0,
+};
+
+static int register_wip(void)
+{
+	rv_register_monitor(&rv_wip);
+	return 0;
+}
+
+static void unregister_wip(void)
+{
+	if (rv_wip.enabled)
+		stop_wip();
+
+	rv_unregister_monitor(&rv_wip);
+}
+
+module_init(register_wip);
+module_exit(unregister_wip);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("dot2k: auto-generated");
+MODULE_DESCRIPTION("wip");
kernel/trace/rv/monitors/wip/wip.h new file +46 -0

46 lines not on this page · raw message

Signature · 1 line
2.35.1
#22 lore raw

PATCH v5 13/16 rv/monitor: Add the wip monitor

In reply to Daniel Bristot de Oliveira

The wakeup in preemptive (wip) monitor verifies if the wakeup events always take place with preemption disabled:

                     |
                     |
                     v
                   #==================#
                   H    preemptive    H <+
                   #==================#  |
                     |                   |
                     | preempt_disable   | preempt_enable
                     v                   |
    sched_waking   +------------------+  |
  +--------------- |                  |  |
  |                |  non_preemptive  |  |
  +--------------> |                  | -+
                   +------------------+

The wakeup event always takes place with preemption disabled because of the scheduler synchronization. However, because the preempt_count and its trace event are not atomic with regard to interrupts, some inconsistencies might happen.

The documentation illustrates one of these cases.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 Documentation/trace/rv/index.rst       |  1 +
 Documentation/trace/rv/monitor_wip.rst | 55 ++++++++++++++++++++++++++
 include/trace/events/rv.h              | 10 +++++
 kernel/trace/rv/Kconfig                | 13 ++++++
 kernel/trace/rv/Makefile               |  1 +
 kernel/trace/rv/monitors/wip/wip.c     | 51 +++++++-----------------
 tools/verification/models/wip.dot      | 16 ++++++++
 7 files changed, 111 insertions(+), 36 deletions(-)
 create mode 100644 Documentation/trace/rv/monitor_wip.rst
 create mode 100644 tools/verification/models/wip.dot
Documentation/trace/rv/index.rst +1 -0
index db2ae3f90b90..4cb71ed628b8 100644
@@ -10,3 +10,4 @@ Runtime Verification
    deterministic_automata.rst
    da_monitor_synthesis.rst
    da_monitor_instrumentation.rst
+   monitor_wip.rst
Documentation/trace/rv/monitor_wip.rst new file +55 -0

55 lines not on this page · raw message

include/trace/events/rv.h +10 -0
index 480aac18f403..90fa36cea517 100644
@@ -56,6 +56,16 @@ DECLARE_EVENT_CLASS(error_da_monitor,
 		__entry->event,
 		__entry->state)
 );
+
+#ifdef CONFIG_RV_MON_WIP
+DEFINE_EVENT(event_da_monitor, event_wip,
+	    TP_PROTO(char *state, char *event, char *next_state, bool final_state),
+	    TP_ARGS(state, event, next_state, final_state));
+
+DEFINE_EVENT(error_da_monitor, error_wip,
+	     TP_PROTO(char *state, char *event),
+	     TP_ARGS(state, event));
+#endif /* CONFIG_RV_MON_WIP */
 #endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */
 
 #ifdef CONFIG_DA_MON_EVENTS_ID
kernel/trace/rv/Kconfig +13 -0
index 7ad6c93cda64..8755ad74ec22 100644
@@ -28,6 +28,19 @@ menuconfig RV
 	  For further information, see:
 	    Documentation/trace/rv/runtime-verification.rst
 
+config RV_MON_WIP
+	depends on RV
+	depends on PREEMPT_TRACER
+	select DA_MON_EVENTS_IMPLICIT
+	bool "wip monitor"
+	help
+	  Enable wip (wakeup in preemptive) sample monitor that illustrates
+	  the usage of per-cpu monitors, and one limitation of the
+	  preempt_disable/enable events.
+
+	  For further information, see:
+	    Documentation/trace/rv/monitor_wip.rst
+
 config RV_REACTORS
 	bool "Runtime verification reactors"
 	default y
kernel/trace/rv/Makefile +1 -0
index 8944274d9b41..b41109d2750a 100644
@@ -2,3 +2,4 @@
 
 obj-$(CONFIG_RV) += rv.o
 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
+obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
kernel/trace/rv/monitors/wip/wip.c +15 -36

92 lines not on this page · raw message

tools/verification/models/wip.dot new file +16 -0
new file mode 100644
index 000000000000..2a53a9700a89
@@ -0,0 +1,16 @@
+digraph state_automaton {
+	{node [shape = circle] "non_preemptive"};
+	{node [shape = plaintext, style=invis, label=""] "__init_preemptive"};
+	{node [shape = doublecircle] "preemptive"};
+	{node [shape = circle] "preemptive"};
+	"__init_preemptive" -> "preemptive";
+	"non_preemptive" [label = "non_preemptive"];
+	"non_preemptive" -> "non_preemptive" [ label = "sched_waking" ];
+	"non_preemptive" -> "preemptive" [ label = "preempt_enable" ];
+	"preemptive" [label = "preemptive"];
+	"preemptive" -> "non_preemptive" [ label = "preempt_disable" ];
+	{ rank = min ;
+		"__init_preemptive";
+		"preemptive";
+	}
+}
Signature · 1 line
2.35.1
#23 lore raw

PATCH v5 14/16 rv/monitor: Add the wwnr monitor

In reply to Daniel Bristot de Oliveira

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.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 Documentation/trace/rv/index.rst        |  1 +
 Documentation/trace/rv/monitor_wwnr.rst | 45 +++++++++++++
 include/trace/events/rv.h               | 12 ++++
 kernel/trace/rv/Kconfig                 | 12 ++++
 kernel/trace/rv/Makefile                |  1 +
 kernel/trace/rv/monitors/wwnr/wwnr.c    | 90 +++++++++++++++++++++++++
 kernel/trace/rv/monitors/wwnr/wwnr.h    | 46 +++++++++++++
 tools/verification/models/wwnr.dot      | 16 +++++
 8 files changed, 223 insertions(+)
 create mode 100644 Documentation/trace/rv/monitor_wwnr.rst
 create mode 100644 kernel/trace/rv/monitors/wwnr/wwnr.c
 create mode 100644 kernel/trace/rv/monitors/wwnr/wwnr.h
 create mode 100644 tools/verification/models/wwnr.dot
Documentation/trace/rv/index.rst +1 -0
index 4cb71ed628b8..15fa966102c0 100644
@@ -11,3 +11,4 @@ Runtime Verification
    da_monitor_synthesis.rst
    da_monitor_instrumentation.rst
    monitor_wip.rst
+   monitor_wwnr.rst
Documentation/trace/rv/monitor_wwnr.rst new file +45 -0

45 lines not on this page · raw message

include/trace/events/rv.h +12 -0
index 90fa36cea517..495d3eece0ee 100644
@@ -122,6 +122,18 @@ DECLARE_EVENT_CLASS(error_da_monitor_id,
 		__entry->event,
 		__entry->state)
 );
+
+#ifdef CONFIG_RV_MON_WWNR
+/* id is the pid of the task */
+DEFINE_EVENT(event_da_monitor_id, event_wwnr,
+	     TP_PROTO(int id, char *state, char *event, char *next_state, bool final_state),
+	     TP_ARGS(id, state, event, next_state, final_state));
+
+DEFINE_EVENT(error_da_monitor_id, error_wwnr,
+	     TP_PROTO(int id, char *state, char *event),
+	     TP_ARGS(id, state, event));
+#endif /* CONFIG_RV_MON_WWNR */
+
 #endif /* CONFIG_DA_MON_EVENTS_ID */
 #endif /* _TRACE_RV_H */
 
kernel/trace/rv/Kconfig +12 -0
index 8755ad74ec22..d8c40fd67e88 100644
@@ -41,6 +41,18 @@ config RV_MON_WIP
 	  For further information, see:
 	    Documentation/trace/rv/monitor_wip.rst
 
+config RV_MON_WWNR
+	depends on RV
+	select DA_MON_EVENTS_ID
+	bool "wwnr monitor"
+	help
+	  Enable wwnr (wakeup while not running) sample monitor, this is a
+	  sample monitor that illustrates the usage of per-task monitor.
+	  The model is borken on purpose: it serves to test reactors.
+
+	  For further information, see:
+	    Documentation/trace/rv/monitor_wwnr.rst
+
 config RV_REACTORS
 	bool "Runtime verification reactors"
 	default y
kernel/trace/rv/Makefile +1 -0
index b41109d2750a..af0ff9a46418 100644
@@ -3,3 +3,4 @@
 obj-$(CONFIG_RV) += rv.o
 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
 obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
+obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
kernel/trace/rv/monitors/wwnr/wwnr.c new file +90 -0

90 lines not on this page · raw message

kernel/trace/rv/monitors/wwnr/wwnr.h new file +46 -0

46 lines not on this page · raw message

tools/verification/models/wwnr.dot new file +16 -0
new file mode 100644
index 000000000000..1b206e83129c
@@ -0,0 +1,16 @@
+digraph state_automaton {
+	{node [shape = plaintext, style=invis, label=""] "__init_not_running"};
+	{node [shape = ellipse] "not_running"};
+	{node [shape = plaintext] "not_running"};
+	{node [shape = plaintext] "running"};
+	"__init_not_running" -> "not_running";
+	"not_running" [label = "not_running", color = green3];
+	"not_running" -> "not_running" [ label = "wakeup" ];
+	"not_running" -> "running" [ label = "switch_in" ];
+	"running" [label = "running"];
+	"running" -> "not_running" [ label = "switch_out" ];
+	{ rank = min ;
+		"__init_not_running";
+		"not_running";
+	}
+}
Signature · 1 line
2.35.1
#24 lore raw

PATCH v5 15/16 rv/reactor: Add the printk reactor

In reply to Daniel Bristot de Oliveira

A reactor that printks the reaction message.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 kernel/trace/rv/Kconfig          |  8 ++++++
 kernel/trace/rv/Makefile         |  3 ++-
 kernel/trace/rv/reactor_printk.c | 42 ++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 kernel/trace/rv/reactor_printk.c
kernel/trace/rv/Kconfig +8 -0
index d8c40fd67e88..f1d92d431130 100644
@@ -63,3 +63,11 @@ config RV_REACTORS
 	  on the model's execution. By default, the monitors have
 	  tracing reactions, printing the monitor output via tracepoints,
 	  but other reactions can be added (on-demand) via this interface.
+
+config RV_REACT_PRINTK
+	bool "Printk reactor"
+	depends on RV_REACTORS
+	default y
+	help
+	  Enables the printk reactor. The printk reactor emits a printk()
+	  message if an exception is found.
kernel/trace/rv/Makefile +2 -1
index af0ff9a46418..a13c750a35c1 100644
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_RV) += rv.o
-obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
 obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
 obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
+obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
+obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
kernel/trace/rv/reactor_printk.c new file +42 -0

42 lines not on this page · raw message

Signature · 1 line
2.35.1
#25 lore raw

Re: [PATCH V5 15/16] rv/reactor: Add the printk reactor

I love your patch! Perhaps something to improve:

Hi Daniel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rostedt-trace/for-next]
[also build test WARNING on tip/sched/core]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220718/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/d1746223447deb1d1646f968512a065a1cd63a9c
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
        git checkout d1746223447deb1d1646f968512a065a1cd63a9c
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/misc/lkdtm/ kernel/trace/rv/

If you fix the issue, kindly add following tag where applicable

sparse warnings: (new ones prefixed by >>)

>> kernel/trace/rv/reactor_printk.c:20:19: sparse: sparse: symbol 'rv_printk' was not declared. Should it be static?
>> kernel/trace/rv/reactor_printk.c:26:5: sparse: sparse: symbol 'register_react_printk' was not declared. Should it be static?
>> kernel/trace/rv/reactor_printk.c:32:6: sparse: sparse: symbol 'unregister_react_printk' was not declared. Should it be static?
Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp
#26 lore raw

Re: [PATCH V5 15/16] rv/reactor: Add the printk reactor

In reply to Daniel Bristot de Oliveira
I love your patch! Perhaps something to improve:

Hi Daniel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rostedt-trace/for-next]
[also build test WARNING on tip/sched/core]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next
config: hexagon-allyesconfig (https://download.01.org/0day-ci/archive/20220718/[email protected]/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 07022e6cf9b5b3baa642be53d0b3c3f1c403dbfd)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/d1746223447deb1d1646f968512a065a1cd63a9c
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220 git checkout d1746223447deb1d1646f968512a065a1cd63a9c
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/net/pcs/ kernel/trace/rv/

If you fix the issue, kindly add following tag where applicable

All warnings (new ones prefixed by >>):

>> kernel/trace/rv/reactor_printk.c:26:5: warning: no previous prototype for function 'register_react_printk' [-Wmissing-prototypes]
   int register_react_printk(void)
       ^
   kernel/trace/rv/reactor_printk.c:26:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int register_react_printk(void)
   ^
   static 
>> kernel/trace/rv/reactor_printk.c:32:6: warning: no previous prototype for function 'unregister_react_printk' [-Wmissing-prototypes]
   void unregister_react_printk(void)
        ^

kernel/trace/rv/reactor_printk.c:32:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void unregister_react_printk(void)
^
static
2 warnings generated.

vim +/register_react_printk +26 kernel/trace/rv/reactor_printk.c

    25	
  > 26	int register_react_printk(void)
    27	{
    28		rv_register_reactor(&rv_printk);
    29		return 0;
    30	}
    31	
  > 32	void unregister_react_printk(void)
    33	{
    34		rv_unregister_reactor(&rv_printk);
    35	}
    36	
Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp
#27 lore raw

PATCH v5 16/16 rv/reactor: Add the panic reactor

In reply to Daniel Bristot de Oliveira

Sample reactor that panics the system when an exception is found. This is useful both to capture a vmcore, or to fail-safe a critical system.

Cc Wim Van Sebroeck <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Steven Rostedt <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Will Deacon <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Marco Elver <[email protected]>
Cc Dmitry Vyukov <[email protected]>
Cc "Paul E. McKenney" <[email protected]>
Cc Shuah Khan <[email protected]>
Cc Gabriele Paoloni <[email protected]>
Cc Juri Lelli <[email protected]>
Cc Clark Williams <[email protected]>
Cc Tao Zhou <[email protected]>
Cc Randy Dunlap <[email protected]>
---
 kernel/trace/rv/Kconfig         |  8 ++++++
 kernel/trace/rv/Makefile        |  1 +
 kernel/trace/rv/reactor_panic.c | 43 +++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+)
 create mode 100644 kernel/trace/rv/reactor_panic.c
kernel/trace/rv/Kconfig +8 -0
index f1d92d431130..ce2a90a89f55 100644
@@ -71,3 +71,11 @@ config RV_REACT_PRINTK
 	help
 	  Enables the printk reactor. The printk reactor emits a printk()
 	  message if an exception is found.
+
+config RV_REACT_PANIC
+	bool "Panic reactor"
+	depends on RV_REACTORS
+	default y
+	help
+	  Enables the panic reactor. The panic reactor emits a printk()
+	  message if an exception is found and panic()s the system.
kernel/trace/rv/Makefile +1 -0
index a13c750a35c1..963d14875b45 100644
@@ -5,3 +5,4 @@ obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o
 obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o
 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
 obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
+obj-$(CONFIG_RV_REACT_PANIC) += reactor_panic.o
kernel/trace/rv/reactor_panic.c new file +43 -0

43 lines not on this page · raw message

Signature · 1 line
2.35.1
#28 lore raw

Re: [PATCH V5 16/16] rv/reactor: Add the panic reactor

I love your patch! Perhaps something to improve:

Hi Daniel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rostedt-trace/for-next]
[also build test WARNING on tip/sched/core]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220718/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/f83faf07d0dad6cfd8fb22ff38b752dd7619bfc0
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
        git checkout f83faf07d0dad6cfd8fb22ff38b752dd7619bfc0
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash drivers/misc/lkdtm/ kernel/trace/rv/

If you fix the issue, kindly add following tag where applicable

sparse warnings: (new ones prefixed by >>)

>> kernel/trace/rv/reactor_panic.c:21:19: sparse: sparse: symbol 'rv_panic' was not declared. Should it be static?
>> kernel/trace/rv/reactor_panic.c:27:5: sparse: sparse: symbol 'register_react_panic' was not declared. Should it be static?
>> kernel/trace/rv/reactor_panic.c:33:6: sparse: sparse: symbol 'unregister_react_panic' was not declared. Should it be static?
Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp
#29 lore raw

Re: [PATCH V5 16/16] rv/reactor: Add the panic reactor

In reply to Daniel Bristot de Oliveira
I love your patch! Perhaps something to improve:

Hi Daniel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on rostedt-trace/for-next]
[also build test WARNING on tip/sched/core]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next
config: hexagon-allyesconfig (https://download.01.org/0day-ci/archive/20220718/[email protected]/config)
compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 07022e6cf9b5b3baa642be53d0b3c3f1c403dbfd)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/f83faf07d0dad6cfd8fb22ff38b752dd7619bfc0
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Daniel-Bristot-de-Oliveira/The-Runtime-Verification-RV-interface/20220714-052220 git checkout f83faf07d0dad6cfd8fb22ff38b752dd7619bfc0
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/net/pcs/ kernel/trace/rv/

If you fix the issue, kindly add following tag where applicable

All warnings (new ones prefixed by >>):

>> kernel/trace/rv/reactor_panic.c:27:5: warning: no previous prototype for function 'register_react_panic' [-Wmissing-prototypes]
   int register_react_panic(void)
       ^
   kernel/trace/rv/reactor_panic.c:27:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int register_react_panic(void)
   ^
   static 
>> kernel/trace/rv/reactor_panic.c:33:6: warning: no previous prototype for function 'unregister_react_panic' [-Wmissing-prototypes]
   void unregister_react_panic(void)
        ^

kernel/trace/rv/reactor_panic.c:33:1: note: declare 'static' if the function is not intended to be used outside of this translation unit void unregister_react_panic(void)
^
static
2 warnings generated.

vim +/register_react_panic +27 kernel/trace/rv/reactor_panic.c

    26	
  > 27	int register_react_panic(void)
    28	{
    29		rv_register_reactor(&rv_panic);
    30		return 0;
    31	}
    32	
  > 33	void unregister_react_panic(void)
    34	{
    35		rv_unregister_reactor(&rv_panic);
    36	}
    37	
Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp