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

rv: Add sco and tss per-cpu monitors

Add 2 per-cpu monitors as part of the sched model:

* sco: scheduling context operations
Monitor to ensure sched_set_state happens only in thread context
* tss: task switch while scheduling
Monitor to ensure sched_switch happens only in scheduling context

To: Ingo Molnar <mingo@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: John Kacur <jkacur@redhat.com>
Cc: Clark Williams <williams@redhat.com>
Link: https://lore.kernel.org/20250305140406.350227-4-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)
9fd420ab cb85c660

+373
+2
kernel/trace/rv/Kconfig
··· 28 28 source "kernel/trace/rv/monitors/wip/Kconfig" 29 29 source "kernel/trace/rv/monitors/wwnr/Kconfig" 30 30 source "kernel/trace/rv/monitors/sched/Kconfig" 31 + source "kernel/trace/rv/monitors/tss/Kconfig" 32 + source "kernel/trace/rv/monitors/sco/Kconfig" 31 33 # Add new monitors here 32 34 33 35 config RV_REACTORS
+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 + obj-$(CONFIG_RV_MON_SCO) += monitors/sco/sco.o 9 11 # Add new monitors here 10 12 obj-$(CONFIG_RV_REACTORS) += rv_reactors.o 11 13 obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
+14
kernel/trace/rv/monitors/sco/Kconfig
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # 3 + config RV_MON_SCO 4 + depends on RV 5 + depends on RV_MON_SCHED 6 + default y 7 + select DA_MON_EVENTS_IMPLICIT 8 + bool "sco monitor" 9 + help 10 + Monitor to ensure sched_set_state happens only in thread context. 11 + This monitor is part of the sched monitors collection. 12 + 13 + For further information, see: 14 + Documentation/trace/rv/monitor_sched.rst
+88
kernel/trace/rv/monitors/sco/sco.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 "sco" 12 + 13 + #include <trace/events/sched.h> 14 + #include <rv_trace.h> 15 + #include <monitors/sched/sched.h> 16 + 17 + #include "sco.h" 18 + 19 + static struct rv_monitor rv_sco; 20 + DECLARE_DA_MON_PER_CPU(sco, unsigned char); 21 + 22 + static void handle_sched_set_state(void *data, struct task_struct *tsk, int state) 23 + { 24 + da_handle_start_event_sco(sched_set_state_sco); 25 + } 26 + 27 + static void handle_schedule_entry(void *data, bool preempt, unsigned long ip) 28 + { 29 + da_handle_event_sco(schedule_entry_sco); 30 + } 31 + 32 + static void handle_schedule_exit(void *data, bool is_switch, unsigned long ip) 33 + { 34 + da_handle_start_event_sco(schedule_exit_sco); 35 + } 36 + 37 + static int enable_sco(void) 38 + { 39 + int retval; 40 + 41 + retval = da_monitor_init_sco(); 42 + if (retval) 43 + return retval; 44 + 45 + rv_attach_trace_probe("sco", sched_set_state_tp, handle_sched_set_state); 46 + rv_attach_trace_probe("sco", sched_entry_tp, handle_schedule_entry); 47 + rv_attach_trace_probe("sco", sched_exit_tp, handle_schedule_exit); 48 + 49 + return 0; 50 + } 51 + 52 + static void disable_sco(void) 53 + { 54 + rv_sco.enabled = 0; 55 + 56 + rv_detach_trace_probe("sco", sched_set_state_tp, handle_sched_set_state); 57 + rv_detach_trace_probe("sco", sched_entry_tp, handle_schedule_entry); 58 + rv_detach_trace_probe("sco", sched_exit_tp, handle_schedule_exit); 59 + 60 + da_monitor_destroy_sco(); 61 + } 62 + 63 + static struct rv_monitor rv_sco = { 64 + .name = "sco", 65 + .description = "scheduling context operations.", 66 + .enable = enable_sco, 67 + .disable = disable_sco, 68 + .reset = da_monitor_reset_all_sco, 69 + .enabled = 0, 70 + }; 71 + 72 + static int __init register_sco(void) 73 + { 74 + rv_register_monitor(&rv_sco, &rv_sched); 75 + return 0; 76 + } 77 + 78 + static void __exit unregister_sco(void) 79 + { 80 + rv_unregister_monitor(&rv_sco); 81 + } 82 + 83 + module_init(register_sco); 84 + module_exit(unregister_sco); 85 + 86 + MODULE_LICENSE("GPL"); 87 + MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 88 + MODULE_DESCRIPTION("sco: scheduling context operations.");
+47
kernel/trace/rv/monitors/sco/sco.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Automatically generated C representation of sco automaton 4 + * For further information about this format, see kernel documentation: 5 + * Documentation/trace/rv/deterministic_automata.rst 6 + */ 7 + 8 + enum states_sco { 9 + thread_context_sco = 0, 10 + scheduling_context_sco, 11 + state_max_sco 12 + }; 13 + 14 + #define INVALID_STATE state_max_sco 15 + 16 + enum events_sco { 17 + sched_set_state_sco = 0, 18 + schedule_entry_sco, 19 + schedule_exit_sco, 20 + event_max_sco 21 + }; 22 + 23 + struct automaton_sco { 24 + char *state_names[state_max_sco]; 25 + char *event_names[event_max_sco]; 26 + unsigned char function[state_max_sco][event_max_sco]; 27 + unsigned char initial_state; 28 + bool final_states[state_max_sco]; 29 + }; 30 + 31 + static const struct automaton_sco automaton_sco = { 32 + .state_names = { 33 + "thread_context", 34 + "scheduling_context" 35 + }, 36 + .event_names = { 37 + "sched_set_state", 38 + "schedule_entry", 39 + "schedule_exit" 40 + }, 41 + .function = { 42 + { thread_context_sco, scheduling_context_sco, INVALID_STATE }, 43 + { INVALID_STATE, INVALID_STATE, thread_context_sco }, 44 + }, 45 + .initial_state = thread_context_sco, 46 + .final_states = { 1, 0 }, 47 + };
+15
kernel/trace/rv/monitors/sco/sco_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_SCO 8 + DEFINE_EVENT(event_da_monitor, event_sco, 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_sco, 13 + TP_PROTO(char *state, char *event), 14 + TP_ARGS(state, event)); 15 + #endif /* CONFIG_RV_MON_SCO */
+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
+91
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, unsigned long ip) 31 + { 32 + da_handle_event_tss(schedule_entry_tss); 33 + } 34 + 35 + static void handle_schedule_exit(void *data, bool is_switch, unsigned long ip) 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 + rv_register_monitor(&rv_tss, &rv_sched); 78 + return 0; 79 + } 80 + 81 + static void __exit unregister_tss(void) 82 + { 83 + rv_unregister_monitor(&rv_tss); 84 + } 85 + 86 + module_init(register_tss); 87 + module_exit(unregister_tss); 88 + 89 + MODULE_LICENSE("GPL"); 90 + MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 91 + 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 */
+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 + #include <monitors/sco/sco_trace.h> 61 63 // Add new monitors based on CONFIG_DA_MON_EVENTS_IMPLICIT here 62 64 63 65 #endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */
+18
tools/verification/models/sched/sco.dot
··· 1 + digraph state_automaton { 2 + center = true; 3 + size = "7,11"; 4 + {node [shape = plaintext] "scheduling_context"}; 5 + {node [shape = plaintext, style=invis, label=""] "__init_thread_context"}; 6 + {node [shape = ellipse] "thread_context"}; 7 + {node [shape = plaintext] "thread_context"}; 8 + "__init_thread_context" -> "thread_context"; 9 + "scheduling_context" [label = "scheduling_context"]; 10 + "scheduling_context" -> "thread_context" [ label = "schedule_exit" ]; 11 + "thread_context" [label = "thread_context", color = green3]; 12 + "thread_context" -> "scheduling_context" [ label = "schedule_entry" ]; 13 + "thread_context" -> "thread_context" [ label = "sched_set_state" ]; 14 + { rank = min ; 15 + "__init_thread_context"; 16 + "thread_context"; 17 + } 18 + }
+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 + }