From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 341E51EE7AD for ; Tue, 25 Mar 2025 14:34:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=iq2DrHdoF4qHMjnXQfndkn3rCF/KU59G6l1cWj8Tr3j9nDzfbqoPaFv8EiuRLSe0VsFX7MQVj9ipLTjpg2VW5NMuH/kyAIpSi8XpTr5Hzk59dVNImDdRRgJyO0C3ZqgvdC7J+uHxY104ca1Fr+N5bsv3DySB+E5qnuhbJhduBqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=Dv60DLAilPAXovwEDzTaAb5UeRlBO5uxNec0pmFygi0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=bTu/I11ngxjt3dWeISsv12+Dl1wcGTMUQHRT0RXvD26jVlDSbCiR4899oIzxiQc2+L0udUg7zE+9FuDzF3Ktc+VHHyPdzRYc/K0XGous7I3N3HngBGi4uOiPWtFaHjzUcZ144e5ZpyJ47Va99C26+Uj9Q3/J3zHatcXUnAsw4uQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id B50AFC4CEED; Tue, 25 Mar 2025 14:34:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002Oyv-0PRb; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143501.952352927@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:37 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Masami Hiramatsu , Juri Lelli , Gabriele Monaco , "Peter Zijlstra (Intel)" Subject: [for-next][PATCH 1/9] sched: Add sched tracepoints for RV task model References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Add the following tracepoints: * sched_entry(bool preempt, ip) Called while entering __schedule * sched_exit(bool is_switch, ip) Called while exiting __schedule * sched_set_state(task, curr_state, state) Called when a task changes its state (to and from running) These tracepoints are useful to describe the Linux task model and are adapted from the patches by Daniel Bristot de Oliveira (https://bristot.me/linux-task-model/). Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Juri Lelli Link: https://lore.kernel.org/20250305140406.350227-2-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Acked-by: Peter Zijlstra (Intel) Signed-off-by: Steven Rostedt (Google) --- include/linux/rv.h | 2 +- include/linux/sched.h | 16 ++++++++++++++++ include/trace/events/sched.h | 13 +++++++++++++ kernel/sched/core.c | 23 ++++++++++++++++++++++- tools/verification/rv/include/rv.h | 2 +- 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/linux/rv.h b/include/linux/rv.h index 8883b41d88ec..55d458be53a4 100644 --- a/include/linux/rv.h +++ b/include/linux/rv.h @@ -7,7 +7,7 @@ #ifndef _LINUX_RV_H #define _LINUX_RV_H =20 -#define MAX_DA_NAME_LEN 24 +#define MAX_DA_NAME_LEN 32 =20 #ifdef CONFIG_RV /* diff --git a/include/linux/sched.h b/include/linux/sched.h index 9632e3318e0d..45a61a0b9790 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -46,6 +46,7 @@ #include #include #include +#include #include =20 /* task_struct member predeclarations (sorted alphabetically): */ @@ -186,6 +187,12 @@ struct user_event_mm; # define debug_rtlock_wait_restore_state() do { } while (0) #endif =20 +#define trace_set_current_state(state_value) \ + do { \ + if (tracepoint_enabled(sched_set_state_tp)) \ + __trace_set_current_state(state_value); \ + } while (0) + /* * set_current_state() includes a barrier so that the write of current->__= state * is correctly serialised wrt the caller's subsequent test of whether to @@ -226,12 +233,14 @@ struct user_event_mm; #define __set_current_state(state_value) \ do { \ debug_normal_state_change((state_value)); \ + trace_set_current_state(state_value); \ WRITE_ONCE(current->__state, (state_value)); \ } while (0) =20 #define set_current_state(state_value) \ do { \ debug_normal_state_change((state_value)); \ + trace_set_current_state(state_value); \ smp_store_mb(current->__state, (state_value)); \ } while (0) =20 @@ -247,6 +256,7 @@ struct user_event_mm; \ raw_spin_lock_irqsave(¤t->pi_lock, flags); \ debug_special_state_change((state_value)); \ + trace_set_current_state(state_value); \ WRITE_ONCE(current->__state, (state_value)); \ raw_spin_unlock_irqrestore(¤t->pi_lock, flags); \ } while (0) @@ -282,6 +292,7 @@ struct user_event_mm; raw_spin_lock(¤t->pi_lock); \ current->saved_state =3D current->__state; \ debug_rtlock_wait_set_state(); \ + trace_set_current_state(TASK_RTLOCK_WAIT); \ WRITE_ONCE(current->__state, TASK_RTLOCK_WAIT); \ raw_spin_unlock(¤t->pi_lock); \ } while (0); @@ -291,6 +302,7 @@ struct user_event_mm; lockdep_assert_irqs_disabled(); \ raw_spin_lock(¤t->pi_lock); \ debug_rtlock_wait_restore_state(); \ + trace_set_current_state(current->saved_state); \ WRITE_ONCE(current->__state, current->saved_state); \ current->saved_state =3D TASK_RUNNING; \ raw_spin_unlock(¤t->pi_lock); \ @@ -327,6 +339,10 @@ extern void io_schedule_finish(int token); extern long io_schedule_timeout(long timeout); extern void io_schedule(void); =20 +/* wrapper function to trace from this header file */ +DECLARE_TRACEPOINT(sched_set_state_tp); +extern void __trace_set_current_state(int state_value); + /** * struct prev_cputime - snapshot of system and user cputime * @utime: time spent in user mode diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index 9ea4c404bd4e..90545125c903 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -824,6 +824,19 @@ DECLARE_TRACE(sched_compute_energy_tp, unsigned long max_util, unsigned long busy_time), TP_ARGS(p, dst_cpu, energy, max_util, busy_time)); =20 +DECLARE_TRACE(sched_entry_tp, + TP_PROTO(bool preempt, unsigned long ip), + TP_ARGS(preempt, ip)); + +DECLARE_TRACE(sched_exit_tp, + TP_PROTO(bool is_switch, unsigned long ip), + TP_ARGS(is_switch, ip)); + +DECLARE_TRACE_CONDITION(sched_set_state_tp, + TP_PROTO(struct task_struct *tsk, int state), + TP_ARGS(tsk, state), + TP_CONDITION(!!(tsk->__state) !=3D !!state)); + #endif /* _TRACE_SCHED_H */ =20 /* This part must be outside protection */ diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9aecd914ac69..8294bf49b62b 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -491,6 +491,16 @@ sched_core_dequeue(struct rq *rq, struct task_struct *= p, int flags) { } =20 #endif /* CONFIG_SCHED_CORE */ =20 +/* need a wrapper since we may need to trace from modules */ +EXPORT_TRACEPOINT_SYMBOL(sched_set_state_tp); + +/* Call via the helper macro trace_set_current_state. */ +void __trace_set_current_state(int state_value) +{ + trace_sched_set_state_tp(current, state_value); +} +EXPORT_SYMBOL(__trace_set_current_state); + /* * Serialization rules: * @@ -5307,6 +5317,12 @@ asmlinkage __visible void schedule_tail(struct task_= struct *prev) */ =20 finish_task_switch(prev); + /* + * This is a special case: the newly created task has just + * switched the context for the first time. It is returning from + * schedule for the first time in this path. + */ + trace_sched_exit_tp(true, CALLER_ADDR0); preempt_enable(); =20 if (current->set_child_tid) @@ -6650,12 +6666,15 @@ static void __sched notrace __schedule(int sched_mo= de) * as a preemption by schedule_debug() and RCU. */ bool preempt =3D sched_mode > SM_NONE; + bool is_switch =3D false; unsigned long *switch_count; unsigned long prev_state; struct rq_flags rf; struct rq *rq; int cpu; =20 + trace_sched_entry_tp(preempt, CALLER_ADDR0); + cpu =3D smp_processor_id(); rq =3D cpu_rq(cpu); prev =3D rq->curr; @@ -6723,7 +6742,8 @@ static void __sched notrace __schedule(int sched_mode) rq->last_seen_need_resched_ns =3D 0; #endif =20 - if (likely(prev !=3D next)) { + is_switch =3D prev !=3D next; + if (likely(is_switch)) { rq->nr_switches++; /* * RCU users of rcu_dereference(rq->curr) may not see @@ -6768,6 +6788,7 @@ static void __sched notrace __schedule(int sched_mode) __balance_callbacks(rq); raw_spin_rq_unlock_irq(rq); } + trace_sched_exit_tp(is_switch, CALLER_ADDR0); } =20 void __noreturn do_task_dead(void) diff --git a/tools/verification/rv/include/rv.h b/tools/verification/rv/inc= lude/rv.h index 770fd6da3610..0cab1037a98f 100644 --- a/tools/verification/rv/include/rv.h +++ b/tools/verification/rv/include/rv.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 =20 #define MAX_DESCRIPTION 1024 -#define MAX_DA_NAME_LEN 24 +#define MAX_DA_NAME_LEN 32 =20 struct monitor { char name[MAX_DA_NAME_LEN]; --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7CC4D25A340 for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=cj3m6rIEcyYERX9iSHVLlP20MYuBw1GocTnHy/X1rNp8nNDVUuqlTYsRBNmLWdfhenLSOAfXHFYlRjpUKC7YIJySvYd/HUPU8BVxo8PhY2H+nm4puAsZIJA37PqnSoBG9nK0QZ8zRD5SuruzMDbXIyTL3pNjI8A8iJR33NBO5SA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=ht9P9iBqmy56WW7Z5mtuUcHyi/zaQtLgNhJnGZ7bcVM=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=l05L14hrm64H6xsI1GLK17Lu5CVlTBlXx667K7nDrTu8WwjcnkCl2h1N0aPIeydb6ipSE/ajQln/UXyAB4hcW+Jc2DwE+zkZGtKHOSDLJsyK67nlbzfX6jcXy3vyi/1jD3WtorVQXV1zEfZFCWM/fjyWAaSIt28xrXdQHz4Lxjg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 012E4C4CEEA; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002OzP-18EW; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143502.118766064@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:38 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Juri Lelli , Gabriele Monaco Subject: [for-next][PATCH 2/9] rv: Add option for nested monitors and include sched References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Monitors describing complex systems, such as the scheduler, can easily grow to the point where they are just hard to understand because of the many possible state transitions. Often it is possible to break such descriptions into smaller monitors, sharing some or all events. Enabling those smaller monitors concurrently is, in fact, testing the system as if we had one single larger monitor. Splitting models into multiple specification is not only easier to understand, but gives some more clues when we see errors. Add the possibility to create container monitors, whose only purpose is to host other nested monitors. Enabling a container monitor enables all nested ones, but it's still possible to enable nested monitors independently. Add the sched monitor as first container, for now empty. Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Link: https://lore.kernel.org/20250305140406.350227-3-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- include/linux/rv.h | 2 +- kernel/trace/rv/Kconfig | 1 + kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/sched/Kconfig | 11 ++ kernel/trace/rv/monitors/sched/sched.c | 38 ++++++ kernel/trace/rv/monitors/sched/sched.h | 3 + kernel/trace/rv/monitors/wip/wip.c | 2 +- kernel/trace/rv/monitors/wwnr/wwnr.c | 2 +- kernel/trace/rv/rv.c | 154 +++++++++++++++++++++---- kernel/trace/rv/rv.h | 4 + kernel/trace/rv/rv_reactors.c | 28 ++++- 11 files changed, 217 insertions(+), 29 deletions(-) create mode 100644 kernel/trace/rv/monitors/sched/Kconfig create mode 100644 kernel/trace/rv/monitors/sched/sched.c create mode 100644 kernel/trace/rv/monitors/sched/sched.h diff --git a/include/linux/rv.h b/include/linux/rv.h index 55d458be53a4..3452b5e4b29e 100644 --- a/include/linux/rv.h +++ b/include/linux/rv.h @@ -56,7 +56,7 @@ struct rv_monitor { =20 bool rv_monitoring_on(void); int rv_unregister_monitor(struct rv_monitor *monitor); -int rv_register_monitor(struct rv_monitor *monitor); +int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *par= ent); int rv_get_task_monitor_slot(void); void rv_put_task_monitor_slot(int slot); =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 8226352a0062..84c98a5327f3 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -27,6 +27,7 @@ menuconfig RV =20 source "kernel/trace/rv/monitors/wip/Kconfig" source "kernel/trace/rv/monitors/wwnr/Kconfig" +source "kernel/trace/rv/monitors/sched/Kconfig" # Add new monitors here =20 config RV_REACTORS diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 188b64668e1f..1c784df03b9a 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -5,6 +5,7 @@ ccflags-y +=3D -I $(src) # needed for trace events obj-$(CONFIG_RV) +=3D rv.o obj-$(CONFIG_RV_MON_WIP) +=3D monitors/wip/wip.o obj-$(CONFIG_RV_MON_WWNR) +=3D monitors/wwnr/wwnr.o +obj-$(CONFIG_RV_MON_SCHED) +=3D monitors/sched/sched.o # Add new monitors here obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o diff --git a/kernel/trace/rv/monitors/sched/Kconfig b/kernel/trace/rv/monit= ors/sched/Kconfig new file mode 100644 index 000000000000..ae3eb410abd7 --- /dev/null +++ b/kernel/trace/rv/monitors/sched/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SCHED + depends on RV + bool "sched monitor" + help + Collection of monitors to check the scheduler behaves according to spec= ifications. + Enable this to enable all scheduler specification supported by the curr= ent kernel. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/sched/sched.c b/kernel/trace/rv/monit= ors/sched/sched.c new file mode 100644 index 000000000000..905e03c3c934 --- /dev/null +++ b/kernel/trace/rv/monitors/sched/sched.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +#define MODULE_NAME "sched" + +#include "sched.h" + +struct rv_monitor rv_sched; + +struct rv_monitor rv_sched =3D { + .name =3D "sched", + .description =3D "container for several scheduler monitor specifications.= ", + .enable =3D NULL, + .disable =3D NULL, + .reset =3D NULL, + .enabled =3D 0, +}; + +static int __init register_sched(void) +{ + rv_register_monitor(&rv_sched, NULL); + return 0; +} + +static void __exit unregister_sched(void) +{ + rv_unregister_monitor(&rv_sched); +} + +module_init(register_sched); +module_exit(unregister_sched); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("sched: container for several scheduler monitor specifi= cations."); diff --git a/kernel/trace/rv/monitors/sched/sched.h b/kernel/trace/rv/monit= ors/sched/sched.h new file mode 100644 index 000000000000..ba148dd8d48b --- /dev/null +++ b/kernel/trace/rv/monitors/sched/sched.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +extern struct rv_monitor rv_sched; diff --git a/kernel/trace/rv/monitors/wip/wip.c b/kernel/trace/rv/monitors/= wip/wip.c index db7389157c87..ed758fec8608 100644 --- a/kernel/trace/rv/monitors/wip/wip.c +++ b/kernel/trace/rv/monitors/wip/wip.c @@ -71,7 +71,7 @@ static struct rv_monitor rv_wip =3D { =20 static int __init register_wip(void) { - rv_register_monitor(&rv_wip); + rv_register_monitor(&rv_wip, NULL); return 0; } =20 diff --git a/kernel/trace/rv/monitors/wwnr/wwnr.c b/kernel/trace/rv/monitor= s/wwnr/wwnr.c index 3b16994a9984..172f31c4b0f3 100644 --- a/kernel/trace/rv/monitors/wwnr/wwnr.c +++ b/kernel/trace/rv/monitors/wwnr/wwnr.c @@ -70,7 +70,7 @@ static struct rv_monitor rv_wwnr =3D { =20 static int __init register_wwnr(void) { - rv_register_monitor(&rv_wwnr); + rv_register_monitor(&rv_wwnr, NULL); return 0; } =20 diff --git a/kernel/trace/rv/rv.c b/kernel/trace/rv/rv.c index 8657fc8806e7..50344aa9f7f9 100644 --- a/kernel/trace/rv/rv.c +++ b/kernel/trace/rv/rv.c @@ -162,7 +162,7 @@ struct dentry *get_monitors_root(void) /* * Interface for the monitor register. */ -static LIST_HEAD(rv_monitors_list); +LIST_HEAD(rv_monitors_list); =20 static int task_monitor_count; static bool task_monitor_slots[RV_PER_TASK_MONITORS]; @@ -206,6 +206,30 @@ void rv_put_task_monitor_slot(int slot) task_monitor_slots[slot] =3D false; } =20 +/* + * Monitors with a parent are nested, + * Monitors without a parent could be standalone or containers. + */ +bool rv_is_nested_monitor(struct rv_monitor_def *mdef) +{ + return mdef->parent !=3D NULL; +} + +/* + * We set our list to have nested monitors listed after their parent + * if a monitor has a child element its a container. + * Containers can be also identified based on their function pointers: + * as they are not real monitors they do not need function definitions + * for enable()/disable(). Use this condition to find empty containers. + * Keep both conditions in case we have some non-compliant containers. + */ +bool rv_is_container_monitor(struct rv_monitor_def *mdef) +{ + struct rv_monitor_def *next =3D list_next_entry(mdef, list); + + return next->parent =3D=3D mdef->monitor || !mdef->monitor->enable; +} + /* * This section collects the monitor/ files and folders. */ @@ -229,7 +253,8 @@ static int __rv_disable_monitor(struct rv_monitor_def *= mdef, bool sync) =20 if (mdef->monitor->enabled) { mdef->monitor->enabled =3D 0; - mdef->monitor->disable(); + if (mdef->monitor->disable) + mdef->monitor->disable(); =20 /* * Wait for the execution of all events to finish. @@ -243,6 +268,60 @@ static int __rv_disable_monitor(struct rv_monitor_def = *mdef, bool sync) return 0; } =20 +static void rv_disable_single(struct rv_monitor_def *mdef) +{ + __rv_disable_monitor(mdef, true); +} + +static int rv_enable_single(struct rv_monitor_def *mdef) +{ + int retval; + + lockdep_assert_held(&rv_interface_lock); + + if (mdef->monitor->enabled) + return 0; + + retval =3D mdef->monitor->enable(); + + if (!retval) + mdef->monitor->enabled =3D 1; + + return retval; +} + +static void rv_disable_container(struct rv_monitor_def *mdef) +{ + struct rv_monitor_def *p =3D mdef; + int enabled =3D 0; + + list_for_each_entry_continue(p, &rv_monitors_list, list) { + if (p->parent !=3D mdef->monitor) + break; + enabled +=3D __rv_disable_monitor(p, false); + } + if (enabled) + tracepoint_synchronize_unregister(); + mdef->monitor->enabled =3D 0; +} + +static int rv_enable_container(struct rv_monitor_def *mdef) +{ + struct rv_monitor_def *p =3D mdef; + int retval =3D 0; + + list_for_each_entry_continue(p, &rv_monitors_list, list) { + if (retval || p->parent !=3D mdef->monitor) + break; + retval =3D rv_enable_single(p); + } + if (retval) + rv_disable_container(mdef); + else + mdef->monitor->enabled =3D 1; + return retval; +} + /** * rv_disable_monitor - disable a given runtime monitor * @mdef: Pointer to the monitor definition structure. @@ -251,7 +330,11 @@ static int __rv_disable_monitor(struct rv_monitor_def = *mdef, bool sync) */ int rv_disable_monitor(struct rv_monitor_def *mdef) { - __rv_disable_monitor(mdef, true); + if (rv_is_container_monitor(mdef)) + rv_disable_container(mdef); + else + rv_disable_single(mdef); + return 0; } =20 @@ -265,15 +348,10 @@ int rv_enable_monitor(struct rv_monitor_def *mdef) { int retval; =20 - lockdep_assert_held(&rv_interface_lock); - - if (mdef->monitor->enabled) - return 0; - - retval =3D mdef->monitor->enable(); - - if (!retval) - mdef->monitor->enabled =3D 1; + if (rv_is_container_monitor(mdef)) + retval =3D rv_enable_container(mdef); + else + retval =3D rv_enable_single(mdef); =20 return retval; } @@ -336,9 +414,9 @@ static const struct file_operations interface_desc_fops= =3D { * the monitor dir, where the specific options of the monitor * are exposed. */ -static int create_monitor_dir(struct rv_monitor_def *mdef) +static int create_monitor_dir(struct rv_monitor_def *mdef, struct rv_monit= or_def *parent) { - struct dentry *root =3D get_monitors_root(); + struct dentry *root =3D parent ? parent->root_d : get_monitors_root(); const char *name =3D mdef->monitor->name; struct dentry *tmp; int retval; @@ -377,7 +455,11 @@ static int monitors_show(struct seq_file *m, void *p) { struct rv_monitor_def *mon_def =3D p; =20 - seq_printf(m, "%s\n", mon_def->monitor->name); + if (mon_def->parent) + seq_printf(m, "%s:%s\n", mon_def->parent->name, + mon_def->monitor->name); + else + seq_printf(m, "%s\n", mon_def->monitor->name); return 0; } =20 @@ -514,7 +596,7 @@ static ssize_t enabled_monitors_write(struct file *filp= , const char __user *user struct rv_monitor_def *mdef; int retval =3D -EINVAL; bool enable =3D true; - char *ptr; + char *ptr, *tmp; int len; =20 if (count < 1 || count > MAX_RV_MONITOR_NAME_SIZE + 1) @@ -541,6 +623,11 @@ static ssize_t enabled_monitors_write(struct file *fil= p, const char __user *user =20 retval =3D -EINVAL; =20 + /* we support 1 nesting level, trim the parent */ + tmp =3D strstr(ptr, ":"); + if (tmp) + ptr =3D tmp+1; + list_for_each_entry(mdef, &rv_monitors_list, list) { if (strcmp(ptr, mdef->monitor->name) !=3D 0) continue; @@ -613,7 +700,7 @@ static void reset_all_monitors(void) struct rv_monitor_def *mdef; =20 list_for_each_entry(mdef, &rv_monitors_list, list) { - if (mdef->monitor->enabled) + if (mdef->monitor->enabled && mdef->monitor->reset) mdef->monitor->reset(); } } @@ -685,18 +772,19 @@ static void destroy_monitor_dir(struct rv_monitor_def= *mdef) /** * rv_register_monitor - register a rv monitor. * @monitor: The rv_monitor to be registered. + * @parent: The parent of the monitor to be registered, NULL if not ne= sted. * * Returns 0 if successful, error otherwise. */ -int rv_register_monitor(struct rv_monitor *monitor) +int rv_register_monitor(struct rv_monitor *monitor, struct rv_monitor *par= ent) { - struct rv_monitor_def *r; + struct rv_monitor_def *r, *p =3D NULL; int retval =3D 0; =20 if (strlen(monitor->name) >=3D MAX_RV_MONITOR_NAME_SIZE) { pr_info("Monitor %s has a name longer than %d\n", monitor->name, MAX_RV_MONITOR_NAME_SIZE); - return -1; + return -EINVAL; } =20 mutex_lock(&rv_interface_lock); @@ -704,11 +792,26 @@ int rv_register_monitor(struct rv_monitor *monitor) list_for_each_entry(r, &rv_monitors_list, list) { if (strcmp(monitor->name, r->monitor->name) =3D=3D 0) { pr_info("Monitor %s is already registered\n", monitor->name); - retval =3D -1; + retval =3D -EEXIST; goto out_unlock; } } =20 + if (parent) { + list_for_each_entry(r, &rv_monitors_list, list) { + if (strcmp(parent->name, r->monitor->name) =3D=3D 0) { + p =3D r; + break; + } + } + } + + if (p && rv_is_nested_monitor(p)) { + pr_info("Parent monitor %s is already nested, cannot nest further\n", + parent->name); + return -EINVAL; + } + r =3D kzalloc(sizeof(struct rv_monitor_def), GFP_KERNEL); if (!r) { retval =3D -ENOMEM; @@ -716,14 +819,19 @@ int rv_register_monitor(struct rv_monitor *monitor) } =20 r->monitor =3D monitor; + r->parent =3D parent; =20 - retval =3D create_monitor_dir(r); + retval =3D create_monitor_dir(r, p); if (retval) { kfree(r); goto out_unlock; } =20 - list_add_tail(&r->list, &rv_monitors_list); + /* keep children close to the parent for easier visualisation */ + if (p) + list_add(&r->list, &p->list); + else + list_add_tail(&r->list, &rv_monitors_list); =20 out_unlock: mutex_unlock(&rv_interface_lock); diff --git a/kernel/trace/rv/rv.h b/kernel/trace/rv/rv.h index db6cb0913dbd..98fca0a1adbc 100644 --- a/kernel/trace/rv/rv.h +++ b/kernel/trace/rv/rv.h @@ -21,6 +21,7 @@ struct rv_interface { #define MAX_RV_REACTOR_NAME_SIZE 32 =20 extern struct mutex rv_interface_lock; +extern struct list_head rv_monitors_list; =20 #ifdef CONFIG_RV_REACTORS struct rv_reactor_def { @@ -34,6 +35,7 @@ struct rv_reactor_def { struct rv_monitor_def { struct list_head list; struct rv_monitor *monitor; + struct rv_monitor *parent; struct dentry *root_d; #ifdef CONFIG_RV_REACTORS struct rv_reactor_def *rdef; @@ -45,6 +47,8 @@ struct rv_monitor_def { struct dentry *get_monitors_root(void); int rv_disable_monitor(struct rv_monitor_def *mdef); int rv_enable_monitor(struct rv_monitor_def *mdef); +bool rv_is_container_monitor(struct rv_monitor_def *mdef); +bool rv_is_nested_monitor(struct rv_monitor_def *mdef); =20 #ifdef CONFIG_RV_REACTORS int reactor_populate_monitor(struct rv_monitor_def *mdef); diff --git a/kernel/trace/rv/rv_reactors.c b/kernel/trace/rv/rv_reactors.c index 7b49cbe388d4..9501ca886d83 100644 --- a/kernel/trace/rv/rv_reactors.c +++ b/kernel/trace/rv/rv_reactors.c @@ -158,8 +158,9 @@ static const struct seq_operations monitor_reactors_seq= _ops =3D { .show =3D monitor_reactor_show }; =20 -static void monitor_swap_reactors(struct rv_monitor_def *mdef, struct rv_r= eactor_def *rdef, - bool reacting) +static void monitor_swap_reactors_single(struct rv_monitor_def *mdef, + struct rv_reactor_def *rdef, + bool reacting, bool nested) { bool monitor_enabled; =20 @@ -179,10 +180,31 @@ static void monitor_swap_reactors(struct rv_monitor_d= ef *mdef, struct rv_reactor mdef->reacting =3D reacting; mdef->monitor->react =3D rdef->reactor->react; =20 - if (monitor_enabled) + /* enable only once if iterating through a container */ + if (monitor_enabled && !nested) rv_enable_monitor(mdef); } =20 +static void monitor_swap_reactors(struct rv_monitor_def *mdef, + struct rv_reactor_def *rdef, bool reacting) +{ + struct rv_monitor_def *p =3D mdef; + + if (rv_is_container_monitor(mdef)) + list_for_each_entry_continue(p, &rv_monitors_list, list) { + if (p->parent !=3D mdef->monitor) + break; + monitor_swap_reactors_single(p, rdef, reacting, true); + } + /* + * This call enables and disables the monitor if they were active. + * In case of a container, we already disabled all and will enable all. + * All nested monitors are enabled also if they were off, we may refine + * this logic in the future. + */ + monitor_swap_reactors_single(mdef, rdef, reacting, false); +} + static ssize_t monitor_reactors_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5685C25A2D0 for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=u+ZOGrRVEtYc4Rbz+rSh/OnI+EckDI/yKB84ZIE95D7WvNcHRD/GDEodpfE65ka37eLqs79qv4vpmA9tmZA2TRIWD8j06C7O7v2kFpZaL7332DaenyKmoGbxxGdppPWLXQ+7SGeqdOIUZdApfKRj5tKZPwREsm0l7m4+1Irz4Ok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=zwD8RJKar/Yad4gCsMq4QQbBGtH6LYz3vomASUvb/9E=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=YRMjaxT3DRsDed6xf0KZ9zfyiI6EUglguIDKZ3sBTQH4Xsk0BnRr2EJqbQ76ip8fS3KGJTfxCo+F1rPfRha11zRDjXlWYZ5UtO2zKUSO/6Q76bLA7p4OGoTx5Jdu2vuo2A88csBcg3N3/gXjosjROBs6uszGlGJuZjneMLphpRA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 01ED0C4CEEE; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002Ozt-1rHx; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143502.291464364@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:39 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, Ingo Molnar , Peter Zijlstra Cc: Tomas Glozar , John Kacur , Juri Lelli , Clark Williams , Gabriele Monaco Subject: [for-next][PATCH 3/9] rv: Add sco and tss per-cpu monitors References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco 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 To: Peter Zijlstra Cc: Juri Lelli Cc: Ingo Molnar Cc: Peter Zijlstra Cc: John Kacur Cc: Clark Williams Link: https://lore.kernel.org/20250305140406.350227-4-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/Kconfig | 2 + kernel/trace/rv/Makefile | 2 + kernel/trace/rv/monitors/sco/Kconfig | 14 ++++ kernel/trace/rv/monitors/sco/sco.c | 88 +++++++++++++++++++++++ kernel/trace/rv/monitors/sco/sco.h | 47 ++++++++++++ kernel/trace/rv/monitors/sco/sco_trace.h | 15 ++++ kernel/trace/rv/monitors/tss/Kconfig | 14 ++++ kernel/trace/rv/monitors/tss/tss.c | 91 ++++++++++++++++++++++++ kernel/trace/rv/monitors/tss/tss.h | 47 ++++++++++++ kernel/trace/rv/monitors/tss/tss_trace.h | 15 ++++ kernel/trace/rv/rv_trace.h | 2 + tools/verification/models/sched/sco.dot | 18 +++++ tools/verification/models/sched/tss.dot | 18 +++++ 13 files changed, 373 insertions(+) create mode 100644 kernel/trace/rv/monitors/sco/Kconfig create mode 100644 kernel/trace/rv/monitors/sco/sco.c create mode 100644 kernel/trace/rv/monitors/sco/sco.h create mode 100644 kernel/trace/rv/monitors/sco/sco_trace.h create mode 100644 kernel/trace/rv/monitors/tss/Kconfig create mode 100644 kernel/trace/rv/monitors/tss/tss.c create mode 100644 kernel/trace/rv/monitors/tss/tss.h create mode 100644 kernel/trace/rv/monitors/tss/tss_trace.h create mode 100644 tools/verification/models/sched/sco.dot create mode 100644 tools/verification/models/sched/tss.dot diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 84c98a5327f3..961ac1e487df 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -28,6 +28,8 @@ menuconfig RV source "kernel/trace/rv/monitors/wip/Kconfig" source "kernel/trace/rv/monitors/wwnr/Kconfig" source "kernel/trace/rv/monitors/sched/Kconfig" +source "kernel/trace/rv/monitors/tss/Kconfig" +source "kernel/trace/rv/monitors/sco/Kconfig" # Add new monitors here =20 config RV_REACTORS diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 1c784df03b9a..ef2a084ff310 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_RV) +=3D rv.o obj-$(CONFIG_RV_MON_WIP) +=3D monitors/wip/wip.o obj-$(CONFIG_RV_MON_WWNR) +=3D monitors/wwnr/wwnr.o obj-$(CONFIG_RV_MON_SCHED) +=3D monitors/sched/sched.o +obj-$(CONFIG_RV_MON_TSS) +=3D monitors/tss/tss.o +obj-$(CONFIG_RV_MON_SCO) +=3D monitors/sco/sco.o # Add new monitors here obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o diff --git a/kernel/trace/rv/monitors/sco/Kconfig b/kernel/trace/rv/monitor= s/sco/Kconfig new file mode 100644 index 000000000000..097c96cccdd7 --- /dev/null +++ b/kernel/trace/rv/monitors/sco/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SCO + depends on RV + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "sco monitor" + help + Monitor to ensure sched_set_state happens only in thread context. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/sco/sco.c b/kernel/trace/rv/monitors/= sco/sco.c new file mode 100644 index 000000000000..4cff59220bfc --- /dev/null +++ b/kernel/trace/rv/monitors/sco/sco.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "sco" + +#include +#include +#include + +#include "sco.h" + +static struct rv_monitor rv_sco; +DECLARE_DA_MON_PER_CPU(sco, unsigned char); + +static void handle_sched_set_state(void *data, struct task_struct *tsk, in= t state) +{ + da_handle_start_event_sco(sched_set_state_sco); +} + +static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +{ + da_handle_event_sco(schedule_entry_sco); +} + +static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +{ + da_handle_start_event_sco(schedule_exit_sco); +} + +static int enable_sco(void) +{ + int retval; + + retval =3D da_monitor_init_sco(); + if (retval) + return retval; + + rv_attach_trace_probe("sco", sched_set_state_tp, handle_sched_set_state); + rv_attach_trace_probe("sco", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("sco", sched_exit_tp, handle_schedule_exit); + + return 0; +} + +static void disable_sco(void) +{ + rv_sco.enabled =3D 0; + + rv_detach_trace_probe("sco", sched_set_state_tp, handle_sched_set_state); + rv_detach_trace_probe("sco", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("sco", sched_exit_tp, handle_schedule_exit); + + da_monitor_destroy_sco(); +} + +static struct rv_monitor rv_sco =3D { + .name =3D "sco", + .description =3D "scheduling context operations.", + .enable =3D enable_sco, + .disable =3D disable_sco, + .reset =3D da_monitor_reset_all_sco, + .enabled =3D 0, +}; + +static int __init register_sco(void) +{ + rv_register_monitor(&rv_sco, &rv_sched); + return 0; +} + +static void __exit unregister_sco(void) +{ + rv_unregister_monitor(&rv_sco); +} + +module_init(register_sco); +module_exit(unregister_sco); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("sco: scheduling context operations."); diff --git a/kernel/trace/rv/monitors/sco/sco.h b/kernel/trace/rv/monitors/= sco/sco.h new file mode 100644 index 000000000000..7a4c1f2d5ca1 --- /dev/null +++ b/kernel/trace/rv/monitors/sco/sco.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of sco automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_sco { + thread_context_sco =3D 0, + scheduling_context_sco, + state_max_sco +}; + +#define INVALID_STATE state_max_sco + +enum events_sco { + sched_set_state_sco =3D 0, + schedule_entry_sco, + schedule_exit_sco, + event_max_sco +}; + +struct automaton_sco { + char *state_names[state_max_sco]; + char *event_names[event_max_sco]; + unsigned char function[state_max_sco][event_max_sco]; + unsigned char initial_state; + bool final_states[state_max_sco]; +}; + +static const struct automaton_sco automaton_sco =3D { + .state_names =3D { + "thread_context", + "scheduling_context" + }, + .event_names =3D { + "sched_set_state", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { thread_context_sco, scheduling_context_sco, INVALID_STATE= }, + { INVALID_STATE, INVALID_STATE, thread_context_sco= }, + }, + .initial_state =3D thread_context_sco, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/sco/sco_trace.h b/kernel/trace/rv/mon= itors/sco/sco_trace.h new file mode 100644 index 000000000000..b711cd9024ec --- /dev/null +++ b/kernel/trace/rv/monitors/sco/sco_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SCO +DEFINE_EVENT(event_da_monitor, event_sco, + TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), + TP_ARGS(state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor, error_sco, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_SCO */ diff --git a/kernel/trace/rv/monitors/tss/Kconfig b/kernel/trace/rv/monitor= s/tss/Kconfig new file mode 100644 index 000000000000..479f86f52e60 --- /dev/null +++ b/kernel/trace/rv/monitors/tss/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_TSS + depends on RV + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "tss monitor" + help + Monitor to ensure sched_switch happens only in scheduling context. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/tss/tss.c b/kernel/trace/rv/monitors/= tss/tss.c new file mode 100644 index 000000000000..542787e6524f --- /dev/null +++ b/kernel/trace/rv/monitors/tss/tss.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "tss" + +#include +#include +#include + +#include "tss.h" + +static struct rv_monitor rv_tss; +DECLARE_DA_MON_PER_CPU(tss, unsigned char); + +static void handle_sched_switch(void *data, bool preempt, + struct task_struct *prev, + struct task_struct *next, + unsigned int prev_state) +{ + da_handle_event_tss(sched_switch_tss); +} + +static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +{ + da_handle_event_tss(schedule_entry_tss); +} + +static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +{ + da_handle_start_event_tss(schedule_exit_tss); +} + +static int enable_tss(void) +{ + int retval; + + retval =3D da_monitor_init_tss(); + if (retval) + return retval; + + rv_attach_trace_probe("tss", sched_switch, handle_sched_switch); + rv_attach_trace_probe("tss", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("tss", sched_exit_tp, handle_schedule_exit); + + return 0; +} + +static void disable_tss(void) +{ + rv_tss.enabled =3D 0; + + rv_detach_trace_probe("tss", sched_switch, handle_sched_switch); + rv_detach_trace_probe("tss", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("tss", sched_exit_tp, handle_schedule_exit); + + da_monitor_destroy_tss(); +} + +static struct rv_monitor rv_tss =3D { + .name =3D "tss", + .description =3D "task switch while scheduling.", + .enable =3D enable_tss, + .disable =3D disable_tss, + .reset =3D da_monitor_reset_all_tss, + .enabled =3D 0, +}; + +static int __init register_tss(void) +{ + rv_register_monitor(&rv_tss, &rv_sched); + return 0; +} + +static void __exit unregister_tss(void) +{ + rv_unregister_monitor(&rv_tss); +} + +module_init(register_tss); +module_exit(unregister_tss); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("tss: task switch while scheduling."); diff --git a/kernel/trace/rv/monitors/tss/tss.h b/kernel/trace/rv/monitors/= tss/tss.h new file mode 100644 index 000000000000..f0a36fda1b87 --- /dev/null +++ b/kernel/trace/rv/monitors/tss/tss.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of tss automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_tss { + thread_tss =3D 0, + sched_tss, + state_max_tss +}; + +#define INVALID_STATE state_max_tss + +enum events_tss { + sched_switch_tss =3D 0, + schedule_entry_tss, + schedule_exit_tss, + event_max_tss +}; + +struct automaton_tss { + char *state_names[state_max_tss]; + char *event_names[event_max_tss]; + unsigned char function[state_max_tss][event_max_tss]; + unsigned char initial_state; + bool final_states[state_max_tss]; +}; + +static const struct automaton_tss automaton_tss =3D { + .state_names =3D { + "thread", + "sched" + }, + .event_names =3D { + "sched_switch", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { INVALID_STATE, sched_tss, INVALID_STATE }, + { sched_tss, INVALID_STATE, thread_tss }, + }, + .initial_state =3D thread_tss, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/tss/tss_trace.h b/kernel/trace/rv/mon= itors/tss/tss_trace.h new file mode 100644 index 000000000000..4619dbb50cc0 --- /dev/null +++ b/kernel/trace/rv/monitors/tss/tss_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_TSS +DEFINE_EVENT(event_da_monitor, event_tss, + TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), + TP_ARGS(state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor, error_tss, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_TSS */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index 5e65097423ba..f49e85ca97a1 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -58,6 +58,8 @@ DECLARE_EVENT_CLASS(error_da_monitor, ); =20 #include +#include +#include // Add new monitors based on CONFIG_DA_MON_EVENTS_IMPLICIT here =20 #endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */ diff --git a/tools/verification/models/sched/sco.dot b/tools/verification/m= odels/sched/sco.dot new file mode 100644 index 000000000000..20b0e3b449a6 --- /dev/null +++ b/tools/verification/models/sched/sco.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext] "scheduling_context"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_thread_con= text"}; + {node [shape =3D ellipse] "thread_context"}; + {node [shape =3D plaintext] "thread_context"}; + "__init_thread_context" -> "thread_context"; + "scheduling_context" [label =3D "scheduling_context"]; + "scheduling_context" -> "thread_context" [ label =3D "schedule_exit" ]; + "thread_context" [label =3D "thread_context", color =3D green3]; + "thread_context" -> "scheduling_context" [ label =3D "schedule_entry" ]; + "thread_context" -> "thread_context" [ label =3D "sched_set_state" ]; + { rank =3D min ; + "__init_thread_context"; + "thread_context"; + } +} diff --git a/tools/verification/models/sched/tss.dot b/tools/verification/m= odels/sched/tss.dot new file mode 100644 index 000000000000..7dfa1d9121bb --- /dev/null +++ b/tools/verification/models/sched/tss.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext] "sched"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_thread"}; + {node [shape =3D ellipse] "thread"}; + {node [shape =3D plaintext] "thread"}; + "__init_thread" -> "thread"; + "sched" [label =3D "sched"]; + "sched" -> "sched" [ label =3D "sched_switch" ]; + "sched" -> "thread" [ label =3D "schedule_exit" ]; + "thread" [label =3D "thread", color =3D green3]; + "thread" -> "sched" [ label =3D "schedule_entry" ]; + { rank =3D min ; + "__init_thread"; + "thread"; + } +} --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8086025A342 for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=RzAlI1OYyfF3ibNurTOoF36gESsS6Hs90CKHQ/AZJ6sLd//N3IiUfpcMBMRDAfiE4ZzhM1WusN1YmjCcz4RgV94NMXWtLMJ07NpoxZtFQJL8FFnICgZ0DnPe750SftTHI7Lmy/r407RxaLQMYuqjNiOLXXOTawHblVOUlBYJPlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=j/22C1ELCqdkl3uiT5TUGnj1yAILJowwAHWxIvGqDvw=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=gFtutG4PGKzfrOi3znBW7kNEBeKLhMdQDZxbOUrCd69LYHKCjq5bg3g/f1IAQjYdUCMxfUPgjIhyaadP2+bB2jhTUV1tLzQJWM+SXtInhqrcjqMIgyN5boGq3diyE3yBrpEyvNJyaBGmVdgszKqtud6ANKKMjs1ip03ZnyStJGQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 30233C4CEEF; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002P0N-2Ykr; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143502.464488872@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:40 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, Ingo Molnar , Peter Zijlstra Cc: Tomas Glozar , John Kacur , Juri Lelli , Clark Williams , Gabriele Monaco Subject: [for-next][PATCH 4/9] rv: Add snroc per-task monitor References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Add a per-task monitor as part of the sched model: * snroc: set non runnable on its own context Monitor to ensure set_state happens only in the respective task's conte= xt To: Ingo Molnar To: Peter Zijlstra Cc: Juri Lelli Cc: Ingo Molnar Cc: Peter Zijlstra Cc: John Kacur Cc: Clark Williams Link: https://lore.kernel.org/20250305140406.350227-5-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/Kconfig | 1 + kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/snroc/Kconfig | 14 ++++ kernel/trace/rv/monitors/snroc/snroc.c | 85 ++++++++++++++++++++ kernel/trace/rv/monitors/snroc/snroc.h | 47 +++++++++++ kernel/trace/rv/monitors/snroc/snroc_trace.h | 15 ++++ kernel/trace/rv/rv_trace.h | 1 + tools/verification/models/sched/snroc.dot | 18 +++++ 8 files changed, 182 insertions(+) create mode 100644 kernel/trace/rv/monitors/snroc/Kconfig create mode 100644 kernel/trace/rv/monitors/snroc/snroc.c create mode 100644 kernel/trace/rv/monitors/snroc/snroc.h create mode 100644 kernel/trace/rv/monitors/snroc/snroc_trace.h create mode 100644 tools/verification/models/sched/snroc.dot diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index 961ac1e487df..c4f1c0fc3abc 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -30,6 +30,7 @@ source "kernel/trace/rv/monitors/wwnr/Kconfig" source "kernel/trace/rv/monitors/sched/Kconfig" source "kernel/trace/rv/monitors/tss/Kconfig" source "kernel/trace/rv/monitors/sco/Kconfig" +source "kernel/trace/rv/monitors/snroc/Kconfig" # Add new monitors here =20 config RV_REACTORS diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index ef2a084ff310..6d11d6400ddd 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_RV_MON_WWNR) +=3D monitors/wwnr/wwnr.o obj-$(CONFIG_RV_MON_SCHED) +=3D monitors/sched/sched.o obj-$(CONFIG_RV_MON_TSS) +=3D monitors/tss/tss.o obj-$(CONFIG_RV_MON_SCO) +=3D monitors/sco/sco.o +obj-$(CONFIG_RV_MON_SNROC) +=3D monitors/snroc/snroc.o # Add new monitors here obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o diff --git a/kernel/trace/rv/monitors/snroc/Kconfig b/kernel/trace/rv/monit= ors/snroc/Kconfig new file mode 100644 index 000000000000..6e4365a2fea3 --- /dev/null +++ b/kernel/trace/rv/monitors/snroc/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SNROC + depends on RV + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_ID + bool "snroc monitor" + help + Monitor to ensure sched_set_state happens only in the respective task's= context. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/snroc/snroc.c b/kernel/trace/rv/monit= ors/snroc/snroc.c new file mode 100644 index 000000000000..bb1f60d55296 --- /dev/null +++ b/kernel/trace/rv/monitors/snroc/snroc.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "snroc" + +#include +#include +#include + +#include "snroc.h" + +static struct rv_monitor rv_snroc; +DECLARE_DA_MON_PER_TASK(snroc, unsigned char); + +static void handle_sched_set_state(void *data, struct task_struct *tsk, in= t state) +{ + da_handle_event_snroc(tsk, sched_set_state_snroc); +} + +static void handle_sched_switch(void *data, bool preempt, + struct task_struct *prev, + struct task_struct *next, + unsigned int prev_state) +{ + da_handle_start_event_snroc(prev, sched_switch_out_snroc); + da_handle_event_snroc(next, sched_switch_in_snroc); +} + +static int enable_snroc(void) +{ + int retval; + + retval =3D da_monitor_init_snroc(); + if (retval) + return retval; + + rv_attach_trace_probe("snroc", sched_set_state_tp, handle_sched_set_state= ); + rv_attach_trace_probe("snroc", sched_switch, handle_sched_switch); + + return 0; +} + +static void disable_snroc(void) +{ + rv_snroc.enabled =3D 0; + + rv_detach_trace_probe("snroc", sched_set_state_tp, handle_sched_set_state= ); + rv_detach_trace_probe("snroc", sched_switch, handle_sched_switch); + + da_monitor_destroy_snroc(); +} + +static struct rv_monitor rv_snroc =3D { + .name =3D "snroc", + .description =3D "set non runnable on its own context.", + .enable =3D enable_snroc, + .disable =3D disable_snroc, + .reset =3D da_monitor_reset_all_snroc, + .enabled =3D 0, +}; + +static int __init register_snroc(void) +{ + rv_register_monitor(&rv_snroc, &rv_sched); + return 0; +} + +static void __exit unregister_snroc(void) +{ + rv_unregister_monitor(&rv_snroc); +} + +module_init(register_snroc); +module_exit(unregister_snroc); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("snroc: set non runnable on its own context."); diff --git a/kernel/trace/rv/monitors/snroc/snroc.h b/kernel/trace/rv/monit= ors/snroc/snroc.h new file mode 100644 index 000000000000..c3650a2b1b10 --- /dev/null +++ b/kernel/trace/rv/monitors/snroc/snroc.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of snroc automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_snroc { + other_context_snroc =3D 0, + own_context_snroc, + state_max_snroc +}; + +#define INVALID_STATE state_max_snroc + +enum events_snroc { + sched_set_state_snroc =3D 0, + sched_switch_in_snroc, + sched_switch_out_snroc, + event_max_snroc +}; + +struct automaton_snroc { + char *state_names[state_max_snroc]; + char *event_names[event_max_snroc]; + unsigned char function[state_max_snroc][event_max_snroc]; + unsigned char initial_state; + bool final_states[state_max_snroc]; +}; + +static const struct automaton_snroc automaton_snroc =3D { + .state_names =3D { + "other_context", + "own_context" + }, + .event_names =3D { + "sched_set_state", + "sched_switch_in", + "sched_switch_out" + }, + .function =3D { + { INVALID_STATE, own_context_snroc, INVALID_STATE }, + { own_context_snroc, INVALID_STATE, other_context_snroc }, + }, + .initial_state =3D other_context_snroc, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/snroc/snroc_trace.h b/kernel/trace/rv= /monitors/snroc/snroc_trace.h new file mode 100644 index 000000000000..50114cef5122 --- /dev/null +++ b/kernel/trace/rv/monitors/snroc/snroc_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SNROC +DEFINE_EVENT(event_da_monitor_id, event_snroc, + TP_PROTO(int id, char *state, char *event, char *next_state, bool fi= nal_state), + TP_ARGS(id, state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor_id, error_snroc, + TP_PROTO(int id, char *state, char *event), + TP_ARGS(id, state, event)); +#endif /* CONFIG_RV_MON_SNROC */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index f49e85ca97a1..a533bc29cfdd 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -120,6 +120,7 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, ); =20 #include +#include // Add new monitors based on CONFIG_DA_MON_EVENTS_ID here =20 #endif /* CONFIG_DA_MON_EVENTS_ID */ diff --git a/tools/verification/models/sched/snroc.dot b/tools/verification= /models/sched/snroc.dot new file mode 100644 index 000000000000..8b71c32d4dca --- /dev/null +++ b/tools/verification/models/sched/snroc.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_other_cont= ext"}; + {node [shape =3D ellipse] "other_context"}; + {node [shape =3D plaintext] "other_context"}; + {node [shape =3D plaintext] "own_context"}; + "__init_other_context" -> "other_context"; + "other_context" [label =3D "other_context", color =3D green3]; + "other_context" -> "own_context" [ label =3D "sched_switch_in" ]; + "own_context" [label =3D "own_context"]; + "own_context" -> "other_context" [ label =3D "sched_switch_out" ]; + "own_context" -> "own_context" [ label =3D "sched_set_state" ]; + { rank =3D min ; + "__init_other_context"; + "other_context"; + } +} --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D4B725A350 for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=QUSfIIcq9v6JczrJ096mZ8xqLwx1PGBaINd1A4H8QYR01Gg5umLjZDt1tC7dy9dirBQ+oAnmmXyt71ZsHV6mejEgk3tLCxJmoZ/6ThdaBdBExMT+1buZPFt2UzftpRWWWdY/yps6qqzl6l1fpKlq7sPtY12NqHr8pgXC1BwkKMQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=7e60gu0eO3mw8otYhMRpWjIs4YbEbwNtySWQVpTRV4c=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=dx0L2PTr5BVgSem2pqP+a/BKGhlE+vf+YBNFIVwNDggxHS3eKnSy4yqU1LZSLPEdwzUgANc02qcupEJhoI5t5ZOM/UkBsN3K9jfxdI+Kykf+0Qszcd/iQ+7YQNKgbRpTvnsazTjhURgm7Q5f4oi7jxgA8AO39MLtStKyS7CSKyQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56837C4CEE4; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002P0r-3HZD; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143502.632940243@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:41 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, Ingo Molnar , Peter Zijlstra Cc: Tomas Glozar , John Kacur , Juri Lelli , Clark Williams , Gabriele Monaco Subject: [for-next][PATCH 5/9] rv: Add scpd, snep and sncid per-cpu monitors References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Add 3 per-cpu monitors as part of the sched model: * scpd: schedule called with preemption disabled Monitor to ensure schedule is called with preemption disabled * snep: schedule does not enable preempt Monitor to ensure schedule does not enable preempt * sncid: schedule not called with interrupt disabled Monitor to ensure schedule is not called with interrupt disabled To: Ingo Molnar To: Peter Zijlstra Cc: Juri Lelli Cc: Ingo Molnar Cc: Peter Zijlstra Cc: John Kacur Cc: Clark Williams Link: https://lore.kernel.org/20250305140406.350227-6-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- kernel/trace/rv/Kconfig | 3 + kernel/trace/rv/Makefile | 3 + kernel/trace/rv/monitors/scpd/Kconfig | 15 +++ kernel/trace/rv/monitors/scpd/scpd.c | 96 ++++++++++++++++++++ kernel/trace/rv/monitors/scpd/scpd.h | 49 ++++++++++ kernel/trace/rv/monitors/scpd/scpd_trace.h | 15 +++ kernel/trace/rv/monitors/sncid/Kconfig | 15 +++ kernel/trace/rv/monitors/sncid/sncid.c | 96 ++++++++++++++++++++ kernel/trace/rv/monitors/sncid/sncid.h | 49 ++++++++++ kernel/trace/rv/monitors/sncid/sncid_trace.h | 15 +++ kernel/trace/rv/monitors/snep/Kconfig | 15 +++ kernel/trace/rv/monitors/snep/snep.c | 96 ++++++++++++++++++++ kernel/trace/rv/monitors/snep/snep.h | 49 ++++++++++ kernel/trace/rv/monitors/snep/snep_trace.h | 15 +++ kernel/trace/rv/rv_trace.h | 3 + tools/verification/models/sched/scpd.dot | 18 ++++ tools/verification/models/sched/sncid.dot | 18 ++++ tools/verification/models/sched/snep.dot | 18 ++++ 18 files changed, 588 insertions(+) create mode 100644 kernel/trace/rv/monitors/scpd/Kconfig create mode 100644 kernel/trace/rv/monitors/scpd/scpd.c create mode 100644 kernel/trace/rv/monitors/scpd/scpd.h create mode 100644 kernel/trace/rv/monitors/scpd/scpd_trace.h create mode 100644 kernel/trace/rv/monitors/sncid/Kconfig create mode 100644 kernel/trace/rv/monitors/sncid/sncid.c create mode 100644 kernel/trace/rv/monitors/sncid/sncid.h create mode 100644 kernel/trace/rv/monitors/sncid/sncid_trace.h create mode 100644 kernel/trace/rv/monitors/snep/Kconfig create mode 100644 kernel/trace/rv/monitors/snep/snep.c create mode 100644 kernel/trace/rv/monitors/snep/snep.h create mode 100644 kernel/trace/rv/monitors/snep/snep_trace.h create mode 100644 tools/verification/models/sched/scpd.dot create mode 100644 tools/verification/models/sched/sncid.dot create mode 100644 tools/verification/models/sched/snep.dot diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index c4f1c0fc3abc..b39f36013ef2 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -31,6 +31,9 @@ source "kernel/trace/rv/monitors/sched/Kconfig" source "kernel/trace/rv/monitors/tss/Kconfig" source "kernel/trace/rv/monitors/sco/Kconfig" source "kernel/trace/rv/monitors/snroc/Kconfig" +source "kernel/trace/rv/monitors/scpd/Kconfig" +source "kernel/trace/rv/monitors/snep/Kconfig" +source "kernel/trace/rv/monitors/sncid/Kconfig" # Add new monitors here =20 config RV_REACTORS diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index 6d11d6400ddd..f9b2cd0483c3 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -9,6 +9,9 @@ obj-$(CONFIG_RV_MON_SCHED) +=3D monitors/sched/sched.o obj-$(CONFIG_RV_MON_TSS) +=3D monitors/tss/tss.o obj-$(CONFIG_RV_MON_SCO) +=3D monitors/sco/sco.o obj-$(CONFIG_RV_MON_SNROC) +=3D monitors/snroc/snroc.o +obj-$(CONFIG_RV_MON_SCPD) +=3D monitors/scpd/scpd.o +obj-$(CONFIG_RV_MON_SNEP) +=3D monitors/snep/snep.o +obj-$(CONFIG_RV_MON_SNCID) +=3D monitors/sncid/sncid.o # Add new monitors here obj-$(CONFIG_RV_REACTORS) +=3D rv_reactors.o obj-$(CONFIG_RV_REACT_PRINTK) +=3D reactor_printk.o diff --git a/kernel/trace/rv/monitors/scpd/Kconfig b/kernel/trace/rv/monito= rs/scpd/Kconfig new file mode 100644 index 000000000000..b9114fbf680f --- /dev/null +++ b/kernel/trace/rv/monitors/scpd/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SCPD + depends on RV + depends on PREEMPT_TRACER + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "scpd monitor" + help + Monitor to ensure schedule is called with preemption disabled. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/scpd/scpd.c b/kernel/trace/rv/monitor= s/scpd/scpd.c new file mode 100644 index 000000000000..cbdd6a5f8d7f --- /dev/null +++ b/kernel/trace/rv/monitors/scpd/scpd.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "scpd" + +#include +#include +#include +#include + +#include "scpd.h" + +static struct rv_monitor rv_scpd; +DECLARE_DA_MON_PER_CPU(scpd, unsigned char); + +static void handle_preempt_disable(void *data, unsigned long ip, unsigned = long parent_ip) +{ + da_handle_event_scpd(preempt_disable_scpd); +} + +static void handle_preempt_enable(void *data, unsigned long ip, unsigned l= ong parent_ip) +{ + da_handle_start_event_scpd(preempt_enable_scpd); +} + +static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +{ + da_handle_event_scpd(schedule_entry_scpd); +} + +static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +{ + da_handle_event_scpd(schedule_exit_scpd); +} + +static int enable_scpd(void) +{ + int retval; + + retval =3D da_monitor_init_scpd(); + if (retval) + return retval; + + rv_attach_trace_probe("scpd", preempt_disable, handle_preempt_disable); + rv_attach_trace_probe("scpd", preempt_enable, handle_preempt_enable); + rv_attach_trace_probe("scpd", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("scpd", sched_exit_tp, handle_schedule_exit); + + return 0; +} + +static void disable_scpd(void) +{ + rv_scpd.enabled =3D 0; + + rv_detach_trace_probe("scpd", preempt_disable, handle_preempt_disable); + rv_detach_trace_probe("scpd", preempt_enable, handle_preempt_enable); + rv_detach_trace_probe("scpd", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("scpd", sched_exit_tp, handle_schedule_exit); + + da_monitor_destroy_scpd(); +} + +static struct rv_monitor rv_scpd =3D { + .name =3D "scpd", + .description =3D "schedule called with preemption disabled.", + .enable =3D enable_scpd, + .disable =3D disable_scpd, + .reset =3D da_monitor_reset_all_scpd, + .enabled =3D 0, +}; + +static int __init register_scpd(void) +{ + rv_register_monitor(&rv_scpd, &rv_sched); + return 0; +} + +static void __exit unregister_scpd(void) +{ + rv_unregister_monitor(&rv_scpd); +} + +module_init(register_scpd); +module_exit(unregister_scpd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("scpd: schedule called with preemption disabled."); diff --git a/kernel/trace/rv/monitors/scpd/scpd.h b/kernel/trace/rv/monitor= s/scpd/scpd.h new file mode 100644 index 000000000000..295f735a5811 --- /dev/null +++ b/kernel/trace/rv/monitors/scpd/scpd.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of scpd automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_scpd { + cant_sched_scpd =3D 0, + can_sched_scpd, + state_max_scpd +}; + +#define INVALID_STATE state_max_scpd + +enum events_scpd { + preempt_disable_scpd =3D 0, + preempt_enable_scpd, + schedule_entry_scpd, + schedule_exit_scpd, + event_max_scpd +}; + +struct automaton_scpd { + char *state_names[state_max_scpd]; + char *event_names[event_max_scpd]; + unsigned char function[state_max_scpd][event_max_scpd]; + unsigned char initial_state; + bool final_states[state_max_scpd]; +}; + +static const struct automaton_scpd automaton_scpd =3D { + .state_names =3D { + "cant_sched", + "can_sched" + }, + .event_names =3D { + "preempt_disable", + "preempt_enable", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { can_sched_scpd, INVALID_STATE, INVALID_STATE, INVALID_= STATE }, + { INVALID_STATE, cant_sched_scpd, can_sched_scpd, can_sch= ed_scpd }, + }, + .initial_state =3D cant_sched_scpd, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/scpd/scpd_trace.h b/kernel/trace/rv/m= onitors/scpd/scpd_trace.h new file mode 100644 index 000000000000..6b0f4aa4732e --- /dev/null +++ b/kernel/trace/rv/monitors/scpd/scpd_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SCPD +DEFINE_EVENT(event_da_monitor, event_scpd, + TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), + TP_ARGS(state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor, error_scpd, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_SCPD */ diff --git a/kernel/trace/rv/monitors/sncid/Kconfig b/kernel/trace/rv/monit= ors/sncid/Kconfig new file mode 100644 index 000000000000..76bcfef4fd10 --- /dev/null +++ b/kernel/trace/rv/monitors/sncid/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SNCID + depends on RV + depends on IRQSOFF_TRACER + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "sncid monitor" + help + Monitor to ensure schedule is not called with interrupt disabled. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/sncid/sncid.c b/kernel/trace/rv/monit= ors/sncid/sncid.c new file mode 100644 index 000000000000..f5037cd6214c --- /dev/null +++ b/kernel/trace/rv/monitors/sncid/sncid.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "sncid" + +#include +#include +#include +#include + +#include "sncid.h" + +static struct rv_monitor rv_sncid; +DECLARE_DA_MON_PER_CPU(sncid, unsigned char); + +static void handle_irq_disable(void *data, unsigned long ip, unsigned long= parent_ip) +{ + da_handle_event_sncid(irq_disable_sncid); +} + +static void handle_irq_enable(void *data, unsigned long ip, unsigned long = parent_ip) +{ + da_handle_start_event_sncid(irq_enable_sncid); +} + +static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +{ + da_handle_start_event_sncid(schedule_entry_sncid); +} + +static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +{ + da_handle_start_event_sncid(schedule_exit_sncid); +} + +static int enable_sncid(void) +{ + int retval; + + retval =3D da_monitor_init_sncid(); + if (retval) + return retval; + + rv_attach_trace_probe("sncid", irq_disable, handle_irq_disable); + rv_attach_trace_probe("sncid", irq_enable, handle_irq_enable); + rv_attach_trace_probe("sncid", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("sncid", sched_exit_tp, handle_schedule_exit); + + return 0; +} + +static void disable_sncid(void) +{ + rv_sncid.enabled =3D 0; + + rv_detach_trace_probe("sncid", irq_disable, handle_irq_disable); + rv_detach_trace_probe("sncid", irq_enable, handle_irq_enable); + rv_detach_trace_probe("sncid", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("sncid", sched_exit_tp, handle_schedule_exit); + + da_monitor_destroy_sncid(); +} + +static struct rv_monitor rv_sncid =3D { + .name =3D "sncid", + .description =3D "schedule not called with interrupt disabled.", + .enable =3D enable_sncid, + .disable =3D disable_sncid, + .reset =3D da_monitor_reset_all_sncid, + .enabled =3D 0, +}; + +static int __init register_sncid(void) +{ + rv_register_monitor(&rv_sncid, &rv_sched); + return 0; +} + +static void __exit unregister_sncid(void) +{ + rv_unregister_monitor(&rv_sncid); +} + +module_init(register_sncid); +module_exit(unregister_sncid); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("sncid: schedule not called with interrupt disabled."); diff --git a/kernel/trace/rv/monitors/sncid/sncid.h b/kernel/trace/rv/monit= ors/sncid/sncid.h new file mode 100644 index 000000000000..21304725142b --- /dev/null +++ b/kernel/trace/rv/monitors/sncid/sncid.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of sncid automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_sncid { + can_sched_sncid =3D 0, + cant_sched_sncid, + state_max_sncid +}; + +#define INVALID_STATE state_max_sncid + +enum events_sncid { + irq_disable_sncid =3D 0, + irq_enable_sncid, + schedule_entry_sncid, + schedule_exit_sncid, + event_max_sncid +}; + +struct automaton_sncid { + char *state_names[state_max_sncid]; + char *event_names[event_max_sncid]; + unsigned char function[state_max_sncid][event_max_sncid]; + unsigned char initial_state; + bool final_states[state_max_sncid]; +}; + +static const struct automaton_sncid automaton_sncid =3D { + .state_names =3D { + "can_sched", + "cant_sched" + }, + .event_names =3D { + "irq_disable", + "irq_enable", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { cant_sched_sncid, INVALID_STATE, can_sched_sncid, can_sched_sncid }, + { INVALID_STATE, can_sched_sncid, INVALID_STATE, INVALID_STATE }, + }, + .initial_state =3D can_sched_sncid, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/sncid/sncid_trace.h b/kernel/trace/rv= /monitors/sncid/sncid_trace.h new file mode 100644 index 000000000000..3ce42a57671d --- /dev/null +++ b/kernel/trace/rv/monitors/sncid/sncid_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SNCID +DEFINE_EVENT(event_da_monitor, event_sncid, + TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), + TP_ARGS(state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor, error_sncid, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_SNCID */ diff --git a/kernel/trace/rv/monitors/snep/Kconfig b/kernel/trace/rv/monito= rs/snep/Kconfig new file mode 100644 index 000000000000..77527f971232 --- /dev/null +++ b/kernel/trace/rv/monitors/snep/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_SNEP + depends on RV + depends on PREEMPT_TRACER + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "snep monitor" + help + Monitor to ensure schedule does not enable preempt. + This monitor is part of the sched monitors collection. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/snep/snep.c b/kernel/trace/rv/monitor= s/snep/snep.c new file mode 100644 index 000000000000..0076ba6d7ea4 --- /dev/null +++ b/kernel/trace/rv/monitors/snep/snep.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "snep" + +#include +#include +#include +#include + +#include "snep.h" + +static struct rv_monitor rv_snep; +DECLARE_DA_MON_PER_CPU(snep, unsigned char); + +static void handle_preempt_disable(void *data, unsigned long ip, unsigned = long parent_ip) +{ + da_handle_start_event_snep(preempt_disable_snep); +} + +static void handle_preempt_enable(void *data, unsigned long ip, unsigned l= ong parent_ip) +{ + da_handle_start_event_snep(preempt_enable_snep); +} + +static void handle_schedule_entry(void *data, bool preempt, unsigned long = ip) +{ + da_handle_event_snep(schedule_entry_snep); +} + +static void handle_schedule_exit(void *data, bool is_switch, unsigned long= ip) +{ + da_handle_start_event_snep(schedule_exit_snep); +} + +static int enable_snep(void) +{ + int retval; + + retval =3D da_monitor_init_snep(); + if (retval) + return retval; + + rv_attach_trace_probe("snep", preempt_disable, handle_preempt_disable); + rv_attach_trace_probe("snep", preempt_enable, handle_preempt_enable); + rv_attach_trace_probe("snep", sched_entry_tp, handle_schedule_entry); + rv_attach_trace_probe("snep", sched_exit_tp, handle_schedule_exit); + + return 0; +} + +static void disable_snep(void) +{ + rv_snep.enabled =3D 0; + + rv_detach_trace_probe("snep", preempt_disable, handle_preempt_disable); + rv_detach_trace_probe("snep", preempt_enable, handle_preempt_enable); + rv_detach_trace_probe("snep", sched_entry_tp, handle_schedule_entry); + rv_detach_trace_probe("snep", sched_exit_tp, handle_schedule_exit); + + da_monitor_destroy_snep(); +} + +static struct rv_monitor rv_snep =3D { + .name =3D "snep", + .description =3D "schedule does not enable preempt.", + .enable =3D enable_snep, + .disable =3D disable_snep, + .reset =3D da_monitor_reset_all_snep, + .enabled =3D 0, +}; + +static int __init register_snep(void) +{ + rv_register_monitor(&rv_snep, &rv_sched); + return 0; +} + +static void __exit unregister_snep(void) +{ + rv_unregister_monitor(&rv_snep); +} + +module_init(register_snep); +module_exit(unregister_snep); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("snep: schedule does not enable preempt."); diff --git a/kernel/trace/rv/monitors/snep/snep.h b/kernel/trace/rv/monitor= s/snep/snep.h new file mode 100644 index 000000000000..6d16b9ad931e --- /dev/null +++ b/kernel/trace/rv/monitors/snep/snep.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of snep automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_snep { + non_scheduling_context_snep =3D 0, + scheduling_contex_snep, + state_max_snep +}; + +#define INVALID_STATE state_max_snep + +enum events_snep { + preempt_disable_snep =3D 0, + preempt_enable_snep, + schedule_entry_snep, + schedule_exit_snep, + event_max_snep +}; + +struct automaton_snep { + char *state_names[state_max_snep]; + char *event_names[event_max_snep]; + unsigned char function[state_max_snep][event_max_snep]; + unsigned char initial_state; + bool final_states[state_max_snep]; +}; + +static const struct automaton_snep automaton_snep =3D { + .state_names =3D { + "non_scheduling_context", + "scheduling_contex" + }, + .event_names =3D { + "preempt_disable", + "preempt_enable", + "schedule_entry", + "schedule_exit" + }, + .function =3D { + { non_scheduling_context_snep, non_scheduling_context_snep, scheduling_c= ontex_snep, INVALID_STATE }, + { INVALID_STATE, INVALID_STATE, INV= ALID_STATE, non_scheduling_context_snep }, + }, + .initial_state =3D non_scheduling_context_snep, + .final_states =3D { 1, 0 }, +}; diff --git a/kernel/trace/rv/monitors/snep/snep_trace.h b/kernel/trace/rv/m= onitors/snep/snep_trace.h new file mode 100644 index 000000000000..01aad49a949a --- /dev/null +++ b/kernel/trace/rv/monitors/snep/snep_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_SNEP +DEFINE_EVENT(event_da_monitor, event_snep, + TP_PROTO(char *state, char *event, char *next_state, bool final_stat= e), + TP_ARGS(state, event, next_state, final_state)); + +DEFINE_EVENT(error_da_monitor, error_snep, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_SNEP */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index a533bc29cfdd..422b75f58891 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -60,6 +60,9 @@ DECLARE_EVENT_CLASS(error_da_monitor, #include #include #include +#include +#include +#include // Add new monitors based on CONFIG_DA_MON_EVENTS_IMPLICIT here =20 #endif /* CONFIG_DA_MON_EVENTS_IMPLICIT */ diff --git a/tools/verification/models/sched/scpd.dot b/tools/verification/= models/sched/scpd.dot new file mode 100644 index 000000000000..340413896765 --- /dev/null +++ b/tools/verification/models/sched/scpd.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext] "can_sched"}; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_cant_sched= "}; + {node [shape =3D ellipse] "cant_sched"}; + {node [shape =3D plaintext] "cant_sched"}; + "__init_cant_sched" -> "cant_sched"; + "can_sched" [label =3D "can_sched"]; + "can_sched" -> "can_sched" [ label =3D "schedule_entry\nschedule_exit" ]; + "can_sched" -> "cant_sched" [ label =3D "preempt_enable" ]; + "cant_sched" [label =3D "cant_sched", color =3D green3]; + "cant_sched" -> "can_sched" [ label =3D "preempt_disable" ]; + { rank =3D min ; + "__init_cant_sched"; + "cant_sched"; + } +} diff --git a/tools/verification/models/sched/sncid.dot b/tools/verification= /models/sched/sncid.dot new file mode 100644 index 000000000000..072851721b50 --- /dev/null +++ b/tools/verification/models/sched/sncid.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_can_sched"= }; + {node [shape =3D ellipse] "can_sched"}; + {node [shape =3D plaintext] "can_sched"}; + {node [shape =3D plaintext] "cant_sched"}; + "__init_can_sched" -> "can_sched"; + "can_sched" [label =3D "can_sched", color =3D green3]; + "can_sched" -> "can_sched" [ label =3D "schedule_entry\nschedule_exit" ]; + "can_sched" -> "cant_sched" [ label =3D "irq_disable" ]; + "cant_sched" [label =3D "cant_sched"]; + "cant_sched" -> "can_sched" [ label =3D "irq_enable" ]; + { rank =3D min ; + "__init_can_sched"; + "can_sched"; + } +} diff --git a/tools/verification/models/sched/snep.dot b/tools/verification/= models/sched/snep.dot new file mode 100644 index 000000000000..fe1300e93f21 --- /dev/null +++ b/tools/verification/models/sched/snep.dot @@ -0,0 +1,18 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_non_schedu= ling_context"}; + {node [shape =3D ellipse] "non_scheduling_context"}; + {node [shape =3D plaintext] "non_scheduling_context"}; + {node [shape =3D plaintext] "scheduling_contex"}; + "__init_non_scheduling_context" -> "non_scheduling_context"; + "non_scheduling_context" [label =3D "non_scheduling_context", color =3D g= reen3]; + "non_scheduling_context" -> "non_scheduling_context" [ label =3D "preempt= _disable\npreempt_enable" ]; + "non_scheduling_context" -> "scheduling_contex" [ label =3D "schedule_ent= ry" ]; + "scheduling_contex" [label =3D "scheduling_contex"]; + "scheduling_contex" -> "non_scheduling_context" [ label =3D "schedule_exi= t" ]; + { rank =3D min ; + "__init_non_scheduling_context"; + "non_scheduling_context"; + } +} --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A83F425A352 for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; cv=none; b=M/Zv1+NZSKOJjJZkhfVPK1VJzGnfKyCPHcn0oAaDOd1tDz2RBNdgJn/l7UdhiTKbmGKHAJ3Myuf74fxWa6xiefaZtoM4NiTnhlxWuQu9NlUpv6NCBx/ln+/TAyhc3JQWdZDfFCzf6pUD9zoI9IXaawLjYwlfTsTuXaM+WdMW49I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913258; c=relaxed/simple; bh=op4bZHNgFkTMeMbsYcAkob/xeuuEeaMPRJ0DS4GK3Ac=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=kObcY9ITxywpYBc5J5QNhytAWKlxO2JAz9DpoNwg34KWqxWDpLVVkxVqaZ+pKgfzJjfSOHpVzG/YH6YWLS0uJkGHOPl6aW6x39oVErSor9G9a1TRne2I/1pWuZvgW06I3kLprGwCXm0KwrLmnly4krbvcyt3otaemBwba+fsQq4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 837CAC4AF09; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Ms-00000002P1L-4066; Tue, 25 Mar 2025 10:35:02 -0400 Message-ID: <20250325143502.803979565@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:42 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Juri Lelli , Gabriele Monaco Subject: [for-next][PATCH 6/9] tools/rv: Add support for nested monitors References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco RV now supports nested monitors, this functionality requires a container monitor, which has virtually no functionality besides holding other monitors, and nested monitors, that have a container as parent. Nested monitors' sysfs folders are physically nested in the container's folder, and they are listed in the available_monitors file with the notation container:monitor. These changes go against the assumption that each line in the available_monitors file correspond to a folder in the rv directory, breaking the functionality of the rv tool. Add support for nested containers in the rv userspace tool, indenting nested monitors while listed and allowing both the notation with and without container name, which are equivalent: # rv list mon1 mon2 container: - nested1 - nested2 ## notation with container name # rv mon container:nested1 ## notation without container name # rv mon nested1 Either way, enabling a nested monitor is the same as enabling any other non-nested monitor. Selecting the container with rv mon enables all the nested monitors, if -t is passed, the trace also includes the monitor name next to the event: # rv mon nested1 -t -0 [004] event state1 x event -> state2 -0 [004] error event not expected in state2 # rv mon sched -t -0 [004] event_nested1 state1 x event -> state2 -0 [004] error_nested1 event not expected in state2 Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Link: https://lore.kernel.org/20250305140406.350227-7-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- tools/verification/rv/include/rv.h | 1 + tools/verification/rv/src/in_kernel.c | 226 ++++++++++++++++++++------ 2 files changed, 179 insertions(+), 48 deletions(-) diff --git a/tools/verification/rv/include/rv.h b/tools/verification/rv/inc= lude/rv.h index 0cab1037a98f..6f668eb266cb 100644 --- a/tools/verification/rv/include/rv.h +++ b/tools/verification/rv/include/rv.h @@ -7,6 +7,7 @@ struct monitor { char name[MAX_DA_NAME_LEN]; char desc[MAX_DESCRIPTION]; int enabled; + int nested; }; =20 int should_stop(void); diff --git a/tools/verification/rv/src/in_kernel.c b/tools/verification/rv/= src/in_kernel.c index f2bbc75a76f4..032b85101929 100644 --- a/tools/verification/rv/src/in_kernel.c +++ b/tools/verification/rv/src/in_kernel.c @@ -6,15 +6,18 @@ */ #include #include +#include #include #include #include +#include =20 #include #include #include =20 static int config_has_id; +static int config_is_container; static int config_my_pid; static int config_trace; =20 @@ -44,6 +47,51 @@ static int __ikm_read_enable(char *monitor_name) return enabled; } =20 +/* + * __ikm_find_monitor - find the full name of a possibly nested module + * + * __does not log errors. + * + * Returns 1 if we found the monitor, -1 on error and 0 if it does not exi= st. + * The string out_name is populated with the full name, which can be + * equal to monitor_name or container/monitor_name if nested + */ +static int __ikm_find_monitor_name(char *monitor_name, char *out_name) +{ + char *available_monitors, container[MAX_DA_NAME_LEN+1], *cursor, *end; + int retval =3D 1; + + available_monitors =3D tracefs_instance_file_read(NULL, "rv/available_mon= itors", NULL); + if (!available_monitors) + return -1; + + cursor =3D strstr(available_monitors, monitor_name); + if (!cursor) { + retval =3D 0; + goto out_free; + } + + for (; cursor > available_monitors; cursor--) + if (*(cursor-1) =3D=3D '\n') + break; + end =3D strstr(cursor, "\n"); + memcpy(out_name, cursor, end-cursor); + out_name[end-cursor] =3D '\0'; + + cursor =3D strstr(out_name, ":"); + if (cursor) + *cursor =3D '/'; + else { + sprintf(container, "%s:", monitor_name); + if (strstr(available_monitors, container)) + config_is_container =3D 1; + } + +out_free: + free(available_monitors); + return retval; +} + /* * ikm_read_enable - reads monitor's enable status * @@ -137,7 +185,17 @@ static char *ikm_read_desc(char *monitor_name) static int ikm_fill_monitor_definition(char *name, struct monitor *ikm) { int enabled; - char *desc; + char *desc, *nested_name; + + nested_name =3D strstr(name, ":"); + if (nested_name) { + *nested_name =3D '/'; + ++nested_name; + ikm->nested =3D 1; + } else { + nested_name =3D name; + ikm->nested =3D 0; + } =20 enabled =3D ikm_read_enable(name); if (enabled < 0) { @@ -151,7 +209,7 @@ static int ikm_fill_monitor_definition(char *name, stru= ct monitor *ikm) return -1; } =20 - strncpy(ikm->name, name, MAX_DA_NAME_LEN); + strncpy(ikm->name, nested_name, MAX_DA_NAME_LEN); ikm->enabled =3D enabled; strncpy(ikm->desc, desc, MAX_DESCRIPTION); =20 @@ -273,7 +331,7 @@ static int ikm_has_id(char *monitor_name) int ikm_list_monitors(void) { char *available_monitors; - struct monitor ikm; + struct monitor ikm =3D {0}; char *curr, *next; int retval; =20 @@ -293,7 +351,9 @@ int ikm_list_monitors(void) if (retval) err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr); =20 - printf("%-24s %s %s\n", ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF= ]"); + printf("%s%-*s %s %s\n", ikm.nested ? " - " : "", + ikm.nested ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN, + ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]"); curr =3D ++next; =20 } while (strlen(curr)); @@ -343,11 +403,11 @@ ikm_event_handler(struct trace_seq *s, struct tep_rec= ord *record, unsigned long long final_state; unsigned long long pid; unsigned long long id; - int cpu =3D record->cpu; int val; + bool missing_id; =20 if (config_has_id) - tep_get_field_val(s, trace_event, "id", record, &id, 1); + missing_id =3D tep_get_field_val(s, trace_event, "id", record, &id, 1); =20 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1); =20 @@ -356,12 +416,21 @@ ikm_event_handler(struct trace_seq *s, struct tep_rec= ord *record, else if (config_my_pid && (config_my_pid =3D=3D pid)) return 0; =20 - tep_print_event(trace_event->tep, s, record, "%16s-%-8d ", TEP_PRINT_COMM= , TEP_PRINT_PID); + tep_print_event(trace_event->tep, s, record, "%16s-%-8d [%.3d] ", + TEP_PRINT_COMM, TEP_PRINT_PID, TEP_PRINT_CPU); =20 - trace_seq_printf(s, "[%.3d] event ", cpu); + if (config_is_container) + tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME); + else + trace_seq_printf(s, "event "); =20 - if (config_has_id) - trace_seq_printf(s, "%8llu ", id); + if (config_has_id) { + if (missing_id) + /* placeholder if we are dealing with a mixed-type container*/ + trace_seq_printf(s, " "); + else + trace_seq_printf(s, "%8llu ", id); + } =20 state =3D tep_get_field_raw(s, trace_event, "state", record, &val, 0); event =3D tep_get_field_raw(s, trace_event, "event", record, &val, 0); @@ -394,9 +463,10 @@ ikm_error_handler(struct trace_seq *s, struct tep_reco= rd *record, int cpu =3D record->cpu; char *state, *event; int val; + bool missing_id; =20 if (config_has_id) - tep_get_field_val(s, trace_event, "id", record, &id, 1); + missing_id =3D tep_get_field_val(s, trace_event, "id", record, &id, 1); =20 tep_get_common_field_val(s, trace_event, "common_pid", record, &pid, 1); =20 @@ -405,10 +475,20 @@ ikm_error_handler(struct trace_seq *s, struct tep_rec= ord *record, else if (config_my_pid =3D=3D pid) return 0; =20 - trace_seq_printf(s, "%8lld [%03d] error ", pid, cpu); + trace_seq_printf(s, "%8lld [%03d] ", pid, cpu); =20 - if (config_has_id) - trace_seq_printf(s, "%8llu ", id); + if (config_is_container) + tep_print_event(trace_event->tep, s, record, "%s ", TEP_PRINT_NAME); + else + trace_seq_printf(s, "error "); + + if (config_has_id) { + if (missing_id) + /* placeholder if we are dealing with a mixed-type container*/ + trace_seq_printf(s, " "); + else + trace_seq_printf(s, "%8llu ", id); + } =20 state =3D tep_get_field_raw(s, trace_event, "state", record, &val, 0); event =3D tep_get_field_raw(s, trace_event, "event", record, &val, 0); @@ -421,6 +501,64 @@ ikm_error_handler(struct trace_seq *s, struct tep_reco= rd *record, return 0; } =20 +static int ikm_enable_trace_events(char *monitor_name, struct trace_instan= ce *inst) +{ + char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' =3D 7 */ + int retval; + + snprintf(event, sizeof(event), "event_%s", monitor_name); + retval =3D tracefs_event_enable(inst->inst, "rv", event); + if (retval) + return -1; + + tep_register_event_handler(inst->tep, -1, "rv", event, + ikm_event_handler, NULL); + + snprintf(event, sizeof(event), "error_%s", monitor_name); + retval =3D tracefs_event_enable(inst->inst, "rv", event); + if (retval) + return -1; + + tep_register_event_handler(inst->tep, -1, "rv", event, + ikm_error_handler, NULL); + + /* set if at least 1 monitor has id in case of a container */ + config_has_id =3D ikm_has_id(monitor_name); + if (config_has_id < 0) + return -1; + + + return 0; +} + +static int ikm_enable_trace_container(char *monitor_name, + struct trace_instance *inst) +{ + DIR *dp; + char *abs_path, rv_path[MAX_PATH]; + struct dirent *ep; + int retval =3D 0; + + snprintf(rv_path, MAX_PATH, "rv/monitors/%s", monitor_name); + abs_path =3D tracefs_instance_get_file(NULL, rv_path); + if (!abs_path) + return -1; + dp =3D opendir(abs_path); + if (!dp) + goto out_free; + + while (!retval && (ep =3D readdir(dp))) { + if (ep->d_type !=3D DT_DIR || ep->d_name[0] =3D=3D '.') + continue; + retval =3D ikm_enable_trace_events(ep->d_name, inst); + } + + closedir(dp); +out_free: + free(abs_path); + return retval; +} + /* * ikm_setup_trace_instance - set up a tracing instance to collect data * @@ -430,19 +568,12 @@ ikm_error_handler(struct trace_seq *s, struct tep_rec= ord *record, */ static struct trace_instance *ikm_setup_trace_instance(char *monitor_name) { - char event[MAX_DA_NAME_LEN + 7]; /* max(error_,event_) + '0' =3D 7 */ struct trace_instance *inst; int retval; =20 if (!config_trace) return NULL; =20 - config_has_id =3D ikm_has_id(monitor_name); - if (config_has_id < 0) { - err_msg("ikm: failed to read monitor %s event format\n", monitor_name); - goto out_err; - } - /* alloc data */ inst =3D calloc(1, sizeof(*inst)); if (!inst) { @@ -454,23 +585,13 @@ static struct trace_instance *ikm_setup_trace_instanc= e(char *monitor_name) if (retval) goto out_free; =20 - /* enable events */ - snprintf(event, sizeof(event), "event_%s", monitor_name); - retval =3D tracefs_event_enable(inst->inst, "rv", event); - if (retval) - goto out_inst; - - tep_register_event_handler(inst->tep, -1, "rv", event, - ikm_event_handler, NULL); - - snprintf(event, sizeof(event), "error_%s", monitor_name); - retval =3D tracefs_event_enable(inst->inst, "rv", event); + if (config_is_container) + retval =3D ikm_enable_trace_container(monitor_name, inst); + else + retval =3D ikm_enable_trace_events(monitor_name, inst); if (retval) goto out_inst; =20 - tep_register_event_handler(inst->tep, -1, "rv", event, - ikm_error_handler, NULL); - /* ready to enable */ tracefs_trace_on(inst->inst); =20 @@ -633,32 +754,41 @@ static int parse_arguments(char *monitor_name, int ar= gc, char **argv) int ikm_run_monitor(char *monitor_name, int argc, char **argv) { struct trace_instance *inst =3D NULL; + char *nested_name, full_name[2*MAX_DA_NAME_LEN]; int retval; =20 - /* - * Check if monitor exists by seeing it is enabled. - */ - retval =3D __ikm_read_enable(monitor_name); - if (retval < 0) + nested_name =3D strstr(monitor_name, ":"); + if (nested_name) + ++nested_name; + else + nested_name =3D monitor_name; + + retval =3D __ikm_find_monitor_name(monitor_name, full_name); + if (!retval) return 0; + if (retval < 0) { + err_msg("ikm: error finding monitor %s\n", nested_name); + return -1; + } =20 + retval =3D __ikm_read_enable(full_name); if (retval) { - err_msg("ikm: monitor %s (in-kernel) is already enabled\n", monitor_name= ); + err_msg("ikm: monitor %s (in-kernel) is already enabled\n", nested_name); return -1; } =20 /* we should be good to go */ - retval =3D parse_arguments(monitor_name, argc, argv); + retval =3D parse_arguments(full_name, argc, argv); if (retval) - ikm_usage(1, monitor_name, "ikm: failed parsing arguments"); + ikm_usage(1, nested_name, "ikm: failed parsing arguments"); =20 if (config_trace) { - inst =3D ikm_setup_trace_instance(monitor_name); + inst =3D ikm_setup_trace_instance(nested_name); if (!inst) return -1; } =20 - retval =3D ikm_enable(monitor_name); + retval =3D ikm_enable(full_name); if (retval < 0) goto out_free_instance; =20 @@ -682,17 +812,17 @@ int ikm_run_monitor(char *monitor_name, int argc, cha= r **argv) sleep(1); } =20 - ikm_disable(monitor_name); + ikm_disable(full_name); ikm_destroy_trace_instance(inst); =20 if (config_reactor && config_initial_reactor) - ikm_write_reactor(monitor_name, config_initial_reactor); + ikm_write_reactor(full_name, config_initial_reactor); =20 return 1; =20 out_free_instance: ikm_destroy_trace_instance(inst); if (config_reactor && config_initial_reactor) - ikm_write_reactor(monitor_name, config_initial_reactor); + ikm_write_reactor(full_name, config_initial_reactor); return -1; } --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 21E1425A63F for ; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; cv=none; b=r4Jt4Dfbr0CfQbWJQZbyMJMWCZq+eYzQCSiZKK9c/TRuscii+NLZ1ljJnw/2vIcecunR+GdMQYa8SOvIxcwUFDWSixAEispl2c+OFQkgtzqgvpSNWzsBnvP5Q8j2hF/uLY2f3HozZJPw4/QoLKJOeP1RHZceYQYYpc+RP+vwlcw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; c=relaxed/simple; bh=p1UvD5es+f6vd4FWSW5Osq7Jzz0sqwLEu4VL8BAEl+0=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=EGFSDCXPFmI3cfuJd+G6/HM9Es5eknKXhNnrpw6JL1akjaLIwvhPVTUmNDWrLIAMvI60tdHsI0v5uLNNbNz4zTRiKF0B7/hYgrxk4WgVtlP4mIU8lEd6HRJbISUUrhXia7gE0qtoA06UAMw03V4JtOVIF1CYxpk1f8n2Nsq/Gqo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id ABF6CC4CEEF; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Mt-00000002P1q-0VHr; Tue, 25 Mar 2025 10:35:03 -0400 Message-ID: <20250325143502.973810949@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:43 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Juri Lelli , Gabriele Monaco Subject: [for-next][PATCH 7/9] verification/dot2k: Add support for nested monitors References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco RV now supports nested monitors, this functionality requires a container monitor, which has virtually no functionality besides holding other monitors, and nested monitors, that have a container as parent. Add the -p flag to pass a parent to a monitor, this sets it up while registering the monitor and adds necessary includes and configurations. Add the -c flag to create a container, since containers are empty, we don't allow supplying a dot model or a monitor type, the template is also different since functions to enable and disable the monitor are not defined, nor any tracepoint. The generated header file only allows to include the rv_monitor structure in children monitors. Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Link: https://lore.kernel.org/20250305140406.350227-8-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- tools/verification/dot2/dot2k | 27 ++++--- tools/verification/dot2/dot2k.py | 79 +++++++++++++++---- .../verification/dot2/dot2k_templates/Kconfig | 1 + .../verification/dot2/dot2k_templates/main.c | 4 +- .../dot2/dot2k_templates/main_container.c | 38 +++++++++ .../dot2/dot2k_templates/main_container.h | 3 + 6 files changed, 125 insertions(+), 27 deletions(-) create mode 100644 tools/verification/dot2/dot2k_templates/main_container.c create mode 100644 tools/verification/dot2/dot2k_templates/main_container.h diff --git a/tools/verification/dot2/dot2k b/tools/verification/dot2/dot2k index 559ba191a1f6..767064f415e7 100644 --- a/tools/verification/dot2/dot2k +++ b/tools/verification/dot2/dot2k @@ -11,22 +11,30 @@ if __name__ =3D=3D '__main__': from dot2.dot2k import dot2k import argparse - import ntpath - import os - import platform import sys =20 + def is_container(): + """Should work even before parsing the arguments""" + return "-c" in sys.argv or "--container" in sys.argv + parser =3D argparse.ArgumentParser(description=3D'transform .dot file = into kernel rv monitor') - parser.add_argument('-d', "--dot", dest=3D"dot_file", required=3DTrue) - parser.add_argument('-t', "--monitor_type", dest=3D"monitor_type", req= uired=3DTrue) - parser.add_argument('-n', "--model_name", dest=3D"model_name", require= d=3DFalse) + parser.add_argument('-d', "--dot", dest=3D"dot_file", required=3Dnot i= s_container()) + parser.add_argument('-t', "--monitor_type", dest=3D"monitor_type", req= uired=3Dnot is_container(), + help=3Df"Available options: {', '.join(dot2k.monit= or_types.keys())}") + parser.add_argument('-n', "--model_name", dest=3D"model_name", require= d=3Dis_container()) parser.add_argument("-D", "--description", dest=3D"description", requi= red=3DFalse) parser.add_argument("-a", "--auto_patch", dest=3D"auto_patch", action=3D"store_true", required=3DFalse, help=3D"Patch the kernel in place") + parser.add_argument("-p", "--parent", dest=3D"parent", + required=3DFalse, help=3D"Create a monitor nested = to parent") + parser.add_argument("-c", "--container", dest=3D"container", + action=3D"store_true", required=3DFalse, + help=3D"Create an empty monitor to be used as a co= ntainer") params =3D parser.parse_args() =20 - print("Opening and parsing the dot file %s" % params.dot_file) + if not is_container(): + print("Opening and parsing the dot file %s" % params.dot_file) try: monitor=3Ddot2k(params.dot_file, params.monitor_type, vars(params)) except Exception as e: @@ -37,8 +45,9 @@ if __name__ =3D=3D '__main__': print("Writing the monitor into the directory %s" % monitor.name) monitor.print_files() print("Almost done, checklist") - print(" - Edit the %s/%s.c to add the instrumentation" % (monitor.nam= e, monitor.name)) - print(monitor.fill_tracepoint_tooltip()) + 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/dot= 2k.py index 153cc14bcca4..745d35a4a379 100644 --- a/tools/verification/dot2/dot2k.py +++ b/tools/verification/dot2/dot2k.py @@ -19,16 +19,31 @@ class dot2k(Dot2c): monitor_type =3D "per_cpu" =20 def __init__(self, file_path, MonitorType, extra_params=3D{}): - super().__init__(file_path, extra_params.get("model_name")) - - self.monitor_type =3D self.monitor_types.get(MonitorType) - if self.monitor_type is None: - raise ValueError("Unknown monitor type: %s" % MonitorType) - - self.monitor_type =3D MonitorType + self.container =3D extra_params.get("container") + self.parent =3D extra_params.get("parent") self.__fill_rv_templates_dir() - self.main_c =3D self.__read_file(self.monitor_templates_dir + "mai= n.c") - self.trace_h =3D self.__read_file(self.monitor_templates_dir + "tr= ace.h") + + 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 t= ype") + if self.parent: + raise ValueError("A container cannot have a parent") + self.name =3D extra_params.get("model_name") + self.events =3D [] + self.states =3D [] + self.main_c =3D self.__read_file(self.monitor_templates_dir + = "main_container.c") + self.main_h =3D self.__read_file(self.monitor_templates_dir + = "main_container.h") + else: + super().__init__(file_path, extra_params.get("model_name")) + + self.monitor_type =3D self.monitor_types.get(MonitorType) + if self.monitor_type is None: + raise ValueError("Unknown monitor type: %s" % MonitorType) + self.monitor_type =3D MonitorType + self.main_c =3D self.__read_file(self.monitor_templates_dir + = "main.c") + self.trace_h =3D self.__read_file(self.monitor_templates_dir += "trace.h") self.kconfig =3D self.__read_file(self.monitor_templates_dir + "Kc= onfig") self.enum_suffix =3D "_%s" % self.name self.description =3D extra_params.get("description", self.name) or= "auto-generated" @@ -105,6 +120,14 @@ class dot2k(Dot2c): def fill_monitor_type(self): return self.monitor_type.upper() =20 + def fill_parent(self): + return "&rv_%s" % self.parent if self.parent else "NULL" + + def fill_include_parent(self): + if self.parent: + return "#include \n" % (self.parent, self.pa= rent) + return "" + def fill_tracepoint_handlers_skel(self): buff =3D [] for event in self.events: @@ -146,6 +169,8 @@ class dot2k(Dot2c): tracepoint_handlers =3D self.fill_tracepoint_handlers_skel() tracepoint_attach =3D self.fill_tracepoint_attach_probe() tracepoint_detach =3D self.fill_tracepoint_detach_helper() + parent =3D self.fill_parent() + parent_include =3D self.fill_include_parent() =20 main_c =3D main_c.replace("%%MONITOR_TYPE%%", monitor_type) main_c =3D main_c.replace("%%MIN_TYPE%%", min_type) @@ -155,6 +180,8 @@ class dot2k(Dot2c): main_c =3D main_c.replace("%%TRACEPOINT_ATTACH%%", tracepoint_atta= ch) main_c =3D main_c.replace("%%TRACEPOINT_DETACH%%", tracepoint_deta= ch) main_c =3D main_c.replace("%%DESCRIPTION%%", self.description) + main_c =3D main_c.replace("%%PARENT%%", parent) + main_c =3D main_c.replace("%%INCLUDE_PARENT%%", parent_include) =20 return main_c =20 @@ -216,6 +243,14 @@ class dot2k(Dot2c): buff.append(" TP_ARGS(%s)" % tp_args_c) return self.__buff_to_string(buff) =20 + def fill_monitor_deps(self): + buff =3D [] + 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 =3D self.trace_h monitor_class =3D self.fill_monitor_class() @@ -233,12 +268,19 @@ class dot2k(Dot2c): def fill_kconfig(self): kconfig =3D self.kconfig monitor_class_type =3D self.fill_monitor_class_type() + monitor_deps =3D self.fill_monitor_deps() kconfig =3D kconfig.replace("%%MODEL_NAME%%", self.name) kconfig =3D kconfig.replace("%%MODEL_NAME_UP%%", self.name.upper()) kconfig =3D kconfig.replace("%%MONITOR_CLASS_TYPE%%", monitor_clas= s_type) kconfig =3D kconfig.replace("%%DESCRIPTION%%", self.description) + kconfig =3D kconfig.replace("%%MONITOR_DEPS%%", monitor_deps) return kconfig =20 + def fill_main_container_h(self): + main_h =3D self.main_h + main_h =3D main_h.replace("%%MODEL_NAME%%", self.name) + return main_h + def __patch_file(self, file, marker, line): file_to_patch =3D os.path.join(self.rv_dir, file) content =3D self.__read_file(file_to_patch) @@ -324,19 +366,24 @@ obj-$(CONFIG_RV_MON_%s) +=3D monitors/%s/%s.o =20 def print_files(self): main_c =3D self.fill_main_c() - model_h =3D self.fill_model_h() =20 self.__create_directory() =20 path =3D "%s.c" % self.name self.__create_file(path, main_c) =20 - path =3D "%s.h" % self.name - self.__create_file(path, model_h) - - trace_h =3D self.fill_trace_h() - path =3D "%s_trace.h" % self.name - self.__create_file(path, trace_h) + if self.container: + main_h =3D self.fill_main_container_h() + path =3D "%s.h" % self.name + self.__create_file(path, main_h) + else: + model_h =3D self.fill_model_h() + path =3D "%s.h" % self.name + self.__create_file(path, model_h) + + trace_h =3D self.fill_trace_h() + path =3D "%s_trace.h" % self.name + self.__create_file(path, trace_h) =20 kconfig =3D self.fill_kconfig() self.__create_file("Kconfig", kconfig) diff --git a/tools/verification/dot2/dot2k_templates/Kconfig b/tools/verifi= cation/dot2/dot2k_templates/Kconfig index 03100eda1707..291b29ea28db 100644 --- a/tools/verification/dot2/dot2k_templates/Kconfig +++ b/tools/verification/dot2/dot2k_templates/Kconfig @@ -2,6 +2,7 @@ # config RV_MON_%%MODEL_NAME_UP%% depends on RV +%%MONITOR_DEPS%% select %%MONITOR_CLASS_TYPE%% bool "%%MODEL_NAME%% monitor" help diff --git a/tools/verification/dot2/dot2k_templates/main.c b/tools/verific= ation/dot2/dot2k_templates/main.c index 9605ca994416..83044a20c89a 100644 --- a/tools/verification/dot2/dot2k_templates/main.c +++ b/tools/verification/dot2/dot2k_templates/main.c @@ -15,7 +15,7 @@ * #include */ #include - +%%INCLUDE_PARENT%% /* * This is the self-generated part of the monitor. Generally, there is no = need * to touch this section. @@ -74,7 +74,7 @@ static struct rv_monitor rv_%%MODEL_NAME%% =3D { =20 static int __init register_%%MODEL_NAME%%(void) { - rv_register_monitor(&rv_%%MODEL_NAME%%); + rv_register_monitor(&rv_%%MODEL_NAME%%, %%PARENT%%); return 0; } =20 diff --git a/tools/verification/dot2/dot2k_templates/main_container.c b/too= ls/verification/dot2/dot2k_templates/main_container.c new file mode 100644 index 000000000000..89fc17cf8958 --- /dev/null +++ b/tools/verification/dot2/dot2k_templates/main_container.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include + +#define MODULE_NAME "%%MODEL_NAME%%" + +#include "%%MODEL_NAME%%.h" + +struct rv_monitor rv_%%MODEL_NAME%%; + +struct rv_monitor rv_%%MODEL_NAME%% =3D { + .name =3D "%%MODEL_NAME%%", + .description =3D "%%DESCRIPTION%%", + .enable =3D NULL, + .disable =3D NULL, + .reset =3D NULL, + .enabled =3D 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/too= ls/verification/dot2/dot2k_templates/main_container.h new file mode 100644 index 000000000000..0f6883ab4bcc --- /dev/null +++ b/tools/verification/dot2/dot2k_templates/main_container.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +extern struct rv_monitor rv_%%MODEL_NAME%%; --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 132AF25A638 for ; Tue, 25 Mar 2025 14:34:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; cv=none; b=UjrOuKAmREix4f8yDVXFk/aYcJNU/yko2ePl4soFaGw9HExK6KFkGp7Hey63PVQTl2UOCfE8uapPwagM8SvkP+vTXPfgqkh9IfR+COG7cqaMm7NnOmK8Ym5jKLtHZE9BPW0C/R5i8kg5AB+5BjeT34w4tFQY7kOpvp978K1OBSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; c=relaxed/simple; bh=PrCjgwJXdAKGTLy2RDPqMHQOsl2AIO8OBNqwsAnQgms=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=VjuZNzNRKbjUay0nxyd82ehkGKfYOCcfGG0OnP00o31WJp8WzeiOUyt6V7/JtDIJrt5fdCxgTH/BGb+c0g3MhNC3CfWru8vjZOTuovHyehcWd/50MdydzRWSQeUk5qFrjd2pyTab/wojxXygk81zvcpgE2zOn3UAZyUwHXOwdTI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id E23B7C4AF0C; Tue, 25 Mar 2025 14:34:18 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Mt-00000002P2L-1FVl; Tue, 25 Mar 2025 10:35:03 -0400 Message-ID: <20250325143503.142711804@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:44 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org, Ingo Molnar , Peter Zijlstra Cc: Tomas Glozar , John Kacur , Juri Lelli , Jonathan Corbet , Clark Williams , Gabriele Monaco Subject: [for-next][PATCH 8/9] Documentation/rv: Add docs for the sched monitors References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Add man page and kernel documentation for the sched monitors, as sched is a container of other monitors, document all in the same page. sched is the first nested monitor, also explain what is a nested monitor and how enabling containers or children monitors work. To: Ingo Molnar To: Peter Zijlstra Cc: Juri Lelli Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Jonathan Corbet Cc: John Kacur Cc: Clark Williams Link: https://lore.kernel.org/20250305140406.350227-9-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- Documentation/tools/rv/rv-mon-sched.rst | 69 +++++++++ Documentation/trace/rv/monitor_sched.rst | 171 +++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 Documentation/tools/rv/rv-mon-sched.rst create mode 100644 Documentation/trace/rv/monitor_sched.rst diff --git a/Documentation/tools/rv/rv-mon-sched.rst b/Documentation/tools/= rv/rv-mon-sched.rst new file mode 100644 index 000000000000..da0fe4c79ae5 --- /dev/null +++ b/Documentation/tools/rv/rv-mon-sched.rst @@ -0,0 +1,69 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +rv-mon-sched +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +----------------------------- +Scheduler monitors collection +----------------------------- + +:Manual section: 1 + +SYNOPSIS +=3D=3D=3D=3D=3D=3D=3D=3D + +**rv mon sched** [*OPTIONS*] + +**rv mon ** [*OPTIONS*] + +**rv mon sched:** [*OPTIONS*] + +DESCRIPTION +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The scheduler monitor collection is a container for several monitors to mo= del +the behaviour of the scheduler. Each monitor describes a specification that +the scheduler should follow. + +As a monitor container, it will enable all nested monitors and set them +according to OPTIONS. +Nevertheless nested monitors can also be activated independently both by n= ame +and by specifying sched: , e.g. to enable only monitor tss you can do any = of: + + # rv mon sched:tss + + # rv mon tss + +See kernel documentation for further information about this monitor: + + +OPTIONS +=3D=3D=3D=3D=3D=3D=3D + +.. include:: common_ikm.rst + +NESTED MONITOR +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The available nested monitors are: + * scpd: schedule called with preemption disabled + * snep: schedule does not enable preempt + * sncid: schedule not called with interrupt disabled + * snroc: set non runnable on its own context + * sco: scheduling context operations + * tss: task switch while scheduling + +SEE ALSO +=3D=3D=3D=3D=3D=3D=3D=3D + +**rv**\(1), **rv-mon**\(1) + +Linux kernel *RV* documentation: + + +AUTHOR +=3D=3D=3D=3D=3D=3D + +Written by Gabriele Monaco + +.. include:: common_appendix.rst diff --git a/Documentation/trace/rv/monitor_sched.rst b/Documentation/trace= /rv/monitor_sched.rst new file mode 100644 index 000000000000..24b2c62a3bc2 --- /dev/null +++ b/Documentation/trace/rv/monitor_sched.rst @@ -0,0 +1,171 @@ +Scheduler monitors +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +- Name: sched +- Type: container for multiple monitors +- Author: Gabriele Monaco , Daniel Bristot de Oliveira= + +Description +----------- + +Monitors describing complex systems, such as the scheduler, can easily gro= w to +the point where they are just hard to understand because of the many possi= ble +state transitions. +Often it is possible to break such descriptions into smaller monitors, +sharing some or all events. Enabling those smaller monitors concurrently i= s, +in fact, testing the system as if we had one single larger monitor. +Splitting models into multiple specification is not only easier to +understand, but gives some more clues when we see errors. + +The sched monitor is a set of specifications to describe the scheduler beh= aviour. +It includes several per-cpu and per-task monitors that work independently = to verify +different specifications the scheduler should follow. + +To make this system as straightforward as possible, sched specifications a= re *nested* +monitors, whereas sched itself is a *container*. +From the interface perspective, sched includes other monitors as sub-direc= tories, +enabling/disabling or setting reactors to sched, propagates the change to = all monitors, +however single monitors can be used independently as well. + +It is important that future modules are built after their container (sched= , in +this case), otherwise the linker would not respect the order and the nesti= ng +wouldn't work as expected. +To do so, simply add them after sched in the Makefile. + +Specifications +-------------- + +The specifications included in sched are currently a work in progress, ada= pting the ones +defined in by Daniel Bristot in [1]. + +Currently we included the following: + +Monitor tss +~~~~~~~~~~~ + +The task switch while scheduling (tss) monitor ensures a task switch happe= ns +only in scheduling context, that is inside a call to `__schedule`:: + + | + | + v + +-----------------+ + | thread | <+ + +-----------------+ | + | | + | schedule_entry | schedule_exit + v | + sched_switch | + +--------------- | + | sched | + +--------------> -+ + +Monitor sco +~~~~~~~~~~~ + +The scheduling context operations (sco) monitor ensures changes in a task = state +happen only in thread context:: + + + | + | + v + sched_set_state +------------------+ + +------------------ | | + | | thread_context | + +-----------------> | | <+ + +------------------+ | + | | + | schedule_entry | schedule_exit + v | + | + scheduling_context -+ + +Monitor snroc +~~~~~~~~~~~~~ + +The set non runnable on its own context (snroc) monitor ensures changes in= a +task state happens only in the respective task's context. This is a per-ta= sk +monitor:: + + | + | + v + +------------------+ + | other_context | <+ + +------------------+ | + | | + | sched_switch_in | sched_switch_out + v | + sched_set_state | + +------------------ | + | own_context | + +-----------------> -+ + +Monitor scpd +~~~~~~~~~~~~ + +The schedule called with preemption disabled (scpd) monitor ensures schedu= le is +called with preemption disabled:: + + | + | + v + +------------------+ + | cant_sched | <+ + +------------------+ | + | | + | preempt_disable | preempt_enable + v | + schedule_entry | + schedule_exit | + +----------------- can_sched | + | | + +----------------> -+ + +Monitor snep +~~~~~~~~~~~~ + +The schedule does not enable preempt (snep) monitor ensures a schedule call +does not enable preemption:: + + | + | + v + preempt_disable +------------------------+ + preempt_enable | | + +------------------ | non_scheduling_context | + | | | + +-----------------> | | <+ + +------------------------+ | + | | + | schedule_entry | schedule_exit + v | + | + scheduling_contex -+ + +Monitor sncid +~~~~~~~~~~~~~ + +The schedule not called with interrupt disabled (sncid) monitor ensures +schedule is not called with interrupt disabled:: + + | + | + v + schedule_entry +--------------+ + schedule_exit | | + +----------------- | can_sched | + | | | + +----------------> | | <+ + +--------------+ | + | | + | irq_disable | irq_enable + v | + | + cant_sched -+ + +References +---------- + +[1] - https://bristot.me/linux-task-model --=20 2.47.2 From nobody Thu Dec 18 01:02:10 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7133525B668 for ; Tue, 25 Mar 2025 14:34:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; cv=none; b=Q+s9pPxrPCFYoifWm+weopWxgmMGq4iEvPptWDJttoL0NAmHfWxQ1D4dmXDILvpwanQCrKc7D3XvWLpXlUXiQtMAU6MKzPmtpSsiQh09ipgyGWD8Qh3aTZEwUoTjft7FTkIUfl33WSKCk1vV8dQ9xtW5NOXsrEqSqAqqhVoJUDw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1742913259; c=relaxed/simple; bh=CryzNEnxPBRHXq02oYSPUJ0eUX222lqvKXI2gty0v4w=; h=Message-ID:Date:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=K/0IiPLEjSORvB7xJuVat94YLsSl6dAQXFo7ES3rExUJZJyliPg1kRp4Fk8nZ3mrrXs4IDIBvEhx6SQAJQv+o4oyFlwvBpNXe/JcOW9xzckM+nm27Gv7knOpKO/zK/3Y/+RuQydT/szDCEU/M6K6H1XY6rd8sKPHqbdVvqNilug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CD11C4CEF1; Tue, 25 Mar 2025 14:34:19 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tx5Mt-00000002P2p-1xW6; Tue, 25 Mar 2025 10:35:03 -0400 Message-ID: <20250325143503.318376722@goodmis.org> User-Agent: quilt/0.68 Date: Tue, 25 Mar 2025 10:34:45 -0400 From: Steven Rostedt To: linux-kernel@vger.kernel.org Cc: Tomas Glozar , John Kacur , Ingo Molnar , Peter Zijlstra , Juri Lelli , Gabriele Monaco Subject: [for-next][PATCH 9/9] tools/rv: Allow rv list to filter for container References: <20250325143436.168114339@goodmis.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Gabriele Monaco Add possibility to supply the container name to rv list: # rv list sched mon1 mon2 mon3 This lists only monitors in sched, without indentation. Supplying -h, any option (string starting with -) or more than 1 argument will still print the usage. Passing a non-existent container prints nothing and passing no container continues to print all monitors, showing indentation for nested monitors, reported after their container. Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Juri Lelli Link: https://lore.kernel.org/20250305140406.350227-10-gmonaco@redhat.com Signed-off-by: Gabriele Monaco Signed-off-by: Steven Rostedt (Google) --- tools/verification/rv/include/in_kernel.h | 2 +- tools/verification/rv/src/in_kernel.c | 36 +++++++++++++++------ tools/verification/rv/src/rv.c | 38 +++++++++++++++-------- 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/tools/verification/rv/include/in_kernel.h b/tools/verification= /rv/include/in_kernel.h index 3090638c8d71..f3bfd3b9895f 100644 --- a/tools/verification/rv/include/in_kernel.h +++ b/tools/verification/rv/include/in_kernel.h @@ -1,3 +1,3 @@ // SPDX-License-Identifier: GPL-2.0 -int ikm_list_monitors(void); +int ikm_list_monitors(char *container); int ikm_run_monitor(char *monitor, int argc, char **argv); diff --git a/tools/verification/rv/src/in_kernel.c b/tools/verification/rv/= src/in_kernel.c index 032b85101929..c0dcee795c0d 100644 --- a/tools/verification/rv/src/in_kernel.c +++ b/tools/verification/rv/src/in_kernel.c @@ -180,19 +180,25 @@ static char *ikm_read_desc(char *monitor_name) /* * ikm_fill_monitor_definition - fill monitor's definition * - * Returns -1 on error, 0 otherwise. + * Returns -1 on error, 1 if the monitor does not belong in the container,= 0 otherwise. + * container can be NULL */ -static int ikm_fill_monitor_definition(char *name, struct monitor *ikm) +static int ikm_fill_monitor_definition(char *name, struct monitor *ikm, ch= ar *container) { int enabled; char *desc, *nested_name; =20 nested_name =3D strstr(name, ":"); if (nested_name) { + /* it belongs in container if it starts with "container:" */ + if (container && strstr(name, container) !=3D name) + return 1; *nested_name =3D '/'; ++nested_name; ikm->nested =3D 1; } else { + if (container) + return 1; nested_name =3D name; ikm->nested =3D 0; } @@ -328,12 +334,12 @@ static int ikm_has_id(char *monitor_name) * * Returns 0 on success, -1 otherwise. */ -int ikm_list_monitors(void) +int ikm_list_monitors(char *container) { char *available_monitors; struct monitor ikm =3D {0}; char *curr, *next; - int retval; + int retval, list_monitor =3D 0; =20 available_monitors =3D tracefs_instance_file_read(NULL, "rv/available_mon= itors", NULL); =20 @@ -347,17 +353,29 @@ int ikm_list_monitors(void) next =3D strstr(curr, "\n"); *next =3D '\0'; =20 - retval =3D ikm_fill_monitor_definition(curr, &ikm); - if (retval) + retval =3D ikm_fill_monitor_definition(curr, &ikm, container); + if (retval < 0) err_msg("ikm: error reading %d in kernel monitor, skipping\n", curr); =20 - printf("%s%-*s %s %s\n", ikm.nested ? " - " : "", - ikm.nested ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN, - ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]"); + if (!retval) { + int indent =3D ikm.nested && !container; + + list_monitor =3D 1; + printf("%s%-*s %s %s\n", indent ? " - " : "", + indent ? MAX_DA_NAME_LEN - 3 : MAX_DA_NAME_LEN, + ikm.name, ikm.desc, ikm.enabled ? "[ON]" : "[OFF]"); + } curr =3D ++next; =20 } while (strlen(curr)); =20 + if (!list_monitor) { + if (container) + printf("-- No monitor found in container %s --\n", container); + else + printf("-- No monitor found --\n"); + } + free(available_monitors); =20 return 0; diff --git a/tools/verification/rv/src/rv.c b/tools/verification/rv/src/rv.c index 1ddb85532816..239de054d1e0 100644 --- a/tools/verification/rv/src/rv.c +++ b/tools/verification/rv/src/rv.c @@ -41,30 +41,42 @@ static void rv_list(int argc, char **argv) { static const char *const usage[] =3D { "", - " usage: rv list [-h]", + " usage: rv list [-h] [container]", "", " list all available monitors", "", " -h/--help: print this menu", + "", + " [container]: list only monitors in this container", NULL, }; - int i; - - if (argc > 1) { + int i, print_help =3D 0, retval =3D 0; + char *container =3D NULL; + + if (argc =3D=3D 2) { + if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { + print_help =3D 1; + retval =3D 0; + } else if (argv[1][0] =3D=3D '-') { + /* assume invalid option */ + print_help =3D 1; + retval =3D 1; + } else + container =3D argv[1]; + } else if (argc > 2) { + /* more than 2 is always usage */ + print_help =3D 1; + retval =3D 1; + } + if (print_help) { fprintf(stderr, "rv version %s\n", VERSION); - - /* more than 1 is always usage */ for (i =3D 0; usage[i]; i++) fprintf(stderr, "%s\n", usage[i]); - - /* but only -h is valid */ - if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) - exit(0); - else - exit(1); + exit(retval); } =20 - ikm_list_monitors(); + ikm_list_monitors(container); + exit(0); } =20 --=20 2.47.2