Skip to content

Commit cce86e0

Browse files
covanamrostedt
authored andcommitted
verification/rvgen: Restructure the classes to prepare for LTL inclusion
Both container generation and DA monitor generation is implemented in the class dot2k. That requires some ugly "if is_container ... else ...". If linear temporal logic support is added at the current state, the "if else" chain is longer and uglier. Furthermore, container generation is irrevelant to .dot files. It is therefore illogical to be implemented in class "dot2k". Clean it up, restructure the dot2k class into the following class hierarchy: (RVGenerator) /\ / \ / \ / \ / \ (Container) (Monitor) /\ / \ / \ / \ (dot2k) [ltl2k] <- intended This allows a simple and clean integration of LTL. Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lore.kernel.org/692137a581ba6bee7a64d37fb7173ae137c47bbd.1751634289.git.namcao@linutronix.de Reviewed-by: Gabriele Monaco <gmonaco@redhat.com> Signed-off-by: Nam Cao <namcao@linutronix.de> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent ccb21fc commit cce86e0

5 files changed

Lines changed: 308 additions & 261 deletions

File tree

tools/verification/rvgen/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@ install:
1919
$(INSTALL) rvgen/dot2c.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/dot2c.py
2020
$(INSTALL) dot2c -D -m 755 $(DESTDIR)$(bindir)/
2121
$(INSTALL) rvgen/dot2k.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/dot2k.py
22+
$(INSTALL) rvgen/container.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/container.py
23+
$(INSTALL) rvgen/generator.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/generator.py
2224
$(INSTALL) __main__.py -D -m 755 $(DESTDIR)$(bindir)/rvgen
2325
cp -rp rvgen/templates $(DESTDIR)$(PYLIB)/rvgen/

tools/verification/rvgen/__main__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
if __name__ == '__main__':
1212
from rvgen.dot2k import dot2k
13+
from rvgen.generator import Monitor
14+
from rvgen.container import Container
1315
import argparse
1416
import sys
1517

@@ -29,7 +31,7 @@
2931
help="Monitor class, either \"da\" or \"ltl\"")
3032
monitor_parser.add_argument('-s', "--spec", dest="spec", help="Monitor specification file")
3133
monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type",
32-
help=f"Available options: {', '.join(dot2k.monitor_types.keys())}")
34+
help=f"Available options: {', '.join(Monitor.monitor_types.keys())}")
3335

3436
container_parser = subparsers.add_parser("container")
3537
container_parser.add_argument('-n', "--model_name", dest="model_name", required=True)
@@ -47,7 +49,7 @@
4749
print("Unknown monitor class:", params.monitor_class)
4850
sys.exit(1)
4951
else:
50-
monitor = dot2k(None, None, vars(params))
52+
monitor = Container(vars(params))
5153
except Exception as e:
5254
print('Error: '+ str(e))
5355
print("Sorry : :-(")
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: GPL-2.0-only
3+
#
4+
# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
5+
#
6+
# Generator for runtime verification monitor container
7+
8+
from . import generator
9+
10+
11+
class Container(generator.RVGenerator):
12+
template_dir = "container"
13+
14+
def __init__(self, extra_params={}):
15+
super().__init__(extra_params)
16+
self.name = extra_params.get("model_name")
17+
self.main_h = self._read_template_file("main.h")
18+
19+
def fill_model_h(self):
20+
main_h = self.main_h
21+
main_h = main_h.replace("%%MODEL_NAME%%", self.name)
22+
return main_h

tools/verification/rvgen/rvgen/dot2k.py

Lines changed: 16 additions & 259 deletions
Original file line numberDiff line numberDiff line change
@@ -9,108 +9,21 @@
99
# Documentation/trace/rv/da_monitor_synthesis.rst
1010

1111
from .dot2c import Dot2c
12-
import platform
13-
import os
12+
from .generator import Monitor
1413

15-
class dot2k(Dot2c):
16-
monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
17-
rv_dir = "kernel/trace/rv"
18-
monitor_type = "per_cpu"
1914

