summaryrefslogtreecommitdiff
path: root/tools/verification/dot2
diff options
context:
space:
mode:
Diffstat (limited to 'tools/verification/dot2')
-rw-r--r--tools/verification/dot2/Makefile26
-rw-r--r--tools/verification/dot2/automata.py206
-rw-r--r--tools/verification/dot2/dot2c26
-rw-r--r--tools/verification/dot2/dot2c.py254
-rw-r--r--tools/verification/dot2/dot2k53
-rw-r--r--tools/verification/dot2/dot2k.py389
-rw-r--r--tools/verification/dot2/dot2k_templates/Kconfig9
-rw-r--r--tools/verification/dot2/dot2k_templates/main.c91
-rw-r--r--tools/verification/dot2/dot2k_templates/main_container.c38
-rw-r--r--tools/verification/dot2/dot2k_templates/main_container.h3
-rw-r--r--tools/verification/dot2/dot2k_templates/trace.h13
11 files changed, 0 insertions, 1108 deletions
diff --git a/tools/verification/dot2/Makefile b/tools/verification/dot2/Makefile
deleted file mode 100644
index 021beb07a521..000000000000
--- a/tools/verification/dot2/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-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)/
- $(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)/
diff --git a/tools/verification/dot2/automata.py b/tools/verification/dot2/automata.py
deleted file mode 100644
index d9a3fe2b74bf..000000000000
--- a/tools/verification/dot2/automata.py
+++ /dev/null
@@ -1,206 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
-#
-# 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
-
-class Automata:
- """Automata class: Reads a dot file and part it as an automata.
-
- Attributes:
- dot_file: A dot file with an state_automaton definition.
- """
-
- invalid_state_str = "INVALID_STATE"
-
- def __init__(self, file_path, model_name=None):
- self.__dot_path = file_path
- self.name = model_name or self.__get_model_name()
- self.__dot_lines = self.__open_dot()
- self.states, self.initial_state, self.final_states = self.__get_state_variables()
- self.events = self.__get_event_variables()
- self.function = self.__create_matrix()
- self.events_start, self.events_start_run = self.__store_init_events()
-
- def __get_model_name(self):
- basename = ntpath.basename(self.__dot_path)
- if not basename.endswith(".dot") and not basename.endswith(".gv"):
- print("not a dot file")
- raise Exception("not a dot file: %s" % self.__dot_path)
-
- model_name = ntpath.splitext(basename)[0]
- if model_name.__len__() == 0:
- raise Exception("not a dot file: %s" % self.__dot_path)
-
- return model_name
-
- def __open_dot(self):
- cursor = 0
- dot_lines = []
- try:
- dot_file = open(self.__dot_path)
- except:
- raise Exception("Cannot open the file: %s" % self.__dot_path)
-
- dot_lines = dot_file.read().splitlines()
- dot_file.close()
-
- # checking the first line:
- line = dot_lines[cursor].split()
-
- if (line[0] != "digraph") and (line[1] != "state_automaton"):
- raise Exception("Not a valid .dot format: %s" % self.__dot_path)
- else:
- cursor += 1
- return dot_lines
-
- def __get_cursor_begin_states(self):
- cursor = 0
- while self.__dot_lines[cursor].split()[0] != "{node":
- cursor += 1
- return cursor
-
- def __get_cursor_begin_events(self):
- cursor = 0
- while self.__dot_lines[cursor].split()[0] != "{node":
- cursor += 1
- while self.__dot_lines[cursor].split()[0] == "{node":
- cursor += 1
- # skip initial state transition
- cursor += 1
- return cursor
-
- def __get_state_variables(self):
- # wait for node declaration
- states = []
- final_states = []
-
- has_final_states = False
- cursor = self.__get_cursor_begin_states()
-
- # process nodes
- while self.__dot_lines[cursor].split()[0] == "{node":
- line = self.__dot_lines[cursor].split()
- raw_state = line[-1]
-
- # "enabled_fired"}; -> enabled_fired
- state = raw_state.replace('"', '').replace('};', '').replace(',','_')
- if state[0:7] == "__init_":
- initial_state = state[7:]
- else:
- states.append(state)
- if "doublecircle" in self.__dot_lines[cursor]:
- final_states.append(state)
- has_final_states = True
-
- if "ellipse" in self.__dot_lines[cursor]:
- final_states.append(state)
- has_final_states = True
-
- cursor += 1
-
- states = sorted(set(states))
- states.remove(initial_state)
-
- # Insert the initial state at the bein og the states
- states.insert(0, initial_state)
-
- if not has_final_states:
- final_states.append(initial_state)
-
- return states, initial_state, final_states
-
- def __get_event_variables(self):
- # here we are at the begin of transitions, take a note, we will return later.
- cursor = self.__get_cursor_begin_events()
-
- events = []
- while self.__dot_lines[cursor].lstrip()[0] == '"':
- # transitions have the format:
- # "all_fired" -> "both_fired" [ label = "disable_irq" ];
- # ------------ event is here ------------^^^^^
- if self.__dot_lines[cursor].split()[1] == "->":
- line = self.__dot_lines[cursor].split()
- event = line[-2].replace('"','')
-
- # when a transition has more than one lables, they are like this
- # "local_irq_enable\nhw_local_irq_enable_n"
- # so split them.
-
- event = event.replace("\\n", " ")
- for i in event.split():
- events.append(i)
- cursor += 1
-
- return sorted(set(events))
-
- def __create_matrix(self):
- # transform the array into a dictionary
- events = self.events
- states = self.states
- events_dict = {}
- states_dict = {}
- nr_event = 0
- for event in events:
- events_dict[event] = nr_event
- nr_event += 1
-
- nr_state = 0
- for state in states:
- states_dict[state] = nr_state
- nr_state += 1
-
- # declare the matrix....
- matrix = [[ self.invalid_state_str for x in range(nr_event)] for y in range(nr_state)]
-
- # and we are back! Let's fill the matrix
- cursor = self.__get_cursor_begin_events()
-
- while self.__dot_lines[cursor].lstrip()[0] == '"':
- if self.__dot_lines[cursor].split()[1] == "->":
- line = self.__dot_lines[cursor].split()
- origin_state = line[0].replace('"','').replace(',','_')
- dest_state = line[2].replace('"','').replace(',','_')
- possible_events = line[-2].replace('"','').replace("\\n", " ")
- for event in possible_events.split():
- matrix[states_dict[origin_state]][events_dict[event]] = dest_state
- cursor += 1
-
- return matrix
-
- def __store_init_events(self):
- events_start = [False] * len(self.events)
- events_start_run = [False] * len(self.events)
- for i, _ in enumerate(self.events):
- curr_event_will_init = 0
- curr_event_from_init = False
- curr_event_used = 0
- for j, _ in enumerate(self.states):
- if self.function[j][i] != self.invalid_state_str:
- curr_event_used += 1
- if self.function[j][i] == self.initial_state:
- curr_event_will_init += 1
- if self.function[0][i] != self.invalid_state_str:
- curr_event_from_init = True
- # this event always leads to init
- if curr_event_will_init and curr_event_used == curr_event_will_init:
- events_start[i] = True
- # this event is only called from init
- if curr_event_from_init and curr_event_used == 1:
- events_start_run[i] = True
- return events_start, events_start_run
-
- def is_start_event(self, event):
- return self.events_start[self.events.index(event)]
-
- def is_start_run_event(self, event):
- # prefer handle_start_event if there
- if any(self.events_start):
- return False
- return self.events_start_run[self.events.index(event)]
diff --git a/tools/verification/dot2/dot2c b/tools/verification/dot2/dot2c
deleted file mode 100644
index 3fe89ab88b65..000000000000
--- a/tools/verification/dot2/dot2c
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
-#
-# 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.
-#
-# For further information, see:
-# Documentation/trace/rv/deterministic_automata.rst
-
-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()
diff --git a/tools/verification/dot2/dot2c.py b/tools/verification/dot2/dot2c.py
deleted file mode 100644
index fa2816ac7b61..000000000000
--- a/tools/verification/dot2/dot2c.py
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
-#
-# 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.
-#
-# For further information, see:
-# Documentation/trace/rv/deterministic_automata.rst
-
-from dot2.automata import Automata
-
-class Dot2c(Automata):
- enum_suffix = ""
- enum_states_def = "states"
- enum_events_def = "events"
- struct_automaton_def = "automaton"
- var_automaton_def = "aut"
-
- def __init__(self, file_path, model_name=None):
- super().__init__(file_path, model_name)
- self.line_length = 100
-
- def __buff_to_string(self, buff):
- string = ""
-
- for line in buff:
- string = string + line + "\n"
-
- # cut off the last \n
- return string[:-1]
-
- def __get_enum_states_content(self):
- buff = []
- buff.append("\t%s%s = 0," % (self.initial_state, self.enum_suffix))
- for state in self.states:
- if state != self.initial_state:
- buff.append("\t%s%s," % (state, self.enum_suffix))
- buff.append("\tstate_max%s" % (self.enum_suffix))
-
- return buff
-
- def get_enum_states_string(self):
- buff = self.__get_enum_states_content()
- return self.__buff_to_string(buff)
-
- def format_states_enum(self):
- buff = []
- buff.append("enum %s {" % self.enum_states_def)
- buff.append(self.get_enum_states_string())
- buff.append("};\n")
-
- return buff
-
- def __get_enum_events_content(self):
- buff = []
- first = True
- for event in self.events:
- if first:
- buff.append("\t%s%s = 0," % (event, self.enum_suffix))
- first = False
- else:
- buff.append("\t%s%s," % (event, self.enum_suffix))
-
- buff.append("\tevent_max%s" % self.enum_suffix)
-
- return buff
-
- def get_enum_events_string(self):
- buff = self.__get_enum_events_content()
- return self.__buff_to_string(buff)
-
- def format_events_enum(self):
- buff = []
- buff.append("enum %s {" % self.enum_events_def)
- buff.append(self.get_enum_events_string())
- buff.append("};\n")
-
- return buff
-
- def get_minimun_type(self):
- min_type = "unsigned char"
-
- if self.states.__len__() > 255:
- min_type = "unsigned short"
-
- if self.states.__len__() > 65535:
- min_type = "unsigned int"
-
- if self.states.__len__() > 1000000:
- raise Exception("Too many states: %d" % self.states.__len__())
-
- return min_type
-
- def format_automaton_definition(self):
- min_type = self.get_minimun_type()
- buff = []
- buff.append("struct %s {" % self.struct_automaton_def)
- buff.append("\tchar *state_names[state_max%s];" % (self.enum_suffix))
- buff.append("\tchar *event_names[event_max%s];" % (self.enum_suffix))
- buff.append("\t%s function[state_max%s][event_max%s];" % (min_type, self.enum_suffix, self.enum_suffix))
- buff.append("\t%s initial_state;" % min_type)
- buff.append("\tbool final_states[state_max%s];" % (self.enum_suffix))
- buff.append("};\n")
- return buff
-
- def format_aut_init_header(self):
- buff = []
- buff.append("static const struct %s %s = {" % (self.struct_automaton_def, self.var_automaton_def))
- return buff
-
- def __get_string_vector_per_line_content(self, buff):
- first = True
- string = ""
- for entry in buff:
- if first:
- string = string + "\t\t\"" + entry
- first = False;
- else:
- string = string + "\",\n\t\t\"" + entry
- string = string + "\""
-
- return string
-
- def get_aut_init_events_string(self):
- return self.__get_string_vector_per_line_content(self.events)
-
- def get_aut_init_states_string(self):
- return self.__get_string_vector_per_line_content(self.states)
-
- def format_aut_init_events_string(self):
- buff = []
- buff.append("\t.event_names = {")
- buff.append(self.get_aut_init_events_string())
- buff.append("\t},")
- return buff
-
- def format_aut_init_states_string(self):
- buff = []
- buff.append("\t.state_names = {")
- buff.append(self.get_aut_init_states_string())
- buff.append("\t},")
-
- return buff
-
- def __get_max_strlen_of_states(self):
- max_state_name = max(self.states, key = len).__len__()
- return max(max_state_name, self.invalid_state_str.__len__())
-
- def __get_state_string_length(self):
- maxlen = self.__get_max_strlen_of_states() + self.enum_suffix.__len__()
- return "%" + str(maxlen) + "s"
-
- def get_aut_init_function(self):
- nr_states = self.states.__len__()
- nr_events = self.events.__len__()
- buff = []
-
- strformat = self.__get_state_string_length()
-
- for x in range(nr_states):
- line = "\t\t{ "
- for y in range(nr_events):
- next_state = self.function[x][y]
- if next_state != self.invalid_state_str:
- next_state = self.function[x][y] + self.enum_suffix
-
- if y != nr_events-1:
- line = line + strformat % next_state + ", "
- else:
- line = line + strformat % next_state + " },"
- buff.append(line)
-
- return self.__buff_to_string(buff)
-
- def format_aut_init_function(self):
- buff = []
- buff.append("\t.function = {")
- buff.append(self.get_aut_init_function())
- buff.append("\t},")
-
- return buff
-
- def get_aut_init_initial_state(self):
- return self.initial_state
-
- def format_aut_init_initial_state(self):
- buff = []
- initial_state = self.get_aut_init_initial_state()
- buff.append("\t.initial_state = " + initial_state + self.enum_suffix + ",")
-
- return buff
-
- def get_aut_init_final_states(self):
- line = ""
- first = True
- for state in self.states:
- if first == False:
- line = line + ', '
- else:
- first = False
-
- if self.final_states.__contains__(state):
- line = line + '1'
- else:
- line = line + '0'
- return line
-
- def format_aut_init_final_states(self):
- buff = []
- buff.append("\t.final_states = { %s }," % self.get_aut_init_final_states())
-
- return buff
-
- def __get_automaton_initialization_footer_string(self):
- footer = "};\n"
- return footer
-
- def format_aut_init_footer(self):
- buff = []
- buff.append(self.__get_automaton_initialization_footer_string())
-
- return buff
-
- def format_invalid_state(self):
- buff = []
- buff.append("#define %s state_max%s\n" % (self.invalid_state_str, self.enum_suffix))
-
- return buff
-
- def format_model(self):
- buff = []
- buff += self.format_states_enum()
- buff += self.format_invalid_state()
- buff += self.format_events_enum()
- buff += self.format_automaton_definition()
- buff += self.format_aut_init_header()
- buff += self.format_aut_init_states_string()
- buff += self.format_aut_init_events_string()
- buff += self.format_aut_init_function()
- buff += self.format_aut_init_initial_state()
- buff += self.format_aut_init_final_states()
- buff += self.format_aut_init_footer()
-
- return buff
-
- def print_model_classic(self):
- buff = self.format_model()
- print(self.__buff_to_string(buff))
diff --git a/tools/verification/dot2/dot2k b/tools/verification/dot2/dot2k
deleted file mode 100644
index 767064f415e7..000000000000
--- a/tools/verification/dot2/dot2k
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
-#
-# 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
- import argparse
- import sys
-
- def is_container():
- """Should work even before parsing the arguments"""
- return "-c" in sys.argv or "--container" in sys.argv
-
- parser = argparse.ArgumentParser(description='transform .dot file into kernel rv monitor')
- parser.add_argument('-d', "--dot", dest="dot_file", required=not is_container())
- parser.add_argument('-t', "--monitor_type", dest="monitor_type", required=not is_container(),
- help=f"Available options: {', '.join(dot2k.monitor_types.keys())}")
- parser.add_argument('-n', "--model_name", dest="model_name", required=is_container())
- parser.add_argument("-D", "--description", dest="description", required=False)
- parser.add_argument("-a", "--auto_patch", dest="auto_patch",
- action="store_true", required=False,
- help="Patch the kernel in place")
- parser.add_argument("-p", "--parent", dest="parent",
- required=False, help="Create a monitor nested to parent")
- parser.add_argument("-c", "--container", dest="container",
- action="store_true", required=False,
- help="Create an empty monitor to be used as a container")
- params = parser.parse_args()
-
- if not is_container():
- print("Opening and parsing the dot file %s" % params.dot_file)
- try:
- monitor=dot2k(params.dot_file, params.monitor_type, vars(params))
- except Exception as e:
- print('Error: '+ str(e))
- print("Sorry : :-(")
- sys.exit(1)
-
- print("Writing the monitor into the directory %s" % monitor.name)
- monitor.print_files()
- print("Almost done, checklist")
- if not is_container():
- print(" - Edit the %s/%s.c to add the instrumentation" % (monitor.name, monitor.name))
- print(monitor.fill_tracepoint_tooltip())
- print(monitor.fill_makefile_tooltip())
- print(monitor.fill_kconfig_tooltip())
- print(monitor.fill_monitor_tooltip())
diff --git a/tools/verification/dot2/dot2k.py b/tools/verification/dot2/dot2k.py
deleted file mode 100644
index 745d35a4a379..000000000000
--- a/tools/verification/dot2/dot2k.py
+++ /dev/null
@@ -1,389 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Copyright (C) 2019-2022 Red Hat, Inc. Daniel Bristot de Oliveira <bristot@kernel.org>
-#
-# 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
-import os
-
-class dot2k(Dot2c):
- monitor_types = { "global" : 1, "per_cpu" : 2, "per_task" : 3 }
- monitor_templates_dir = "dot2/dot2k_templates/"
- rv_dir = "kernel/trace/rv"
- monitor_type = "per_cpu"
-
- def __init__(self, file_path, MonitorType, extra_params={}):
- self.container = extra_params.get("container")
- self.parent = extra_params.get("parent")
- self.__fill_rv_templates_dir()
-
- if self.container:
- if file_path:
- raise ValueError("A container does not require a dot file")
- if MonitorType:
- raise ValueError("A container does not require a monitor type")
- if self.parent:
- raise ValueError("A container cannot have a parent")
- self.name = extra_params.get("model_name")
- self.events = []
- self.states = []
- self.main_c = self.__read_file(self.monitor_templates_dir + "main_container.c")
- self.main_h = self.__read_file(self.monitor_templates_dir + "main_container.h")
- else:
- super().__init__(file_path, extra_params.get("model_name"))
-
- self.monitor_type = self.monitor_types.get(MonitorType)
- if self.monitor_type is None:
- raise ValueError("Unknown monitor type: %s" % MonitorType)
- self.monitor_type = MonitorType
- self.main_c = self.__read_file(self.monitor_templates_dir + "main.c")
- self.trace_h = self.__read_file(self.monitor_templates_dir + "trace.h")
- self.kconfig = self.__read_file(self.monitor_templates_dir + "Kconfig")
- self.enum_suffix = "_%s" % self.name
- self.description = extra_params.get("description", self.name) or "auto-generated"
- self.auto_patch = extra_params.get("auto_patch")
- if self.auto_patch:
- self.__fill_rv_kernel_dir()
-
- def __fill_rv_templates_dir(self):
-
- if os.path.exists(self.monitor_templates_dir):
- return
-
- if platform.system() != "Linux":
- raise OSError("I can only run on Linux.")
-
- kernel_path = "/lib/modules/%s/build/tools/verification/dot2/dot2k_templates/" % (platform.release())
-
- if os.path.exists(kernel_path):
- self.monitor_templates_dir = kernel_path
- return
-
- if os.path.exists("/usr/share/dot2/dot2k_templates/"):
- self.monitor_templates_dir = "/usr/share/dot2/dot2k_templates/"
- return
-
- raise FileNotFoundError("Could not find the template directory, do you have the kernel source installed?")
-
- def __fill_rv_kernel_dir(self):
-
- # first try if we are running in the kernel tree root
- if os.path.exists(self.rv_dir):
- return
-
- # offset if we are running inside the kernel tree from verification/dot2
- kernel_path = os.path.join("../..", self.rv_dir)
-
- if os.path.exists(kernel_path):
- self.rv_dir = kernel_path
- return
-
- if platform.system() != "Linux":
- raise OSError("I can only run on Linux.")
-
- kernel_path = os.path.join("/lib/modules/%s/build" % platform.release(), self.rv_dir)
-
- # if the current kernel is from a distro this may not be a full kernel tree
- # verify that one of the files we are going to modify is available
- if os.path.exists(os.path.join(kernel_path, "rv_trace.h")):
- self.rv_dir = kernel_path
- return
-
- raise FileNotFoundError("Could not find the rv directory, do you have the kernel source installed?")
-
- def __read_file(self, path):
- try:
- fd = open(path, 'r')
- except OSError:
- raise Exception("Cannot open the file: %s" % path)
-
- content = fd.read()
-
- fd.close()
- return content
-
- def __buff_to_string(self, buff):
- string = ""
-
- for line in buff:
- string = string + line + "\n"
-
- # cut off the last \n
- return string[:-1]
-
- def fill_monitor_type(self):
- return self.monitor_type.upper()
-
- def fill_parent(self):
- return "&rv_%s" % self.parent if self.parent else "NULL"
-
- def fill_include_parent(self):
- if self.parent:
- return "#include <monitors/%s/%s.h>\n" % (self.parent, self.parent)
- return ""
-
- def fill_tracepoint_handlers_skel(self):
- buff = []
- for event in self.events:
- buff.append("static void handle_%s(void *data, /* XXX: fill header */)" % event)
- buff.append("{")
- handle = "handle_event"
- if self.is_start_event(event):
- buff.append("\t/* XXX: validate that this event always leads to the initial state */")
- handle = "handle_start_event"
- elif self.is_start_run_event(event):
- buff.append("\t/* XXX: validate that this event is only valid in the initial state */")
- handle = "handle_start_run_event"
- if self.monitor_type == "per_task":
- buff.append("\tstruct task_struct *p = /* XXX: how do I get p? */;");
- buff.append("\tda_%s_%s(p, %s%s);" % (handle, self.name, event, self.enum_suffix));
- else:
- buff.append("\tda_%s_%s(%s%s);" % (handle, self.name, event, self.enum_suffix));
- buff.append("}")
- buff.append("")
- return self.__buff_to_string(buff)
-
- def fill_tracepoint_attach_probe(self):
- buff = []
- for event in self.events:
- buff.append("\trv_attach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
- return self.__buff_to_string(buff)
-
- def fill_tracepoint_detach_helper(self):
- buff = []
- for event in self.events:
- buff.append("\trv_detach_trace_probe(\"%s\", /* XXX: tracepoint */, handle_%s);" % (self.name, event))
- return self.__buff_to_string(buff)
-
- def fill_main_c(self):
- main_c = self.main_c
- monitor_type = self.fill_monitor_type()
- min_type = self.get_minimun_type()
- nr_events = len(self.events)
- tracepoint_handlers = self.fill_tracepoint_handlers_skel()
- tracepoint_attach = self.fill_tracepoint_attach_probe()
- tracepoint_detach = self.fill_tracepoint_detach_helper()
- parent = self.fill_parent()
- parent_include = self.fill_include_parent()
-
- main_c = main_c.replace("%%MONITOR_TYPE%%", monitor_type)
- main_c = main_c.replace("%%MIN_TYPE%%", min_type)
- main_c = main_c.replace("%%MODEL_NAME%%", self.name)
- main_c = main_c.replace("%%NR_EVENTS%%", str(nr_events))
- main_c = main_c.replace("%%TRACEPOINT_HANDLERS_SKEL%%", tracepoint_handlers)
- main_c = main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_attach)
- main_c = main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_detach)
- main_c = main_c.replace("%%DESCRIPTION%%", self.description)
- main_c = main_c.replace("%%PARENT%%", parent)
- main_c = main_c.replace("%%INCLUDE_PARENT%%", parent_include)
-
- return main_c
-
- def fill_model_h_header(self):
- buff = []
- buff.append("/* SPDX-License-Identifier: GPL-2.0 */")
- buff.append("/*")
- buff.append(" * Automatically generated C representation of %s automaton" % (self.name))
- buff.append(" * For further information about this format, see kernel documentation:")
- buff.append(" * Documentation/trace/rv/deterministic_automata.rst")
- buff.append(" */")
- buff.append("")
-
- return buff
-
- def fill_model_h(self):
- #
- # Adjust the definition names
- #
- self.enum_states_def = "states_%s" % self.name
- self.enum_events_def = "events_%s" % self.name
- self.struct_automaton_def = "automaton_%s" % self.name
- self.var_automaton_def = "automaton_%s" % self.name
-
- buff = self.fill_model_h_header()
- buff += self.format_model()
-
- return self.__buff_to_string(buff)
-
- def fill_monitor_class_type(self):
- if self.monitor_type == "per_task":
- return "DA_MON_EVENTS_ID"
- return "DA_MON_EVENTS_IMPLICIT"
-
- def fill_monitor_class(self):
- if self.monitor_type == "per_task":
- return "da_monitor_id"
- return "da_monitor"
-
- def fill_tracepoint_args_skel(self, tp_type):
- buff = []
- tp_args_event = [
- ("char *", "state"),
- ("char *", "event"),
- ("char *", "next_state"),
- ("bool ", "final_state"),
- ]
- tp_args_error = [
- ("char *", "state"),
- ("char *", "event"),
- ]
- tp_args_id = ("int ", "id")
- tp_args = tp_args_event if tp_type == "event" else tp_args_error
- if self.monitor_type == "per_task":
- tp_args.insert(0, tp_args_id)
- tp_proto_c = ", ".join([a+b for a,b in tp_args])
- tp_args_c = ", ".join([b for a,b in tp_args])
- buff.append(" TP_PROTO(%s)," % tp_proto_c)
- buff.append(" TP_ARGS(%s)" % tp_args_c)
- return self.__buff_to_string(buff)
-
- def fill_monitor_deps(self):
- buff = []
- buff.append(" # XXX: add dependencies if there")
- if self.parent:
- buff.append(" depends on RV_MON_%s" % self.parent.upper())
- buff.append(" default y")
- return self.__buff_to_string(buff)
-
- def fill_trace_h(self):
- trace_h = self.trace_h
- monitor_class = self.fill_monitor_class()
- monitor_class_type = self.fill_monitor_class_type()
- tracepoint_args_skel_event = self.fill_tracepoint_args_skel("event")
- tracepoint_args_skel_error = self.fill_tracepoint_args_skel("error")
- trace_h = trace_h.replace("%%MODEL_NAME%%", self.name)
- trace_h = trace_h.replace("%%MODEL_NAME_UP%%", self.name.upper())
- trace_h = trace_h.replace("%%MONITOR_CLASS%%", monitor_class)
- trace_h = trace_h.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type)
- trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_EVENT%%", tracepoint_args_skel_event)
- trace_h = trace_h.replace("%%TRACEPOINT_ARGS_SKEL_ERROR%%", tracepoint_args_skel_error)
- return trace_h
-
- def fill_kconfig(self):
- kconfig = self.kconfig
- monitor_class_type = self.fill_monitor_class_type()
- monitor_deps = self.fill_monitor_deps()
- kconfig = kconfig.replace("%%MODEL_NAME%%", self.name)
- kconfig = kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper())
- kconfig = kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_class_type)
- kconfig = kconfig.replace("%%DESCRIPTION%%", self.description)
- kconfig = kconfig.replace("%%MONITOR_DEPS%%", monitor_deps)
- return kconfig
-
- def fill_main_container_h(self):
- main_h = self.main_h
- main_h = main_h.replace("%%MODEL_NAME%%", self.name)
- return main_h
-
- def __patch_file(self, file, marker, line):
- file_to_patch = os.path.join(self.rv_dir, file)
- content = self.__read_file(file_to_patch)
- content = content.replace(marker, line + "\n" + marker)
- self.__write_file(file_to_patch, content)
-
- def fill_tracepoint_tooltip(self):
- monitor_class_type = self.fill_monitor_class_type()
- if self.auto_patch:
- self.__patch_file("rv_trace.h",
- "// Add new monitors based on CONFIG_%s here" % monitor_class_type,
- "#include <monitors/%s/%s_trace.h>" % (self.name, self.name))
- return " - Patching %s/rv_trace.h, double check the result" % self.rv_dir
-
- return """ - Edit %s/rv_trace.h:
-Add this line where other tracepoints are included and %s is defined:
-#include <monitors/%s/%s_trace.h>
-""" % (self.rv_dir, monitor_class_type, self.name, self.name)
-
- def fill_kconfig_tooltip(self):
- if self.auto_patch:
- self.__patch_file("Kconfig",
- "# Add new monitors here",
- "source \"kernel/trace/rv/monitors/%s/Kconfig\"" % (self.name))
- return " - Patching %s/Kconfig, double check the result" % self.rv_dir
-
- return """ - Edit %s/Kconfig:
-Add this line where other monitors are included:
-source \"kernel/trace/rv/monitors/%s/Kconfig\"
-""" % (self.rv_dir, self.name)
-
- def fill_makefile_tooltip(self):
- name = self.name
- name_up = name.upper()
- if self.auto_patch:
- self.__patch_file("Makefile",
- "# Add new monitors here",
- "obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o" % (name_up, name, name))
- return " - Patching %s/Makefile, double check the result" % self.rv_dir
-
- return """ - Edit %s/Makefile:
-Add this line where other monitors are included:
-obj-$(CONFIG_RV_MON_%s) += monitors/%s/%s.o
-""" % (self.rv_dir, name_up, name, name)
-
- def fill_monitor_tooltip(self):
- if self.auto_patch:
- return " - Monitor created in %s/monitors/%s" % (self.rv_dir, self. name)
- return " - Move %s/ to the kernel's monitor directory (%s/monitors)" % (self.name, self.rv_dir)
-
- def __create_directory(self):
- path = self.name
- if self.auto_patch:
- path = os.path.join(self.rv_dir, "monitors", path)
- try:
- os.mkdir(path)
- except FileExistsError:
- return
- except:
- print("Fail creating the output dir: %s" % self.name)
-
- def __write_file(self, file_name, content):
- try:
- file = open(file_name, 'w')
- except:
- print("Fail writing to file: %s" % file_name)
-
- file.write(content)
-
- file.close()
-
- def __create_file(self, file_name, content):
- path = "%s/%s" % (self.name, file_name)
- if self.auto_patch:
- path = os.path.join(self.rv_dir, "monitors", path)
- self.__write_file(path, content)
-
- def __get_main_name(self):
- path = "%s/%s" % (self.name, "main.c")
- if not os.path.exists(path):
- return "main.c"
- return "__main.c"
-
- def print_files(self):
- main_c = self.fill_main_c()
-
- self.__create_directory()
-
- path = "%s.c" % self.name
- self.__create_file(path, main_c)
-
- if self.container:
- main_h = self.fill_main_container_h()
- path = "%s.h" % self.name
- self.__create_file(path, main_h)
- else:
- model_h = self.fill_model_h()
- path = "%s.h" % self.name
- self.__create_file(path, model_h)
-
- trace_h = self.fill_trace_h()
- path = "%s_trace.h" % self.name
- self.__create_file(path, trace_h)
-
- kconfig = self.fill_kconfig()
- self.__create_file("Kconfig", kconfig)
diff --git a/tools/verification/dot2/dot2k_templates/Kconfig b/tools/verification/dot2/dot2k_templates/Kconfig
deleted file mode 100644
index 291b29ea28db..000000000000
--- a/tools/verification/dot2/dot2k_templates/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-config RV_MON_%%MODEL_NAME_UP%%
- depends on RV
-%%MONITOR_DEPS%%
- select %%MONITOR_CLASS_TYPE%%
- bool "%%MODEL_NAME%% monitor"
- help
- %%DESCRIPTION%%
diff --git a/tools/verification/dot2/dot2k_templates/main.c b/tools/verification/dot2/dot2k_templates/main.c
deleted file mode 100644
index 83044a20c89a..000000000000
--- a/tools/verification/dot2/dot2k_templates/main.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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 "%%MODEL_NAME%%"
-
-/*
- * XXX: include required tracepoint headers, e.g.,
- * #include <trace/events/sched.h>
- */
-#include <rv_trace.h>
-%%INCLUDE_PARENT%%
-/*
- * This is the self-generated part of the monitor. Generally, there is no need
- * to touch this section.
- */
-#include "%%MODEL_NAME%%.h"
-
-/*
- * Declare the deterministic automata monitor.
- *
- * The rv monitor reference is needed for the monitor declaration.
- */
-static struct rv_monitor rv_%%MODEL_NAME%%;
-DECLARE_DA_MON_%%MONITOR_TYPE%%(%%MODEL_NAME%%, %%MIN_TYPE%%);
-
-/*
- * 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.
- *
- */
-%%TRACEPOINT_HANDLERS_SKEL%%
-static int enable_%%MODEL_NAME%%(void)
-{
- int retval;
-
- retval = da_monitor_init_%%MODEL_NAME%%();
- if (retval)
- return retval;
-
-%%TRACEPOINT_ATTACH%%
-
- return 0;
-}
-
-static void disable_%%MODEL_NAME%%(void)
-{
- rv_%%MODEL_NAME%%.enabled = 0;
-
-%%TRACEPOINT_DETACH%%
-
- da_monitor_destroy_%%MODEL_NAME%%();
-}
-
-/*
- * This is the monitor register section.
- */
-static struct rv_monitor rv_%%MODEL_NAME%% = {
- .name = "%%MODEL_NAME%%",
- .description = "%%DESCRIPTION%%",
- .enable = enable_%%MODEL_NAME%%,
- .disable = disable_%%MODEL_NAME%%,
- .reset = da_monitor_reset_all_%%MODEL_NAME%%,
- .enabled = 0,
-};
-
-static int __init register_%%MODEL_NAME%%(void)
-{
- rv_register_monitor(&rv_%%MODEL_NAME%%, %%PARENT%%);
- return 0;
-}
-
-static void __exit unregister_%%MODEL_NAME%%(void)
-{
- rv_unregister_monitor(&rv_%%MODEL_NAME%%);
-}
-
-module_init(register_%%MODEL_NAME%%);
-module_exit(unregister_%%MODEL_NAME%%);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("dot2k: auto-generated");
-MODULE_DESCRIPTION("%%MODEL_NAME%%: %%DESCRIPTION%%");
diff --git a/tools/verification/dot2/dot2k_templates/main_container.c b/tools/verification/dot2/dot2k_templates/main_container.c
deleted file mode 100644
index 89fc17cf8958..000000000000
--- a/tools/verification/dot2/dot2k_templates/main_container.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/rv.h>
-
-#define MODULE_NAME "%%MODEL_NAME%%"
-
-#include "%%MODEL_NAME%%.h"
-
-struct rv_monitor rv_%%MODEL_NAME%%;
-
-struct rv_monitor rv_%%MODEL_NAME%% = {
- .name = "%%MODEL_NAME%%",
- .description = "%%DESCRIPTION%%",
- .enable = NULL,
- .disable = NULL,
- .reset = NULL,
- .enabled = 0,
-};
-
-static int __init register_%%MODEL_NAME%%(void)
-{
- rv_register_monitor(&rv_%%MODEL_NAME%%, NULL);
- return 0;
-}
-
-static void __exit unregister_%%MODEL_NAME%%(void)
-{
- rv_unregister_monitor(&rv_%%MODEL_NAME%%);
-}
-
-module_init(register_%%MODEL_NAME%%);
-module_exit(unregister_%%MODEL_NAME%%);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("dot2k: auto-generated");
-MODULE_DESCRIPTION("%%MODEL_NAME%%: %%DESCRIPTION%%");
diff --git a/tools/verification/dot2/dot2k_templates/main_container.h b/tools/verification/dot2/dot2k_templates/main_container.h
deleted file mode 100644
index 0f6883ab4bcc..000000000000
--- a/tools/verification/dot2/dot2k_templates/main_container.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-extern struct rv_monitor rv_%%MODEL_NAME%%;
diff --git a/tools/verification/dot2/dot2k_templates/trace.h b/tools/verification/dot2/dot2k_templates/trace.h
deleted file mode 100644
index 87d3a1308926..000000000000
--- a/tools/verification/dot2/dot2k_templates/trace.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-/*
- * Snippet to be included in rv_trace.h
- */
-
-#ifdef CONFIG_RV_MON_%%MODEL_NAME_UP%%
-DEFINE_EVENT(event_%%MONITOR_CLASS%%, event_%%MODEL_NAME%%,
-%%TRACEPOINT_ARGS_SKEL_EVENT%%);
-
-DEFINE_EVENT(error_%%MONITOR_CLASS%%, error_%%MODEL_NAME%%,
-%%TRACEPOINT_ARGS_SKEL_ERROR%%);
-#endif /* CONFIG_RV_MON_%%MODEL_NAME_UP%% */