From nobody Tue Feb 10 04:12:46 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 96923223DED for ; Wed, 14 May 2025 08:44:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747212289; cv=none; b=Y6Y8HLtYU60DL43ZgGHMeKdgrYASb+Pqu7caiuAKUt6wQUQCPP2sfLg6xmXU2v2yGcoNdFfd35gH2ybVg1BuCAF94Xbcqjkvr5E/evlson4XdzaWNej5to8/etyLmiu0QtgnkX+xPdsCpPqbJpJNQ/vxb9oRoLrA5Yq1eM1r38k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747212289; c=relaxed/simple; bh=JQllrsynzjm68Qj/f/HNSQitBzIq2FfcbBmseRxy/mA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SKkFOiFjKQC1phNjRBwXcIzxqQiKMDb4G67LTEBKPXe0R5GR5vMWyFJm9BFtO52ELiG6jGobqem2MxBBC8bD8CcZtFtEv0mx46Z+SzSPnxChFGd1ra8NUravqCaFMupezcWHUK+VOTbvBZ1i6uC6xTm5yBAk0MT/d8uy7E3OS0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=eDfT7ykd; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="eDfT7ykd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1747212286; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tDUti7k9M7nDIV6nH94mmZUc7PAtTA41xzVPHy++Yzo=; b=eDfT7ykd7U7VfL9oZF69b7dYsQJA1m/dbbRvGIrdb1AuDhLjZNpb0y5SYrbrmT4FuY1ZVC V+3cO6rWp8e2JMVElbyPX+QMNtxDufY6lJJsf3DPfwG6AeICGZ98UjbR8X8p5M4f9Hbnkj UmeS1mMGWhnH/xIzK30+mNrV4+yHnZE= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-17-MlX00-HuN-GuKdOmZA5pVw-1; Wed, 14 May 2025 04:44:43 -0400 X-MC-Unique: MlX00-HuN-GuKdOmZA5pVw-1 X-Mimecast-MFC-AGG-ID: MlX00-HuN-GuKdOmZA5pVw_1747212281 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D138A180035E; Wed, 14 May 2025 08:44:41 +0000 (UTC) Received: from gmonaco-thinkpadt14gen3.rmtit.com (unknown [10.44.32.189]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 48A761953B80; Wed, 14 May 2025 08:44:35 +0000 (UTC) From: Gabriele Monaco To: linux-kernel@vger.kernel.org, Steven Rostedt , Jonathan Corbet , Masami Hiramatsu , linux-trace-kernel@vger.kernel.org, linux-doc@vger.kernel.org Cc: Gabriele Monaco , Ingo Molnar , Peter Zijlstra , Nam Cao , Tomas Glozar , Juri Lelli Subject: [RFC PATCH v2 12/12] rv: Add opid per-cpu monitor Date: Wed, 14 May 2025 10:43:14 +0200 Message-ID: <20250514084314.57976-13-gmonaco@redhat.com> In-Reply-To: <20250514084314.57976-1-gmonaco@redhat.com> References: <20250514084314.57976-1-gmonaco@redhat.com> 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 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 Content-Type: text/plain; charset="utf-8" Add a per-cpu monitor as part of the sched model: * opid: operations with preemption and irq disabled Monitor to ensure wakeup and need_resched occur with irq and preemption disabled or in irq handlers. Signed-off-by: Gabriele Monaco --- Documentation/trace/rv/monitor_sched.rst | 48 +++++++ kernel/trace/rv/Kconfig | 1 + kernel/trace/rv/Makefile | 1 + kernel/trace/rv/monitors/opid/Kconfig | 17 +++ kernel/trace/rv/monitors/opid/opid.c | 151 +++++++++++++++++++++ kernel/trace/rv/monitors/opid/opid.h | 64 +++++++++ kernel/trace/rv/monitors/opid/opid_trace.h | 15 ++ kernel/trace/rv/rv_trace.h | 1 + tools/verification/models/sched/opid.dot | 35 +++++ 9 files changed, 333 insertions(+) create mode 100644 kernel/trace/rv/monitors/opid/Kconfig create mode 100644 kernel/trace/rv/monitors/opid/opid.c create mode 100644 kernel/trace/rv/monitors/opid/opid.h create mode 100644 kernel/trace/rv/monitors/opid/opid_trace.h create mode 100644 tools/verification/models/sched/opid.dot diff --git a/Documentation/trace/rv/monitor_sched.rst b/Documentation/trace= /rv/monitor_sched.rst index 97f0f1a10f43..f044bca7ac31 100644 --- a/Documentation/trace/rv/monitor_sched.rst +++ b/Documentation/trace/rv/monitor_sched.rst @@ -315,6 +315,54 @@ after the task got to ``sleeping`` until a ``wakeup``:: | | +----------------------------+ =20 +Monitor opid +------------ + +The operations with preemption and irq disabled (opid) monitor ensures +operations like ``wakeup`` and ``need_resched`` occur with interrupts and +preemption disabled or during IRQs, in such case preemption may not be dis= abled +explicitly. +``need_resched`` can be set by some RCU internals functions, in which case= it +doesn't match a task wakeup and might occur with only interrupts disabled:: + + | sched_need_resched + | sched_waking + | irq_entry + | +--------------------+ + v v | + +------------------------------------------------------+ + +----------- | disabled | <+ + | +------------------------------------------------------+ | + | | ^ | + | | preempt_disable sched_need_resched | + | preempt_enable | +--------------------+ | + | v | v | | + | +------------------------------------------------------+ | + | | irq_disabled | | + | +------------------------------------------------------+ | + | | | ^ | + | irq_entry | | | + | sched_need_resched v | irq_disable | + | sched_waking +--------------+ | | | + | +----- | | irq_enable | | + | | | in_irq | | | | + | +----> | | | | | + | +--------------+ | | irq_dis= able + | | | | | + | irq_enable | irq_enable | | | + | v v | | + | #=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D# | + | H enabled H | + | #=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D# | + | | ^ ^ preempt_enable | | + | preempt_disable preempt_enable +--------------------+ | + | v | | + | +------------------+ | | + +----------> | preempt_disabled | -+ | + +------------------+ | + | | + +-------------------------------------------------------+ + References ---------- =20 diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig index f106cf7b2fd3..9ebb80931a9f 100644 --- a/kernel/trace/rv/Kconfig +++ b/kernel/trace/rv/Kconfig @@ -36,6 +36,7 @@ source "kernel/trace/rv/monitors/sncid/Kconfig" source "kernel/trace/rv/monitors/sts/Kconfig" source "kernel/trace/rv/monitors/nrp/Kconfig" source "kernel/trace/rv/monitors/sssw/Kconfig" +source "kernel/trace/rv/monitors/opid/Kconfig" # Add new monitors here =20 config RV_REACTORS diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile index c076cf48af18..0eca5e77d0d2 100644 --- a/kernel/trace/rv/Makefile +++ b/kernel/trace/rv/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_RV_MON_SNCID) +=3D monitors/sncid/sncid.o obj-$(CONFIG_RV_MON_STS) +=3D monitors/sts/sts.o obj-$(CONFIG_RV_MON_NRP) +=3D monitors/nrp/nrp.o obj-$(CONFIG_RV_MON_SSSW) +=3D monitors/sssw/sssw.o +obj-$(CONFIG_RV_MON_OPID) +=3D monitors/opid/opid.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/opid/Kconfig b/kernel/trace/rv/monito= rs/opid/Kconfig new file mode 100644 index 000000000000..c59d51654cd1 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/Kconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +config RV_MON_OPID + depends on RV + depends on IRQSOFF_TRACER + depends on PREEMPT_TRACER + depends on RV_MON_SCHED + default y + select DA_MON_EVENTS_IMPLICIT + bool "opid monitor" + help + Monitor to ensure operations like wakeup and need resched occur with + interrupts and preemption disabled or during IRQs, where preemption + may not be disabled explicitly. + + For further information, see: + Documentation/trace/rv/monitor_sched.rst diff --git a/kernel/trace/rv/monitors/opid/opid.c b/kernel/trace/rv/monitor= s/opid/opid.c new file mode 100644 index 000000000000..d8732d681753 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/opid.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_NAME "opid" + +#include +#include +#include +#include +#include + +#include "opid.h" + +static struct rv_monitor rv_opid; +DECLARE_DA_MON_PER_CPU(opid, unsigned char); + +#ifdef CONFIG_X86_LOCAL_APIC +#include + +static void handle_vector_irq_entry(void *data, int vector) +{ + da_handle_event_opid(irq_entry_opid); +} + +static void attach_vector_irq(void) { + rv_attach_trace_probe("opid", local_timer_entry, handle_vector_irq_entry); +} + +static void detach_vector_irq(void) { + rv_detach_trace_probe("opid", local_timer_entry, handle_vector_irq_entry); +} + +#else +/* We assume irq_entry tracepoints are sufficient on other architectures */ +static void attach_vector_irq() { } +static void detach_vector_irq() { } +#endif + +static void handle_irq_disable(void *data, unsigned long ip, unsigned long= parent_ip) +{ + da_handle_event_opid(irq_disable_opid); +} + +static void handle_irq_enable(void *data, unsigned long ip, unsigned long = parent_ip) +{ + da_handle_event_opid(irq_enable_opid); +} + +static void handle_irq_entry(void *data, int irq, struct irqaction *action) +{ + da_handle_event_opid(irq_entry_opid); +} + +static void handle_preempt_disable(void *data, unsigned long ip, unsigned = long parent_ip) +{ + da_handle_event_opid(preempt_disable_opid); +} + +static void handle_preempt_enable(void *data, unsigned long ip, unsigned l= ong parent_ip) +{ + da_handle_event_opid(preempt_enable_opid); +} + +static void handle_sched_need_resched(void *data, struct task_struct *tsk,= int cpu, int tif) +{ + if(in_irq()) + da_handle_event_opid(sched_need_resched_opid); + else + da_handle_start_event_opid(sched_need_resched_opid); +} + +static void handle_sched_waking(void *data, struct task_struct *p) +{ + if(in_irq()) + da_handle_event_opid(sched_waking_opid); + else + da_handle_start_event_opid(sched_waking_opid); +} + +static int enable_opid(void) +{ + int retval; + + retval =3D da_monitor_init_opid(); + if (retval) + return retval; + + rv_attach_trace_probe("opid", irq_disable, handle_irq_disable); + rv_attach_trace_probe("opid", irq_enable, handle_irq_enable); + rv_attach_trace_probe("opid", irq_handler_entry, handle_irq_entry); + rv_attach_trace_probe("opid", preempt_disable, handle_preempt_disable); + rv_attach_trace_probe("opid", preempt_enable, handle_preempt_enable); + rv_attach_trace_probe("opid", sched_set_need_resched_tp, handle_sched_nee= d_resched); + rv_attach_trace_probe("opid", sched_waking, handle_sched_waking); + attach_vector_irq(); + + return 0; +} + +static void disable_opid(void) +{ + rv_opid.enabled =3D 0; + + rv_detach_trace_probe("opid", irq_disable, handle_irq_disable); + rv_detach_trace_probe("opid", irq_enable, handle_irq_enable); + rv_detach_trace_probe("opid", irq_handler_entry, handle_irq_entry); + rv_detach_trace_probe("opid", preempt_disable, handle_preempt_disable); + rv_detach_trace_probe("opid", preempt_enable, handle_preempt_enable); + rv_detach_trace_probe("opid", sched_set_need_resched_tp, handle_sched_nee= d_resched); + rv_detach_trace_probe("opid", sched_waking, handle_sched_waking); + detach_vector_irq(); + + da_monitor_destroy_opid(); +} + +/* + * This is the monitor register section. + */ +static struct rv_monitor rv_opid =3D { + .name =3D "opid", + .description =3D "operations with preemption and irq disabled.", + .enable =3D enable_opid, + .disable =3D disable_opid, + .reset =3D da_monitor_reset_all_opid, + .enabled =3D 0, +}; + +static int __init register_opid(void) +{ + rv_register_monitor(&rv_opid, &rv_sched); + return 0; +} + +static void __exit unregister_opid(void) +{ + rv_unregister_monitor(&rv_opid); +} + +module_init(register_opid); +module_exit(unregister_opid); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gabriele Monaco "); +MODULE_DESCRIPTION("opid: operations with preemption and irq disabled."); diff --git a/kernel/trace/rv/monitors/opid/opid.h b/kernel/trace/rv/monitor= s/opid/opid.h new file mode 100644 index 000000000000..4c6d4a3964c5 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/opid.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Automatically generated C representation of opid automaton + * For further information about this format, see kernel documentation: + * Documentation/trace/rv/deterministic_automata.rst + */ + +enum states_opid { + disabled_opid =3D 0, + enabled_opid, + in_irq_opid, + irq_disabled_opid, + preempt_disabled_opid, + state_max_opid +}; + +#define INVALID_STATE state_max_opid + +enum events_opid { + irq_disable_opid =3D 0, + irq_enable_opid, + irq_entry_opid, + preempt_disable_opid, + preempt_enable_opid, + sched_need_resched_opid, + sched_waking_opid, + event_max_opid +}; + +struct automaton_opid { + char *state_names[state_max_opid]; + char *event_names[event_max_opid]; + unsigned char function[state_max_opid][event_max_opid]; + unsigned char initial_state; + bool final_states[state_max_opid]; +}; + +static const struct automaton_opid automaton_opid =3D { + .state_names =3D { + "disabled", + "enabled", + "in_irq", + "irq_disabled", + "preempt_disabled" + }, + .event_names =3D { + "irq_disable", + "irq_enable", + "irq_entry", + "preempt_disable", + "preempt_enable", + "sched_need_resched", + "sched_waking" + }, + .function =3D { + { INVALID_STATE, preempt_disabled_opid, disabled_opid, = INVALID_STATE, irq_disabled_opid, disabled_opid, = disabled_opid }, + { irq_disabled_opid, INVALID_STATE, INVALID_STATE, p= reempt_disabled_opid, enabled_opid, INVALID_STATE, = INVALID_STATE }, + { INVALID_STATE, enabled_opid, INVALID_STATE, = INVALID_STATE, INVALID_STATE, in_irq_opid, = in_irq_opid }, + { INVALID_STATE, enabled_opid, in_irq_opid, = disabled_opid, INVALID_STATE, irq_disabled_opid, = INVALID_STATE }, + { disabled_opid, INVALID_STATE, INVALID_STATE, = INVALID_STATE, enabled_opid, INVALID_STATE, = INVALID_STATE }, + }, + .initial_state =3D disabled_opid, + .final_states =3D { 0, 1, 0, 0, 0 }, +}; diff --git a/kernel/trace/rv/monitors/opid/opid_trace.h b/kernel/trace/rv/m= onitors/opid/opid_trace.h new file mode 100644 index 000000000000..3df6ff955c30 --- /dev/null +++ b/kernel/trace/rv/monitors/opid/opid_trace.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* + * Snippet to be included in rv_trace.h + */ + +#ifdef CONFIG_RV_MON_OPID +DEFINE_EVENT(event_da_monitor, event_opid, + 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_opid, + TP_PROTO(char *state, char *event), + TP_ARGS(state, event)); +#endif /* CONFIG_RV_MON_OPID */ diff --git a/kernel/trace/rv/rv_trace.h b/kernel/trace/rv/rv_trace.h index d12ab74dcabc..5d3c5c3f7545 100644 --- a/kernel/trace/rv/rv_trace.h +++ b/kernel/trace/rv/rv_trace.h @@ -63,6 +63,7 @@ DECLARE_EVENT_CLASS(error_da_monitor, #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/opid.dot b/tools/verification/= models/sched/opid.dot new file mode 100644 index 000000000000..2d5e1df3405f --- /dev/null +++ b/tools/verification/models/sched/opid.dot @@ -0,0 +1,35 @@ +digraph state_automaton { + center =3D true; + size =3D "7,11"; + {node [shape =3D plaintext, style=3Dinvis, label=3D""] "__init_disabled"}; + {node [shape =3D circle] "disabled"}; + {node [shape =3D doublecircle] "enabled"}; + {node [shape =3D circle] "enabled"}; + {node [shape =3D circle] "in_irq"}; + {node [shape =3D circle] "irq_disabled"}; + {node [shape =3D circle] "preempt_disabled"}; + "__init_disabled" -> "disabled"; + "disabled" [label =3D "disabled"]; + "disabled" -> "disabled" [ label =3D "sched_need_resched\nsched_waking\ni= rq_entry" ]; + "disabled" -> "irq_disabled" [ label =3D "preempt_enable" ]; + "disabled" -> "preempt_disabled" [ label =3D "irq_enable" ]; + "enabled" [label =3D "enabled", color =3D green3]; + "enabled" -> "enabled" [ label =3D "preempt_enable" ]; + "enabled" -> "irq_disabled" [ label =3D "irq_disable" ]; + "enabled" -> "preempt_disabled" [ label =3D "preempt_disable" ]; + "in_irq" [label =3D "in_irq"]; + "in_irq" -> "enabled" [ label =3D "irq_enable" ]; + "in_irq" -> "in_irq" [ label =3D "sched_need_resched\nsched_waking" ]; + "irq_disabled" [label =3D "irq_disabled"]; + "irq_disabled" -> "disabled" [ label =3D "preempt_disable" ]; + "irq_disabled" -> "enabled" [ label =3D "irq_enable" ]; + "irq_disabled" -> "in_irq" [ label =3D "irq_entry" ]; + "irq_disabled" -> "irq_disabled" [ label =3D "sched_need_resched" ]; + "preempt_disabled" [label =3D "preempt_disabled"]; + "preempt_disabled" -> "disabled" [ label =3D "irq_disable" ]; + "preempt_disabled" -> "enabled" [ label =3D "preempt_enable" ]; + { rank =3D min ; + "__init_disabled"; + "disabled"; + } +} --=20 2.49.0