20-
def __init__(self, file_path, MonitorType, extra_params={}):
21-
self.container = extra_params.get("subcmd") == "container"
22-
self.parent = extra_params.get("parent")
23-
if self.container:
24-
self.abs_template_dir = os.path.join(os.path.dirname(__file__), "templates/container")
25-
else:
26-
self.abs_template_dir = os.path.join(os.path.dirname(__file__), "templates/dot2k")
27-
28-
if self.container:
29-
if file_path:
30-
raise ValueError("A container does not require a dot file")
31-
if MonitorType:
32-
raise ValueError("A container does not require a monitor type")
33-
if self.parent:
34-
raise ValueError("A container cannot have a parent")
35-
self.name = extra_params.get("model_name")
36-
self.events = []
37-
self.states = []
38-
self.main_h = self._read_template_file("main.h")
39-
else:
40-
super().__init__(file_path, extra_params.get("model_name"))
15+
class dot2k(Monitor, Dot2c):
16+
template_dir = "dot2k"
4117

42-
self.monitor_type = self.monitor_types.get(MonitorType)
43-
if self.monitor_type is None:
44-
raise ValueError("Unknown monitor type: %s" % MonitorType)
45-
self.monitor_type = MonitorType
46-
self.trace_h = self._read_template_file("trace.h")
47-
48-
self.main_c = self._read_template_file("main.c")
49-
self.kconfig = self._read_template_file("Kconfig")
18+
def __init__(self, file_path, MonitorType, extra_params={}):
19+
self.monitor_type = MonitorType
20+
Monitor.__init__(self, extra_params)
21+
Dot2c.__init__(self, file_path, extra_params.get("model_name"))
5022
self.enum_suffix = "_%s" % self.name
51-
self.description = extra_params.get("description", self.name) or "auto-generated"
52-
self.auto_patch = extra_params.get("auto_patch")
53-
if self.auto_patch:
54-
self.__fill_rv_kernel_dir()
55-
56-
def __fill_rv_kernel_dir(self):
57-
58-
# first try if we are running in the kernel tree root
59-
if os.path.exists(self.rv_dir):
60-
return
61-
62-
# offset if we are running inside the kernel tree from verification/dot2
63-
kernel_path = os.path.join("../..", self.rv_dir)
64-
65-
if os.path.exists(kernel_path):
66-
self.rv_dir = kernel_path
67-
return
68-
69-
if platform.system() != "Linux":
70-
raise OSError("I can only run on Linux.")
71-
72-
kernel_path = os.path.join("/lib/modules/%s/build" % platform.release(), self.rv_dir)
73-
74-
# if the current kernel is from a distro this may not be a full kernel tree
75-
# verify that one of the files we are going to modify is available
76-
if os.path.exists(os.path.join(kernel_path, "rv_trace.h")):
77-
self.rv_dir = kernel_path
78-
return
79-
80-
raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?")
81-
82-
def __read_file(self, path):
83-
try:
84-
fd = open(path, 'r')
85-
except OSError:
86-
raise Exception("Cannot open the file: %s" % path)
87-
88-
content = fd.read()
89-
90-
fd.close()
91-
return content
92-
93-
def _read_template_file(self, file):
94-
try:
95-
path = os.path.join(self.abs_template_dir, file)
96-
return self.__read_file(path)
97-
except Exception:
98-
# Specific template file not found. Try the generic template file in the template/
99-
# directory, which is one level up
100-
path = os.path.join(self.abs_template_dir, "..", file)
101-
return self.__read_file(path)
10223

10324
def fill_monitor_type(self):
10425
return self.monitor_type.upper()
10526

