Skip to content

Commit 2334cf7

Browse files
glemcorostedt
authored andcommitted
verification/dot2k: Add support for nested monitors
RV now supports nested monitors, this functionality requires a container monitor, which has virtually no functionality besides holding other monitors, and nested monitors, that have a container as parent. Add the -p flag to pass a parent to a monitor, this sets it up while registering the monitor and adds necessary includes and configurations. Add the -c flag to create a container, since containers are empty, we don't allow supplying a dot model or a monitor type, the template is also different since functions to enable and disable the monitor are not defined, nor any tracepoint. The generated header file only allows to include the rv_monitor structure in children monitors. Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Juri Lelli <juri.lelli@redhat.com> Link: https://lore.kernel.org/20250305140406.350227-8-gmonaco@redhat.com Signed-off-by: Gabriele Monaco <gmonaco@redhat.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent eba321a commit 2334cf7

File tree

6 files changed

+125
-27
lines changed

6 files changed

+125
-27
lines changed

tools/verification/dot2/dot2k

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,30 @@
1111
if __name__ == '__main__':
1212
from dot2.dot2k import dot2k
1313
import argparse
14-
import ntpath
15-
import os
16-
import platform
1714
import sys
1815

16+
def is_container():
17+
"""Should work even before parsing the arguments"""
18+
return "-c" in sys.argv or "--container" in sys.argv
19+
1920
parser = argparse.ArgumentParser(description='transform .dot file into kernel rv monitor')
20-
parser.add_argument('-d', "--dot", dest="dot_file", required=True)
21-
parser.add_argument('-t', "--monitor_type", dest="monitor_type", required=True)
22-
parser.add_argument('-n', "--model_name", dest="model_name", required=False)
21+
parser.add_argument('-d', "--dot", dest="dot_file", required=not is_container())
22+
parser.add_argument('-t', "--monitor_type", dest="monitor_type", required=not is_container(),
23+
help=f"Available options: {', '.join(dot2k.monitor_types.keys())}")
24+
parser.add_argument('-n', "--model_name", dest="model_name", required=is_container())
2325
parser.add_argument("-D", "--description", dest="description", required=False)
2426
parser.add_argument("-a", "--auto_patch", dest="auto_patch",
2527
action="store_true", required=False,
2628
help="Patch the kernel in place")
29+
parser.add_argument("-p", "--parent", dest="parent",
30+
required=False, help="Create a monitor nested to parent")
31+
parser.add_argument("-c", "--container", dest="container",
32+
action="store_true", required=False,
33+
help="Create an empty monitor to be used as a container")
2734
params = parser.parse_args()
2835

29-
print("Opening and parsing the dot file %s" % params.dot_file)
36+
if not is_container():
37+
print("Opening and parsing the dot file %s" % params.dot_file)
3038
try:
3139
monitor=dot2k(params.dot_file, params.monitor_type, vars(params))
3240
except Exception as e:
@@ -37,8 +45,9 @@ if __name__ == '__main__':
3745
print("Writing the monitor into the directory %s" % monitor.name)
3846
monitor.print_files()
3947
print("Almost done, checklist")
40-
print(" - Edit the %s/%s.c to add the instrumentation" % (monitor.name, monitor.name))
41-
print(monitor.fill_tracepoint_tooltip())
48+
if not is_container():
49+
print(" - Edit the %s/%s.c to add the instrumentation" % (monitor.name, monitor.name))
50+
print(monitor.fill_tracepoint_tooltip())
4251
print(monitor.fill_makefile_tooltip())
4352
print(monitor.fill_kconfig_tooltip())
4453
print(monitor.fill_monitor_tooltip())

tools/verification/dot2/dot2k.py

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,31 @@ class dot2k(Dot2c):
1919
monitor_type = "per_cpu"
2020

