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

rv: Replace tss and sncid monitors with more complete sts

The tss monitor currently guarantees task switches can happen only while
scheduling, whereas the sncid monitor enforces scheduling occurs with
interrupt disabled.

Replace the monitors with a more comprehensive specification which
implies both but also ensures that:
* each scheduler call disable interrupts to switch
* each task switch happens with interrupts disabled

Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Nam Cao <namcao@linutronix.de>
Cc: Tomas Glozar <tglozar@redhat.com>
Cc: Juri Lelli <jlelli@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/20250728135022.255578-8-gmonaco@redhat.com
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Gabriele Monaco and committed by
Steven Rostedt (Google)
d0096c2f adcc3bfa

+384 -409
+47 -38
Documentation/trace/rv/monitor_sched.rst
··· 40 40 41 41 Currently we included the following: 42 42 43 - Monitor tss 44 - ~~~~~~~~~~~ 45 - 46 - The task switch while scheduling (tss) monitor ensures a task switch happens 47 - only in scheduling context, that is inside a call to `__schedule`:: 48 - 49 - | 50 - | 51 - v 52 - +-----------------+ 53 - | thread | <+ 54 - +-----------------+ | 55 - | | 56 - | schedule_entry | schedule_exit 57 - v | 58 - sched_switch | 59 - +--------------- | 60 - | sched | 61 - +--------------> -+ 62 - 63 43 Monitor sco 64 44 ~~~~~~~~~~~ 65 45 ··· 124 144 | 125 145 scheduling_contex -+ 126 146 127 - Monitor sncid 128 - ~~~~~~~~~~~~~ 147 + Monitor sts 148 + ~~~~~~~~~~~ 129 149 130 - The schedule not called with interrupt disabled (sncid) monitor ensures 131 - schedule is not called with interrupt disabled:: 150 + The schedule implies task switch (sts) monitor ensures a task switch happens 151 + only in scheduling context and up to once, as well as scheduling occurs with 152 + interrupts enabled but no task switch can happen before interrupts are 153 + disabled. When the next task picked for execution is the same as the previously 154 + running one, no real task switch occurs but interrupts are disabled nonetheless:: 132 155 133 - | 134 - | 135 - v 136 - schedule_entry +--------------+ 137 - schedule_exit | | 138 - +----------------- | can_sched | 139 - | | | 140 - +----------------> | | <+ 141 - +--------------+ | 142 - | | 143 - | irq_disable | irq_enable 144 - v | 145 - | 146 - cant_sched -+ 156 + irq_entry | 157 + +----+ | 158 + v | v 159 + +------------+ irq_enable #===================# irq_disable 160 + | | ------------> H H irq_entry 161 + | cant_sched | <------------ H H irq_enable 162 + | | irq_disable H can_sched H --------------+ 163 + +------------+ H H | 164 + H H | 165 + +---------------> H H <-------------+ 166 + | #===================# 167 + | | 168 + schedule_exit | schedule_entry 169 + | v 170 + | +-------------------+ irq_enable 171 + | | scheduling | <---------------+ 172 + | +-------------------+ | 173 + | | | 174 + | | irq_disable +--------+ irq_entry 175 + | v | | --------+ 176 + | +-------------------+ irq_entry | in_irq | | 177 + | | | -----------> | | <-------+ 178 + | | disable_to_switch | +--------+ 179 + | | | --+ 180 + | +-------------------+ | 181 + | | | 182 + | | sched_switch | 183 + | v | 184 + | +-------------------+ | 185 + | | switching | | irq_enable 186 + | +-------------------+ | 187 + | | | 188 + | | irq_enable | 189 + | v | 190 + | +-------------------+ | 191 + +-- | enable_to_exit | <-+ 192 + +-------------------+ 193 + ^ | irq_disable 194 + | | irq_entry 195 + +---------------+ irq_enable 147 196 148 197 References 149 198 ----------
+1 -2
kernel/trace/rv/Kconfig
··· 50 50 source "kernel/trace/rv/monitors/wwnr/Kconfig" 51 51 52 52 source "kernel/trace/rv/monitors/sched/Kconfig" 53 - source "kernel/trace/rv/monitors/tss/Kconfig" 54 53 source "kernel/trace/rv/monitors/sco/Kconfig" 55 54 source "kernel/trace/rv/monitors/snroc/Kconfig" 56 55 source "kernel/trace/rv/monitors/scpd/Kconfig" 57 56 source "kernel/trace/rv/monitors/snep/Kconfig" 58 - source "kernel/trace/rv/monitors/sncid/Kconfig" 57 + source "kernel/trace/rv/monitors/sts/Kconfig" 59 58 # Add new sched monitors here 60 59 61 60 source "kernel/trace/rv/monitors/rtapp/Kconfig"
+1 -2
kernel/trace/rv/Makefile
··· 6 6 obj-$(CONFIG_RV_MON_WIP) += monitors/wip/wip.o 7 7 obj-$(CONFIG_RV_MON_WWNR) += monitors/wwnr/wwnr.o 8 8 obj-$(CONFIG_RV_MON_SCHED) += monitors/sched/sched.o 9 - obj-$(CONFIG_RV_MON_TSS) += monitors/tss/tss.o 10 9 obj-$(CONFIG_RV_MON_SCO) += monitors/sco/sco.o 11 10 obj-$(CONFIG_RV_MON_SNROC) += monitors/snroc/snroc.o 12 11 obj-$(CONFIG_RV_MON_SCPD) += monitors/scpd/scpd.o 13 12 obj-$(CONFIG_RV_MON_SNEP) += monitors/snep/snep.o 14 - obj-$(CONFIG_RV_MON_SNCID) += monitors/sncid/sncid.o 15 13 obj-$(CONFIG_RV_MON_RTAPP) += monitors/rtapp/rtapp.o 16 14 obj-$(CONFIG_RV_MON_PAGEFAULT) += monitors/pagefault/pagefault.o 17 15 obj-$(CONFIG_RV_MON_SLEEP) += monitors/sleep/sleep.o 16 + obj-$(CONFIG_RV_MON_STS) += monitors/sts/sts.o 18 17 # Add new monitors here 19 18 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o 20 19 obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
-15
kernel/trace/rv/monitors/sncid/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - # 3 - config RV_MON_SNCID 4 - depends on RV 5 - depends on TRACE_IRQFLAGS 6 - depends on RV_MON_SCHED 7 - default y 8 - select DA_MON_EVENTS_IMPLICIT 9 - bool "sncid monitor" 10 - help 11 - Monitor to ensure schedule is not called with interrupt disabled. 12 - This monitor is part of the sched monitors collection. 13 - 14 - For further information, see: 15 - Documentation/trace/rv/monitor_sched.rst
-95
kernel/trace/rv/monitors/sncid/sncid.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/ftrace.h> 3 - #include <linux/tracepoint.h> 4 - #include <linux/kernel.h> 5 - #include <linux/module.h> 6 - #include <linux/init.h> 7 - #include <linux/rv.h> 8 - #include <rv/instrumentation.h> 9 - #include <rv/da_monitor.h> 10 - 11 - #define MODULE_NAME "sncid" 12 - 13 - #include <trace/events/sched.h> 14 - #include <trace/events/preemptirq.h> 15 - #include <rv_trace.h> 16 - #include <monitors/sched/sched.h> 17 - 18 - #include "sncid.h" 19 - 20 - static struct rv_monitor rv_sncid; 21 - DECLARE_DA_MON_PER_CPU(sncid, unsigned char); 22 - 23 - static void handle_irq_disable(void *data, unsigned long ip, unsigned long parent_ip) 24 - { 25 - da_handle_event_sncid(irq_disable_sncid); 26 - } 27 - 28 - static void handle_irq_enable(void *data, unsigned long ip, unsigned long parent_ip) 29 - { 30 - da_handle_start_event_sncid(irq_enable_sncid); 31 - } 32 - 33 - static void handle_schedule_entry(void *data, bool preempt) 34 - { 35 - da_handle_start_event_sncid(schedule_entry_sncid); 36 - } 37 - 38 - static void handle_schedule_exit(void *data, bool is_switch) 39 - { 40 - da_handle_start_event_sncid(schedule_exit_sncid); 41 - } 42 - 43 - static int enable_sncid(void) 44 - { 45 - int retval; 46 - 47 - retval = da_monitor_init_sncid(); 48 - if (retval) 49 - return retval; 50 - 51 - rv_attach_trace_probe("sncid", irq_disable, handle_irq_disable); 52 - rv_attach_trace_probe("sncid", irq_enable, handle_irq_enable); 53 - rv_attach_trace_probe("sncid", sched_entry_tp, handle_schedule_entry); 54 - rv_attach_trace_probe("sncid", sched_exit_tp, handle_schedule_exit); 55 - 56 - return 0; 57 - } 58 - 59 - static void disable_sncid(void) 60 - { 61 - rv_sncid.enabled = 0; 62 - 63 - rv_detach_trace_probe("sncid", irq_disable, handle_irq_disable); 64 - rv_detach_trace_probe("sncid", irq_enable, handle_irq_enable); 65 - rv_detach_trace_probe("sncid", sched_entry_tp, handle_schedule_entry); 66 - rv_detach_trace_probe("sncid", sched_exit_tp, handle_schedule_exit); 67 - 68 - da_monitor_destroy_sncid(); 69 - } 70 - 71 - static struct rv_monitor rv_sncid = { 72 - .name = "sncid", 73 - .description = "schedule not called with interrupt disabled.", 74 - .enable = enable_sncid, 75 - .disable = disable_sncid, 76 - .reset = da_monitor_reset_all_sncid, 77 - .enabled = 0, 78 - }; 79 - 80 - static int __init register_sncid(void) 81 - { 82 - return rv_register_monitor(&rv_sncid, &rv_sched); 83 - } 84 - 85 - static void __exit unregister_sncid(void) 86 - { 87 - rv_unregister_monitor(&rv_sncid); 88 - } 89 - 90 - module_init(register_sncid); 91 - module_exit(unregister_sncid); 92 - 93 - MODULE_LICENSE("GPL"); 94 - MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 95 - MODULE_DESCRIPTION("sncid: schedule not called with interrupt disabled.");
-49
kernel/trace/rv/monitors/sncid/sncid.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Automatically generated C representation of sncid automaton 4 - * For further information about this format, see kernel documentation: 5 - * Documentation/trace/rv/deterministic_automata.rst 6 - */ 7 - 8 - enum states_sncid { 9 - can_sched_sncid = 0, 10 - cant_sched_sncid, 11 - state_max_sncid 12 - }; 13 - 14 - #define INVALID_STATE state_max_sncid 15 - 16 - enum events_sncid { 17 - irq_disable_sncid = 0, 18 - irq_enable_sncid, 19 - schedule_entry_sncid, 20 - schedule_exit_sncid, 21 - event_max_sncid 22 - }; 23 - 24 - struct automaton_sncid { 25 - char *state_names[state_max_sncid]; 26 - char *event_names[event_max_sncid]; 27 - unsigned char function[state_max_sncid][event_max_sncid]; 28 - unsigned char initial_state; 29 - bool final_states[state_max_sncid]; 30 - }; 31 - 32 - static const struct automaton_sncid automaton_sncid = { 33 - .state_names = { 34 - "can_sched", 35 - "cant_sched" 36 - }, 37 - .event_names = { 38 - "irq_disable", 39 - "irq_enable", 40 - "schedule_entry", 41 - "schedule_exit" 42 - }, 43 - .function = { 44 - { cant_sched_sncid, INVALID_STATE, can_sched_sncid, can_sched_sncid }, 45 - { INVALID_STATE, can_sched_sncid, INVALID_STATE, INVALID_STATE }, 46 - }, 47 - .initial_state = can_sched_sncid, 48 - .final_states = { 1, 0 }, 49 - };
+4 -4
kernel/trace/rv/monitors/sncid/sncid_trace.h kernel/trace/rv/monitors/sts/sts_trace.h
··· 4 4 * Snippet to be included in rv_trace.h 5 5 */ 6 6 7 - #ifdef CONFIG_RV_MON_SNCID 8 - DEFINE_EVENT(event_da_monitor, event_sncid, 7 + #ifdef CONFIG_RV_MON_STS 8 + DEFINE_EVENT(event_da_monitor, event_sts, 9 9 TP_PROTO(char *state, char *event, char *next_state, bool final_state), 10 10 TP_ARGS(state, event, next_state, final_state)); 11 11 12 - DEFINE_EVENT(error_da_monitor, error_sncid, 12 + DEFINE_EVENT(error_da_monitor, error_sts, 13 13 TP_PROTO(char *state, char *event), 14 14 TP_ARGS(state, event)); 15 - #endif /* CONFIG_RV_MON_SNCID */ 15 + #endif /* CONFIG_RV_MON_STS */
+19
kernel/trace/rv/monitors/sts/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + config RV_MON_STS 4 + depends on RV 5 + depends on TRACE_IRQFLAGS 6 + depends on RV_MON_SCHED 7 + default y 8 + select DA_MON_EVENTS_IMPLICIT 9 + bool "sts monitor" 10 + help 11 + Monitor to ensure relationships between scheduler and task switches 12 + * the scheduler is called and returns with interrupts disabled 13 + * each call to the scheduler has up to one switch 14 + * switches only happen inside the scheduler 15 + * each call to the scheduler disables interrupts to switch 16 + This monitor is part of the sched monitors collection. 17 + 18 + For further information, see: 19 + Documentation/trace/rv/monitor_sched.rst
+156
kernel/trace/rv/monitors/sts/sts.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <linux/ftrace.h> 3 + #include <linux/tracepoint.h> 4 + #include <linux/kernel.h> 5 + #include <linux/module.h> 6 + #include <linux/init.h> 7 + #include <linux/rv.h> 8 + #include <rv/instrumentation.h> 9 + #include <rv/da_monitor.h> 10 + 11 + #define MODULE_NAME "sts" 12 + 13 + #include <trace/events/sched.h> 14 + #include <trace/events/irq.h> 15 + #include <trace/events/preemptirq.h> 16 + #include <rv_trace.h> 17 + #include <monitors/sched/sched.h> 18 + 19 + #include "sts.h" 20 + 21 + static struct rv_monitor rv_sts; 22 + DECLARE_DA_MON_PER_CPU(sts, unsigned char); 23 + 24 + #ifdef CONFIG_X86_LOCAL_APIC 25 + #include <asm/trace/irq_vectors.h> 26 + 27 + static void handle_vector_irq_entry(void *data, int vector) 28 + { 29 + da_handle_event_sts(irq_entry_sts); 30 + } 31 + 32 + static void attach_vector_irq(void) 33 + { 34 + rv_attach_trace_probe("sts", local_timer_entry, handle_vector_irq_entry); 35 + if (IS_ENABLED(CONFIG_IRQ_WORK)) 36 + rv_attach_trace_probe("sts", irq_work_entry, handle_vector_irq_entry); 37 + if (IS_ENABLED(CONFIG_SMP)) { 38 + rv_attach_trace_probe("sts", reschedule_entry, handle_vector_irq_entry); 39 + rv_attach_trace_probe("sts", call_function_entry, handle_vector_irq_entry); 40 + rv_attach_trace_probe("sts", call_function_single_entry, handle_vector_irq_entry); 41 + } 42 + } 43 + 44 + static void detach_vector_irq(void) 45 + { 46 + rv_detach_trace_probe("sts", local_timer_entry, handle_vector_irq_entry); 47 + if (IS_ENABLED(CONFIG_IRQ_WORK)) 48 + rv_detach_trace_probe("sts", irq_work_entry, handle_vector_irq_entry); 49 + if (IS_ENABLED(CONFIG_SMP)) { 50 + rv_detach_trace_probe("sts", reschedule_entry, handle_vector_irq_entry); 51 + rv_detach_trace_probe("sts", call_function_entry, handle_vector_irq_entry); 52 + rv_detach_trace_probe("sts", call_function_single_entry, handle_vector_irq_entry); 53 + } 54 + } 55 + 56 + #else 57 + /* We assume irq_entry tracepoints are sufficient on other architectures */ 58 + static void attach_vector_irq(void) { } 59 + static void detach_vector_irq(void) { } 60 + #endif 61 + 62 + static void handle_irq_disable(void *data, unsigned long ip, unsigned long parent_ip) 63 + { 64 + da_handle_event_sts(irq_disable_sts); 65 + } 66 + 67 + static void handle_irq_enable(void *data, unsigned long ip, unsigned long parent_ip) 68 + { 69 + da_handle_event_sts(irq_enable_sts); 70 + } 71 + 72 + static void handle_irq_entry(void *data, int irq, struct irqaction *action) 73 + { 74 + da_handle_event_sts(irq_entry_sts); 75 + } 76 + 77 + static void handle_sched_switch(void *data, bool preempt, 78 + struct task_struct *prev, 79 + struct task_struct *next, 80 + unsigned int prev_state) 81 + { 82 + da_handle_event_sts(sched_switch_sts); 83 + } 84 + 85 + static void handle_schedule_entry(void *data, bool preempt) 86 + { 87 + da_handle_event_sts(schedule_entry_sts); 88 + } 89 + 90 + static void handle_schedule_exit(void *data, bool is_switch) 91 + { 92 + da_handle_start_event_sts(schedule_exit_sts); 93 + } 94 + 95 + static int enable_sts(void) 96 + { 97 + int retval; 98 + 99 + retval = da_monitor_init_sts(); 100 + if (retval) 101 + return retval; 102 + 103 + rv_attach_trace_probe("sts", irq_disable, handle_irq_disable); 104 + rv_attach_trace_probe("sts", irq_enable, handle_irq_enable); 105 + rv_attach_trace_probe("sts", irq_handler_entry, handle_irq_entry); 106 + rv_attach_trace_probe("sts", sched_switch, handle_sched_switch); 107 + rv_attach_trace_probe("sts", sched_entry_tp, handle_schedule_entry); 108 + rv_attach_trace_probe("sts", sched_exit_tp, handle_schedule_exit); 109 + attach_vector_irq(); 110 + 111 + return 0; 112 + } 113 + 114 + static void disable_sts(void) 115 + { 116 + rv_sts.enabled = 0; 117 + 118 + rv_detach_trace_probe("sts", irq_disable, handle_irq_disable); 119 + rv_detach_trace_probe("sts", irq_enable, handle_irq_enable); 120 + rv_detach_trace_probe("sts", irq_handler_entry, handle_irq_entry); 121 + rv_detach_trace_probe("sts", sched_switch, handle_sched_switch); 122 + rv_detach_trace_probe("sts", sched_entry_tp, handle_schedule_entry); 123 + rv_detach_trace_probe("sts", sched_exit_tp, handle_schedule_exit); 124 + detach_vector_irq(); 125 + 126 + da_monitor_destroy_sts(); 127 + } 128 + 129 + /* 130 + * This is the monitor register section. 131 + */ 132 + static struct rv_monitor rv_sts = { 133 + .name = "sts", 134 + .description = "schedule implies task switch.", 135 + .enable = enable_sts, 136 + .disable = disable_sts, 137 + .reset = da_monitor_reset_all_sts, 138 + .enabled = 0, 139 + }; 140 + 141 + static int __init register_sts(void) 142 + { 143 + return rv_register_monitor(&rv_sts, &rv_sched); 144 + } 145 + 146 + static void __exit unregister_sts(void) 147 + { 148 + rv_unregister_monitor(&rv_sts); 149 + } 150 + 151 + module_init(register_sts); 152 + module_exit(unregister_sts); 153 + 154 + MODULE_LICENSE("GPL"); 155 + MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 156 + MODULE_DESCRIPTION("sts: schedule implies task switch.");
+117
kernel/trace/rv/monitors/sts/sts.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Automatically generated C representation of sts automaton 4 + * For further information about this format, see kernel documentation: 5 + * Documentation/trace/rv/deterministic_automata.rst 6 + */ 7 + 8 + enum states_sts { 9 + can_sched_sts = 0, 10 + cant_sched_sts, 11 + disable_to_switch_sts, 12 + enable_to_exit_sts, 13 + in_irq_sts, 14 + scheduling_sts, 15 + switching_sts, 16 + state_max_sts 17 + }; 18 + 19 + #define INVALID_STATE state_max_sts 20 + 21 + enum events_sts { 22 + irq_disable_sts = 0, 23 + irq_enable_sts, 24 + irq_entry_sts, 25 + sched_switch_sts, 26 + schedule_entry_sts, 27 + schedule_exit_sts, 28 + event_max_sts 29 + }; 30 + 31 + struct automaton_sts { 32 + char *state_names[state_max_sts]; 33 + char *event_names[event_max_sts]; 34 + unsigned char function[state_max_sts][event_max_sts]; 35 + unsigned char initial_state; 36 + bool final_states[state_max_sts]; 37 + }; 38 + 39 + static const struct automaton_sts automaton_sts = { 40 + .state_names = { 41 + "can_sched", 42 + "cant_sched", 43 + "disable_to_switch", 44 + "enable_to_exit", 45 + "in_irq", 46 + "scheduling", 47 + "switching" 48 + }, 49 + .event_names = { 50 + "irq_disable", 51 + "irq_enable", 52 + "irq_entry", 53 + "sched_switch", 54 + "schedule_entry", 55 + "schedule_exit" 56 + }, 57 + .function = { 58 + { 59 + cant_sched_sts, 60 + INVALID_STATE, 61 + INVALID_STATE, 62 + INVALID_STATE, 63 + scheduling_sts, 64 + INVALID_STATE 65 + }, 66 + { 67 + INVALID_STATE, 68 + can_sched_sts, 69 + cant_sched_sts, 70 + INVALID_STATE, 71 + INVALID_STATE, 72 + INVALID_STATE 73 + }, 74 + { 75 + INVALID_STATE, 76 + enable_to_exit_sts, 77 + in_irq_sts, 78 + switching_sts, 79 + INVALID_STATE, 80 + INVALID_STATE 81 + }, 82 + { 83 + enable_to_exit_sts, 84 + enable_to_exit_sts, 85 + enable_to_exit_sts, 86 + INVALID_STATE, 87 + INVALID_STATE, 88 + can_sched_sts 89 + }, 90 + { 91 + INVALID_STATE, 92 + scheduling_sts, 93 + in_irq_sts, 94 + INVALID_STATE, 95 + INVALID_STATE, 96 + INVALID_STATE 97 + }, 98 + { 99 + disable_to_switch_sts, 100 + INVALID_STATE, 101 + INVALID_STATE, 102 + INVALID_STATE, 103 + INVALID_STATE, 104 + INVALID_STATE 105 + }, 106 + { 107 + INVALID_STATE, 108 + enable_to_exit_sts, 109 + INVALID_STATE, 110 + INVALID_STATE, 111 + INVALID_STATE, 112 + INVALID_STATE 113 + }, 114 + }, 115 + .initial_state = can_sched_sts, 116 + .final_states = { 1, 0, 0, 0, 0, 0, 0 }, 117 + };
-14
kernel/trace/rv/monitors/tss/Kconfig
··· 1 - # SPDX-License-Identifier: GPL-2.0-only 2 - # 3 - config RV_MON_TSS 4 - depends on RV 5 - depends on RV_MON_SCHED 6 - default y 7 - select DA_MON_EVENTS_IMPLICIT 8 - bool "tss monitor" 9 - help 10 - Monitor to ensure sched_switch happens only in scheduling context. 11 - This monitor is part of the sched monitors collection. 12 - 13 - For further information, see: 14 - Documentation/trace/rv/monitor_sched.rst
-90
kernel/trace/rv/monitors/tss/tss.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/ftrace.h> 3 - #include <linux/tracepoint.h> 4 - #include <linux/kernel.h> 5 - #include <linux/module.h> 6 - #include <linux/init.h> 7 - #include <linux/rv.h> 8 - #include <rv/instrumentation.h> 9 - #include <rv/da_monitor.h> 10 - 11 - #define MODULE_NAME "tss" 12 - 13 - #include <trace/events/sched.h> 14 - #include <rv_trace.h> 15 - #include <monitors/sched/sched.h> 16 - 17 - #include "tss.h" 18 - 19 - static struct rv_monitor rv_tss; 20 - DECLARE_DA_MON_PER_CPU(tss, unsigned char); 21 - 22 - static void handle_sched_switch(void *data, bool preempt, 23 - struct task_struct *prev, 24 - struct task_struct *next, 25 - unsigned int prev_state) 26 - { 27 - da_handle_event_tss(sched_switch_tss); 28 - } 29 - 30 - static void handle_schedule_entry(void *data, bool preempt) 31 - { 32 - da_handle_event_tss(schedule_entry_tss); 33 - } 34 - 35 - static void handle_schedule_exit(void *data, bool is_switch) 36 - { 37 - da_handle_start_event_tss(schedule_exit_tss); 38 - } 39 - 40 - static int enable_tss(void) 41 - { 42 - int retval; 43 - 44 - retval = da_monitor_init_tss(); 45 - if (retval) 46 - return retval; 47 - 48 - rv_attach_trace_probe("tss", sched_switch, handle_sched_switch); 49 - rv_attach_trace_probe("tss", sched_entry_tp, handle_schedule_entry); 50 - rv_attach_trace_probe("tss", sched_exit_tp, handle_schedule_exit); 51 - 52 - return 0; 53 - } 54 - 55 - static void disable_tss(void) 56 - { 57 - rv_tss.enabled = 0; 58 - 59 - rv_detach_trace_probe("tss", sched_switch, handle_sched_switch); 60 - rv_detach_trace_probe("tss", sched_entry_tp, handle_schedule_entry); 61 - rv_detach_trace_probe("tss", sched_exit_tp, handle_schedule_exit); 62 - 63 - da_monitor_destroy_tss(); 64 - } 65 - 66 - static struct rv_monitor rv_tss = { 67 - .name = "tss", 68 - .description = "task switch while scheduling.", 69 - .enable = enable_tss, 70 - .disable = disable_tss, 71 - .reset = da_monitor_reset_all_tss, 72 - .enabled = 0, 73 - }; 74 - 75 - static int __init register_tss(void) 76 - { 77 - return rv_register_monitor(&rv_tss, &rv_sched); 78 - } 79 - 80 - static void __exit unregister_tss(void) 81 - { 82 - rv_unregister_monitor(&rv_tss); 83 - } 84 - 85 - module_init(register_tss); 86 - module_exit(unregister_tss); 87 - 88 - MODULE_LICENSE("GPL"); 89 - MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 90 - MODULE_DESCRIPTION("tss: task switch while scheduling.");
-47
kernel/trace/rv/monitors/tss/tss.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * Automatically generated C representation of tss automaton 4 - * For further information about this format, see kernel documentation: 5 - * Documentation/trace/rv/deterministic_automata.rst 6 - */ 7 - 8 - enum states_tss { 9 - thread_tss = 0, 10 - sched_tss, 11 - state_max_tss 12 - }; 13 - 14 - #define INVALID_STATE state_max_tss 15 - 16 - enum events_tss { 17 - sched_switch_tss = 0, 18 - schedule_entry_tss, 19 - schedule_exit_tss, 20 - event_max_tss 21 - }; 22 - 23 - struct automaton_tss { 24 - char *state_names[state_max_tss]; 25 - char *event_names[event_max_tss]; 26 - unsigned char function[state_max_tss][event_max_tss]; 27 - unsigned char initial_state; 28 - bool final_states[state_max_tss]; 29 - }; 30 - 31 - static const struct automaton_tss automaton_tss = { 32 - .state_names = { 33 - "thread", 34 - "sched" 35 - }, 36 - .event_names = { 37 - "sched_switch", 38 - "schedule_entry", 39 - "schedule_exit" 40 - }, 41 - .function = { 42 - { INVALID_STATE, sched_tss, INVALID_STATE }, 43 - { sched_tss, INVALID_STATE, thread_tss }, 44 - }, 45 - .initial_state = thread_tss, 46 - .final_states = { 1, 0 }, 47 - };
-15
kernel/trace/rv/monitors/tss/tss_trace.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - 3 - /* 4 - * Snippet to be included in rv_trace.h 5 - */ 6 - 7 - #ifdef CONFIG_RV_MON_TSS 8 - DEFINE_EVENT(event_da_monitor, event_tss, 9 - TP_PROTO(char *state, char *event, char *next_state, bool final_state), 10 - TP_ARGS(state, event, next_state, final_state)); 11 - 12 - DEFINE_EVENT(error_da_monitor, error_tss, 13 - TP_PROTO(char *state, char *event), 14 - TP_ARGS(state, event)); 15 - #endif /* CONFIG_RV_MON_TSS */
+1 -2
kernel/trace/rv/rv_trace.h
··· 58 58 ); 59 59 60 60 #include <monitors/wip/wip_trace.h> 61 - #include <monitors/tss/tss_trace.h> 62 61 #include <monitors/sco/sco_trace.h> 63 62 #include <monitors/scpd/scpd_trace.h> 64 63 #include <monitors/snep/snep_trace.h> 65 - #include <monitors/sncid/sncid_trace.h> 64 + #include <monitors/sts/sts_trace.h> 66 65 // Add new monitors based on CONFIG_DA_MON_EVENTS_IMPLICIT here 67 66 68 67 #endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */
-18
tools/verification/models/sched/sncid.dot
··· 1 - digraph state_automaton { 2 - center = true; 3 - size = "7,11"; 4 - {node [shape = plaintext, style=invis, label=""] "__init_can_sched"}; 5 - {node [shape = ellipse] "can_sched"}; 6 - {node [shape = plaintext] "can_sched"}; 7 - {node [shape = plaintext] "cant_sched"}; 8 - "__init_can_sched" -> "can_sched"; 9 - "can_sched" [label = "can_sched", color = green3]; 10 - "can_sched" -> "can_sched" [ label = "schedule_entry\nschedule_exit" ]; 11 - "can_sched" -> "cant_sched" [ label = "irq_disable" ]; 12 - "cant_sched" [label = "cant_sched"]; 13 - "cant_sched" -> "can_sched" [ label = "irq_enable" ]; 14 - { rank = min ; 15 - "__init_can_sched"; 16 - "can_sched"; 17 - } 18 - }
+38
tools/verification/models/sched/sts.dot
··· 1 + digraph state_automaton { 2 + center = true; 3 + size = "7,11"; 4 + {node [shape = plaintext, style=invis, label=""] "__init_can_sched"}; 5 + {node [shape = doublecircle] "can_sched"}; 6 + {node [shape = circle] "can_sched"}; 7 + {node [shape = circle] "cant_sched"}; 8 + {node [shape = circle] "disable_to_switch"}; 9 + {node [shape = circle] "enable_to_exit"}; 10 + {node [shape = circle] "in_irq"}; 11 + {node [shape = circle] "scheduling"}; 12 + {node [shape = circle] "switching"}; 13 + "__init_can_sched" -> "can_sched"; 14 + "can_sched" [label = "can_sched", color = green3]; 15 + "can_sched" -> "cant_sched" [ label = "irq_disable" ]; 16 + "can_sched" -> "scheduling" [ label = "schedule_entry" ]; 17 + "cant_sched" [label = "cant_sched"]; 18 + "cant_sched" -> "can_sched" [ label = "irq_enable" ]; 19 + "cant_sched" -> "cant_sched" [ label = "irq_entry" ]; 20 + "disable_to_switch" [label = "disable_to_switch"]; 21 + "disable_to_switch" -> "enable_to_exit" [ label = "irq_enable" ]; 22 + "disable_to_switch" -> "in_irq" [ label = "irq_entry" ]; 23 + "disable_to_switch" -> "switching" [ label = "sched_switch" ]; 24 + "enable_to_exit" [label = "enable_to_exit"]; 25 + "enable_to_exit" -> "can_sched" [ label = "schedule_exit" ]; 26 + "enable_to_exit" -> "enable_to_exit" [ label = "irq_disable\nirq_entry\nirq_enable" ]; 27 + "in_irq" [label = "in_irq"]; 28 + "in_irq" -> "in_irq" [ label = "irq_entry" ]; 29 + "in_irq" -> "scheduling" [ label = "irq_enable" ]; 30 + "scheduling" [label = "scheduling"]; 31 + "scheduling" -> "disable_to_switch" [ label = "irq_disable" ]; 32 + "switching" [label = "switching"]; 33 + "switching" -> "enable_to_exit" [ label = "irq_enable" ]; 34 + { rank = min ; 35 + "__init_can_sched"; 36 + "can_sched"; 37 + } 38 + }
-18
tools/verification/models/sched/tss.dot
··· 1 - digraph state_automaton { 2 - center = true; 3 - size = "7,11"; 4 - {node [shape = plaintext] "sched"}; 5 - {node [shape = plaintext, style=invis, label=""] "__init_thread"}; 6 - {node [shape = ellipse] "thread"}; 7 - {node [shape = plaintext] "thread"}; 8 - "__init_thread" -> "thread"; 9 - "sched" [label = "sched"]; 10 - "sched" -> "sched" [ label = "sched_switch" ]; 11 - "sched" -> "thread" [ label = "schedule_exit" ]; 12 - "thread" [label = "thread", color = green3]; 13 - "thread" -> "sched" [ label = "schedule_entry" ]; 14 - { rank = min ; 15 - "__init_thread"; 16 - "thread"; 17 - } 18 - }