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

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>

authored by

Nam Cao and committed by
Steven Rostedt (Google)
cce86e03 ccb21fc8

+308 -261
+2
tools/verification/rvgen/Makefile
··· 19 19 $(INSTALL) rvgen/dot2c.py -D -m 644 $(DESTDIR)$(PYLIB)/rvgen/dot2c.py 20 20 $(INSTALL) dot2c -D -m 755 $(DESTDIR)$(bindir)/ 21 21 $(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 22 24 $(INSTALL) __main__.py -D -m 755 $(DESTDIR)$(bindir)/rvgen 23 25 cp -rp rvgen/templates $(DESTDIR)$(PYLIB)/rvgen/
+4 -2
tools/verification/rvgen/__main__.py
··· 10 10 11 11 if __name__ == '__main__': 12 12 from rvgen.dot2k import dot2k 13 + from rvgen.generator import Monitor 14 + from rvgen.container import Container 13 15 import argparse 14 16 import sys 15 17 ··· 31 29 help="Monitor class, either \"da\" or \"ltl\"") 32 30 monitor_parser.add_argument('-s', "--spec", dest="spec", help="Monitor specification file") 33 31 monitor_parser.add_argument('-t', "--monitor_type", dest="monitor_type", 34 - help=f"Available options: {', '.join(dot2k.monitor_types.keys())}") 32 + help=f"Available options: {', '.join(Monitor.monitor_types.keys())}") 35 33 36 34 container_parser = subparsers.add_parser("container") 37 35 container_parser.add_argument('-n', "--model_name", dest="model_name", required=True) ··· 49 47 print("Unknown monitor class:", params.monitor_class) 50 48 sys.exit(1) 51 49 else: 52 - monitor = dot2k(None, None, vars(params)) 50 + monitor = Container(vars(params)) 53 51 except Exception as e: 54 52 print('Error: '+ str(e)) 55 53 print("Sorry : :-(")
+22
tools/verification/rvgen/rvgen/container.py
··· 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
+16 -259
tools/verification/rvgen/rvgen/dot2k.py
··· 9 9 # Documentation/trace/rv/da_monitor_synthesis.rst 10 10 11 11 from .dot2c import Dot2c 12 - import platform 13 - import os 12 + from .generator import Monitor 14 13 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" 14 + 15 + class dot2k(Monitor, Dot2c): 16 + template_dir = "dot2k" 19 17 20 18 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")) 41 - 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") 19 + self.monitor_type = MonitorType 20 + Monitor.__init__(self, extra_params) 21 + Dot2c.__init__(self, file_path, extra_params.get("model_name")) 50 22 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) 102 23 103 24 def fill_monitor_type(self): 104 25 return self.monitor_type.upper() 105 - 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 26 114 27 def fill_tracepoint_handlers_skel(self): 115 28 buff = [] ··· 56 143 for event in self.events: 57 144 buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event)) 58 145 return '\n'.join(buff) 59 - 60 - def fill_main_c(self): 61 - main_c = self.main_c 62 - monitor_type = self.fill_monitor_type() 63 - min_type = self.get_minimun_type() 64 - nr_events = len(self.events) 65 - tracepoint_handlers = self.fill_tracepoint_handlers_skel() 66 - tracepoint_attach = self.fill_tracepoint_attach_probe() 67 - tracepoint_detach = self.fill_tracepoint_detach_helper() 68 - parent = self.fill_parent() 69 - parent_include = self.fill_include_parent() 70 - 71 - main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type) 72 - main_c = main_c.replace("%%MIN_TYPE%%", min_type) 73 - main_c = main_c.replace("%%MODEL_NAME%%", self.name) 74 - main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events)) 75 - main_c = main_c.replace("%%TRACEPOINT_HANDLERS_SKEL%%", tracepoint_handlers) 76 - main_c = main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_attach) 77 - main_c = main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_detach) 78 - main_c = main_c.replace("%%DESCRIPTION%%", self.description) 79 - main_c = main_c.replace("%%PARENT%%", parent) 80 - main_c = main_c.replace("%%INCLUDE_PARENT%%", parent_include) 81 - 82 - return main_c 83 146 84 147 def fill_model_h_header(self): 85 148 buff = [] ··· 115 226 buff.append(" TP_ARGS(%s)" % tp_args_c) 116 227 return '\n'.join(buff) 117 228 118 - def fill_monitor_deps(self): 119 - buff = [] 120 - buff.append(" # XXX: add dependencies if there") 121 - if self.parent: 122 - buff.append(" depends on RV_MON_%s" % self.parent.upper()) 123 - buff.append(" default y") 124 - return '\n'.join(buff) 229 + def fill_main_c(self): 230 + main_c = super().fill_main_c() 125 231 126 - def fill_trace_h(self): 127 - trace_h = self.trace_h 128 - monitor_class = self.fill_monitor_class() 129 - monitor_class_type = self.fill_monitor_class_type() 130 - tracepoint_args_skel_event = self.fill_tracepoint_args_skel("event") 131 - tracepoint_args_skel_error = self.fill_tracepoint_args_skel("error") 132 - trace_h = trace_h.replace("%%MODEL_NAME%%", self.name) 133 - trace_h = trace_h.replace("%%MODEL_NAME_UP%%", self.name.upper()) 134 - trace_h = trace_h.replace("%%MONITOR_CLASS%%", monitor_class) 135 - trace_h = trace_h.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type) 136 - trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_EVENT%%", tracepoint_args_skel_event) 137 - trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_ERROR%%", tracepoint_args_skel_error) 138 - return trace_h 232 + min_type = self.get_minimun_type() 233 + nr_events = len(self.events) 234 + monitor_type = self.fill_monitor_type() 139 235 140 - def fill_kconfig(self): 141 - kconfig = self.kconfig 142 - monitor_class_type = self.fill_monitor_class_type() 143 - monitor_deps = self.fill_monitor_deps() 144 - kconfig = kconfig.replace("%%MODEL_NAME%%", self.name) 145 - kconfig = kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper()) 146 - kconfig = kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type) 147 - kconfig = kconfig.replace("%%DESCRIPTION%%", self.description) 148 - kconfig = kconfig.replace("%%MONITOR_DEPS%%", monitor_deps) 149 - return kconfig 236 + main_c = main_c.replace("%%MIN_TYPE%%", min_type) 237 + main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events)) 238 + main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type) 150 239 151 - def fill_main_container_h(self): 152 - main_h = self.main_h 153 - main_h = main_h.replace("%%MODEL_NAME%%", self.name) 154 - return main_h 155 - 156 - def __patch_file(self, file, marker, line): 157 - file_to_patch = os.path.join(self.rv_dir, file) 158 - content = self.__read_file(file_to_patch) 159 - content = content.replace(marker, line + "\n" + marker) 160 - self.__write_file(file_to_patch, content) 161 - 162 - def fill_tracepoint_tooltip(self): 163 - monitor_class_type = self.fill_monitor_class_type() 164 - if self.auto_patch: 165 - self.__patch_file("rv_trace.h", 166 - "// Add new monitors based on CONFIG_%s here" % monitor_class_type, 167 - "#include <monitors/%s/%s_trace.h>" % (self.name, self.name)) 168 - return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir 169 - 170 - return """ - Edit %s/rv_trace.h: 171 - Add this line where other tracepoints are included and %s is defined: 172 - #include <monitors/%s/%s_trace.h> 173 - """ % (self.rv_dir, monitor_class_type, self.name, self.name) 174 - 175 - def fill_kconfig_tooltip(self): 176 - if self.auto_patch: 177 - self.__patch_file("Kconfig", 178 - "# Add new monitors here", 179 - "source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name)) 180 - return " - Patching %s/Kconfig, double check the result" % self.rv_dir 181 - 182 - return """ - Edit %s/Kconfig: 183 - Add this line where other monitors are included: 184 - source \"kernel/trace/rv/monitors/%s/Kconfig\" 185 - """ % (self.rv_dir, self.name) 186 - 187 - def fill_makefile_tooltip(self): 188 - name = self.name 189 - name_up = name.upper() 190 - if self.auto_patch: 191 - self.__patch_file("Makefile", 192 - "# Add new monitors here", 193 - "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name)) 194 - return " - Patching %s/Makefile, double check the result" % self.rv_dir 195 - 196 - return """ - Edit %s/Makefile: 197 - Add this line where other monitors are included: 198 - obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o 199 - """ % (self.rv_dir, name_up, name, name) 200 - 201 - def fill_monitor_tooltip(self): 202 - if self.auto_patch: 203 - return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name) 204 - return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir) 205 - 206 - def __create_directory(self): 207 - path = self.name 208 - if self.auto_patch: 209 - path = os.path.join(self.rv_dir, "monitors", path) 210 - try: 211 - os.mkdir(path) 212 - except FileExistsError: 213 - return 214 - except: 215 - print("Fail creating the output dir: %s" % self.name) 216 - 217 - def __write_file(self, file_name, content): 218 - try: 219 - file = open(file_name, 'w') 220 - except: 221 - print("Fail writing to file: %s" % file_name) 222 - 223 - file.write(content) 224 - 225 - file.close() 226 - 227 - def __create_file(self, file_name, content): 228 - path = "%s/%s" % (self.name, file_name) 229 - if self.auto_patch: 230 - path = os.path.join(self.rv_dir, "monitors", path) 231 - self.__write_file(path, content) 232 - 233 - def __get_main_name(self): 234 - path = "%s/%s" % (self.name, "main.c") 235 - if not os.path.exists(path): 236 - return "main.c" 237 - return "__main.c" 238 - 239 - def print_files(self): 240 - main_c = self.fill_main_c() 241 - 242 - self.__create_directory() 243 - 244 - path = "%s.c" % self.name 245 - self.__create_file(path, main_c) 246 - 247 - if self.container: 248 - main_h = self.fill_main_container_h() 249 - path = "%s.h" % self.name 250 - self.__create_file(path, main_h) 251 - else: 252 - model_h = self.fill_model_h() 253 - path = "%s.h" % self.name 254 - self.__create_file(path, model_h) 255 - 256 - trace_h = self.fill_trace_h() 257 - path = "%s_trace.h" % self.name 258 - self.__create_file(path, trace_h) 259 - 260 - kconfig = self.fill_kconfig() 261 - self.__create_file("Kconfig", kconfig) 240 + return main_c
+264
tools/verification/rvgen/rvgen/generator.py
··· 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 + # Abtract class for generating kernel runtime verification monitors from specification file 7 + 8 + import platform 9 + import os 10 + 11 + 12 + class RVGenerator: 13 + rv_dir = "kernel/trace/rv" 14 + 15 + def __init__(self, extra_params={}): 16 + self.name = extra_params.get("model_name") 17 + self.parent = extra_params.get("parent") 18 + self.abs_template_dir = \ 19 + os.path.join(os.path.dirname(__file__), "templates", self.template_dir) 20 + self.main_c = self._read_template_file("main.c") 21 + self.kconfig = self._read_template_file("Kconfig") 22 + self.description = extra_params.get("description", self.name) or "auto-generated" 23 + self.auto_patch = extra_params.get("auto_patch") 24 + if self.auto_patch: 25 + self.__fill_rv_kernel_dir() 26 + 27 + def __fill_rv_kernel_dir(self): 28 + 29 + # first try if we are running in the kernel tree root 30 + if os.path.exists(self.rv_dir): 31 + return 32 + 33 + # offset if we are running inside the kernel tree from verification/dot2 34 + kernel_path = os.path.join("../..", self.rv_dir) 35 + 36 + if os.path.exists(kernel_path): 37 + self.rv_dir = kernel_path 38 + return 39 + 40 + if platform.system() != "Linux": 41 + raise OSError("I can only run on Linux.") 42 + 43 + kernel_path = os.path.join("/lib/modules/%s/build" % platform.release(), self.rv_dir) 44 + 45 + # if the current kernel is from a distro this may not be a full kernel tree 46 + # verify that one of the files we are going to modify is available 47 + if os.path.exists(os.path.join(kernel_path, "rv_trace.h")): 48 + self.rv_dir = kernel_path 49 + return 50 + 51 + raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?") 52 + 53 + def _read_file(self, path): 54 + try: 55 + fd = open(path, 'r') 56 + except OSError: 57 + raise Exception("Cannot open the file: %s" % path) 58 + 59 + content = fd.read() 60 + 61 + fd.close() 62 + return content 63 + 64 + def _read_template_file(self, file): 65 + try: 66 + path = os.path.join(self.abs_template_dir, file) 67 + return self._read_file(path) 68 + except Exception: 69 + # Specific template file not found. Try the generic template file in the template/ 70 + # directory, which is one level up 71 + path = os.path.join(self.abs_template_dir, "..", file) 72 + return self._read_file(path) 73 + 74 + def fill_parent(self): 75 + return "&rv_%s" % self.parent if self.parent else "NULL" 76 + 77 + def fill_include_parent(self): 78 + if self.parent: 79 + return "#include <monitors/%s/%s.h>\n" % (self.parent, self.parent) 80 + return "" 81 + 82 + def fill_tracepoint_handlers_skel(self): 83 + return "NotImplemented" 84 + 85 + def fill_tracepoint_attach_probe(self): 86 + return "NotImplemented" 87 + 88 + def fill_tracepoint_detach_helper(self): 89 + return "NotImplemented" 90 + 91 + def fill_main_c(self): 92 + main_c = self.main_c 93 + tracepoint_handlers = self.fill_tracepoint_handlers_skel() 94 + tracepoint_attach = self.fill_tracepoint_attach_probe() 95 + tracepoint_detach = self.fill_tracepoint_detach_helper() 96 + parent = self.fill_parent() 97 + parent_include = self.fill_include_parent() 98 + 99 + main_c = main_c.replace("%%MODEL_NAME%%", self.name) 100 + main_c = main_c.replace("%%TRACEPOINT_HANDLERS_SKEL%%", tracepoint_handlers) 101 + main_c = main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_attach) 102 + main_c = main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_detach) 103 + main_c = main_c.replace("%%DESCRIPTION%%", self.description) 104 + main_c = main_c.replace("%%PARENT%%", parent) 105 + main_c = main_c.replace("%%INCLUDE_PARENT%%", parent_include) 106 + 107 + return main_c 108 + 109 + def fill_model_h(self): 110 + return "NotImplemented" 111 + 112 + def fill_monitor_class_type(self): 113 + return "NotImplemented" 114 + 115 + def fill_monitor_class(self): 116 + return "NotImplemented" 117 + 118 + def fill_tracepoint_args_skel(self, tp_type): 119 + return "NotImplemented" 120 + 121 + def fill_monitor_deps(self): 122 + buff = [] 123 + buff.append(" # XXX: add dependencies if there") 124 + if self.parent: 125 + buff.append(" depends on RV_MON_%s" % self.parent.upper()) 126 + buff.append(" default y") 127 + return '\n'.join(buff) 128 + 129 + def fill_kconfig(self): 130 + kconfig = self.kconfig 131 + monitor_class_type = self.fill_monitor_class_type() 132 + monitor_deps = self.fill_monitor_deps() 133 + kconfig = kconfig.replace("%%MODEL_NAME%%", self.name) 134 + kconfig = kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper()) 135 + kconfig = kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type) 136 + kconfig = kconfig.replace("%%DESCRIPTION%%", self.description) 137 + kconfig = kconfig.replace("%%MONITOR_DEPS%%", monitor_deps) 138 + return kconfig 139 + 140 + def __patch_file(self, file, marker, line): 141 + file_to_patch = os.path.join(self.rv_dir, file) 142 + content = self._read_file(file_to_patch) 143 + content = content.replace(marker, line + "\n" + marker) 144 + self.__write_file(file_to_patch, content) 145 + 146 + def fill_tracepoint_tooltip(self): 147 + monitor_class_type = self.fill_monitor_class_type() 148 + if self.auto_patch: 149 + self.__patch_file("rv_trace.h", 150 + "// Add new monitors based on CONFIG_%s here" % monitor_class_type, 151 + "#include <monitors/%s/%s_trace.h>" % (self.name, self.name)) 152 + return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir 153 + 154 + return """ - Edit %s/rv_trace.h: 155 + Add this line where other tracepoints are included and %s is defined: 156 + #include <monitors/%s/%s_trace.h> 157 + """ % (self.rv_dir, monitor_class_type, self.name, self.name) 158 + 159 + def fill_kconfig_tooltip(self): 160 + if self.auto_patch: 161 + self.__patch_file("Kconfig", 162 + "# Add new monitors here", 163 + "source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name)) 164 + return " - Patching %s/Kconfig, double check the result" % self.rv_dir 165 + 166 + return """ - Edit %s/Kconfig: 167 + Add this line where other monitors are included: 168 + source \"kernel/trace/rv/monitors/%s/Kconfig\" 169 + """ % (self.rv_dir, self.name) 170 + 171 + def fill_makefile_tooltip(self): 172 + name = self.name 173 + name_up = name.upper() 174 + if self.auto_patch: 175 + self.__patch_file("Makefile", 176 + "# Add new monitors here", 177 + "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name)) 178 + return " - Patching %s/Makefile, double check the result" % self.rv_dir 179 + 180 + return """ - Edit %s/Makefile: 181 + Add this line where other monitors are included: 182 + obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o 183 + """ % (self.rv_dir, name_up, name, name) 184 + 185 + def fill_monitor_tooltip(self): 186 + if self.auto_patch: 187 + return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name) 188 + return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir) 189 + 190 + def __create_directory(self): 191 + path = self.name 192 + if self.auto_patch: 193 + path = os.path.join(self.rv_dir, "monitors", path) 194 + try: 195 + os.mkdir(path) 196 + except FileExistsError: 197 + return 198 + except: 199 + print("Fail creating the output dir: %s" % self.name) 200 + 201 + def __write_file(self, file_name, content): 202 + try: 203 + file = open(file_name, 'w') 204 + except: 205 + print("Fail writing to file: %s" % file_name) 206 + 207 + file.write(content) 208 + 209 + file.close() 210 + 211 + def _create_file(self, file_name, content): 212 + path = "%s/%s" % (self.name, file_name) 213 + if self.auto_patch: 214 + path = os.path.join(self.rv_dir, "monitors", path) 215 + self.__write_file(path, content) 216 + 217 + def __get_main_name(self): 218 + path = "%s/%s" % (self.name, "main.c") 219 + if not os.path.exists(path): 220 + return "main.c" 221 + return "__main.c" 222 + 223 + def print_files(self): 224 + main_c = self.fill_main_c() 225 + 226 + self.__create_directory() 227 + 228 + path = "%s.c" % self.name 229 + self._create_file(path, main_c) 230 + 231 + model_h = self.fill_model_h() 232 + path = "%s.h" % self.name 233 + self._create_file(path, model_h) 234 + 235 + kconfig = self.fill_kconfig() 236 + self._create_file("Kconfig", kconfig) 237 + 238 + 239 + class Monitor(RVGenerator): 240 + monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 } 241 + 242 + def __init__(self, extra_params={}): 243 + super().__init__(extra_params) 244 + self.trace_h = self._read_template_file("trace.h") 245 + 246 + def fill_trace_h(self): 247 + trace_h = self.trace_h 248 + monitor_class = self.fill_monitor_class() 249 + monitor_class_type = self.fill_monitor_class_type() 250 + tracepoint_args_skel_event = self.fill_tracepoint_args_skel("event") 251 + tracepoint_args_skel_error = self.fill_tracepoint_args_skel("error") 252 + trace_h = trace_h.replace("%%MODEL_NAME%%", self.name) 253 + trace_h = trace_h.replace("%%MODEL_NAME_UP%%", self.name.upper()) 254 + trace_h = trace_h.replace("%%MONITOR_CLASS%%", monitor_class) 255 + trace_h = trace_h.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type) 256 + trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_EVENT%%", tracepoint_args_skel_event) 257 + trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_ERROR%%", tracepoint_args_skel_error) 258 + return trace_h 259 + 260 + def print_files(self): 261 + super().print_files() 262 + trace_h = self.fill_trace_h() 263 + path = "%s_trace.h" % self.name 264 + self._create_file(path, trace_h)