106-
def fill_parent(self):
107-
return "&rv_%s" % self.parent if self.parent else "NULL"
108-
109-
def fill_include_parent(self):
110-
if self.parent:
111-
return "#include <monitors/%s/%s.h>\n" % (self.parent, self.parent)
112-
return ""
113-
11427
def fill_tracepoint_handlers_skel(self):
11528
buff = []
11629
for event in self.events:
@@ -144,30 +57,6 @@ def fill_tracepoint_detach_helper(self):
14457
buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
14558
return '\n'.join(buff)
14659

147-
def fill_main_c(self):
148-
main_c = self.main_c
149-
monitor_type = self.fill_monitor_type()
150-
min_type = self.get_minimun_type()
151-
nr_events = len(self.events)
152-
tracepoint_handlers = self.fill_tracepoint_handlers_skel()
153-
tracepoint_attach = self.fill_tracepoint_attach_probe()
154-
tracepoint_detach = self.fill_tracepoint_detach_helper()
155-
parent = self.fill_parent()
156-
parent_include = self.fill_include_parent()
157-
158-
main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
159-
main_c = main_c.replace("%%MIN_TYPE%%", min_type)
160-
main_c = main_c.replace("%%MODEL_NAME%%", self.name)
161-
main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events))
162-
main_c = main_c.replace("%%TRACEPOINT_HANDLERS_SKEL%%", tracepoint_handlers)
163-
main_c = main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_attach)
164-
main_c = main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_detach)
165-
main_c = main_c.replace("%%DESCRIPTION%%", self.description)
166-
main_c = main_c.replace("%%PARENT%%", parent)
167-
main_c = main_c.replace("%%INCLUDE_PARENT%%", parent_include)
168-
169-
return main_c
170-
17160
def fill_model_h_header(self):
17261
buff = []
17362
buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
@@ -226,147 +115,15 @@ def fill_tracepoint_args_skel(self, tp_type):
226115
buff.append(" TP_ARGS(%s)" % tp_args_c)
227116
return '\n'.join(buff)
228117

