* [PATCH 1/9] rv: Fix __user specifier usage in extract_params()
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 2/9] rv: Fix read_lock scope in per-task DA cleanup Gabriele Monaco
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Masami Hiramatsu,
Nam Cao, linux-trace-kernel
Cc: kernel test robot, Wen Yang
The attributes variables extracted from syscalls in the helper are both
defined with the __user specifier although only the actual pointer to
user data should be marked.
Remove the __user specifier from attr.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202604150820.Ny143u6X-lkp@intel.com
Fixes: b133207deb72 ("rv: Add nomiss deadline monitor")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
kernel/trace/rv/monitors/deadline/deadline.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/rv/monitors/deadline/deadline.h b/kernel/trace/rv/monitors/deadline/deadline.h
index 0bbfd2543329..78fca873d61e 100644
--- a/kernel/trace/rv/monitors/deadline/deadline.h
+++ b/kernel/trace/rv/monitors/deadline/deadline.h
@@ -95,7 +95,8 @@ static inline u8 get_server_type(struct task_struct *tsk)
static inline int extract_params(struct pt_regs *regs, long id, pid_t *pid_out)
{
size_t size = offsetofend(struct sched_attr, sched_flags);
- struct sched_attr __user *uattr, attr;
+ struct sched_attr __user *uattr;
+ struct sched_attr attr;
int new_policy = -1, ret;
unsigned long args[6];
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 2/9] rv: Fix read_lock scope in per-task DA cleanup
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
2026-05-12 14:02 ` [PATCH 1/9] rv: Fix __user specifier usage in extract_params() Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 3/9] rv: Reset per-task DA monitors before releasing the slot Gabriele Monaco
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Nam Cao,
linux-trace-kernel
Cc: Wen Yang
The da_monitor_reset_all() function for per-task monitors takes
tasklist_lock while iterating over tasks, then keeps it also while
iterating over idle tasks (one per CPU). The latter is not necessary
since the lock needs to guard only for_each_process_thread().
Use a scoped_guard for more compact syntax and adjust the scope only
where the lock is necessary.
Fixes: 30984ccf31b7f ("rv: Refactor da_monitor to minimise macros")
Fixes: 8259cb14a7068 ("rv: Reset per-task monitors also for idle tasks")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 39765ff6f098..250888812125 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -272,12 +272,12 @@ static void da_monitor_reset_all(void)
struct task_struct *g, *p;
int cpu;
- read_lock(&tasklist_lock);
- for_each_process_thread(g, p)
- da_monitor_reset(da_get_monitor(p));
+ scoped_guard(read_lock, &tasklist_lock) {
+ for_each_process_thread(g, p)
+ da_monitor_reset(da_get_monitor(p));
+ }
for_each_present_cpu(cpu)
da_monitor_reset(da_get_monitor(idle_task(cpu)));
- read_unlock(&tasklist_lock);
}
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 3/9] rv: Reset per-task DA monitors before releasing the slot
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
2026-05-12 14:02 ` [PATCH 1/9] rv: Fix __user specifier usage in extract_params() Gabriele Monaco
2026-05-12 14:02 ` [PATCH 2/9] rv: Fix read_lock scope in per-task DA cleanup Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 4/9] rv: Prevent task migration while handling per-CPU events Gabriele Monaco
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Nam Cao,
linux-trace-kernel
Cc: Wen Yang
Per-task monitors use task_mon_slot to determine which slot in the array
to use for the monitor. During destruction, this slot is returned but
this is done before resetting the monitor. As a result, the monitor's
reset is in fact resetting a slot that is outside of the array
(RV_PER_TASK_MONITOR_INIT).
Release the slot only after the reset to avoid out-of-bound memory
access.
Fixes: 30984ccf31b7f ("rv: Refactor da_monitor to minimise macros")
Fixes: 792575348ff70 ("rv/include: Add deterministic automata monitor definition via C macros")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 250888812125..0b7028df08fb 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -309,10 +309,11 @@ static inline void da_monitor_destroy(void)
WARN_ONCE(1, "Disabling a disabled monitor: " __stringify(MONITOR_NAME));
return;
}
- rv_put_task_monitor_slot(task_mon_slot);
- task_mon_slot = RV_PER_TASK_MONITOR_INIT;
da_monitor_reset_all();
+
+ rv_put_task_monitor_slot(task_mon_slot);
+ task_mon_slot = RV_PER_TASK_MONITOR_INIT;
}
#elif RV_MON_TYPE == RV_MON_PER_OBJ
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 4/9] rv: Prevent task migration while handling per-CPU events
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (2 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 3/9] rv: Reset per-task DA monitors before releasing the slot Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 5/9] rv: Ensure all pending probes terminate on per-obj monitor destroy Gabriele Monaco
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, linux-trace-kernel
Cc: Nam Cao, Wen Yang
Tracepoint handlers are now fully preemptible. When a per-CPU monitor
handles an event, it retrieves the monitor state using a per-CPU
pointer. If the event itself doesn't disable preemption, the task can
migrate to a different CPU and we risk updating the wrong monitor.
Mitigate this by explicitly disabling task migration before acquiring
the monitor pointer. This cannot guarantee the monitor runs on the
correct CPU but reduces the race condition window and prevents warnings.
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 0b7028df08fb..a9fd284195ee 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -181,6 +181,10 @@ static inline void da_monitor_destroy(void)
da_monitor_reset_all();
}
+#ifndef da_implicit_guard
+#define da_implicit_guard()
+#endif
+
#elif RV_MON_TYPE == RV_MON_PER_CPU
/*
* Functions to define, init and get a per-cpu monitor.
@@ -230,6 +234,10 @@ static inline void da_monitor_destroy(void)
da_monitor_reset_all();
}
+#ifndef da_implicit_guard
+#define da_implicit_guard() guard(migrate)()
+#endif
+
#elif RV_MON_TYPE == RV_MON_PER_TASK
/*
* Functions to define, init and get a per-task monitor.
@@ -677,6 +685,7 @@ static inline bool __da_handle_start_run_event(struct da_monitor *da_mon,
*/
static inline void da_handle_event(enum events event)
{
+ da_implicit_guard();
__da_handle_event(da_get_monitor(), event, 0);
}
@@ -692,6 +701,7 @@ static inline void da_handle_event(enum events event)
*/
static inline bool da_handle_start_event(enum events event)
{
+ da_implicit_guard();
return __da_handle_start_event(da_get_monitor(), event, 0);
}
@@ -703,6 +713,7 @@ static inline bool da_handle_start_event(enum events event)
*/
static inline bool da_handle_start_run_event(enum events event)
{
+ da_implicit_guard();
return __da_handle_start_run_event(da_get_monitor(), event, 0);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 5/9] rv: Ensure all pending probes terminate on per-obj monitor destroy
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (3 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 4/9] rv: Prevent task migration while handling per-CPU events Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 6/9] rv: Ensure synchronous cleanup for HA monitors Gabriele Monaco
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Nam Cao,
linux-trace-kernel
Cc: Wen Yang
The monitor disable/destroy sequence detaches all probes and resets the
monitor's data, however it doesn't wait for pending probes. This is an
issue with per-object monitors, which free the monitor storage.
Call tracepoint_synchronize_unregister() to make sure to wait for all
pending probes before destroying the monitor storage.
Fixes: 4a24127bd6cb ("rv: Add support for per-object monitors in DA/HA")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index a9fd284195ee..a4a13b62d1a4 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -515,9 +515,10 @@ static inline void da_monitor_destroy(void)
struct hlist_node *tmp;
int bkt;
+ tracepoint_synchronize_unregister();
/*
- * This function is called after all probes are disabled, we need only
- * worry about concurrency against old events.
+ * This function is called after all probes are disabled and no longer
+ * pending, we can safely assume no concurrent user.
*/
synchronize_rcu();
hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) {
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 6/9] rv: Ensure synchronous cleanup for HA monitors
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (4 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 5/9] rv: Ensure all pending probes terminate on per-obj monitor destroy Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 7/9] rv: Do not rely on clean monitor when initialising HA Gabriele Monaco
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Nam Cao,
linux-trace-kernel
Cc: Wen Yang
HA monitors may start timers, all cleanup functions currently stop the
timers asynchronously to avoid sleeping in the wrong context.
Nothing makes sure running callbacks terminate on cleanup.
Run the entire HA timer callback in an RCU read-side critical section,
this way we can simply synchronize_rcu() with any pending timer and are
sure any cleanup using kfree_rcu() runs after callbacks terminated.
Additionally make sure any unlikely callback running late won't run any
code if the monitor is marked as disabled.
Fixes: f5587d1b6ec9 ("rv: Add Hybrid Automata monitor type")
Fixes: 4a24127bd6cb ("rv: Add support for per-object monitors in DA/HA")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 23 +++++++++++++++++++----
include/rv/ha_monitor.h | 18 ++++++++++++++++--
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index a4a13b62d1a4..402d3b935c08 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -57,6 +57,15 @@ static struct rv_monitor rv_this;
#define da_monitor_reset_hook(da_mon)
#endif
+/*
+ * Hook to allow the implementation of hybrid automata: define it with a
+ * function that waits for the termination of all monitors background
+ * activities (e.g. all timers). This hook can sleep.
+ */
+#ifndef da_monitor_sync_hook
+#define da_monitor_sync_hook()
+#endif
+
/*
* Type for the target id, default to int but can be overridden.
* A long type can work as hash table key (PER_OBJ) but will be downgraded to
@@ -179,6 +188,7 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
#ifndef da_implicit_guard
@@ -232,6 +242,7 @@ static inline int da_monitor_init(void)
static inline void da_monitor_destroy(void)
{
da_monitor_reset_all();
+ da_monitor_sync_hook();
}
#ifndef da_implicit_guard
@@ -319,6 +330,7 @@ static inline void da_monitor_destroy(void)
}
da_monitor_reset_all();
+ da_monitor_sync_hook();
rv_put_task_monitor_slot(task_mon_slot);
task_mon_slot = RV_PER_TASK_MONITOR_INIT;
@@ -497,10 +509,9 @@ static void da_monitor_reset_all(void)
struct da_monitor_storage *mon_storage;
int bkt;
- rcu_read_lock();
+ guard(rcu)();
hash_for_each_rcu(da_monitor_ht, bkt, mon_storage, node)
da_monitor_reset(&mon_storage->rv.da_mon);
- rcu_read_unlock();
}
static inline int da_monitor_init(void)
@@ -516,13 +527,17 @@ static inline void da_monitor_destroy(void)
int bkt;
tracepoint_synchronize_unregister();
+ scoped_guard(rcu) {
+ hash_for_each_rcu(da_monitor_ht, bkt, mon_storage, node) {
+ da_monitor_reset_hook(&mon_storage->rv.da_mon);
+ }
+ }
+ da_monitor_sync_hook();
/*
* This function is called after all probes are disabled and no longer
* pending, we can safely assume no concurrent user.
*/
- synchronize_rcu();
hash_for_each_safe(da_monitor_ht, bkt, tmp, mon_storage, node) {
- da_monitor_reset_hook(&mon_storage->rv.da_mon);
hash_del_rcu(&mon_storage->node);
kfree(mon_storage);
}
diff --git a/include/rv/ha_monitor.h b/include/rv/ha_monitor.h
index d59507e8cb30..47ff1a41febe 100644
--- a/include/rv/ha_monitor.h
+++ b/include/rv/ha_monitor.h
@@ -36,6 +36,7 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
#define da_monitor_event_hook ha_monitor_handle_constraint
#define da_monitor_init_hook ha_monitor_init_env
#define da_monitor_reset_hook ha_monitor_reset_env
+#define da_monitor_sync_hook() synchronize_rcu()
#include <rv/da_monitor.h>
#include <linux/seq_buf.h>
@@ -237,12 +238,25 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
return false;
}
+/*
+ * __ha_monitor_timer_callback - generic callback representation
+ *
+ * This callback runs in an RCU read-side critical section to allow the
+ * destruction sequence to easily synchronize_rcu() with all pending timer
+ * after asynchronously disabling them.
+ */
static inline void __ha_monitor_timer_callback(struct ha_monitor *ha_mon)
{
- enum states curr_state = READ_ONCE(ha_mon->da_mon.curr_state);
DECLARE_SEQ_BUF(env_string, ENV_BUFFER_SIZE);
- u64 time_ns = ha_get_ns();
+ enum states curr_state;
+ u64 time_ns;
+
+ if (unlikely(!da_monitor_handling_event(&ha_mon->da_mon)))
+ return;
+ guard(rcu)();
+ curr_state = READ_ONCE(ha_mon->da_mon.curr_state);
+ time_ns = ha_get_ns();
ha_get_env_string(&env_string, ha_mon, time_ns);
ha_react(curr_state, EVENT_NONE, env_string.buffer);
ha_trace_error_env(ha_mon, model_get_state_name(curr_state),
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 7/9] rv: Do not rely on clean monitor when initialising HA
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (5 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 6/9] rv: Ensure synchronous cleanup for HA monitors Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 8/9] rv: Add automatic cleanup handlers for per-task HA monitors Gabriele Monaco
2026-05-12 14:02 ` [PATCH 9/9] rv: Mandate deallocation for per-obj monitors Gabriele Monaco
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Masami Hiramatsu,
Nam Cao, linux-trace-kernel
Cc: Wen Yang
Hybrid Automata monitors hook into the DA implementation when doing
da_monitor_reset(). This function is called both on initialisation and
teardown, HA monitors try to cancel a timer only when it's initialised
relying on the da_mon->monitoring flag. This flag could however be
corrupted during initialisation. This happens for instance on per-task
monitors that share the same storage with different type of monitors
like LTL or in case of races during a previous teardown.
Stop relying on the monitoring flag during initialisation, assume that
can have any value, so skip timer cancellation in any case when a local
flag is set. New monitors (e.g. new tasks) are always zero-initialised
so they are safe.
Reported-by: Wen Yang <wen.yang@linux.dev>
Closes: https://lore.kernel.org/lkml/d02c656aada7d071f083460a5c9a454363669b61.1778522945.git.wen.yang@linux.dev
Fixes: f5587d1b6ec9 ("rv: Add Hybrid Automata monitor type")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/ha_monitor.h | 31 ++++++++++++++++++-
kernel/trace/rv/monitors/nomiss/nomiss.c | 4 +--
kernel/trace/rv/monitors/opid/opid.c | 4 +--
kernel/trace/rv/monitors/stall/stall.c | 4 +--
.../rvgen/rvgen/templates/dot2k/main.c | 4 +--
5 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/include/rv/ha_monitor.h b/include/rv/ha_monitor.h
index 47ff1a41febe..11ae85bad492 100644
--- a/include/rv/ha_monitor.h
+++ b/include/rv/ha_monitor.h
@@ -116,6 +116,35 @@ static enum hrtimer_restart ha_monitor_timer_callback(struct hrtimer *hrtimer);
#define ha_get_ns() 0
#endif /* HA_CLK_NS */
+static bool ha_mon_initializing;
+
+static int ha_monitor_init(void)
+{
+ int ret;
+
+ ha_mon_initializing = true;
+ ret = da_monitor_init();
+ ha_mon_initializing = false;
+ return ret;
+}
+
+static void ha_monitor_destroy(void)
+{
+ da_monitor_destroy();
+}
+
+/*
+ * ha_monitor_uninitialized - are fields like the timer initialized?
+ *
+ * On a clean monitor, we can assume an active monitor (monitoring) is
+ * initialized, however the monitoring field cannot be trusted during
+ * initialization.
+ */
+static inline bool ha_monitor_uninitialized(struct da_monitor *da_mon)
+{
+ return ha_mon_initializing || !da_monitoring(da_mon);
+}
+
/* Should be supplied by the monitor */
static u64 ha_get_env(struct ha_monitor *ha_mon, enum envs env, u64 time_ns);
static bool ha_verify_constraint(struct ha_monitor *ha_mon,
@@ -160,7 +189,7 @@ static inline void ha_monitor_reset_env(struct da_monitor *da_mon)
struct ha_monitor *ha_mon = to_ha_monitor(da_mon);
/* Initialisation resets the monitor before initialising the timer */
- if (likely(da_monitoring(da_mon)))
+ if (likely(!ha_monitor_uninitialized(da_mon)))
ha_cancel_timer(ha_mon);
}
diff --git a/kernel/trace/rv/monitors/nomiss/nomiss.c b/kernel/trace/rv/monitors/nomiss/nomiss.c
index 31f90f3638d8..8ead8783c29f 100644
--- a/kernel/trace/rv/monitors/nomiss/nomiss.c
+++ b/kernel/trace/rv/monitors/nomiss/nomiss.c
@@ -227,7 +227,7 @@ static int enable_nomiss(void)
{
int retval;
- retval = da_monitor_init();
+ retval = ha_monitor_init();
if (retval)
return retval;
@@ -263,7 +263,7 @@ static void disable_nomiss(void)
rv_detach_trace_probe("nomiss", sched_switch, handle_sched_switch);
rv_detach_trace_probe("nomiss", sched_wakeup, handle_sched_wakeup);
- da_monitor_destroy();
+ ha_monitor_destroy();
}
static struct rv_monitor rv_this = {
diff --git a/kernel/trace/rv/monitors/opid/opid.c b/kernel/trace/rv/monitors/opid/opid.c
index 4594c7c46601..2922318c6112 100644
--- a/kernel/trace/rv/monitors/opid/opid.c
+++ b/kernel/trace/rv/monitors/opid/opid.c
@@ -73,7 +73,7 @@ static int enable_opid(void)
{
int retval;
- retval = da_monitor_init();
+ retval = ha_monitor_init();
if (retval)
return retval;
@@ -90,7 +90,7 @@ static void disable_opid(void)
rv_detach_trace_probe("opid", sched_set_need_resched_tp, handle_sched_need_resched);
rv_detach_trace_probe("opid", sched_waking, handle_sched_waking);
- da_monitor_destroy();
+ ha_monitor_destroy();
}
/*
diff --git a/kernel/trace/rv/monitors/stall/stall.c b/kernel/trace/rv/monitors/stall/stall.c
index 9ccfda6b0e73..3c38fb1a0159 100644
--- a/kernel/trace/rv/monitors/stall/stall.c
+++ b/kernel/trace/rv/monitors/stall/stall.c
@@ -103,7 +103,7 @@ static int enable_stall(void)
{
int retval;
- retval = da_monitor_init();
+ retval = ha_monitor_init();
if (retval)
return retval;
@@ -120,7 +120,7 @@ static void disable_stall(void)
rv_detach_trace_probe("stall", sched_switch, handle_sched_switch);
rv_detach_trace_probe("stall", sched_wakeup, handle_sched_wakeup);
- da_monitor_destroy();
+ ha_monitor_destroy();
}
static struct rv_monitor rv_this = {
diff --git a/tools/verification/rvgen/rvgen/templates/dot2k/main.c b/tools/verification/rvgen/rvgen/templates/dot2k/main.c
index bf0999f6657a..889446760e3c 100644
--- a/tools/verification/rvgen/rvgen/templates/dot2k/main.c
+++ b/tools/verification/rvgen/rvgen/templates/dot2k/main.c
@@ -35,7 +35,7 @@ static int enable_%%MODEL_NAME%%(void)
{
int retval;
- retval = da_monitor_init();
+ retval = %%MONITOR_CLASS%%_monitor_init();
if (retval)
return retval;
@@ -50,7 +50,7 @@ static void disable_%%MODEL_NAME%%(void)
%%TRACEPOINT_DETACH%%
- da_monitor_destroy();
+ %%MONITOR_CLASS%%_monitor_destroy();
}
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 8/9] rv: Add automatic cleanup handlers for per-task HA monitors
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (6 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 7/9] rv: Do not rely on clean monitor when initialising HA Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
2026-05-12 14:02 ` [PATCH 9/9] rv: Mandate deallocation for per-obj monitors Gabriele Monaco
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Nam Cao,
linux-trace-kernel
Cc: Wen Yang
Hybrid automata monitors may start timers, depending on the model, these
may remain active on an exiting task and cause false positives or even
access freed memory.
Add an enable/disable hook in the HA code, currently only populated by
the per-task handler for registration and deregistration.
This hooks to the sched_process_exit event and ensures the timer is
stopped for every exiting task. The handler is enabled automatically but
may be disabled, for instance if the monitor uses the event for another
purpose (but should still manually ensure timers are stopped).
Fixes: f5587d1b6ec9 ("rv: Add Hybrid Automata monitor type")
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/ha_monitor.h | 44 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/include/rv/ha_monitor.h b/include/rv/ha_monitor.h
index 11ae85bad492..1bdf866e9c63 100644
--- a/include/rv/ha_monitor.h
+++ b/include/rv/ha_monitor.h
@@ -28,6 +28,7 @@ static inline void ha_monitor_init_env(struct da_monitor *da_mon);
static inline void ha_monitor_reset_env(struct da_monitor *da_mon);
static inline void ha_setup_timer(struct ha_monitor *ha_mon);
static inline bool ha_cancel_timer(struct ha_monitor *ha_mon);
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon);
static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
enum states curr_state,
enum events event,
@@ -38,6 +39,26 @@ static bool ha_monitor_handle_constraint(struct da_monitor *da_mon,
#define da_monitor_reset_hook ha_monitor_reset_env
#define da_monitor_sync_hook() synchronize_rcu()
+#if !defined(HA_SKIP_AUTO_CLEANUP) && RV_MON_TYPE == RV_MON_PER_TASK
+/*
+ * Automatic cleanup handlers for per-task HA monitors, only skip if you know
+ * what you are doing (e.g. you want to implement cleanup manually in another
+ * handler doing more things).
+ */
+static void ha_handle_sched_process_exit(void *data, struct task_struct *p,
+ bool group_dead);
+
+#define ha_monitor_enable_hook() \
+ rv_attach_trace_probe(__stringify(MONITOR_NAME), sched_process_exit, \
+ ha_handle_sched_process_exit)
+#define ha_monitor_disable_hook() \
+ rv_detach_trace_probe(__stringify(MONITOR_NAME), sched_process_exit, \
+ ha_handle_sched_process_exit)
+#else
+#define ha_monitor_enable_hook()
+#define ha_monitor_disable_hook()
+#endif
+
#include <rv/da_monitor.h>
#include <linux/seq_buf.h>
@@ -124,12 +145,14 @@ static int ha_monitor_init(void)
ha_mon_initializing = true;
ret = da_monitor_init();
+ ha_monitor_enable_hook();
ha_mon_initializing = false;
return ret;
}
static void ha_monitor_destroy(void)
{
+ ha_monitor_disable_hook();
da_monitor_destroy();
}
@@ -230,6 +253,18 @@ static inline void ha_trace_error_env(struct ha_monitor *ha_mon,
{
CONCATENATE(trace_error_env_, MONITOR_NAME)(id, curr_state, event, env);
}
+
+#if !defined(HA_SKIP_AUTO_CLEANUP) && RV_MON_TYPE == RV_MON_PER_TASK
+static void ha_handle_sched_process_exit(void *data, struct task_struct *p,
+ bool group_dead)
+{
+ struct da_monitor *da_mon = da_get_monitor(p);
+
+ if (likely(!ha_monitor_uninitialized(da_mon)))
+ ha_cancel_timer_sync(to_ha_monitor(da_mon));
+}
+#endif
+
#endif /* RV_MON_TYPE */
/*
@@ -455,6 +490,10 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return timer_delete(&ha_mon->timer);
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon)
+{
+ timer_delete_sync(&ha_mon->timer);
+}
#elif HA_TIMER_TYPE == HA_TIMER_HRTIMER
/*
* Helper functions to handle the monitor timer.
@@ -506,6 +545,10 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return hrtimer_try_to_cancel(&ha_mon->hrtimer) == 1;
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon)
+{
+ hrtimer_cancel(&ha_mon->hrtimer);
+}
#else /* HA_TIMER_NONE */
/*
* Start function is intentionally not defined, monitors using timers must
@@ -516,6 +559,7 @@ static inline bool ha_cancel_timer(struct ha_monitor *ha_mon)
{
return false;
}
+static inline void ha_cancel_timer_sync(struct ha_monitor *ha_mon) { }
#endif
#endif
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 9/9] rv: Mandate deallocation for per-obj monitors
2026-05-12 14:02 [PATCH 0/9] rv: Fixes on Deterministic and Hybrid Automata Gabriele Monaco
` (7 preceding siblings ...)
2026-05-12 14:02 ` [PATCH 8/9] rv: Add automatic cleanup handlers for per-task HA monitors Gabriele Monaco
@ 2026-05-12 14:02 ` Gabriele Monaco
8 siblings, 0 replies; 10+ messages in thread
From: Gabriele Monaco @ 2026-05-12 14:02 UTC (permalink / raw)
To: linux-kernel, Steven Rostedt, Gabriele Monaco, Masami Hiramatsu,
linux-trace-kernel
Cc: Nam Cao, Wen Yang
The per-object monitors use a hash tables and dynamic allocation of the
monitor storage, functions to clean a monitor that is no longer needed
are provided but nothing ensures the monitor actually uses them.
Remove the inline specifier on the deallocation function to let the
compiler warn in case it isn't referenced. If the monitor really doesn't
need one (for instance because instances will never cease to exist
before disabling the monitor), the da_skip_deallocation() helper macro
can be used to silence the warning.
Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
---
include/rv/da_monitor.h | 14 +++++++++++++-
kernel/trace/rv/monitors/deadline/deadline.h | 5 ++++-
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/include/rv/da_monitor.h b/include/rv/da_monitor.h
index 402d3b935c08..378d23ab7dfb 100644
--- a/include/rv/da_monitor.h
+++ b/include/rv/da_monitor.h
@@ -489,8 +489,11 @@ static inline monitor_target da_get_target_by_id(da_id_type id)
* locks.
* This function includes an RCU read-side critical section to synchronise
* against da_monitor_destroy().
+ * NOTE: inline is omitted on purpose to let the compiler warn if this function
+ * is never referenced. For monitors that don't require a deallocation hook,
+ * da_skip_deallocation() can be used.
*/
-static inline void da_destroy_storage(da_id_type id)
+static void da_destroy_storage(da_id_type id)
{
struct da_monitor_storage *mon_storage;
@@ -504,6 +507,15 @@ static inline void da_destroy_storage(da_id_type id)
kfree_rcu(mon_storage, rcu);
}
+/*
+ * da_skip_deallocation - explicitly mark a deallocation function as not required
+ *
+ * Only use when you are absolutely sure the monitor doesn't require a
+ * deallocation hook (i.e. it's not possible for an object to finish existing
+ * when the monitor is still running).
+ */
+#define da_skip_deallocation(hook) ((void)hook)
+
static void da_monitor_reset_all(void)
{
struct da_monitor_storage *mon_storage;
diff --git a/kernel/trace/rv/monitors/deadline/deadline.h b/kernel/trace/rv/monitors/deadline/deadline.h
index 78fca873d61e..c39fd79148c2 100644
--- a/kernel/trace/rv/monitors/deadline/deadline.h
+++ b/kernel/trace/rv/monitors/deadline/deadline.h
@@ -194,7 +194,10 @@ static void __maybe_unused handle_newtask(void *data, struct task_struct *task,
da_create_storage(EXPAND_ID_TASK(task), NULL);
}
-static void __maybe_unused handle_exit(void *data, struct task_struct *p, bool group_dead)
+/*
+ * Deallocation hook, use da_skip_deallocation() when not necessary
+ */
+static void handle_exit(void *data, struct task_struct *p, bool group_dead)
{
if (p->policy == SCHED_DEADLINE)
da_destroy_storage(get_entity_id(&p->dl, DL_TASK, DL_TASK));
--
2.54.0
^ permalink raw reply related [flat|nested] 10+ messages in thread