2121
def __init__(self, file_path, MonitorType, extra_params={}):
22-
super().__init__(file_path, extra_params.get("model_name"))
23-
24-
self.monitor_type = self.monitor_types.get(MonitorType)
25-
if self.monitor_type is None:
26-
raise ValueError("Unknown monitor type: %s" % MonitorType)
27-
28-
self.monitor_type = MonitorType
22+
self.container = extra_params.get("container")
23+
self.parent = extra_params.get("parent")
2924
self.__fill_rv_templates_dir()
30-
self.main_c = self.__read_file(self.monitor_templates_dir + "main.c")
31-
self.trace_h = self.__read_file(self.monitor_templates_dir + "trace.h")
25+
26+
if self.container:
27+
if file_path:
28+
raise ValueError("A container does not require a dot file")
29+
if MonitorType:
30+
raise ValueError("A container does not require a monitor type")
31+
if self.parent:
32+
raise ValueError("A container cannot have a parent")
33+
self.name = extra_params.get("model_name")
34+
self.events = []
35+
self.states = []
36+
self.main_c = self.__read_file(self.monitor_templates_dir + "main_container.c")
37+
self.main_h = self.__read_file(self.monitor_templates_dir + "main_container.h")
38+
else:
39+
super().__init__(file_path, extra_params.get("model_name"))
40+
41+
self.monitor_type = self.monitor_types.get(MonitorType)
42+
if self.monitor_type is None:
43+
raise ValueError("Unknown monitor type: %s" % MonitorType)
44+
self.monitor_type = MonitorType
45+
self.main_c = self.__read_file(self.monitor_templates_dir + "main.c")
46+
self.trace_h = self.__read_file(self.monitor_templates_dir + "trace.h")
3247
self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig")
3348
self.enum_suffix = "_%s" % self.name
3449
self.description = extra_params.get("description", self.name) or "auto-generated"
@@ -105,6 +120,14 @@ def __buff_to_string(self, buff):
105120
def fill_monitor_type(self):
106121
return self.monitor_type.upper()
107122

123+
def fill_parent(self):
124+
return "&rv_%s" % self.parent if self.parent else "NULL"
125+
126+
def fill_include_parent(self):
127+
if self.parent:
128+
return "#include <monitors/%s/%s.h>\n" % (self.parent, self.parent)
129+
return ""
130+
108131
def fill_tracepoint_handlers_skel(self):
109132
buff = []
110133
for event in self.events:
@@ -146,6 +169,8 @@ def fill_main_c(self):
146169
tracepoint_handlers = self.fill_tracepoint_handlers_skel()
147170
tracepoint_attach = self.fill_tracepoint_attach_probe()
148171
tracepoint_detach = self.fill_tracepoint_detach_helper()
172+
parent = self.fill_parent()
173+
parent_include = self.fill_include_parent()
149174

150175
main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
151176
main_c = main_c.replace("%%MIN_TYPE%%", min_type)
@@ -155,6 +180,8 @@ def fill_main_c(self):
155180
main_c = main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_attach)
156181
main_c = main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_detach)
157182
main_c = main_c.replace("%%DESCRIPTION%%", self.description)
183+
main_c = main_c.replace("%%PARENT%%", parent)
184+
main_c = main_c.replace("%%INCLUDE_PARENT%%", parent_include)
158185

159186
return main_c
160187

@@ -216,6 +243,14 @@ def fill_tracepoint_args_skel(self, tp_type):
216243
buff.append(" TP_ARGS(%s)" % tp_args_c)
217244
return self.__buff_to_string(buff)
218245

246+
def fill_monitor_deps(self):
247+
buff = []
248+
buff.append(" # XXX: add dependencies if there")
249+
if self.parent:
250+
buff.append(" depends on RV_MON_%s" % self.parent.upper())
251+
buff.append(" default y")
252+
return self.__buff_to_string(buff)
253+
219254
def fill_trace_h(self):
220255
trace_h = self.trace_h
221256
monitor_class = self.fill_monitor_class()
@@ -233,12 +268,19 @@ def fill_trace_h(self):
233268
def fill_kconfig(self):
234269
kconfig = self.kconfig
235270
monitor_class_type = self.fill_monitor_class_type()
271+
monitor_deps = self.fill_monitor_deps()
236272
kconfig = kconfig.replace("%%MODEL_NAME%%", self.name)
237273
kconfig = kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper())
238274
kconfig = kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type)
239275
kconfig = kconfig.replace("%%DESCRIPTION%%", self.description)
276+
kconfig = kconfig.replace("%%MONITOR_DEPS%%", monitor_deps)
240277
return kconfig
241278