229-
def fill_monitor_deps(self):
230-
buff = []
231-
buff.append(" # XXX: add dependencies if there")
232-
if self.parent:
233-
buff.append(" depends on RV_MON_%s" % self.parent.upper())
234-
buff.append(" default y")
235-
return '\n'.join(buff)
236-
237-
def fill_trace_h(self):
238-
trace_h = self.trace_h
239-
monitor_class = self.fill_monitor_class()
240-
monitor_class_type = self.fill_monitor_class_type()
241-
tracepoint_args_skel_event = self.fill_tracepoint_args_skel("event")
242-
tracepoint_args_skel_error = self.fill_tracepoint_args_skel("error")
243-
trace_h = trace_h.replace("%%MODEL_NAME%%", self.name)
244-
trace_h = trace_h.replace("%%MODEL_NAME_UP%%", self.name.upper())
245-
trace_h = trace_h.replace("%%MONITOR_CLASS%%", monitor_class)
246-
trace_h = trace_h.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type)
247-
trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_EVENT%%", tracepoint_args_skel_event)
248-
trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_ERROR%%", tracepoint_args_skel_error)
249-
return trace_h
250-
251-
def fill_kconfig(self):
252-
kconfig = self.kconfig
253-
monitor_class_type = self.fill_monitor_class_type()
254-
monitor_deps = self.fill_monitor_deps()
255-
kconfig = kconfig.replace("%%MODEL_NAME%%", self.name)
256-
kconfig = kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper())
257-
kconfig = kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type)
258-
kconfig = kconfig.replace("%%DESCRIPTION%%", self.description)
259-
kconfig = kconfig.replace("%%MONITOR_DEPS%%", monitor_deps)
260-
return kconfig
261-
262-
def fill_main_container_h(self):
263-
main_h = self.main_h
264-
main_h = main_h.replace("%%MODEL_NAME%%", self.name)
265-
return main_h
266-
267-
def __patch_file(self, file, marker, line):
268-
file_to_patch = os.path.join(self.rv_dir, file)
269-
content = self.__read_file(file_to_patch)
270-
content = content.replace(marker, line + "\n" + marker)
271-
self.__write_file(file_to_patch, content)
272-
273-
def fill_tracepoint_tooltip(self):
274-
monitor_class_type = self.fill_monitor_class_type()
275-
if self.auto_patch:
276-
self.__patch_file("rv_trace.h",
277-
"// Add new monitors based on CONFIG_%s here" % monitor_class_type,
278-
"#include <monitors/%s/%s_trace.h>" % (self.name, self.name))
279-
return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir
280-
281-
return """ - Edit %s/rv_trace.h:
282-
Add this line where other tracepoints are included and %s is defined:
283-
#include <monitors/%s/%s_trace.h>
284-
""" % (self.rv_dir, monitor_class_type, self.name, self.name)
285-
286-
def fill_kconfig_tooltip(self):
287-
if self.auto_patch:
288-
self.__patch_file("Kconfig",
289-
"# Add new monitors here",
290-
"source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name))
291-
return " - Patching %s/Kconfig, double check the result" % self.rv_dir
292-
293-
return """ - Edit %s/Kconfig:
294-
Add this line where other monitors are included:
295-
source \"kernel/trace/rv/monitors/%s/Kconfig\"
296-
""" % (self.rv_dir, self.name)
297-
298-
def fill_makefile_tooltip(self):
299-
name = self.name
300-
name_up = name.upper()
301-
if self.auto_patch:
302-
self.__patch_file("Makefile",
303-
"# Add new monitors here",
304-
"obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name))
305-
return " - Patching %s/Makefile, double check the result" % self.rv_dir
306-
307-
return """ - Edit %s/Makefile:
308-
Add this line where other monitors are included:
309-
obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
310-
""" % (self.rv_dir, name_up, name, name)
311-
312-
def fill_monitor_tooltip(self):
313-
if self.auto_patch:
314-
return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name)
315-
return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir)
316-
317-
def __create_directory(self):
318-
path = self.name
319-
if self.auto_patch:
320-
path = os.path.join(self.rv_dir, "monitors", path)
321-
try:
322-
os.mkdir(path)
323-
except FileExistsError:
324-
return
325-
except:
326-
print("Fail creating the output dir: %s" % self.name)
327-
328-
def __write_file(self, file_name, content):
329-
try:
330-
file = open(file_name, 'w')
331-
except:
332-
print("Fail writing to file: %s" % file_name)
333-
334-
file.write(content)
335-
336-
file.close()
337-
338-
def __create_file(self, file_name, content):
339-
path = "%s/%s" % (self.name, file_name)
340-
if self.auto_patch:
341-
path = os.path.join(self.rv_dir, "monitors", path)
342-
self.__write_file(path, content)
343-
344-
def __get_main_name(self):
345-
path = "%s/%s" % (self.name, "main.c")
346-
if not os.path.exists(path):
347-
return "main.c"
348-
return "__main.c"
349-
350-
def print_files(self):
351-
main_c = self.fill_main_c()
352-
353-
self.__create_directory()
354-
355-
path = "%s.c" % self.name
356-
self.__create_file(path, main_c)
118+
def fill_main_c(self):
119+
main_c = super().fill_main_c()
357120

358-
if self.container:
359-
main_h = self.fill_main_container_h()
360-
path = "%s.h" % self.name
361-
self.__create_file(path, main_h)
362-
else:
363-
model_h = self.fill_model_h()
364-
path = "%s.h" % self.name
365-
self.__create_file(path, model_h)
121+
min_type = self.get_minimun_type()
122+
nr_events = len(self.events)
123+
monitor_type = self.fill_monitor_type()
366124

367-
trace_h = self.fill_trace_h()
368-
path = "%s_trace.h" % self.name
369-
self.__create_file(path, trace_h)
125+
main_c = main_c.replace("%%MIN_TYPE%%", min_type)
126+
main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events))
127+
main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
370128

371-
kconfig = self.fill_kconfig()
372-
self.__create_file("Kconfig", kconfig)
129+
return main_c

0 commit comments

Comments
 (0)