279+
def fill_main_container_h(self):
280+
main_h = self.main_h
281+
main_h = main_h.replace("%%MODEL_NAME%%", self.name)
282+
return main_h
283+
242284
def __patch_file(self, file, marker, line):
243285
file_to_patch = os.path.join(self.rv_dir, file)
244286
content = self.__read_file(file_to_patch)
@@ -324,19 +366,24 @@ def __get_main_name(self):
324366

325367
def print_files(self):
326368
main_c = self.fill_main_c()
327-
model_h = self.fill_model_h()
328369

329370
self.__create_directory()
330371

331372
path = "%s.c" % self.name
332373
self.__create_file(path, main_c)
333374

334-
path = "%s.h" % self.name
335-
self.__create_file(path, model_h)
336-
337-
trace_h = self.fill_trace_h()
338-
path = "%s_trace.h" % self.name
339-
self.__create_file(path, trace_h)
375+
if self.container:
376+
main_h = self.fill_main_container_h()
377+
path = "%s.h" % self.name
378+
self.__create_file(path, main_h)
379+
else:
380+
model_h = self.fill_model_h()
381+
path = "%s.h" % self.name
382+
self.__create_file(path, model_h)
383+
384+
trace_h = self.fill_trace_h()
385+
path = "%s_trace.h" % self.name
386+
self.__create_file(path, trace_h)
340387

341388
kconfig = self.fill_kconfig()
342389
self.__create_file("Kconfig", kconfig)

tools/verification/dot2/dot2k_templates/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#
33
config RV_MON_%%MODEL_NAME_UP%%
44
depends on RV
5+
%%MONITOR_DEPS%%
56
select %%MONITOR_CLASS_TYPE%%
67
bool "%%MODEL_NAME%% monitor"
78
help

tools/verification/dot2/dot2k_templates/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* #include <trace/events/sched.h>
1616
*/
1717
#include <rv_trace.h>
18-
18+
%%INCLUDE_PARENT%%
1919
/*
2020
* This is the self-generated part of the monitor. Generally, there is no need
2121
* to touch this section.
@@ -74,7 +74,7 @@ static struct rv_monitor rv_%%MODEL_NAME%% = {
7474

7575
static int __init register_%%MODEL_NAME%%(void)
7676
{
77-
rv_register_monitor(&rv_%%MODEL_NAME%%);
77+
rv_register_monitor(&rv_%%MODEL_NAME%%, %%PARENT%%);
7878
return 0;
7979
}
8080

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/kernel.h>
3+
#include <linux/module.h>
4+
#include <linux/init.h>
5+
#include <linux/rv.h>
6+
7+
#define MODULE_NAME "%%MODEL_NAME%%"
8+
9+
#include "%%MODEL_NAME%%.h"
10+
11+
struct rv_monitor rv_%%MODEL_NAME%%;
12+
13+
struct rv_monitor rv_%%MODEL_NAME%% = {
14+
.name = "%%MODEL_NAME%%",
15+
.description = "%%DESCRIPTION%%",
16+
.enable = NULL,
17+
.disable = NULL,
18+
.reset = NULL,
19+
.enabled = 0,
20+
};
21+
22+
static int __init register_%%MODEL_NAME%%(void)
23+
{
24+
rv_register_monitor(&rv_%%MODEL_NAME%%, NULL);
25+
return 0;
26+
}
27+
28+
static void __exit unregister_%%MODEL_NAME%%(void)
29+
{
30+
rv_unregister_monitor(&rv_%%MODEL_NAME%%);
31+
}
32+
33+
module_init(register_%%MODEL_NAME%%);
34+
module_exit(unregister_%%MODEL_NAME%%);
35+
36+
MODULE_LICENSE("GPL");
37+
MODULE_AUTHOR("dot2k: auto-generated");
38+
MODULE_DESCRIPTION("%%MODEL_NAME%%: %%DESCRIPTION%%");
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
extern struct rv_monitor rv_%%MODEL_NAME%%;

0 commit comments

Comments
 (0)